From 449a01d2659c207b012e6d3bb6edfff8c94a4e55 Mon Sep 17 00:00:00 2001 From: Sushma Kalakota Date: Wed, 8 Jan 2020 15:05:10 -0700 Subject: [PATCH 0001/4444] PCI: vmd: Add two VMD Device IDs Add new VMD device IDs that require the bus restriction mode. Signed-off-by: Sushma Kalakota Signed-off-by: Jon Derrick Signed-off-by: Lorenzo Pieralisi --- drivers/pci/controller/vmd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c index 212842263f55..c502b6c0daf5 100644 --- a/drivers/pci/controller/vmd.c +++ b/drivers/pci/controller/vmd.c @@ -868,6 +868,10 @@ static const struct pci_device_id vmd_ids[] = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_28C0), .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW | VMD_FEAT_HAS_BUS_RESTRICTIONS,}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x467f), + .driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4c3d), + .driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_9A0B), .driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,}, {0,} From 692751879ea876dec81357e6f1f8ca0ced131ceb Mon Sep 17 00:00:00 2001 From: Mike Looijmans Date: Tue, 7 Jan 2020 08:53:40 +0100 Subject: [PATCH 0002/4444] clk, clk-si5341: Support multiple input ports The Si5341 and Si5340 have multiple input clock options. So far, the driver only supported the XTAL input, this adds support for the three external clock inputs as well. If the clock chip isn't programmed at boot, the driver will default to the XTAL input as before. If there is no "xtal" clock input available, it will pick the first connected input (e.g. "in0") as the input clock for the PLL. One can use clock-assigned-parents to select a particular clock as input. Signed-off-by: Mike Looijmans Link: https://lkml.kernel.org/r/20200107075340.14528-1-mike.looijmans@topic.nl Signed-off-by: Stephen Boyd --- drivers/clk/clk-si5341.c | 212 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 196 insertions(+), 16 deletions(-) diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c index 6e780c2a9e6b..3c228b018116 100644 --- a/drivers/clk/clk-si5341.c +++ b/drivers/clk/clk-si5341.c @@ -16,6 +16,8 @@ #include #include +#define SI5341_NUM_INPUTS 4 + #define SI5341_MAX_NUM_OUTPUTS 10 #define SI5340_MAX_NUM_OUTPUTS 4 @@ -56,8 +58,8 @@ struct clk_si5341 { struct i2c_client *i2c_client; struct clk_si5341_synth synth[SI5341_NUM_SYNTH]; struct clk_si5341_output clk[SI5341_MAX_NUM_OUTPUTS]; - struct clk *pxtal; - const char *pxtal_name; + struct clk *input_clk[SI5341_NUM_INPUTS]; + const char *input_clk_name[SI5341_NUM_INPUTS]; const u16 *reg_output_offset; const u16 *reg_rdiv_offset; u64 freq_vco; /* 13500–14256 MHz */ @@ -78,10 +80,25 @@ struct clk_si5341_output_config { #define SI5341_DEVICE_REV 0x0005 #define SI5341_STATUS 0x000C #define SI5341_SOFT_RST 0x001C +#define SI5341_IN_SEL 0x0021 +#define SI5341_XAXB_CFG 0x090E +#define SI5341_IN_EN 0x0949 +#define SI5341_INX_TO_PFD_EN 0x094A + +/* Input selection */ +#define SI5341_IN_SEL_MASK 0x06 +#define SI5341_IN_SEL_SHIFT 1 +#define SI5341_IN_SEL_REGCTRL 0x01 +#define SI5341_INX_TO_PFD_SHIFT 4 + +/* XTAL config bits */ +#define SI5341_XAXB_CFG_EXTCLK_EN BIT(0) +#define SI5341_XAXB_CFG_PDNB BIT(1) /* Input dividers (48-bit) */ #define SI5341_IN_PDIV(x) (0x0208 + ((x) * 10)) #define SI5341_IN_PSET(x) (0x020E + ((x) * 10)) +#define SI5341_PX_UPD 0x0230 /* PLL configuration */ #define SI5341_PLL_M_NUM 0x0235 @@ -120,6 +137,10 @@ struct si5341_reg_default { u8 value; }; +static const char * const si5341_input_clock_names[] = { + "in0", "in1", "in2", "xtal" +}; + /* Output configuration registers 0..9 are not quite logically organized */ static const u16 si5341_reg_output_offset[] = { 0x0108, @@ -390,7 +411,112 @@ static unsigned long si5341_clk_recalc_rate(struct clk_hw *hw, return (unsigned long)res; } +static int si5341_clk_get_selected_input(struct clk_si5341 *data) +{ + int err; + u32 val; + + err = regmap_read(data->regmap, SI5341_IN_SEL, &val); + if (err < 0) + return err; + + return (val & SI5341_IN_SEL_MASK) >> SI5341_IN_SEL_SHIFT; +} + +static u8 si5341_clk_get_parent(struct clk_hw *hw) +{ + struct clk_si5341 *data = to_clk_si5341(hw); + int res = si5341_clk_get_selected_input(data); + + if (res < 0) + return 0; /* Apparently we cannot report errors */ + + return res; +} + +static int si5341_clk_reparent(struct clk_si5341 *data, u8 index) +{ + int err; + u8 val; + + val = (index << SI5341_IN_SEL_SHIFT) & SI5341_IN_SEL_MASK; + /* Enable register-based input selection */ + val |= SI5341_IN_SEL_REGCTRL; + + err = regmap_update_bits(data->regmap, + SI5341_IN_SEL, SI5341_IN_SEL_REGCTRL | SI5341_IN_SEL_MASK, val); + if (err < 0) + return err; + + if (index < 3) { + /* Enable input buffer for selected input */ + err = regmap_update_bits(data->regmap, + SI5341_IN_EN, 0x07, BIT(index)); + if (err < 0) + return err; + + /* Enables the input to phase detector */ + err = regmap_update_bits(data->regmap, SI5341_INX_TO_PFD_EN, + 0x7 << SI5341_INX_TO_PFD_SHIFT, + BIT(index + SI5341_INX_TO_PFD_SHIFT)); + if (err < 0) + return err; + + /* Power down XTAL oscillator and buffer */ + err = regmap_update_bits(data->regmap, SI5341_XAXB_CFG, + SI5341_XAXB_CFG_PDNB, 0); + if (err < 0) + return err; + + /* + * Set the P divider to "1". There's no explanation in the + * datasheet of these registers, but the clockbuilder software + * programs a "1" when the input is being used. + */ + err = regmap_write(data->regmap, SI5341_IN_PDIV(index), 1); + if (err < 0) + return err; + + err = regmap_write(data->regmap, SI5341_IN_PSET(index), 1); + if (err < 0) + return err; + + /* Set update PDIV bit */ + err = regmap_write(data->regmap, SI5341_PX_UPD, BIT(index)); + if (err < 0) + return err; + } else { + /* Disable all input buffers */ + err = regmap_update_bits(data->regmap, SI5341_IN_EN, 0x07, 0); + if (err < 0) + return err; + + /* Disable input to phase detector */ + err = regmap_update_bits(data->regmap, SI5341_INX_TO_PFD_EN, + 0x7 << SI5341_INX_TO_PFD_SHIFT, 0); + if (err < 0) + return err; + + /* Power up XTAL oscillator and buffer */ + err = regmap_update_bits(data->regmap, SI5341_XAXB_CFG, + SI5341_XAXB_CFG_PDNB, SI5341_XAXB_CFG_PDNB); + if (err < 0) + return err; + } + + return 0; +} + +static int si5341_clk_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_si5341 *data = to_clk_si5341(hw); + + return si5341_clk_reparent(data, index); +} + static const struct clk_ops si5341_clk_ops = { + .set_parent = si5341_clk_set_parent, + .get_parent = si5341_clk_get_parent, .recalc_rate = si5341_clk_recalc_rate, }; @@ -985,7 +1111,8 @@ static const struct regmap_range si5341_regmap_volatile_range[] = { regmap_reg_range(0x000C, 0x0012), /* Status */ regmap_reg_range(0x001C, 0x001E), /* reset, finc/fdec */ regmap_reg_range(0x00E2, 0x00FE), /* NVM, interrupts, device ready */ - /* Update bits for synth config */ + /* Update bits for P divider and synth config */ + regmap_reg_range(SI5341_PX_UPD, SI5341_PX_UPD), regmap_reg_range(SI5341_SYNTH_N_UPD(0), SI5341_SYNTH_N_UPD(0)), regmap_reg_range(SI5341_SYNTH_N_UPD(1), SI5341_SYNTH_N_UPD(1)), regmap_reg_range(SI5341_SYNTH_N_UPD(2), SI5341_SYNTH_N_UPD(2)), @@ -1122,6 +1249,7 @@ static int si5341_initialize_pll(struct clk_si5341 *data) struct device_node *np = data->i2c_client->dev.of_node; u32 m_num = 0; u32 m_den = 0; + int sel; if (of_property_read_u32(np, "silabs,pll-m-num", &m_num)) { dev_err(&data->i2c_client->dev, @@ -1135,7 +1263,11 @@ static int si5341_initialize_pll(struct clk_si5341 *data) if (!m_num || !m_den) { dev_err(&data->i2c_client->dev, "PLL configuration invalid, assume 14GHz\n"); - m_den = clk_get_rate(data->pxtal) / 10; + sel = si5341_clk_get_selected_input(data); + if (sel < 0) + return sel; + + m_den = clk_get_rate(data->input_clk[sel]) / 10; m_num = 1400000000; } @@ -1143,11 +1275,52 @@ static int si5341_initialize_pll(struct clk_si5341 *data) SI5341_PLL_M_NUM, m_num, m_den); } +static int si5341_clk_select_active_input(struct clk_si5341 *data) +{ + int res; + int err; + int i; + + res = si5341_clk_get_selected_input(data); + if (res < 0) + return res; + + /* If the current register setting is invalid, pick the first input */ + if (!data->input_clk[res]) { + dev_dbg(&data->i2c_client->dev, + "Input %d not connected, rerouting\n", res); + res = -ENODEV; + for (i = 0; i < SI5341_NUM_INPUTS; ++i) { + if (data->input_clk[i]) { + res = i; + break; + } + } + if (res < 0) { + dev_err(&data->i2c_client->dev, + "No clock input available\n"); + return res; + } + } + + /* Make sure the selected clock is also enabled and routed */ + err = si5341_clk_reparent(data, res); + if (err < 0) + return err; + + err = clk_prepare_enable(data->input_clk[res]); + if (err < 0) + return err; + + return res; +} + static int si5341_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct clk_si5341 *data; struct clk_init_data init; + struct clk *input; const char *root_clock_name; const char *synth_clock_names[SI5341_NUM_SYNTH]; int err; @@ -1161,12 +1334,16 @@ static int si5341_probe(struct i2c_client *client, data->i2c_client = client; - data->pxtal = devm_clk_get(&client->dev, "xtal"); - if (IS_ERR(data->pxtal)) { - if (PTR_ERR(data->pxtal) == -EPROBE_DEFER) - return -EPROBE_DEFER; - - dev_err(&client->dev, "Missing xtal clock input\n"); + for (i = 0; i < SI5341_NUM_INPUTS; ++i) { + input = devm_clk_get(&client->dev, si5341_input_clock_names[i]); + if (IS_ERR(input)) { + if (PTR_ERR(input) == -EPROBE_DEFER) + return -EPROBE_DEFER; + data->input_clk_name[i] = si5341_input_clock_names[i]; + } else { + data->input_clk[i] = input; + data->input_clk_name[i] = __clk_get_name(input); + } } err = si5341_dt_parse_dt(client, config); @@ -1188,9 +1365,6 @@ static int si5341_probe(struct i2c_client *client, if (err < 0) return err; - /* "Activate" the xtal (usually a fixed clock) */ - clk_prepare_enable(data->pxtal); - if (of_property_read_bool(client->dev.of_node, "silabs,reprogram")) { initialization_required = true; } else { @@ -1223,7 +1397,14 @@ static int si5341_probe(struct i2c_client *client, ARRAY_SIZE(si5341_reg_defaults)); if (err < 0) return err; + } + /* Input must be up and running at this point */ + err = si5341_clk_select_active_input(data); + if (err < 0) + return err; + + if (initialization_required) { /* PLL configuration is required */ err = si5341_initialize_pll(data); if (err < 0) @@ -1231,9 +1412,8 @@ static int si5341_probe(struct i2c_client *client, } /* Register the PLL */ - data->pxtal_name = __clk_get_name(data->pxtal); - init.parent_names = &data->pxtal_name; - init.num_parents = 1; /* For now, only XTAL input supported */ + init.parent_names = data->input_clk_name; + init.num_parents = SI5341_NUM_INPUTS; init.ops = &si5341_clk_ops; init.flags = 0; data->hw.init = &init; From a6c5729b0ae1164326c8899a67a40cbe4325e82e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 31 Jan 2020 09:28:33 +0100 Subject: [PATCH 0003/4444] openrisc: configs: Cleanup CONFIG_CROSS_COMPILE CONFIG_CROSS_COMPILE is gone since commit f1089c92da79 ("kbuild: remove CONFIG_CROSS_COMPILE support"). Signed-off-by: Krzysztof Kozlowski Signed-off-by: Stafford Horne --- Documentation/openrisc/openrisc_port.rst | 4 ++-- arch/openrisc/configs/or1ksim_defconfig | 1 - arch/openrisc/configs/simple_smp_defconfig | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Documentation/openrisc/openrisc_port.rst b/Documentation/openrisc/openrisc_port.rst index a18747a8d191..4b2c437942a0 100644 --- a/Documentation/openrisc/openrisc_port.rst +++ b/Documentation/openrisc/openrisc_port.rst @@ -37,8 +37,8 @@ or Stafford's toolchain build and release scripts. Build the Linux kernel as usual:: - make ARCH=openrisc defconfig - make ARCH=openrisc + make ARCH=openrisc CROSS_COMPILE="or1k-linux-" defconfig + make ARCH=openrisc CROSS_COMPILE="or1k-linux-" 3) Running on FPGA (optional) diff --git a/arch/openrisc/configs/or1ksim_defconfig b/arch/openrisc/configs/or1ksim_defconfig index d8ff4f8ffb88..75f2da324d0e 100644 --- a/arch/openrisc/configs/or1ksim_defconfig +++ b/arch/openrisc/configs/or1ksim_defconfig @@ -1,4 +1,3 @@ -CONFIG_CROSS_COMPILE="or1k-linux-" CONFIG_NO_HZ=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y diff --git a/arch/openrisc/configs/simple_smp_defconfig b/arch/openrisc/configs/simple_smp_defconfig index 64278992df9c..ff49d868e040 100644 --- a/arch/openrisc/configs/simple_smp_defconfig +++ b/arch/openrisc/configs/simple_smp_defconfig @@ -1,4 +1,3 @@ -CONFIG_CROSS_COMPILE="or1k-linux-" CONFIG_LOCALVERSION="-simple-smp" CONFIG_NO_HZ=y CONFIG_LOG_BUF_SHIFT=14 From fc74d716600545304a066bfd9d54cbd07e531701 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Dec 2019 16:42:58 +0100 Subject: [PATCH 0004/4444] openrisc: use mmgrab Mmgrab was introduced in commit f1f1007644ff ("mm: add new mmgrab() helper") and most of the kernel was updated to use it. Update a remaining file. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) @@ expression e; @@ - atomic_inc(&e->mm_count); + mmgrab(e); Signed-off-by: Julia Lawall Signed-off-by: Stafford Horne [shorne: Added missing sched/mm.h include] --- arch/openrisc/kernel/smp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/openrisc/kernel/smp.c b/arch/openrisc/kernel/smp.c index 7d518ee8bddc..bd1e660bbc89 100644 --- a/arch/openrisc/kernel/smp.c +++ b/arch/openrisc/kernel/smp.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -113,7 +114,7 @@ asmlinkage __init void secondary_start_kernel(void) * All kernel threads share the same mm context; grab a * reference and switch to it. */ - atomic_inc(&mm->mm_count); + mmgrab(mm); current->active_mm = mm; cpumask_set_cpu(cpu, mm_cpumask(mm)); From 165c0946a863cdfd056e472d8a9673d7197ef066 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Feb 2020 17:28:01 +0100 Subject: [PATCH 0005/4444] ALSA: hda/hdmi: Reduce hda_jack_tbl lookup at unsol event handling Pass hda_jack_tbl object to hdmi_intrinsic_event() along with res from hdmi_unsol_event() so that we can reduce the lookup of the same hda_jack_tbl object again. Minor code refactoring. Reviewed-by: Kai Vehmanen Reviewed-by: Nikhil Mahale Link: https://lore.kernel.org/r/20200206162804.4734-2-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 5119a9ae3d8a..c65d16dea08c 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -779,21 +779,9 @@ static void jack_callback(struct hda_codec *codec, check_presence_and_report(codec, jack->nid, jack->dev_id); } -static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) +static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res, + struct hda_jack_tbl *jack) { - int tag = res >> AC_UNSOL_RES_TAG_SHIFT; - struct hda_jack_tbl *jack; - - if (codec->dp_mst) { - int dev_entry = - (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT; - - jack = snd_hda_jack_tbl_get_from_tag(codec, tag, dev_entry); - } else { - jack = snd_hda_jack_tbl_get_from_tag(codec, tag, 0); - } - if (!jack) - return; jack->jack_dirty = 1; codec_dbg(codec, @@ -853,7 +841,7 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) } if (subtag == 0) - hdmi_intrinsic_event(codec, res); + hdmi_intrinsic_event(codec, res, jack); else hdmi_non_intrinsic_event(codec, res); } From db8454023b7f9ca6d341cc83ce033a1f0e33d9c3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Feb 2020 17:28:02 +0100 Subject: [PATCH 0006/4444] ALSA: hda/hdmi: Don't use standard hda_jack for generic HDMI jacks The current HDMI codec driver code manages the jack detection in two different ways: for Intel codecs with audio component, the driver creates snd_jack objects by itself while the standard hda_jack stuff is used for the rest. This was basically because the audio component doesn't need the pin sense reading and the unsol event handling, hence it just needs to report the corresponding jacks directly. It was a bit messy but not too messy until the driver got DP-MST support for Nvidia that re-uses the part of dyn_pcm_assign feature while keeping the pin sense and the unsol event handling. Now, for DP-MST, we use hda_jack for pin sensing and unsol events but use the own snd_jack objects. Meanwhile for non-DP-MST, hda_jack is used for pin sense and unsol events, and the jacks are bound on hda_jack. Moreover, there is a polling mode support where the unsol event isn't used. For those, we also have special handling. For simplifying those messes, this patch unifies the snd_jack handling over all generic HDMI codes. The driver creates snd_jack objects just like Intel codecs did in the past but now for all devices. For the system without audio component binding, we still need the pin sense and the unsol event handling, and those are still done with the hda_jack table as before. But hda_jack is no longer used for the actual snd_jack handling. Since the hda_jack is no longer used for jack reporting, we removed snd_hda_jack_report_sync() calls, which also allowed to simplify the return type of hda_present_sense() and co. pin_idx_to_pcm_jack() was simplified as well because it behaves same for all cases now. Note that the hda_jack is still used for the simple HDMI codecs; they are really simple enough, so no big reason to change intrusively. Reviewed-by: Nikhil Mahale Link: https://lore.kernel.org/r/20200206162804.4734-3-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 219 ++++++++++--------------------------- 1 file changed, 57 insertions(+), 162 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index c65d16dea08c..98a8c4f97d6b 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -154,7 +154,6 @@ struct hdmi_spec { struct hda_multi_out multiout; struct hda_pcm_stream pcm_playback; - bool use_jack_detect; /* jack detection enabled */ bool use_acomp_notifier; /* use eld_notify callback for hotplug */ bool acomp_registered; /* audio component registered in this driver */ struct drm_audio_component_audio_ops drm_audio_ops; @@ -753,7 +752,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, * Unsolicited events */ -static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll); +static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll); static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid, int dev_id) @@ -764,8 +763,7 @@ static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid, if (pin_idx < 0) return; mutex_lock(&spec->pcm_lock); - if (hdmi_present_sense(get_pin(spec, pin_idx), 1)) - snd_hda_jack_report_sync(codec); + hdmi_present_sense(get_pin(spec, pin_idx), 1); mutex_unlock(&spec->pcm_lock); } @@ -1542,35 +1540,38 @@ static struct snd_jack *pin_idx_to_pcm_jack(struct hda_codec *codec, struct hdmi_spec_per_pin *per_pin) { struct hdmi_spec *spec = codec->spec; - struct snd_jack *jack = NULL; - struct hda_jack_tbl *jack_tbl; - /* if !dyn_pcm_assign, get jack from hda_jack_tbl - * in !dyn_pcm_assign case, spec->pcm_rec[].jack is not - * NULL even after snd_hda_jack_tbl_clear() is called to - * free snd_jack. This may cause access invalid memory - * when calling snd_jack_report - */ - if (per_pin->pcm_idx >= 0 && spec->dyn_pcm_assign) { - jack = spec->pcm_rec[per_pin->pcm_idx].jack; - } else if (!spec->dyn_pcm_assign) { - /* - * jack tbl doesn't support DP MST - * DP MST will use dyn_pcm_assign, - * so DP MST will never come here - */ - jack_tbl = snd_hda_jack_tbl_get_mst(codec, per_pin->pin_nid, - per_pin->dev_id); - if (jack_tbl) - jack = jack_tbl->jack; - } - return jack; + if (per_pin->pcm_idx >= 0) + return spec->pcm_rec[per_pin->pcm_idx].jack; + else + return NULL; } + +static void do_update_eld(struct hda_codec *codec, + struct hdmi_spec_per_pin *per_pin, + struct hdmi_eld *eld) +{ + struct snd_jack *pcm_jack; + bool changed; + + /* + * pcm_idx >=0 before update_eld() means it is in monitor + * disconnected event. Jack must be fetched before update_eld(). + */ + pcm_jack = pin_idx_to_pcm_jack(codec, per_pin); + changed = update_eld(codec, per_pin, eld); + if (!pcm_jack) + pcm_jack = pin_idx_to_pcm_jack(codec, per_pin); + if (changed && pcm_jack) + snd_jack_report(pcm_jack, + (eld->monitor_present && eld->eld_valid) ? + SND_JACK_AVOUT : 0); +} + /* update ELD and jack state via HD-audio verbs */ -static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, +static void hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, int repoll) { - struct hda_jack_tbl *jack; struct hda_codec *codec = per_pin->codec; struct hdmi_spec *spec = codec->spec; struct hdmi_eld *eld = &spec->temp_eld; @@ -1585,9 +1586,7 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, * the unsolicited response to avoid custom WARs. */ int present; - bool ret; bool do_repoll = false; - struct snd_jack *pcm_jack = NULL; present = snd_hda_jack_pin_sense(codec, pin_nid, dev_id); @@ -1615,53 +1614,12 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, do_repoll = true; } - if (do_repoll) { + if (do_repoll) schedule_delayed_work(&per_pin->work, msecs_to_jiffies(300)); - } else { - /* - * pcm_idx >=0 before update_eld() means it is in monitor - * disconnected event. Jack must be fetched before - * update_eld(). - */ - pcm_jack = pin_idx_to_pcm_jack(codec, per_pin); - update_eld(codec, per_pin, eld); - if (!pcm_jack) - pcm_jack = pin_idx_to_pcm_jack(codec, per_pin); - } + else + do_update_eld(codec, per_pin, eld); - ret = !repoll || !eld->monitor_present || eld->eld_valid; - - jack = snd_hda_jack_tbl_get_mst(codec, pin_nid, per_pin->dev_id); - if (jack) { - jack->block_report = !ret; - jack->pin_sense = (eld->monitor_present && eld->eld_valid) ? - AC_PINSENSE_PRESENCE : 0; - - if (spec->dyn_pcm_assign && pcm_jack && !do_repoll) { - int state = 0; - - if (jack->pin_sense & AC_PINSENSE_PRESENCE) - state = SND_JACK_AVOUT; - snd_jack_report(pcm_jack, state); - } - - /* - * snd_hda_jack_pin_sense() call at the beginning of this - * function, updates jack->pins_sense and clears - * jack->jack_dirty, therefore snd_hda_jack_report_sync() will - * not override the jack->pin_sense. - * - * snd_hda_jack_report_sync() is superfluous for dyn_pcm_assign - * case. The jack->pin_sense update was already performed, and - * hda_jack->jack is NULL for dyn_pcm_assign. - * - * Don't call snd_hda_jack_report_sync() for - * dyn_pcm_assign. - */ - ret = ret && !spec->dyn_pcm_assign; - } mutex_unlock(&per_pin->lock); - return ret; } /* update ELD and jack state via audio component */ @@ -1670,8 +1628,6 @@ static void sync_eld_via_acomp(struct hda_codec *codec, { struct hdmi_spec *spec = codec->spec; struct hdmi_eld *eld = &spec->temp_eld; - struct snd_jack *jack = NULL; - bool changed; int size; mutex_lock(&per_pin->lock); @@ -1694,21 +1650,11 @@ static void sync_eld_via_acomp(struct hda_codec *codec, eld->eld_size = 0; } - /* pcm_idx >=0 before update_eld() means it is in monitor - * disconnected event. Jack must be fetched before update_eld() - */ - jack = pin_idx_to_pcm_jack(codec, per_pin); - changed = update_eld(codec, per_pin, eld); - if (jack == NULL) - jack = pin_idx_to_pcm_jack(codec, per_pin); - if (changed && jack) - snd_jack_report(jack, - (eld->monitor_present && eld->eld_valid) ? - SND_JACK_AVOUT : 0); + do_update_eld(codec, per_pin, eld); mutex_unlock(&per_pin->lock); } -static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) +static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) { struct hda_codec *codec = per_pin->codec; int ret; @@ -1718,16 +1664,13 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) ret = snd_hda_power_up_pm(codec); if (ret < 0 && pm_runtime_suspended(hda_codec_dev(codec))) { snd_hda_power_down_pm(codec); - return false; + return; } - ret = hdmi_present_sense_via_verbs(per_pin, repoll); + hdmi_present_sense_via_verbs(per_pin, repoll); snd_hda_power_down_pm(codec); } else { sync_eld_via_acomp(codec, per_pin); - ret = false; /* don't call snd_hda_jack_report_sync() */ } - - return ret; } static void hdmi_repoll_eld(struct work_struct *work) @@ -1747,8 +1690,7 @@ static void hdmi_repoll_eld(struct work_struct *work) per_pin->repoll_count = 0; mutex_lock(&spec->pcm_lock); - if (hdmi_present_sense(per_pin, per_pin->repoll_count)) - snd_hda_jack_report_sync(per_pin->codec); + hdmi_present_sense(per_pin, per_pin->repoll_count); mutex_unlock(&spec->pcm_lock); } @@ -2194,15 +2136,23 @@ static void free_hdmi_jack_priv(struct snd_jack *jack) pcm->jack = NULL; } -static int add_hdmi_jack_kctl(struct hda_codec *codec, - struct hdmi_spec *spec, - int pcm_idx, - const char *name) +static int generic_hdmi_build_jack(struct hda_codec *codec, int pcm_idx) { + char hdmi_str[32] = "HDMI/DP"; + struct hdmi_spec *spec = codec->spec; + struct hdmi_spec_per_pin *per_pin = get_pin(spec, pcm_idx); struct snd_jack *jack; + int pcmdev = get_pcm_rec(spec, pcm_idx)->device; int err; - err = snd_jack_new(codec->card, name, SND_JACK_AVOUT, &jack, + if (pcmdev > 0) + sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev); + if (!spec->dyn_pcm_assign && + !is_jack_detectable(codec, per_pin->pin_nid)) + strncat(hdmi_str, " Phantom", + sizeof(hdmi_str) - strlen(hdmi_str) - 1); + + err = snd_jack_new(codec->card, hdmi_str, SND_JACK_AVOUT, &jack, true, false); if (err < 0) return err; @@ -2213,48 +2163,6 @@ static int add_hdmi_jack_kctl(struct hda_codec *codec, return 0; } -static int generic_hdmi_build_jack(struct hda_codec *codec, int pcm_idx) -{ - char hdmi_str[32] = "HDMI/DP"; - struct hdmi_spec *spec = codec->spec; - struct hdmi_spec_per_pin *per_pin; - struct hda_jack_tbl *jack; - int pcmdev = get_pcm_rec(spec, pcm_idx)->device; - bool phantom_jack; - int ret; - - if (pcmdev > 0) - sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev); - - if (spec->dyn_pcm_assign) - return add_hdmi_jack_kctl(codec, spec, pcm_idx, hdmi_str); - - /* for !dyn_pcm_assign, we still use hda_jack for compatibility */ - /* if !dyn_pcm_assign, it must be non-MST mode. - * This means pcms and pins are statically mapped. - * And pcm_idx is pin_idx. - */ - per_pin = get_pin(spec, pcm_idx); - phantom_jack = !is_jack_detectable(codec, per_pin->pin_nid); - if (phantom_jack) - strncat(hdmi_str, " Phantom", - sizeof(hdmi_str) - strlen(hdmi_str) - 1); - ret = snd_hda_jack_add_kctl_mst(codec, per_pin->pin_nid, - per_pin->dev_id, hdmi_str, phantom_jack, - 0, NULL); - if (ret < 0) - return ret; - jack = snd_hda_jack_tbl_get_mst(codec, per_pin->pin_nid, - per_pin->dev_id); - if (jack == NULL) - return 0; - /* assign jack->jack to pcm_rec[].jack to - * align with dyn_pcm_assign mode - */ - spec->pcm_rec[pcm_idx].jack = jack->jack; - return 0; -} - static int generic_hdmi_build_controls(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; @@ -2343,7 +2251,6 @@ static int generic_hdmi_init(struct hda_codec *codec) int pin_idx; mutex_lock(&spec->bind_lock); - spec->use_jack_detect = !codec->jackpoll_interval; for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); hda_nid_t pin_nid = per_pin->pin_nid; @@ -2353,12 +2260,8 @@ static int generic_hdmi_init(struct hda_codec *codec) hdmi_init_pin(codec, pin_nid); if (codec_has_acomp(codec)) continue; - if (spec->use_jack_detect) - snd_hda_jack_detect_enable(codec, pin_nid, dev_id); - else - snd_hda_jack_detect_enable_callback_mst(codec, pin_nid, - dev_id, - jack_callback); + snd_hda_jack_detect_enable_callback_mst(codec, pin_nid, dev_id, + jack_callback); } mutex_unlock(&spec->bind_lock); return 0; @@ -2520,12 +2423,6 @@ static void reprogram_jack_detect(struct hda_codec *codec, hda_nid_t nid, unsigned int val = use_acomp ? 0 : (AC_USRSP_EN | tbl->tag); snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_UNSOLICITED_ENABLE, val); - } else { - /* if no jack entry was defined beforehand, create a new one - * at need (i.e. only when notifier is cleared) - */ - if (!use_acomp) - snd_hda_jack_detect_enable(codec, nid, dev_id); } } @@ -2541,13 +2438,11 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp, spec->use_acomp_notifier = use_acomp; spec->codec->relaxed_resume = use_acomp; /* reprogram each jack detection logic depending on the notifier */ - if (spec->use_jack_detect) { - for (i = 0; i < spec->num_pins; i++) - reprogram_jack_detect(spec->codec, - get_pin(spec, i)->pin_nid, - get_pin(spec, i)->dev_id, - use_acomp); - } + for (i = 0; i < spec->num_pins; i++) + reprogram_jack_detect(spec->codec, + get_pin(spec, i)->pin_nid, + get_pin(spec, i)->dev_id, + use_acomp); mutex_unlock(&spec->bind_lock); } From ae47e2ec5b4504cd91968e97ce2dab4ccd346fb6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Feb 2020 17:28:03 +0100 Subject: [PATCH 0007/4444] ALSA: hda/hdmi: Move runtime PM resume into hdmi_present_sense_via_verbs() For improving the readability, move the runtime PM handling code from hdmi_present_sense() to hdmi_present_sense_via_verbs(). Now hdmi_present_sense() became symmetric for both audio-component and legacy cases. Just a minor code refactoring. Reviewed-by: Kai Vehmanen Reviewed-by: Nikhil Mahale Link: https://lore.kernel.org/r/20200206162804.4734-4-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 98a8c4f97d6b..437177294d78 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1587,6 +1587,11 @@ static void hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, */ int present; bool do_repoll = false; + int ret; + + ret = snd_hda_power_up_pm(codec); + if (ret < 0 && pm_runtime_suspended(hda_codec_dev(codec))) + goto out; present = snd_hda_jack_pin_sense(codec, pin_nid, dev_id); @@ -1620,6 +1625,8 @@ static void hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, do_update_eld(codec, per_pin, eld); mutex_unlock(&per_pin->lock); + out: + snd_hda_power_down_pm(codec); } /* update ELD and jack state via audio component */ @@ -1657,20 +1664,11 @@ static void sync_eld_via_acomp(struct hda_codec *codec, static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) { struct hda_codec *codec = per_pin->codec; - int ret; - /* no temporary power up/down needed for component notifier */ - if (!codec_has_acomp(codec)) { - ret = snd_hda_power_up_pm(codec); - if (ret < 0 && pm_runtime_suspended(hda_codec_dev(codec))) { - snd_hda_power_down_pm(codec); - return; - } + if (!codec_has_acomp(codec)) hdmi_present_sense_via_verbs(per_pin, repoll); - snd_hda_power_down_pm(codec); - } else { + else sync_eld_via_acomp(codec, per_pin); - } } static void hdmi_repoll_eld(struct work_struct *work) From adf615a605017089c8948f393087080e1b61b114 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Feb 2020 17:28:04 +0100 Subject: [PATCH 0008/4444] ALSA: hda/hdmi: Move ELD parse and jack reporting into update_eld() This is a final step of the cleanup series: move the HDMI ELD parser call into update_eld() function so that we can unify the calls. The ELD validity check is unified in update_eld(), too. Along with it, the repoll scheduling is moved to update_eld() as well, where sync_eld_via_acomp() just passes 0 for skipping it. Reviewed-by: Kai Vehmanen Reviewed-by: Nikhil Mahale Link: https://lore.kernel.org/r/20200206162804.4734-5-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 110 ++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 62 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 437177294d78..bb287a916dae 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1466,21 +1466,60 @@ static void hdmi_pcm_reset_pin(struct hdmi_spec *spec, per_pin->channels = 0; } +static struct snd_jack *pin_idx_to_pcm_jack(struct hda_codec *codec, + struct hdmi_spec_per_pin *per_pin) +{ + struct hdmi_spec *spec = codec->spec; + + if (per_pin->pcm_idx >= 0) + return spec->pcm_rec[per_pin->pcm_idx].jack; + else + return NULL; +} + /* update per_pin ELD from the given new ELD; * setup info frame and notification accordingly + * also notify ELD kctl and report jack status changes */ -static bool update_eld(struct hda_codec *codec, +static void update_eld(struct hda_codec *codec, struct hdmi_spec_per_pin *per_pin, - struct hdmi_eld *eld) + struct hdmi_eld *eld, + int repoll) { struct hdmi_eld *pin_eld = &per_pin->sink_eld; struct hdmi_spec *spec = codec->spec; + struct snd_jack *pcm_jack; bool old_eld_valid = pin_eld->eld_valid; bool eld_changed; int pcm_idx; + if (eld->eld_valid) { + if (eld->eld_size <= 0 || + snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer, + eld->eld_size) < 0) { + eld->eld_valid = false; + if (repoll) { + schedule_delayed_work(&per_pin->work, + msecs_to_jiffies(300)); + return; + } + } + } + + if (!eld->eld_valid || eld->eld_size <= 0) { + eld->eld_valid = false; + eld->eld_size = 0; + } + /* for monitor disconnection, save pcm_idx firstly */ pcm_idx = per_pin->pcm_idx; + + /* + * pcm_idx >=0 before update_eld() means it is in monitor + * disconnected event. Jack must be fetched before update_eld(). + */ + pcm_jack = pin_idx_to_pcm_jack(codec, per_pin); + if (spec->dyn_pcm_assign) { if (eld->eld_valid) { hdmi_attach_hda_pcm(spec, per_pin); @@ -1495,6 +1534,8 @@ static bool update_eld(struct hda_codec *codec, */ if (pcm_idx == -1) pcm_idx = per_pin->pcm_idx; + if (!pcm_jack) + pcm_jack = pin_idx_to_pcm_jack(codec, per_pin); if (eld->eld_valid) snd_hdmi_show_eld(codec, &eld->info); @@ -1533,36 +1574,8 @@ static bool update_eld(struct hda_codec *codec, SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO, &get_hdmi_pcm(spec, pcm_idx)->eld_ctl->id); - return eld_changed; -} -static struct snd_jack *pin_idx_to_pcm_jack(struct hda_codec *codec, - struct hdmi_spec_per_pin *per_pin) -{ - struct hdmi_spec *spec = codec->spec; - - if (per_pin->pcm_idx >= 0) - return spec->pcm_rec[per_pin->pcm_idx].jack; - else - return NULL; -} - -static void do_update_eld(struct hda_codec *codec, - struct hdmi_spec_per_pin *per_pin, - struct hdmi_eld *eld) -{ - struct snd_jack *pcm_jack; - bool changed; - - /* - * pcm_idx >=0 before update_eld() means it is in monitor - * disconnected event. Jack must be fetched before update_eld(). - */ - pcm_jack = pin_idx_to_pcm_jack(codec, per_pin); - changed = update_eld(codec, per_pin, eld); - if (!pcm_jack) - pcm_jack = pin_idx_to_pcm_jack(codec, per_pin); - if (changed && pcm_jack) + if (eld_changed && pcm_jack) snd_jack_report(pcm_jack, (eld->monitor_present && eld->eld_valid) ? SND_JACK_AVOUT : 0); @@ -1586,7 +1599,6 @@ static void hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, * the unsolicited response to avoid custom WARs. */ int present; - bool do_repoll = false; int ret; ret = snd_hda_power_up_pm(codec); @@ -1610,20 +1622,9 @@ static void hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, if (spec->ops.pin_get_eld(codec, pin_nid, dev_id, eld->eld_buffer, &eld->eld_size) < 0) eld->eld_valid = false; - else { - if (snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer, - eld->eld_size) < 0) - eld->eld_valid = false; - } - if (!eld->eld_valid && repoll) - do_repoll = true; } - if (do_repoll) - schedule_delayed_work(&per_pin->work, msecs_to_jiffies(300)); - else - do_update_eld(codec, per_pin, eld); - + update_eld(codec, per_pin, eld, repoll); mutex_unlock(&per_pin->lock); out: snd_hda_power_down_pm(codec); @@ -1635,29 +1636,14 @@ static void sync_eld_via_acomp(struct hda_codec *codec, { struct hdmi_spec *spec = codec->spec; struct hdmi_eld *eld = &spec->temp_eld; - int size; mutex_lock(&per_pin->lock); eld->monitor_present = false; - size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid, + eld->eld_size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid, per_pin->dev_id, &eld->monitor_present, eld->eld_buffer, ELD_MAX_SIZE); - if (size > 0) { - size = min(size, ELD_MAX_SIZE); - if (snd_hdmi_parse_eld(codec, &eld->info, - eld->eld_buffer, size) < 0) - size = -EINVAL; - } - - if (size > 0) { - eld->eld_valid = true; - eld->eld_size = size; - } else { - eld->eld_valid = false; - eld->eld_size = 0; - } - - do_update_eld(codec, per_pin, eld); + eld->eld_valid = (eld->eld_size > 0); + update_eld(codec, per_pin, eld, 0); mutex_unlock(&per_pin->lock); } From c5bb086741c1f5cf05630dab7318433b71abb1f1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Feb 2020 17:31:50 +0100 Subject: [PATCH 0009/4444] ALSA: via82xx: Fix endianness annotations The internal page tables are in little endian, hence they should be __le32 type. This fixes the relevant sparse warnings: sound/pci/via82xx.c:454:60: warning: incorrect type in assignment (different base types) sound/pci/via82xx.c:454:60: expected unsigned int [usertype] sound/pci/via82xx.c:454:60: got restricted __le32 [usertype] .... No functional changes, just sparse warning fixes. Link: https://lore.kernel.org/r/20200206163152.6073-2-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/via82xx.c | 6 ++++-- sound/pci/via82xx_modem.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 799789c8eea9..8b03e2dc503f 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -414,6 +414,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre { unsigned int i, idx, ofs, rest; struct via82xx *chip = snd_pcm_substream_chip(substream); + __le32 *pgtbl; if (dev->table.area == NULL) { /* the start of each lists must be aligned to 8 bytes, @@ -435,6 +436,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre /* fill the entries */ idx = 0; ofs = 0; + pgtbl = (__le32 *)dev->table.area; for (i = 0; i < periods; i++) { rest = fragsize; /* fill descriptors for a period. @@ -451,7 +453,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre return -EINVAL; } addr = snd_pcm_sgbuf_get_addr(substream, ofs); - ((u32 *)dev->table.area)[idx << 1] = cpu_to_le32(addr); + pgtbl[idx << 1] = cpu_to_le32(addr); r = snd_pcm_sgbuf_get_chunk_size(substream, ofs, rest); rest -= r; if (! rest) { @@ -466,7 +468,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre "tbl %d: at %d size %d (rest %d)\n", idx, ofs, r, rest); */ - ((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag); + pgtbl[(idx<<1) + 1] = cpu_to_le32(r | flag); dev->idx_table[idx].offset = ofs; dev->idx_table[idx].size = r; ofs += r; diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 84e589803e2e..607b7100db1c 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -267,6 +267,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre { unsigned int i, idx, ofs, rest; struct via82xx_modem *chip = snd_pcm_substream_chip(substream); + __le32 *pgtbl; if (dev->table.area == NULL) { /* the start of each lists must be aligned to 8 bytes, @@ -288,6 +289,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre /* fill the entries */ idx = 0; ofs = 0; + pgtbl = (__le32 *)dev->table.area; for (i = 0; i < periods; i++) { rest = fragsize; /* fill descriptors for a period. @@ -304,7 +306,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre return -EINVAL; } addr = snd_pcm_sgbuf_get_addr(substream, ofs); - ((u32 *)dev->table.area)[idx << 1] = cpu_to_le32(addr); + pgtbl[idx << 1] = cpu_to_le32(addr); r = PAGE_SIZE - (ofs % PAGE_SIZE); if (rest < r) r = rest; @@ -321,7 +323,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre "tbl %d: at %d size %d (rest %d)\n", idx, ofs, r, rest); */ - ((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag); + pgtbl[(idx<<1) + 1] = cpu_to_le32(r | flag); dev->idx_table[idx].offset = ofs; dev->idx_table[idx].size = r; ofs += r; From 6a7322df2c2825bb2f45d247432a3b7d3f3ed233 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Feb 2020 17:31:51 +0100 Subject: [PATCH 0010/4444] ALSA: emu10k1: Fix endianness annotations The internal page tables are little endian, hence they should be __le32 type. This fixes the relevant sparse warning: sound/pci/emu10k1/emu10k1_main.c:2013:51: warning: incorrect type in assignment (different base types) sound/pci/emu10k1/emu10k1_main.c:2013:51: expected unsigned int [usertype] sound/pci/emu10k1/emu10k1_main.c:2013:51: got restricted __le32 [usertype] No functional changes, just sparse warning fixes. Link: https://lore.kernel.org/r/20200206163152.6073-3-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emu10k1_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index a89a7e603ca8..6ff581733a19 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1789,6 +1789,7 @@ int snd_emu10k1_create(struct snd_card *card, int idx, err; int is_audigy; size_t page_table_size; + __le32 *pgtbl; unsigned int silent_page; const struct snd_emu_chip_details *c; static const struct snd_device_ops ops = { @@ -2009,8 +2010,9 @@ int snd_emu10k1_create(struct snd_card *card, /* Clear silent pages and set up pointers */ memset(emu->silent_page.area, 0, emu->silent_page.bytes); silent_page = emu->silent_page.addr << emu->address_mode; + pgtbl = (__le32 *)emu->ptb_pages.area; for (idx = 0; idx < (emu->address_mode ? MAXPAGES1 : MAXPAGES0); idx++) - ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx); + pgtbl[idx] = cpu_to_le32(silent_page | idx); /* set up voice indices */ for (idx = 0; idx < NUM_G; idx++) { From f4caf8993e92e65cf716cbd7c30091ab6dbeb8c7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Feb 2020 17:31:52 +0100 Subject: [PATCH 0011/4444] ALSA: emu8000: Fix the cast to __user pointer Fixes the sparse warnings. The cast to __user pointer needs __force: sound/isa/sb/emu8000_pcm.c:528:9: warning: cast removes address space '' of expression No functional changes, just sparse warning fixes. Link: https://lore.kernel.org/r/20200206163152.6073-4-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/isa/sb/emu8000_pcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c index e377ac93f37f..8e8257c574b0 100644 --- a/sound/isa/sb/emu8000_pcm.c +++ b/sound/isa/sb/emu8000_pcm.c @@ -435,7 +435,7 @@ enum { #define LOOP_WRITE(rec, offset, _buf, count, mode) \ do { \ struct snd_emu8000 *emu = (rec)->emu; \ - unsigned short *buf = (unsigned short *)(_buf); \ + unsigned short *buf = (__force unsigned short *)(_buf); \ snd_emu8000_write_wait(emu, 1); \ EMU8000_SMALW_WRITE(emu, offset); \ while (count > 0) { \ @@ -492,7 +492,7 @@ static int emu8k_pcm_silence(struct snd_pcm_substream *subs, #define LOOP_WRITE(rec, pos, _buf, count, mode) \ do { \ struct snd_emu8000 *emu = rec->emu; \ - unsigned short *buf = (unsigned short *)(_buf); \ + unsigned short *buf = (__force unsigned short *)(_buf); \ snd_emu8000_write_wait(emu, 1); \ EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]); \ if (rec->voices > 1) \ From 8c356c524af88c0ad4d75b30fa201ed43d9a64c2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Feb 2020 17:39:38 +0100 Subject: [PATCH 0012/4444] ALSA: aloop: Fix PCM format assignment Fix sparse warnings about PCM format assignment regarding the strong typed snd_pcm_format_t: sound/drivers/aloop.c:352:45: warning: restricted snd_pcm_format_t degrades to integer sound/drivers/aloop.c:355:39: warning: incorrect type in assignment (different base types) sound/drivers/aloop.c:355:39: expected unsigned int format sound/drivers/aloop.c:355:39: got restricted snd_pcm_format_t [usertype] format sound/drivers/aloop.c:1435:34: warning: incorrect type in assignment (different base types) sound/drivers/aloop.c:1435:34: expected long max sound/drivers/aloop.c:1435:34: got restricted snd_pcm_format_t [usertype] sound/drivers/aloop.c:1565:39: warning: incorrect type in assignment (different base types) sound/drivers/aloop.c:1565:39: expected unsigned int format sound/drivers/aloop.c:1565:39: got restricted snd_pcm_format_t [usertype] Some code in this driver assigns an integer value to snd_pcm_format_t via control API, and they need to be with the explicit cast. No functional changes, just sparse warning fixes. Link: https://lore.kernel.org/r/20200206163945.6797-2-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/drivers/aloop.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index d78a27271d6d..251eaf1152e2 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -118,7 +118,7 @@ struct loopback_cable { struct loopback_setup { unsigned int notify: 1; unsigned int rate_shift; - unsigned int format; + snd_pcm_format_t format; unsigned int rate; unsigned int channels; struct snd_ctl_elem_id active_id; @@ -1432,7 +1432,7 @@ static int loopback_format_info(struct snd_kcontrol *kcontrol, uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = 0; - uinfo->value.integer.max = SNDRV_PCM_FORMAT_LAST; + uinfo->value.integer.max = (__force int)SNDRV_PCM_FORMAT_LAST; uinfo->value.integer.step = 1; return 0; } @@ -1443,7 +1443,7 @@ static int loopback_format_get(struct snd_kcontrol *kcontrol, struct loopback *loopback = snd_kcontrol_chip(kcontrol); ucontrol->value.integer.value[0] = - loopback->setup[kcontrol->id.subdevice] + (__force int)loopback->setup[kcontrol->id.subdevice] [kcontrol->id.device].format; return 0; } From b9c7d41087bc1755e01f9584f0bdbce0bb8b195d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Feb 2020 17:39:39 +0100 Subject: [PATCH 0013/4444] ALSA: pcm: More helper macros for reducing snd_pcm_format_t cast snd_pcm_format_t is a strong-typed integer and requires the explicit cast with __force if converted or compared with a normal integer value. Since most of use cases do iterate over all formats and test / set the mask, provide a couple of new helper macros that do the explicit cast. Link: https://lore.kernel.org/r/20200206163945.6797-3-tiwai@suse.de Signed-off-by: Takashi Iwai --- include/sound/pcm.h | 9 +++++++++ include/sound/pcm_params.h | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index f657ff08f317..31a4b300e4c9 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -1415,6 +1415,15 @@ static inline u64 pcm_format_to_bits(snd_pcm_format_t pcm_format) return 1ULL << (__force int) pcm_format; } +/** + * pcm_for_each_format - helper to iterate for each format type + * @f: the iterator variable in snd_pcm_format_t type + */ +#define pcm_for_each_format(f) \ + for ((f) = SNDRV_PCM_FORMAT_FIRST; \ + (__force int)(f) <= (__force int)SNDRV_PCM_FORMAT_LAST; \ + (f) = (__force snd_pcm_format_t)((__force int)(f) + 1)) + /* printk helpers */ #define pcm_err(pcm, fmt, args...) \ dev_err((pcm)->card->dev, fmt, ##args) diff --git a/include/sound/pcm_params.h b/include/sound/pcm_params.h index 661450a2095b..36f94735d23d 100644 --- a/include/sound/pcm_params.h +++ b/include/sound/pcm_params.h @@ -133,6 +133,13 @@ static inline int snd_mask_test(const struct snd_mask *mask, unsigned int val) return mask->bits[MASK_OFS(val)] & MASK_BIT(val); } +/* Most of drivers need only this one */ +static inline int snd_mask_test_format(const struct snd_mask *mask, + snd_pcm_format_t format) +{ + return snd_mask_test(mask, (__force unsigned int)format); +} + static inline int snd_mask_single(const struct snd_mask *mask) { int i, c = 0; From 5b29f05396bde54788a18633155ffa3f4d745f0d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Feb 2020 17:39:40 +0100 Subject: [PATCH 0014/4444] ALSA: usb-audio: Use pcm_for_each_format() macro for PCM format iterations The new macro can fix the sparse warnings gracefully: sound/usb/proc.c:73:31: warning: restricted snd_pcm_format_t degrades to integer sound/usb/proc.c:73:38: warning: restricted snd_pcm_format_t degrades to integer sound/usb/proc.c:73:61: warning: restricted snd_pcm_format_t degrades to integer No functional changes, just sparse warning fixes. Link: https://lore.kernel.org/r/20200206163945.6797-4-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/proc.c b/sound/usb/proc.c index ffbf4bd9208c..4174ad11fca6 100644 --- a/sound/usb/proc.c +++ b/sound/usb/proc.c @@ -70,7 +70,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s snd_iprintf(buffer, " Interface %d\n", fp->iface); snd_iprintf(buffer, " Altset %d\n", fp->altsetting); snd_iprintf(buffer, " Format:"); - for (fmt = 0; fmt <= SNDRV_PCM_FORMAT_LAST; ++fmt) + pcm_for_each_format(fmt) if (fp->formats & pcm_format_to_bits(fmt)) snd_iprintf(buffer, " %s", snd_pcm_format_name(fmt)); From c5f72ef15cb89284b0d7b0c167d9a713bb3781e8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Feb 2020 17:39:41 +0100 Subject: [PATCH 0015/4444] ALSA: dummy: Use standard macros for fixing PCM format cast Simplify the code with the new macros for PCM format type iterations. This fixes the sparse warnings nicely: sound/drivers/dummy.c:906:25: warning: restricted snd_pcm_format_t degrades to integer sound/drivers/dummy.c:908:25: warning: incorrect type in argument 1 (different base types) sound/drivers/dummy.c:908:25: expected restricted snd_pcm_format_t [usertype] format sound/drivers/dummy.c:908:25: got int [assigned] i No functional changes, just sparse warning fixes. Link: https://lore.kernel.org/r/20200206163945.6797-5-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/drivers/dummy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 02ac3f4e0c02..b5486de08b97 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -901,10 +901,10 @@ static int snd_card_dummy_new_mixer(struct snd_dummy *dummy) static void print_formats(struct snd_dummy *dummy, struct snd_info_buffer *buffer) { - int i; + snd_pcm_format_t i; - for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { - if (dummy->pcm_hw.formats & (1ULL << i)) + pcm_for_each_format(i) { + if (dummy->pcm_hw.formats & pcm_format_to_bits(i)) snd_iprintf(buffer, " %s", snd_pcm_format_name(i)); } } From ba71d227f4a250d7975e8296fed3aac9cb6105c9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Feb 2020 17:39:42 +0100 Subject: [PATCH 0016/4444] ALSA: pcm: Use standard macros for fixing PCM format cast Simplify the code with the new macros for PCM format type iterations. This fixes the sparse warnings nicely: sound/core/pcm_native.c:2302:26: warning: restricted snd_pcm_format_t degrades to integer sound/core/pcm_native.c:2306:54: warning: incorrect type in argument 1 (different base types) sound/core/pcm_native.c:2306:54: expected restricted snd_pcm_format_t [usertype] format sound/core/pcm_native.c:2306:54: got unsigned int [assigned] k .... No functional changes, just sparse warning fixes. Link: https://lore.kernel.org/r/20200206163945.6797-6-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/oss/pcm_oss.c | 19 ++++++++----------- sound/core/pcm_native.c | 15 ++++++++------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 13db77771f0f..707eb2a9d50c 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -884,20 +884,17 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) sformat = snd_pcm_plug_slave_format(format, sformat_mask); if ((__force int)sformat < 0 || - !snd_mask_test(sformat_mask, (__force int)sformat)) { - for (sformat = (__force snd_pcm_format_t)0; - (__force int)sformat <= (__force int)SNDRV_PCM_FORMAT_LAST; - sformat = (__force snd_pcm_format_t)((__force int)sformat + 1)) { - if (snd_mask_test(sformat_mask, (__force int)sformat) && + !snd_mask_test_format(sformat_mask, sformat)) { + pcm_for_each_format(sformat) { + if (snd_mask_test_format(sformat_mask, sformat) && snd_pcm_oss_format_to(sformat) >= 0) - break; - } - if ((__force int)sformat > (__force int)SNDRV_PCM_FORMAT_LAST) { - pcm_dbg(substream->pcm, "Cannot find a format!!!\n"); - err = -EINVAL; - goto failure; + goto format_found; } + pcm_dbg(substream->pcm, "Cannot find a format!!!\n"); + err = -EINVAL; + goto failure; } + format_found: err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, (__force int)sformat, 0); if (err < 0) goto failure; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 336406bcb59e..900f9cfd4646 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2293,21 +2293,21 @@ static int snd_pcm_hw_rule_mulkdiv(struct snd_pcm_hw_params *params, static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { - unsigned int k; + snd_pcm_format_t k; const struct snd_interval *i = hw_param_interval_c(params, rule->deps[0]); struct snd_mask m; struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); snd_mask_any(&m); - for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) { + pcm_for_each_format(k) { int bits; - if (! snd_mask_test(mask, k)) + if (!snd_mask_test_format(mask, k)) continue; bits = snd_pcm_format_physical_width(k); if (bits <= 0) continue; /* ignore invalid formats */ if ((unsigned)bits < i->min || (unsigned)bits > i->max) - snd_mask_reset(&m, k); + snd_mask_reset(&m, (__force unsigned)k); } return snd_mask_refine(mask, &m); } @@ -2316,14 +2316,15 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { struct snd_interval t; - unsigned int k; + snd_pcm_format_t k; + t.min = UINT_MAX; t.max = 0; t.openmin = 0; t.openmax = 0; - for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) { + pcm_for_each_format(k) { int bits; - if (! snd_mask_test(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), k)) + if (!snd_mask_test_format(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), k)) continue; bits = snd_pcm_format_physical_width(k); if (bits <= 0) From f9b0c053a29fdc0ad58e816554216523b29930f8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Feb 2020 17:39:43 +0100 Subject: [PATCH 0017/4444] ALSA: pcm: Use a macro for parameter masks to reduce the needed cast The parameter bit mask needs often explicit cast with __force, e.g. for the PCM subformat type. Instead of adding __force at each place, which is error prone, this patch introduces a new macro and replaces the all bit shift with it. This fixes the sparse warnings like the following: sound/core/pcm_native.c:2508:30: warning: restricted snd_pcm_access_t degrades to integer No functional changes, just sparse warning fixes. Link: https://lore.kernel.org/r/20200206163945.6797-7-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/pcm_native.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 900f9cfd4646..559633d4702d 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -228,6 +228,9 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream, return err; } +/* macro for simplified cast */ +#define PARAM_MASK_BIT(b) (1U << (__force int)(b)) + static bool hw_support_mmap(struct snd_pcm_substream *substream) { if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP)) @@ -257,7 +260,7 @@ static int constrain_mask_params(struct snd_pcm_substream *substream, return -EINVAL; /* This parameter is not requested to change by a caller. */ - if (!(params->rmask & (1 << k))) + if (!(params->rmask & PARAM_MASK_BIT(k))) continue; if (trace_hw_mask_param_enabled()) @@ -271,7 +274,7 @@ static int constrain_mask_params(struct snd_pcm_substream *substream, /* Set corresponding flag so that the caller gets it. */ trace_hw_mask_param(substream, k, 0, &old_mask, m); - params->cmask |= 1 << k; + params->cmask |= PARAM_MASK_BIT(k); } return 0; @@ -293,7 +296,7 @@ static int constrain_interval_params(struct snd_pcm_substream *substream, return -EINVAL; /* This parameter is not requested to change by a caller. */ - if (!(params->rmask & (1 << k))) + if (!(params->rmask & PARAM_MASK_BIT(k))) continue; if (trace_hw_interval_param_enabled()) @@ -307,7 +310,7 @@ static int constrain_interval_params(struct snd_pcm_substream *substream, /* Set corresponding flag so that the caller gets it. */ trace_hw_interval_param(substream, k, 0, &old_interval, i); - params->cmask |= 1 << k; + params->cmask |= PARAM_MASK_BIT(k); } return 0; @@ -349,7 +352,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream, * have 0 so that the parameters are never changed anymore. */ for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) - vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0; + vstamps[k] = (params->rmask & PARAM_MASK_BIT(k)) ? 1 : 0; /* Due to the above design, actual sequence number starts at 2. */ stamp = 2; @@ -417,7 +420,7 @@ retry: hw_param_interval(params, r->var)); } - params->cmask |= (1 << r->var); + params->cmask |= PARAM_MASK_BIT(r->var); vstamps[r->var] = stamp; again = true; } @@ -486,9 +489,9 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, params->info = 0; params->fifo_size = 0; - if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS)) + if (params->rmask & PARAM_MASK_BIT(SNDRV_PCM_HW_PARAM_SAMPLE_BITS)) params->msbits = 0; - if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) { + if (params->rmask & PARAM_MASK_BIT(SNDRV_PCM_HW_PARAM_RATE)) { params->rate_num = 0; params->rate_den = 0; } @@ -2506,16 +2509,16 @@ static int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream) unsigned int mask = 0; if (hw->info & SNDRV_PCM_INFO_INTERLEAVED) - mask |= 1 << SNDRV_PCM_ACCESS_RW_INTERLEAVED; + mask |= PARAM_MASK_BIT(SNDRV_PCM_ACCESS_RW_INTERLEAVED); if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED) - mask |= 1 << SNDRV_PCM_ACCESS_RW_NONINTERLEAVED; + mask |= PARAM_MASK_BIT(SNDRV_PCM_ACCESS_RW_NONINTERLEAVED); if (hw_support_mmap(substream)) { if (hw->info & SNDRV_PCM_INFO_INTERLEAVED) - mask |= 1 << SNDRV_PCM_ACCESS_MMAP_INTERLEAVED; + mask |= PARAM_MASK_BIT(SNDRV_PCM_ACCESS_MMAP_INTERLEAVED); if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED) - mask |= 1 << SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED; + mask |= PARAM_MASK_BIT(SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED); if (hw->info & SNDRV_PCM_INFO_COMPLEX) - mask |= 1 << SNDRV_PCM_ACCESS_MMAP_COMPLEX; + mask |= PARAM_MASK_BIT(SNDRV_PCM_ACCESS_MMAP_COMPLEX); } err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_ACCESS, mask); if (err < 0) @@ -2525,7 +2528,8 @@ static int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream) if (err < 0) return err; - err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1 << SNDRV_PCM_SUBFORMAT_STD); + err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, + PARAM_MASK_BIT(SNDRV_PCM_SUBFORMAT_STD)); if (err < 0) return err; From 89e0b9a060febbf85b985d2f3aa6afea3473276e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Feb 2020 17:39:44 +0100 Subject: [PATCH 0018/4444] ALSA: pcm_dmaengine: Use pcm_for_each_format() macro for PCM format iteration The new macro can fix the sparse warnings gracefully: sound/core/pcm_dmaengine.c:429:50: warning: restricted snd_pcm_format_t degrades to integer sound/core/pcm_dmaengine.c:429:55: warning: restricted snd_pcm_format_t degrades to integer sound/core/pcm_dmaengine.c:429:79: warning: restricted snd_pcm_format_t degrades to integer No functional changes, just sparse warning fixes. Link: https://lore.kernel.org/r/20200206163945.6797-8-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/pcm_dmaengine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index 5749a8a49784..b37c70864b57 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c @@ -426,7 +426,7 @@ int snd_dmaengine_pcm_refine_runtime_hwparams( * default assumption is that it supports 1, 2 and 4 bytes * widths. */ - for (i = SNDRV_PCM_FORMAT_FIRST; i <= SNDRV_PCM_FORMAT_LAST; i++) { + pcm_for_each_format(i) { int bits = snd_pcm_format_physical_width(i); /* From 49d9e43f36fd4b71a4c1888f86c09cf73be73d0b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Feb 2020 17:39:45 +0100 Subject: [PATCH 0019/4444] ALSA: pcm: Minor refactoring Make a common helper for validating the format type. This reduces the number of cast in the code that are needed for suppressing sparse warnings. No functional changes, just minor refactoring. Link: https://lore.kernel.org/r/20200206163945.6797-9-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/pcm_misc.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index a6a541511534..cf3e8c26e00a 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c @@ -42,6 +42,11 @@ struct pcm_format_data { /* we do lots of calculations on snd_pcm_format_t; shut up sparse */ #define INT __force int +static bool valid_format(snd_pcm_format_t format) +{ + return (INT)format >= 0 && (INT)format <= (INT)SNDRV_PCM_FORMAT_LAST; +} + static const struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = { [SNDRV_PCM_FORMAT_S8] = { .width = 8, .phys = 8, .le = -1, .signd = 1, @@ -259,7 +264,7 @@ static const struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = int snd_pcm_format_signed(snd_pcm_format_t format) { int val; - if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) + if (!valid_format(format)) return -EINVAL; if ((val = pcm_formats[(INT)format].signd) < 0) return -EINVAL; @@ -307,7 +312,7 @@ EXPORT_SYMBOL(snd_pcm_format_linear); int snd_pcm_format_little_endian(snd_pcm_format_t format) { int val; - if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) + if (!valid_format(format)) return -EINVAL; if ((val = pcm_formats[(INT)format].le) < 0) return -EINVAL; @@ -343,7 +348,7 @@ EXPORT_SYMBOL(snd_pcm_format_big_endian); int snd_pcm_format_width(snd_pcm_format_t format) { int val; - if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) + if (!valid_format(format)) return -EINVAL; if ((val = pcm_formats[(INT)format].width) == 0) return -EINVAL; @@ -361,7 +366,7 @@ EXPORT_SYMBOL(snd_pcm_format_width); int snd_pcm_format_physical_width(snd_pcm_format_t format) { int val; - if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) + if (!valid_format(format)) return -EINVAL; if ((val = pcm_formats[(INT)format].phys) == 0) return -EINVAL; @@ -394,7 +399,7 @@ EXPORT_SYMBOL(snd_pcm_format_size); */ const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format) { - if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) + if (!valid_format(format)) return NULL; if (! pcm_formats[(INT)format].phys) return NULL; @@ -418,7 +423,7 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int unsigned char *dst; const unsigned char *pat; - if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) + if (!valid_format(format)) return -EINVAL; if (samples == 0) return 0; From 0cc629722221701a1b1030477c44dfbaca6c110d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 8 Feb 2020 22:20:06 +0000 Subject: [PATCH 0020/4444] ALSA: hdsp: remove redundant assignment to variable err Variable err is being assigned with a value that is never read, it is assigned a new value in the next statement. The assignment is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20200208222006.37376-1-colin.king@canonical.com Signed-off-by: Takashi Iwai --- sound/pci/rme9652/hdsp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index cc06f0a1a7e4..227aece17e39 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -3353,7 +3353,8 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) return; } } else { - int err = -EINVAL; + int err; + err = hdsp_request_fw_loader(hdsp); if (err < 0) { snd_iprintf(buffer, From 4dca80b4df0a7aa4f8865b0bd6f48962c5994b1e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 8 Feb 2020 22:27:56 +0000 Subject: [PATCH 0021/4444] ALSA: hda: remove redundant assignment to variable timeout Variable timeout is being assigned with the value 200 that is never read, it is assigned a new value in a following do-loop. The assignment is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20200208222756.37707-1-colin.king@canonical.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_controller.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 2609e391ce54..9765652a73d7 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -373,7 +373,7 @@ static int azx_get_sync_time(ktime_t *device, u32 wallclk_ctr, wallclk_cycles; bool direction; u32 dma_select; - u32 timeout = 200; + u32 timeout; u32 retry_count = 0; runtime = substream->runtime; From f18b529a662c18a060e29404d64188398bbf35e4 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 8 Feb 2020 22:34:43 +0000 Subject: [PATCH 0022/4444] ALSA: ali5451: remove redundant variable capture_flag Variable capture_flag is only ever assigned values, it is never read and hence it is redundant. Remove it. Addresses-Coverity ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20200208223443.38047-1-colin.king@canonical.com Signed-off-by: Takashi Iwai --- sound/pci/ali5451/ali5451.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 4f524a9dbbca..4462375d2d82 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -1070,7 +1070,7 @@ static int snd_ali_trigger(struct snd_pcm_substream *substream, { struct snd_ali *codec = snd_pcm_substream_chip(substream); struct snd_pcm_substream *s; - unsigned int what, whati, capture_flag; + unsigned int what, whati; struct snd_ali_voice *pvoice, *evoice; unsigned int val; int do_start; @@ -1088,7 +1088,7 @@ static int snd_ali_trigger(struct snd_pcm_substream *substream, return -EINVAL; } - what = whati = capture_flag = 0; + what = whati = 0; snd_pcm_group_for_each_entry(s, substream) { if ((struct snd_ali *) snd_pcm_substream_chip(s) == codec) { pvoice = s->runtime->private_data; @@ -1110,8 +1110,6 @@ static int snd_ali_trigger(struct snd_pcm_substream *substream, evoice->running = 0; } snd_pcm_trigger_done(s, substream); - if (pvoice->mode) - capture_flag = 1; } } spin_lock(&codec->reg_lock); From 0e023687ca552147a76540377be4c642b1313d53 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 8 Feb 2020 22:42:06 +0000 Subject: [PATCH 0023/4444] ALSA: info: remove redundant assignment to variable c Variable c is being assigned with the value -1 that is never read, it is assigned a new value in a following while-loop. The assignment is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20200208224206.38540-1-colin.king@canonical.com Signed-off-by: Takashi Iwai --- sound/core/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/core/info.c b/sound/core/info.c index ca87ae4c30ba..8c6bc5241df5 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -604,7 +604,7 @@ int snd_info_card_free(struct snd_card *card) */ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len) { - int c = -1; + int c; if (snd_BUG_ON(!buffer || !buffer->buffer)) return 1; From 30bd02bd634f4a483e965fb41a076e47ea9681ef Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 16 Jan 2020 23:11:46 +0000 Subject: [PATCH 0024/4444] arm64: dts: sun50i: H6: Add SPI controllers nodes and pinmuxes The Allwinner H6 SoC contains two SPI controllers similar to the H3/A64, but with the added capability of 3-wire and 4-wire operation modes. For now the driver does not support those, but the SPI registers are fully backwards-compatible, just adding bits and registers which were formerly reserved. So we can use the existing driver in "legacy" SPI modes, for instance to access the SPI NOR flash soldered on the PineH64 board. We use an H6 specific compatible string in addition to the existing H3 string, so when the driver later gains QSPI support, it should work automatically without any DT changes. Tested by accessing the SPI flash on a Pine H64 board (SPI0), also connecting another SPI flash to the SPI1 header pins. Signed-off-by: Andre Przywara Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 55 ++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index 3329283e38ab..41b58ffa8596 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -338,6 +338,31 @@ bias-pull-up; }; + /omit-if-no-ref/ + spi0_pins: spi0-pins { + pins = "PC0", "PC2", "PC3"; + function = "spi0"; + }; + + /* pin shared with MMC2-CMD (eMMC) */ + /omit-if-no-ref/ + spi0_cs_pin: spi0-cs-pin { + pins = "PC5"; + function = "spi0"; + }; + + /omit-if-no-ref/ + spi1_pins: spi1-pins { + pins = "PH4", "PH5", "PH6"; + function = "spi1"; + }; + + /omit-if-no-ref/ + spi1_cs_pin: spi1-cs-pin { + pins = "PH3"; + function = "spi1"; + }; + spdif_tx_pin: spdif-tx-pin { pins = "PH7"; function = "spdif"; @@ -504,6 +529,36 @@ #size-cells = <0>; }; + spi0: spi@5010000 { + compatible = "allwinner,sun50i-h6-spi", + "allwinner,sun8i-h3-spi"; + reg = <0x05010000 0x1000>; + interrupts = ; + clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>; + clock-names = "ahb", "mod"; + dmas = <&dma 22>, <&dma 22>; + dma-names = "rx", "tx"; + resets = <&ccu RST_BUS_SPI0>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + spi1: spi@5011000 { + compatible = "allwinner,sun50i-h6-spi", + "allwinner,sun8i-h3-spi"; + reg = <0x05011000 0x1000>; + interrupts = ; + clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>; + clock-names = "ahb", "mod"; + dmas = <&dma 23>, <&dma 23>; + dma-names = "rx", "tx"; + resets = <&ccu RST_BUS_SPI1>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + emac: ethernet@5020000 { compatible = "allwinner,sun50i-h6-emac", "allwinner,sun50i-a64-emac"; From e757bdd01780d0ea3e6774247b735caf2d1a9e92 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 16 Jan 2020 23:11:47 +0000 Subject: [PATCH 0025/4444] arm64: dts: allwinner: h6: Pine H64: Add SPI flash node The Pine H64 board comes with SPI flash soldered on the board, connected to the SPI0 pins (so it can also boot from there). Add the required SPI flash DT node to describe this. Unfortunately the SPI CS0 pin collides with the eMMC CMD pin, so we can't use both eMMC and SPI flash at the same time (the first to claim the pin would win, the other's probe routine would then fail). To avoid losing the more useful eMMC device by chance, mark the SPI device as "disabled" for now. A user or some U-Boot code could fix this up if needed, for instance if no eMMC has been detected (it's socketed). Signed-off-by: Andre Przywara Signed-off-by: Maxime Ripard --- .../boot/dts/allwinner/sun50i-h6-pine-h64.dts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts index d1c2aa5b3a20..3c9dd0d69754 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts @@ -14,6 +14,7 @@ aliases { ethernet0 = &emac; serial0 = &uart0; + spi0 = &spi0; }; chosen { @@ -278,6 +279,24 @@ vcc-pm-supply = <®_aldo1>; }; +/* + * The CS pin is shared with the MMC2 CMD pin, so we cannot have the SPI + * flash and eMMC at the same time, as one of them would fail probing. + * Disable SPI0 in here, to prefer the more useful eMMC. U-Boot can + * fix this up in no eMMC is connected. + */ +&spi0 { + pinctrl-0 = <&spi0_pins>, <&spi0_cs_pin>; + pinctrl-names = "default"; + status = "disabled"; + + flash@0 { + compatible = "winbond,w25q128", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <4000000>; + }; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_ph_pins>; From e2c9e67e44fedcf37b383d3cacc525674bed457f Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 16 Jan 2020 23:11:48 +0000 Subject: [PATCH 0026/4444] dt-bindings: spi: sunxi: Document new compatible strings The Allwinner H6 SPI controller has advanced features over the H3 version, but remains compatible with it. Document the usual "specific", "fallback" compatible string pair. Also add the R40 version while at it. Signed-off-by: Andre Przywara Signed-off-by: Maxime Ripard --- .../bindings/spi/allwinner,sun6i-a31-spi.yaml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml index 0565dc49e449..243a6b1e66ea 100644 --- a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml +++ b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml @@ -18,9 +18,14 @@ properties: "#size-cells": true compatible: - enum: - - allwinner,sun6i-a31-spi - - allwinner,sun8i-h3-spi + oneOf: + - const: allwinner,sun6i-a31-spi + - const: allwinner,sun8i-h3-spi + - items: + - enum: + - allwinner,sun8i-r40-spi + - allwinner,sun50i-h6-spi + - const: allwinner,sun8i-h3-spi reg: maxItems: 1 From 39b6343d1d4180b83edec31e1d0b36fe1ccfaf77 Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Thu, 16 Jan 2020 11:36:35 +0800 Subject: [PATCH 0027/4444] dt-bindings: arm: sunxi: add binding for PineTab tablet Add the device tree binding for Pine64's PineTab tablet, which uses Allwinner A64 SoC. Signed-off-by: Icenowy Zheng Reviewed-by: Rob Herring Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/arm/sunxi.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml index 327ce6730823..159060b65c5d 100644 --- a/Documentation/devicetree/bindings/arm/sunxi.yaml +++ b/Documentation/devicetree/bindings/arm/sunxi.yaml @@ -636,6 +636,11 @@ properties: - const: pine64,pinebook - const: allwinner,sun50i-a64 + - description: Pine64 PineTab + items: + - const: pine64,pinetab + - const: allwinner,sun50i-a64 + - description: Pine64 SoPine Baseboard items: - const: pine64,sopine-baseboard From 674ef1d0a7b23681699994a892a1ed508c7df122 Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Thu, 16 Jan 2020 11:36:36 +0800 Subject: [PATCH 0028/4444] arm64: dts: allwinner: a64: add support for PineTab PineTab is a 10.1" tablet by Pine64 with Allwinner A64 inside. It includes the following peripherals: USB: - A microUSB Type-B port connected to the OTG-capable USB PHY of Allwinner A64. The ID pin is connected to a GPIO of the A64 SoC, and the Vbus is connected to the Vbus of AXP803 PMIC. These enables OTG functionality on this port. - A USB Type-A port is connected to the internal hub attached to the non-OTG USB PHY of Allwinner A64. - There are reserved pins for an external keyboard connected to the internal hub. Power: - The microUSB port has its Vbus connected to AXP803, mentioned above. - A DC jack (of a strange size, 2.5mm outer diameter) is connected to the ACIN of AXP803. - A Li-Polymer battery is connected to the battery pins of AXP803. Storage: - An tradition Pine64 eMMC slot is on the board, mounted with an eMMC module by factory. - An external microSD slot is hidden under a protect case. Display: - A MIPI-DSI LCD panel (800x1280) is connected to the DSI port of A64 SoC. - A mini HDMI port. Input: - A touch panel attached to a Goodix GT9271 touch controller. - Volume keys connected to the LRADC of the A64 SoC. Camera: - An OV5640 CMOS camera is at rear, connected to the CSI bus of A64 SoC. - A GC2145 CMOS camera is at front, shares the same CSI bus with OV5640. Audio: - A headphone jack is conencted to the SoC's internal codec. - A speaker connected is to the Line Out port of SoC's internal codec, via an amplifier. Misc: - Debug UART is muxed with the headphone jack, with the switch next to the microSD slot. - A bosch BMA223 accelerometer is connected to the I2C bus of A64 SoC. - Wi-Fi and Bluetooth are available via a RTL8723CS chip, similar to the one in Pinebook. This commit adds a basically usable device tree for it, implementing most of the features mentioned above. HDMI is not supported now because bad LCD-HDMI coexistence situation of mainline A64 display driver, the front camera currently lacks a driver and a facility to share the bus with the rear one, and the accelerometer currently lacks a DT binding. Signed-off-by: Icenowy Zheng Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/Makefile | 1 + .../boot/dts/allwinner/sun50i-a64-pinetab.dts | 460 ++++++++++++++++++ 2 files changed, 461 insertions(+) create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile index cf4f78617c3f..6dad63881cd3 100644 --- a/arch/arm64/boot/dts/allwinner/Makefile +++ b/arch/arm64/boot/dts/allwinner/Makefile @@ -9,6 +9,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-orangepi-win.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-lts.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-plus.dtb sun50i-a64-pine64.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinebook.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinetab.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-sopine-baseboard.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-teres-i.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-bananapi-m2-plus.dtb diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts new file mode 100644 index 000000000000..316e8a443913 --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts @@ -0,0 +1,460 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2019 Icenowy Zheng + * + */ + +/dts-v1/; + +#include "sun50i-a64.dtsi" +#include "sun50i-a64-cpu-opp.dtsi" + +#include +#include +#include + +/ { + model = "PineTab"; + compatible = "pine64,pinetab", "allwinner,sun50i-a64"; + + aliases { + serial0 = &uart0; + ethernet0 = &rtl8723cs; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>; + brightness-levels = <0 16 18 20 22 24 26 29 32 35 38 42 46 51 56 62 68 75 83 91 100>; + default-brightness-level = <15>; + enable-gpios = <&pio 3 23 GPIO_ACTIVE_HIGH>; /* PD23 */ + power-supply = <&vdd_bl>; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + i2c-csi { + compatible = "i2c-gpio"; + sda-gpios = <&pio 4 13 GPIO_ACTIVE_HIGH>; /* PE13 */ + scl-gpios = <&pio 4 12 GPIO_ACTIVE_HIGH>; /* PE12 */ + i2c-gpio,delay-us = <5>; + #address-cells = <1>; + #size-cells = <0>; + + /* Rear camera */ + ov5640: camera@3c { + compatible = "ovti,ov5640"; + reg = <0x3c>; + pinctrl-names = "default"; + pinctrl-0 = <&csi_mclk_pin>; + clocks = <&ccu CLK_CSI_MCLK>; + clock-names = "xclk"; + + AVDD-supply = <®_dldo3>; + DOVDD-supply = <®_aldo1>; + DVDD-supply = <®_eldo3>; + reset-gpios = <&pio 4 14 GPIO_ACTIVE_LOW>; /* PE14 */ + powerdown-gpios = <&pio 4 15 GPIO_ACTIVE_HIGH>; /* PE15 */ + + port { + ov5640_ep: endpoint { + remote-endpoint = <&csi_ep>; + bus-width = <8>; + hsync-active = <1>; /* Active high */ + vsync-active = <0>; /* Active low */ + data-active = <1>; /* Active high */ + pclk-sample = <1>; /* Rising */ + }; + }; + }; + }; + + speaker_amp: audio-amplifier { + compatible = "simple-audio-amplifier"; + enable-gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>; /* PH7 */ + sound-name-prefix = "Speaker Amp"; + }; + + vdd_bl: regulator@0 { + compatible = "regulator-fixed"; + regulator-name = "bl-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pio 7 6 GPIO_ACTIVE_HIGH>; /* PH6 */ + enable-active-high; + }; + + wifi_pwrseq: wifi_pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */ + post-power-on-delay-ms = <200>; + }; +}; + +&codec { + status = "okay"; +}; + +&codec_analog { + hpvcc-supply = <®_eldo1>; + status = "okay"; +}; + +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + +&cpu1 { + cpu-supply = <®_dcdc2>; +}; + +&cpu2 { + cpu-supply = <®_dcdc2>; +}; + +&cpu3 { + cpu-supply = <®_dcdc2>; +}; + +&csi { + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + csi_ep: endpoint { + remote-endpoint = <&ov5640_ep>; + bus-width = <8>; + hsync-active = <1>; /* Active high */ + vsync-active = <0>; /* Active low */ + data-active = <1>; /* Active high */ + pclk-sample = <1>; /* Rising */ + }; + }; +}; + +&dai { + status = "okay"; +}; + +&de { + status = "okay"; +}; + +&dphy { + status = "okay"; +}; + +&dsi { + vcc-dsi-supply = <®_dldo1>; + status = "okay"; + + panel@0 { + compatible = "feixin,k101-im2ba02"; + reg = <0>; + avdd-supply = <®_dc1sw>; + dvdd-supply = <®_dc1sw>; + cvdd-supply = <®_ldo_io1>; + reset-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */ + backlight = <&backlight>; + }; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + touchscreen@5d { + compatible = "goodix,gt9271"; + reg = <0x5d>; + interrupt-parent = <&pio>; + interrupts = <7 4 IRQ_TYPE_LEVEL_HIGH>; /* PH4 */ + irq-gpios = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */ + reset-gpios = <&pio 7 8 GPIO_ACTIVE_HIGH>; /* PH8 */ + AVDD28-supply = <®_ldo_io1>; + }; +}; + +&i2c0_pins { + bias-pull-up; +}; + +&i2c1 { + status = "okay"; + + /* TODO: add Bochs BMA223 accelerometer here */ +}; + +&lradc { + vref-supply = <®_aldo3>; + status = "okay"; + + button-200 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <200000>; + }; + + button-400 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <400000>; + }; +}; + +&mixer1 { + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins>; + vmmc-supply = <®_dcdc1>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; + disable-wp; + bus-width = <4>; + status = "okay"; +}; + +&mmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + vmmc-supply = <®_dldo4>; + vqmmc-supply = <®_eldo1>; + mmc-pwrseq = <&wifi_pwrseq>; + bus-width = <4>; + non-removable; + status = "okay"; + + rtl8723cs: wifi@1 { + reg = <1>; + }; +}; + +&mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins>; + vmmc-supply = <®_dcdc1>; + vqmmc-supply = <®_dcdc1>; + bus-width = <8>; + non-removable; + cap-mmc-hw-reset; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&pwm { + status = "okay"; +}; + +&r_rsb { + status = "okay"; + + axp803: pmic@3a3 { + compatible = "x-powers,axp803"; + reg = <0x3a3>; + interrupt-parent = <&r_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + x-powers,drive-vbus-en; + }; +}; + +#include "axp803.dtsi" + +&ac_power_supply { + status = "okay"; +}; + +&battery_power_supply { + status = "okay"; +}; + +®_aldo1 { + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-name = "dovdd-csi"; +}; + +®_aldo2 { + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-pl"; +}; + +®_aldo3 { + regulator-always-on; + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-pll-avcc"; +}; + +®_dc1sw { + regulator-name = "vcc-lcd"; +}; + +®_dcdc1 { + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-3v3"; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1300000>; + regulator-name = "vdd-cpux"; +}; + +/* DCDC3 is polyphased with DCDC2 */ + +®_dcdc5 { + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-name = "vcc-dram"; +}; + +®_dcdc6 { + regulator-always-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-name = "vdd-sys"; +}; + +®_dldo1 { + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-hdmi-dsi-sensor"; +}; + +®_dldo3 { + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-name = "avdd-csi"; +}; + +®_dldo4 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-wifi"; +}; + +®_drivevbus { + regulator-name = "usb0-vbus"; + status = "okay"; +}; + +®_eldo1 { + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "cpvdd"; +}; + +®_eldo2 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcca-1v8"; +}; + +®_eldo3 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "dvdd-1v8-csi"; +}; + +®_fldo1 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-name = "vcc-1v2-hsic"; +}; + +®_fldo2 { + regulator-always-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-name = "vdd-cpus"; +}; + +®_ldo_io0 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-usb"; + status = "okay"; +}; + +®_ldo_io1 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <3500000>; + regulator-name = "vcc-touchscreen"; + status = "okay"; +}; + +®_rtc_ldo { + regulator-name = "vcc-rtc"; +}; + +&sound { + status = "okay"; + simple-audio-card,aux-devs = <&codec_analog>, <&speaker_amp>; + simple-audio-card,widgets = "Microphone", "Internal Microphone Left", + "Microphone", "Internal Microphone Right", + "Headphone", "Headphone Jack", + "Speaker", "Internal Speaker"; + simple-audio-card,routing = + "Left DAC", "AIF1 Slot 0 Left", + "Right DAC", "AIF1 Slot 0 Right", + "Speaker Amp INL", "LINEOUT", + "Speaker Amp INR", "LINEOUT", + "Internal Speaker", "Speaker Amp OUTL", + "Internal Speaker", "Speaker Amp OUTR", + "Headphone Jack", "HP", + "AIF1 Slot 0 Left ADC", "Left ADC", + "AIF1 Slot 0 Right ADC", "Right ADC", + "Internal Microphone Left", "MBIAS", + "MIC1", "Internal Microphone Left", + "Internal Microphone Right", "HBIAS", + "MIC2", "Internal Microphone Right"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pb_pins>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usb_power_supply { + status = "okay"; +}; + +&usbphy { + usb0_id_det-gpios = <&pio 7 9 GPIO_ACTIVE_HIGH>; /* PH9 */ + usb0_vbus_power-supply = <&usb_power_supply>; + usb0_vbus-supply = <®_drivevbus>; + usb1_vbus-supply = <®_ldo_io0>; + status = "okay"; +}; From 787615ad874151af11017e95e29b7f1ef1c1590f Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 19 Jan 2020 10:30:56 -0600 Subject: [PATCH 0029/4444] arm64: dts: allwinner: Enable button wakeup on Orange Pi PC2 The Orange Pi PC2 features a GPIO button. As the button is connected to Port L (pin PL3), it can be used as a wakeup source. Enable this. Signed-off-by: Samuel Holland Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts index 70b5f0998421..c4f89c312f42 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts @@ -61,6 +61,7 @@ label = "sw4"; linux,code = ; gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>; + wakeup-source; }; }; From 9e556ec5731eb3a7df3ee27e832d74b17390499e Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 19 Jan 2020 10:30:57 -0600 Subject: [PATCH 0030/4444] arm64: dts: allwinner: pinebook: Remove unused vcc3v3 regulator This fixed regulator has no consumers, GPIOs, or other connections. Remove it. Signed-off-by: Samuel Holland Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts index 3d894b208901..ff32ca1a495e 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts @@ -63,13 +63,6 @@ }; }; - reg_vcc3v3: vcc3v3 { - compatible = "regulator-fixed"; - regulator-name = "vcc3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - wifi_pwrseq: wifi_pwrseq { compatible = "mmc-pwrseq-simple"; reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */ From c0e79b069e4ff6e0881d82ba831424ca7362e828 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 19 Jan 2020 10:30:59 -0600 Subject: [PATCH 0031/4444] arm64: dts: allwinner: pinebook: Sort device tree nodes The r_i2c node should come before r_rsb, and in any case should not separate the axp803 node from its subnodes. Signed-off-by: Samuel Holland Signed-off-by: Maxime Ripard --- .../boot/dts/allwinner/sun50i-a64-pinebook.dts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts index ff32ca1a495e..77784f7b1da7 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts @@ -172,6 +172,14 @@ status = "okay"; }; +/* The ANX6345 eDP-bridge is on r_i2c */ +&r_i2c { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&r_i2c_pl89_pins>; + status = "okay"; +}; + &r_rsb { status = "okay"; @@ -183,14 +191,6 @@ }; }; -/* The ANX6345 eDP-bridge is on r_i2c */ -&r_i2c { - clock-frequency = <100000>; - pinctrl-names = "default"; - pinctrl-0 = <&r_i2c_pl89_pins>; - status = "okay"; -}; - #include "axp803.dtsi" &ac_power_supply { From c3d22680df8da15c6ee2a6a157fcf3078915cc26 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 19 Jan 2020 10:31:00 -0600 Subject: [PATCH 0032/4444] arm64: dts: allwinner: pinebook: Make simplefb more consistent Boards generally reference the simplefb nodes from the SoC dtsi by label, not by full path. simplefb_hdmi is already like this in the Pinebook DTS. Update simplefb_lcd to match. Signed-off-by: Samuel Holland Signed-off-by: Maxime Ripard --- .../arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts index 77784f7b1da7..224bed65d008 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts @@ -41,12 +41,6 @@ chosen { stdout-path = "serial0:115200n8"; - - framebuffer-lcd { - panel-supply = <®_dc1sw>; - dvdd25-supply = <®_dldo2>; - dvdd12-supply = <®_fldo1>; - }; }; gpio_keys { @@ -316,6 +310,12 @@ regulator-name = "vcc-rtc"; }; +&simplefb_lcd { + panel-supply = <®_dc1sw>; + dvdd25-supply = <®_dldo2>; + dvdd12-supply = <®_fldo1>; +}; + &simplefb_hdmi { vcc-hdmi-supply = <®_dldo1>; }; From 412e19c34f501da68c19d8fdd7de4c535ea89d3b Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 19 Jan 2020 10:31:01 -0600 Subject: [PATCH 0033/4444] arm64: dts: allwinner: pinebook: Document MMC0 CD pin name Normally GPIO pin references are followed by a comment giving the pin name for searchability. Add the comment here where it was missing. Signed-off-by: Samuel Holland Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts index 224bed65d008..a1e15777d524 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts @@ -119,7 +119,7 @@ pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins>; vmmc-supply = <®_dcdc1>; - cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ disable-wp; bus-width = <4>; status = "okay"; From 9de2b6bf5ecb1f2149ffe19e4aefbdcbe68790f1 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 19 Jan 2020 10:31:02 -0600 Subject: [PATCH 0034/4444] arm64: dts: allwinner: pinebook: Add GPIO port regulators Allwinner A64 SoC has separate supplies for PC, PD, PE, PG and PL. VCC-PC and VCC-PG are supplied by ELDO1 at 1.8v. VCC-PD is supplied by DCDC1 (VCC-IO) at 3.3v. VCC-PE is supplied by ALDO1, and is unused. VCC-PL creates a circular dependency, so it is omitted for now. Signed-off-by: Samuel Holland Signed-off-by: Maxime Ripard --- .../boot/dts/allwinner/sun50i-a64-pinebook.dts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts index a1e15777d524..1ec39120323f 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts @@ -162,6 +162,13 @@ status = "okay"; }; +&pio { + vcc-pc-supply = <®_eldo1>; + vcc-pd-supply = <®_dcdc1>; + vcc-pe-supply = <®_aldo1>; + vcc-pg-supply = <®_eldo1>; +}; + &pwm { status = "okay"; }; @@ -174,6 +181,16 @@ status = "okay"; }; +&r_pio { + /* + * FIXME: We can't add that supply for now since it would + * create a circular dependency between pinctrl, the regulator + * and the RSB Bus. + * + * vcc-pl-supply = <®_aldo2>; + */ +}; + &r_rsb { status = "okay"; From 47ef030c3a796e07fec12c6981bbb46bcb258e2e Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 19 Jan 2020 10:31:03 -0600 Subject: [PATCH 0035/4444] arm64: dts: allwinner: pinebook: Fix backlight regulator The output from the backlight regulator is labeled as "VBKLT" in the schematic. Using the equation and resistor values from the schematic, the output is approximately 18V, not 3.3V. Since the regulator in use (SS6640STR) is a boost regulator powered by PS (battery or AC input), which are both >3.3V, the output could not be 3.3V anyway. Signed-off-by: Samuel Holland Signed-off-by: Maxime Ripard --- .../dts/allwinner/sun50i-a64-pinebook.dts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts index 1ec39120323f..313f4e6edc19 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts @@ -21,22 +21,13 @@ ethernet0 = &rtl8723cs; }; - vdd_bl: regulator@0 { - compatible = "regulator-fixed"; - regulator-name = "bl-3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - gpio = <&pio 7 6 GPIO_ACTIVE_HIGH>; /* PH6 */ - enable-active-high; - }; - backlight: backlight { compatible = "pwm-backlight"; pwms = <&pwm 0 50000 0>; brightness-levels = <0 5 10 15 20 30 40 55 70 85 100>; default-brightness-level = <2>; enable-gpios = <&pio 3 23 GPIO_ACTIVE_HIGH>; /* PD23 */ - power-supply = <&vdd_bl>; + power-supply = <®_vbklt>; }; chosen { @@ -57,6 +48,15 @@ }; }; + reg_vbklt: vbklt { + compatible = "regulator-fixed"; + regulator-name = "vbklt"; + regulator-min-microvolt = <18000000>; + regulator-max-microvolt = <18000000>; + gpio = <&pio 7 6 GPIO_ACTIVE_HIGH>; /* PH6 */ + enable-active-high; + }; + wifi_pwrseq: wifi_pwrseq { compatible = "mmc-pwrseq-simple"; reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */ From e95d8d03b5904a373895c14a44eb60264c7bc041 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 19 Jan 2020 10:31:04 -0600 Subject: [PATCH 0036/4444] arm64: dts: allwinner: pinebook: Fix 5v0 boost regulator Now that AXP803 GPIO support is available, we can properly model the hardware. Replace the use of GPIO0-LDO with a fixed regulator controlled by GPIO0. This boost regulator is used to power the (internal and external) USB ports, as well as the speakers. Signed-off-by: Samuel Holland Signed-off-by: Maxime Ripard --- .../dts/allwinner/sun50i-a64-pinebook.dts | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts index 313f4e6edc19..c06c540e6c08 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts @@ -57,6 +57,15 @@ enable-active-high; }; + reg_vcc5v0: vcc5v0 { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&axp_gpio 0 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + wifi_pwrseq: wifi_pwrseq { compatible = "mmc-pwrseq-simple"; reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */ @@ -64,12 +73,7 @@ speaker_amp: audio-amplifier { compatible = "simple-audio-amplifier"; - /* - * TODO This is actually a fixed regulator controlled by - * the GPIO line on the PMIC. This should be corrected - * once GPIO support is added for this PMIC. - */ - VCC-supply = <®_ldo_io0>; + VCC-supply = <®_vcc5v0>; enable-gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>; /* PH7 */ sound-name-prefix = "Speaker Amp"; }; @@ -316,13 +320,6 @@ regulator-name = "vdd-cpus"; }; -®_ldo_io0 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-name = "vcc-usb"; - status = "okay"; -}; - ®_rtc_ldo { regulator-name = "vcc-rtc"; }; @@ -371,7 +368,7 @@ }; &usbphy { - usb0_vbus-supply = <®_ldo_io0>; - usb1_vbus-supply = <®_ldo_io0>; + usb0_vbus-supply = <®_vcc5v0>; + usb1_vbus-supply = <®_vcc5v0>; status = "okay"; }; From 5a5e52161894ab70062e6989aa15f672664334f8 Mon Sep 17 00:00:00 2001 From: Emmanuel Vadot Date: Sat, 18 Jan 2020 16:24:59 +0100 Subject: [PATCH 0037/4444] arm64: dts: allwinner: a64: Add gpio bank supply for A64-Olinuxino Add the regulators for each bank on this boards. For VCC-PL only add a comment on what regulator is used. We cannot add the property without causing a circular dependency as the PL pins are used to talk to the PMIC. Signed-off-by: Emmanuel Vadot Signed-off-by: Maxime Ripard --- .../boot/dts/allwinner/sun50i-a64-olinuxino.dts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts index 6dfafa1c879b..5fa9ca0191a8 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts @@ -158,6 +158,17 @@ */ }; +&pio { + vcc-pa-supply = <®_dcdc1>; + vcc-pb-supply = <®_dcdc1>; + vcc-pc-supply = <®_dcdc1>; + vcc-pd-supply = <®_dcdc1>; + vcc-pe-supply = <®_aldo1>; + vcc-pf-supply = <®_dcdc1>; + vcc-pg-supply = <®_dldo4>; + vcc-ph-supply = <®_dcdc1>; +}; + &r_rsb { status = "okay"; @@ -170,6 +181,12 @@ }; }; +/* VCC-PL is powered by aldo2 but we cannot add it as the RSB */ +/* interface used to talk to the PMIC in on the PL pins */ +/* &r_pio { */ +/* vcc-pl-supply = <®_aldo2>; */ +/* }; */ + #include "axp803.dtsi" &ac_power_supply { From 6a7be15a66e6138d7efad71278177d8432bd4ea5 Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Mon, 6 Jan 2020 17:46:39 +0000 Subject: [PATCH 0038/4444] ARM: dts: sun8i-r40: Add thermal sensor and thermal zones There are two sensors, sensor0 for CPU, sensor1 for GPU. Signed-off-by: Yangtao Li Tested-by: Corentin Labbe Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-r40.dtsi | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi index 8f09a24b36ec..d5442b5b6fd2 100644 --- a/arch/arm/boot/dts/sun8i-r40.dtsi +++ b/arch/arm/boot/dts/sun8i-r40.dtsi @@ -47,6 +47,7 @@ #include #include #include +#include / { #address-cells = <1>; @@ -110,6 +111,22 @@ status = "disabled"; }; + thermal-zones { + cpu_thermal: cpu0-thermal { + /* milliseconds */ + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&ths 0>; + }; + + gpu_thermal: gpu-thermal { + /* milliseconds */ + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&ths 1>; + }; + }; + soc { compatible = "simple-bus"; #address-cells = <1>; @@ -500,6 +517,17 @@ clocks = <&osc24M>; }; + ths: thermal-sensor@1c24c00 { + compatible = "allwinner,sun8i-r40-ths"; + reg = <0x01c24c00 0x100>; + clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_THS>; + clock-names = "bus", "mod"; + interrupts = ; + resets = <&ccu RST_BUS_THS>; + /* TODO: add nvmem-cells for calibration */ + #thermal-sensor-cells = <1>; + }; + uart0: serial@1c28000 { compatible = "snps,dw-apb-uart"; reg = <0x01c28000 0x400>; From a630fe34ddc09ec9b82df4867a8680d0929fe926 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 28 Jan 2020 22:08:45 +0100 Subject: [PATCH 0039/4444] gpio: pxa: Avoid a warning when gpio0 and gpio1 IRQS are not there Not all platforms use those. Let's use platform_get_irq_byname_optional() instead platform_get_irq_byname() so that we avoid a useless warning: [ 1.359455] pxa-gpio d4019000.gpio: IRQ gpio0 not found [ 1.359583] pxa-gpio d4019000.gpio: IRQ gpio1 not found Signed-off-by: Lubomir Rintel Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pxa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 9888b62f37af..567742d962ae 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -652,8 +652,8 @@ static int pxa_gpio_probe(struct platform_device *pdev) if (!pchip->irqdomain) return -ENOMEM; - irq0 = platform_get_irq_byname(pdev, "gpio0"); - irq1 = platform_get_irq_byname(pdev, "gpio1"); + irq0 = platform_get_irq_byname_optional(pdev, "gpio0"); + irq1 = platform_get_irq_byname_optional(pdev, "gpio1"); irq_mux = platform_get_irq_byname(pdev, "gpio_mux"); if ((irq0 > 0 && irq1 <= 0) || (irq0 <= 0 && irq1 > 0) || (irq_mux <= 0)) From 47d7d116661993499d626f7ec6f7679e83d59f15 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 31 Jan 2020 20:29:17 +0800 Subject: [PATCH 0040/4444] gpio: wcd934x: Don't change gpio direction in wcd_gpio_set The .set callback should just set output value. Signed-off-by: Axel Lin Reviewed-by: Srinivas Kandagatla Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-wcd934x.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-wcd934x.c b/drivers/gpio/gpio-wcd934x.c index 74913f2e5697..9d4ec8941b9b 100644 --- a/drivers/gpio/gpio-wcd934x.c +++ b/drivers/gpio/gpio-wcd934x.c @@ -66,7 +66,10 @@ static int wcd_gpio_get(struct gpio_chip *chip, unsigned int pin) static void wcd_gpio_set(struct gpio_chip *chip, unsigned int pin, int val) { - wcd_gpio_direction_output(chip, pin, val); + struct wcd_gpio_data *data = gpiochip_get_data(chip); + + regmap_update_bits(data->map, WCD_REG_VAL_CTL_OFFSET, + WCD_PIN_MASK(pin), val ? WCD_PIN_MASK(pin) : 0); } static int wcd_gpio_probe(struct platform_device *pdev) From 47203198ed3df0f6896d07613182c05cb94110a5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 31 Jan 2020 20:29:18 +0800 Subject: [PATCH 0041/4444] gpio: wcd934x: Fix logic of wcd_gpio_get The check with register value and mask should be & rather than &&. While at it, also use "unsigned int" for value variable because regmap_read() takes unsigned int *val argument. Signed-off-by: Axel Lin Reviewed-by: Srinivas Kandagatla Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-wcd934x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-wcd934x.c b/drivers/gpio/gpio-wcd934x.c index 9d4ec8941b9b..1cbce5990855 100644 --- a/drivers/gpio/gpio-wcd934x.c +++ b/drivers/gpio/gpio-wcd934x.c @@ -57,11 +57,11 @@ static int wcd_gpio_direction_output(struct gpio_chip *chip, unsigned int pin, static int wcd_gpio_get(struct gpio_chip *chip, unsigned int pin) { struct wcd_gpio_data *data = gpiochip_get_data(chip); - int value; + unsigned int value; regmap_read(data->map, WCD_REG_VAL_CTL_OFFSET, &value); - return !!(value && WCD_PIN_MASK(pin)); + return !!(value & WCD_PIN_MASK(pin)); } static void wcd_gpio_set(struct gpio_chip *chip, unsigned int pin, int val) From 4837621cd61e6b81a182098889143c6c9a06b0f3 Mon Sep 17 00:00:00 2001 From: Markus Pietrek Date: Mon, 27 Jan 2020 11:35:41 +0100 Subject: [PATCH 0042/4444] eeprom: at24: add TPF0001 ACPI ID for 24c1024 device This ID is used at leas on some variants of MSC C6B-SLH board. Signed-off-by: Markus Pietrek Signed-off-by: Oleksij Rempel Signed-off-by: Bartosz Golaszewski --- drivers/misc/eeprom/at24.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 031eb64549af..b84e6a3daed4 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -227,6 +227,7 @@ MODULE_DEVICE_TABLE(of, at24_of_match); static const struct acpi_device_id at24_acpi_ids[] = { { "INT3499", (kernel_ulong_t)&at24_data_INT3499 }, + { "TPF0001", (kernel_ulong_t)&at24_data_24c1024 }, { /* END OF LIST */ } }; MODULE_DEVICE_TABLE(acpi, at24_acpi_ids); From 71af05a7d0eb63fa5a6b64f296a5f2c8d84d6a9e Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 31 Jan 2020 10:58:11 +0530 Subject: [PATCH 0043/4444] firmware: arm_scmi: Update doc style comments Fix minor formatting issues with the doc style comments. Signed-off-by: Viresh Kumar Link: https://lore.kernel.org/r/1bff7c0d1ad2c8b6eeff9660421f414f8c612eb2.1580448239.git.viresh.kumar@linaro.org Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 4 ++-- drivers/firmware/arm_scmi/driver.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index df35358ff324..227934871929 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -33,8 +33,8 @@ enum scmi_common_cmd { /** * struct scmi_msg_resp_prot_version - Response for a message * - * @major_version: Major version of the ABI that firmware supports * @minor_version: Minor version of the ABI that firmware supports + * @major_version: Major version of the ABI that firmware supports * * In general, ABI version changes follow the rule that minor version increments * are backward compatible. Major revision changes in ABI may not be @@ -88,7 +88,7 @@ struct scmi_msg { * message. If request-ACK protocol is used, we can reuse the same * buffer for the rx path as we use for the tx path. * @done: command message transmit completion event - * @async: pointer to delayed response message received event completion + * @async_done: pointer to delayed response message received event completion */ struct scmi_xfer { int transfer_id; diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 2c96f6b5a7d8..978eafb53471 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -119,9 +119,9 @@ struct scmi_chan_info { * * @dev: Device pointer * @desc: SoC description for this instance - * @handle: Instance of SCMI handle to send to clients * @version: SCMI revision information containing protocol version, * implementation version and (sub-)vendor identification. + * @handle: Instance of SCMI handle to send to clients * @tx_minfo: Universal Transmit Message management info * @tx_idr: IDR object to map protocol id to Tx channel info pointer * @rx_idr: IDR object to map protocol id to Rx channel info pointer From c4eb83660aef549a6a50965ec5f0af9c8306d2e9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 31 Jan 2020 10:58:12 +0530 Subject: [PATCH 0044/4444] firmware: arm_scmi: Move macros and helpers to common.h Move message header specific macros and helper routines to common.h as they will be used outside of driver.c in a later commit. Signed-off-by: Viresh Kumar Link: https://lore.kernel.org/r/6615db480370719b0a0241447a5f3feb8eea421f.1580448239.git.viresh.kumar@linaro.org Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 40 ++++++++++++++++++++++++++++++ drivers/firmware/arm_scmi/driver.c | 40 ------------------------------ 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 227934871929..934b5a23f10b 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -47,6 +47,19 @@ struct scmi_msg_resp_prot_version { __le16 major_version; }; +#define MSG_ID_MASK GENMASK(7, 0) +#define MSG_XTRACT_ID(hdr) FIELD_GET(MSG_ID_MASK, (hdr)) +#define MSG_TYPE_MASK GENMASK(9, 8) +#define MSG_XTRACT_TYPE(hdr) FIELD_GET(MSG_TYPE_MASK, (hdr)) +#define MSG_TYPE_COMMAND 0 +#define MSG_TYPE_DELAYED_RESP 2 +#define MSG_TYPE_NOTIFICATION 3 +#define MSG_PROTOCOL_ID_MASK GENMASK(17, 10) +#define MSG_XTRACT_PROT_ID(hdr) FIELD_GET(MSG_PROTOCOL_ID_MASK, (hdr)) +#define MSG_TOKEN_ID_MASK GENMASK(27, 18) +#define MSG_XTRACT_TOKEN(hdr) FIELD_GET(MSG_TOKEN_ID_MASK, (hdr)) +#define MSG_TOKEN_MAX (MSG_XTRACT_TOKEN(MSG_TOKEN_ID_MASK) + 1) + /** * struct scmi_msg_hdr - Message(Tx/Rx) header * @@ -67,6 +80,33 @@ struct scmi_msg_hdr { bool poll_completion; }; +/** + * pack_scmi_header() - packs and returns 32-bit header + * + * @hdr: pointer to header containing all the information on message id, + * protocol id and sequence id. + * + * Return: 32-bit packed message header to be sent to the platform. + */ +static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr) +{ + return FIELD_PREP(MSG_ID_MASK, hdr->id) | + FIELD_PREP(MSG_TOKEN_ID_MASK, hdr->seq) | + FIELD_PREP(MSG_PROTOCOL_ID_MASK, hdr->protocol_id); +} + +/** + * unpack_scmi_header() - unpacks and records message and protocol id + * + * @msg_hdr: 32-bit packed message header sent from the platform + * @hdr: pointer to header to fetch message and protocol id. + */ +static inline void unpack_scmi_header(u32 msg_hdr, struct scmi_msg_hdr *hdr) +{ + hdr->id = MSG_XTRACT_ID(msg_hdr); + hdr->protocol_id = MSG_XTRACT_PROT_ID(msg_hdr); +} + /** * struct scmi_msg - Message(Tx/Rx) structure * diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 978eafb53471..716423063b14 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -32,19 +32,6 @@ #define CREATE_TRACE_POINTS #include -#define MSG_ID_MASK GENMASK(7, 0) -#define MSG_XTRACT_ID(hdr) FIELD_GET(MSG_ID_MASK, (hdr)) -#define MSG_TYPE_MASK GENMASK(9, 8) -#define MSG_XTRACT_TYPE(hdr) FIELD_GET(MSG_TYPE_MASK, (hdr)) -#define MSG_TYPE_COMMAND 0 -#define MSG_TYPE_DELAYED_RESP 2 -#define MSG_TYPE_NOTIFICATION 3 -#define MSG_PROTOCOL_ID_MASK GENMASK(17, 10) -#define MSG_XTRACT_PROT_ID(hdr) FIELD_GET(MSG_PROTOCOL_ID_MASK, (hdr)) -#define MSG_TOKEN_ID_MASK GENMASK(27, 18) -#define MSG_XTRACT_TOKEN(hdr) FIELD_GET(MSG_TOKEN_ID_MASK, (hdr)) -#define MSG_TOKEN_MAX (MSG_XTRACT_TOKEN(MSG_TOKEN_ID_MASK) + 1) - enum scmi_error_codes { SCMI_SUCCESS = 0, /* Success */ SCMI_ERR_SUPPORT = -1, /* Not supported */ @@ -210,33 +197,6 @@ static void scmi_fetch_response(struct scmi_xfer *xfer, memcpy_fromio(xfer->rx.buf, mem->msg_payload + 4, xfer->rx.len); } -/** - * pack_scmi_header() - packs and returns 32-bit header - * - * @hdr: pointer to header containing all the information on message id, - * protocol id and sequence id. - * - * Return: 32-bit packed message header to be sent to the platform. - */ -static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr) -{ - return FIELD_PREP(MSG_ID_MASK, hdr->id) | - FIELD_PREP(MSG_TOKEN_ID_MASK, hdr->seq) | - FIELD_PREP(MSG_PROTOCOL_ID_MASK, hdr->protocol_id); -} - -/** - * unpack_scmi_header() - unpacks and records message and protocol id - * - * @msg_hdr: 32-bit packed message header sent from the platform - * @hdr: pointer to header to fetch message and protocol id. - */ -static inline void unpack_scmi_header(u32 msg_hdr, struct scmi_msg_hdr *hdr) -{ - hdr->id = MSG_XTRACT_ID(msg_hdr); - hdr->protocol_id = MSG_XTRACT_PROT_ID(msg_hdr); -} - /** * scmi_tx_prepare() - mailbox client callback to prepare for the transfer * From 5c8a47a5a91d4d6e185f758d61997613d9c5d6ac Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 31 Jan 2020 10:58:13 +0530 Subject: [PATCH 0045/4444] firmware: arm_scmi: Make scmi core independent of the transport type The SCMI specification is fairly independent of the transport protocol, which can be a simple mailbox (already implemented) or anything else. The current Linux implementation however is very much dependent on the mailbox transport layer. This patch makes the SCMI core code (driver.c) independent of the mailbox transport layer and moves all mailbox related code to a new file: mailbox.c and all struct shared_mem related code to a new file: shmem.c. We can now implement more transport protocols to transport SCMI messages. The transport protocols just need to provide struct scmi_transport_ops, with its version of the callbacks to enable exchange of SCMI messages. Signed-off-by: Viresh Kumar Link: https://lore.kernel.org/r/8698a3cec199b8feab35c2339f02dc232bfd773b.1580448239.git.viresh.kumar@linaro.org Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/Makefile | 3 +- drivers/firmware/arm_scmi/common.h | 71 ++++++++ drivers/firmware/arm_scmi/driver.c | 251 ++++------------------------ drivers/firmware/arm_scmi/mailbox.c | 184 ++++++++++++++++++++ drivers/firmware/arm_scmi/shmem.c | 83 +++++++++ 5 files changed, 373 insertions(+), 219 deletions(-) create mode 100644 drivers/firmware/arm_scmi/mailbox.c create mode 100644 drivers/firmware/arm_scmi/shmem.c diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile index 5f298f00a82e..6694d0d908d6 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-y = scmi-bus.o scmi-driver.o scmi-protocols.o +obj-y = scmi-bus.o scmi-driver.o scmi-protocols.o scmi-transport.o scmi-bus-y = bus.o scmi-driver-y = driver.o +scmi-transport-y = mailbox.o shmem.o scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 934b5a23f10b..5ac06469b01c 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -153,3 +153,74 @@ void scmi_setup_protocol_implemented(const struct scmi_handle *handle, u8 *prot_imp); int scmi_base_protocol_init(struct scmi_handle *h); + +/* SCMI Transport */ +/** + * struct scmi_chan_info - Structure representing a SCMI channel information + * + * @dev: Reference to device in the SCMI hierarchy corresponding to this + * channel + * @handle: Pointer to SCMI entity handle + * @transport_info: Transport layer related information + */ +struct scmi_chan_info { + struct device *dev; + struct scmi_handle *handle; + void *transport_info; +}; + +/** + * struct scmi_transport_ops - Structure representing a SCMI transport ops + * + * @chan_available: Callback to check if channel is available or not + * @chan_setup: Callback to allocate and setup a channel + * @chan_free: Callback to free a channel + * @send_message: Callback to send a message + * @mark_txdone: Callback to mark tx as done + * @fetch_response: Callback to fetch response + * @poll_done: Callback to poll transfer status + */ +struct scmi_transport_ops { + bool (*chan_available)(struct device *dev, int idx); + int (*chan_setup)(struct scmi_chan_info *cinfo, struct device *dev, + bool tx); + int (*chan_free)(int id, void *p, void *data); + int (*send_message)(struct scmi_chan_info *cinfo, + struct scmi_xfer *xfer); + void (*mark_txdone)(struct scmi_chan_info *cinfo, int ret); + void (*fetch_response)(struct scmi_chan_info *cinfo, + struct scmi_xfer *xfer); + bool (*poll_done)(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer); +}; + +/** + * struct scmi_desc - Description of SoC integration + * + * @ops: Pointer to the transport specific ops structure + * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds) + * @max_msg: Maximum number of messages that can be pending + * simultaneously in the system + * @max_msg_size: Maximum size of data per message that can be handled. + */ +struct scmi_desc { + struct scmi_transport_ops *ops; + int max_rx_timeout_ms; + int max_msg; + int max_msg_size; +}; + +extern const struct scmi_desc scmi_mailbox_desc; + +void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr); +void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id); + +/* shmem related declarations */ +struct scmi_shared_mem; + +void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem, + struct scmi_xfer *xfer); +u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem); +void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem, + struct scmi_xfer *xfer); +bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem, + struct scmi_xfer *xfer); diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 716423063b14..dbec767222e9 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -19,12 +19,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include "common.h" @@ -69,38 +67,6 @@ struct scmi_xfers_info { spinlock_t xfer_lock; }; -/** - * struct scmi_desc - Description of SoC integration - * - * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds) - * @max_msg: Maximum number of messages that can be pending - * simultaneously in the system - * @max_msg_size: Maximum size of data per message that can be handled. - */ -struct scmi_desc { - int max_rx_timeout_ms; - int max_msg; - int max_msg_size; -}; - -/** - * struct scmi_chan_info - Structure representing a SCMI channel information - * - * @cl: Mailbox Client - * @chan: Transmit/Receive mailbox channel - * @payload: Transmit/Receive mailbox channel payload area - * @dev: Reference to device in the SCMI hierarchy corresponding to this - * channel - * @handle: Pointer to SCMI entity handle - */ -struct scmi_chan_info { - struct mbox_client cl; - struct mbox_chan *chan; - void __iomem *payload; - struct device *dev; - struct scmi_handle *handle; -}; - /** * struct scmi_info - Structure representing a SCMI instance * @@ -130,27 +96,8 @@ struct scmi_info { int users; }; -#define client_to_scmi_chan_info(c) container_of(c, struct scmi_chan_info, cl) #define handle_to_scmi_info(h) container_of(h, struct scmi_info, handle) -/* - * SCMI specification requires all parameters, message headers, return - * arguments or any protocol data to be expressed in little endian - * format only. - */ -struct scmi_shared_mem { - __le32 reserved; - __le32 channel_status; -#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR BIT(1) -#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE BIT(0) - __le32 reserved1[2]; - __le32 flags; -#define SCMI_SHMEM_FLAG_INTR_ENABLED BIT(0) - __le32 length; - __le32 msg_header; - u8 msg_payload[0]; -}; - static const int scmi_linux_errmap[] = { /* better than switch case as long as return value is continuous */ 0, /* SCMI_SUCCESS */ @@ -186,50 +133,6 @@ static inline void scmi_dump_header_dbg(struct device *dev, hdr->id, hdr->seq, hdr->protocol_id); } -static void scmi_fetch_response(struct scmi_xfer *xfer, - struct scmi_shared_mem __iomem *mem) -{ - xfer->hdr.status = ioread32(mem->msg_payload); - /* Skip the length of header and status in payload area i.e 8 bytes */ - xfer->rx.len = min_t(size_t, xfer->rx.len, ioread32(&mem->length) - 8); - - /* Take a copy to the rx buffer.. */ - memcpy_fromio(xfer->rx.buf, mem->msg_payload + 4, xfer->rx.len); -} - -/** - * scmi_tx_prepare() - mailbox client callback to prepare for the transfer - * - * @cl: client pointer - * @m: mailbox message - * - * This function prepares the shared memory which contains the header and the - * payload. - */ -static void scmi_tx_prepare(struct mbox_client *cl, void *m) -{ - struct scmi_xfer *t = m; - struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl); - struct scmi_shared_mem __iomem *mem = cinfo->payload; - - /* - * Ideally channel must be free by now unless OS timeout last - * request and platform continued to process the same, wait - * until it releases the shared memory, otherwise we may endup - * overwriting its response with new message payload or vice-versa - */ - spin_until_cond(ioread32(&mem->channel_status) & - SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE); - /* Mark channel busy + clear error */ - iowrite32(0x0, &mem->channel_status); - iowrite32(t->hdr.poll_completion ? 0 : SCMI_SHMEM_FLAG_INTR_ENABLED, - &mem->flags); - iowrite32(sizeof(mem->msg_header) + t->tx.len, &mem->length); - iowrite32(pack_scmi_header(&t->hdr), &mem->msg_header); - if (t->tx.buf) - memcpy_toio(mem->msg_payload, t->tx.buf, t->tx.len); -} - /** * scmi_xfer_get() - Allocate one message * @@ -298,10 +201,10 @@ __scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer) } /** - * scmi_rx_callback() - mailbox client callback for receive messages + * scmi_rx_callback() - callback for receiving messages * - * @cl: client pointer - * @m: mailbox message + * @cinfo: SCMI channel info + * @msg_hdr: Message header * * Processes one received message to appropriate transfer information and * signals completion of the transfer. @@ -309,21 +212,14 @@ __scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer) * NOTE: This function will be invoked in IRQ context, hence should be * as optimal as possible. */ -static void scmi_rx_callback(struct mbox_client *cl, void *m) +void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr) { - u8 msg_type; - u32 msg_hdr; - u16 xfer_id; - struct scmi_xfer *xfer; - struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl); - struct device *dev = cinfo->dev; struct scmi_info *info = handle_to_scmi_info(cinfo->handle); struct scmi_xfers_info *minfo = &info->tx_minfo; - struct scmi_shared_mem __iomem *mem = cinfo->payload; - - msg_hdr = ioread32(&mem->msg_header); - msg_type = MSG_XTRACT_TYPE(msg_hdr); - xfer_id = MSG_XTRACT_TOKEN(msg_hdr); + u16 xfer_id = MSG_XTRACT_TOKEN(msg_hdr); + u8 msg_type = MSG_XTRACT_TYPE(msg_hdr); + struct device *dev = cinfo->dev; + struct scmi_xfer *xfer; if (msg_type == MSG_TYPE_NOTIFICATION) return; /* Notifications not yet supported */ @@ -338,7 +234,7 @@ static void scmi_rx_callback(struct mbox_client *cl, void *m) scmi_dump_header_dbg(dev, &xfer->hdr); - scmi_fetch_response(xfer, mem); + info->desc->ops->fetch_response(cinfo, xfer); trace_scmi_rx_done(xfer->transfer_id, xfer->hdr.id, xfer->hdr.protocol_id, xfer->hdr.seq, @@ -363,28 +259,15 @@ void scmi_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer) __scmi_xfer_put(&info->tx_minfo, xfer); } -static bool -scmi_xfer_poll_done(const struct scmi_chan_info *cinfo, struct scmi_xfer *xfer) -{ - struct scmi_shared_mem __iomem *mem = cinfo->payload; - u16 xfer_id = MSG_XTRACT_TOKEN(ioread32(&mem->msg_header)); - - if (xfer->hdr.seq != xfer_id) - return false; - - return ioread32(&mem->channel_status) & - (SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR | - SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE); -} - #define SCMI_MAX_POLL_TO_NS (100 * NSEC_PER_USEC) -static bool scmi_xfer_done_no_timeout(const struct scmi_chan_info *cinfo, +static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer, ktime_t stop) { - ktime_t __cur = ktime_get(); + struct scmi_info *info = handle_to_scmi_info(cinfo->handle); - return scmi_xfer_poll_done(cinfo, xfer) || ktime_after(__cur, stop); + return info->desc->ops->poll_done(cinfo, xfer) || + ktime_after(ktime_get(), stop); } /** @@ -413,29 +296,26 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer) xfer->hdr.protocol_id, xfer->hdr.seq, xfer->hdr.poll_completion); - ret = mbox_send_message(cinfo->chan, xfer); + ret = info->desc->ops->send_message(cinfo, xfer); if (ret < 0) { - dev_dbg(dev, "mbox send fail %d\n", ret); + dev_dbg(dev, "Failed to send message %d\n", ret); return ret; } - /* mbox_send_message returns non-negative value on success, so reset */ - ret = 0; - if (xfer->hdr.poll_completion) { ktime_t stop = ktime_add_ns(ktime_get(), SCMI_MAX_POLL_TO_NS); spin_until_cond(scmi_xfer_done_no_timeout(cinfo, xfer, stop)); if (ktime_before(ktime_get(), stop)) - scmi_fetch_response(xfer, cinfo->payload); + info->desc->ops->fetch_response(cinfo, xfer); else ret = -ETIMEDOUT; } else { /* And we wait for the response. */ timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms); if (!wait_for_completion_timeout(&xfer->done, timeout)) { - dev_err(dev, "mbox timed out in resp(caller: %pS)\n", + dev_err(dev, "timed out in resp(caller: %pS)\n", (void *)_RET_IP_); ret = -ETIMEDOUT; } @@ -444,13 +324,8 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer) if (!ret && xfer->hdr.status) ret = scmi_to_linux_errno(xfer->hdr.status); - /* - * NOTE: we might prefer not to need the mailbox ticker to manage the - * transfer queueing since the protocol layer queues things by itself. - * Unfortunately, we have to kick the mailbox framework after we have - * received our message. - */ - mbox_client_txdone(cinfo->chan, ret); + if (info->desc->ops->mark_txdone) + info->desc->ops->mark_txdone(cinfo, ret); trace_scmi_xfer_end(xfer->transfer_id, xfer->hdr.id, xfer->hdr.protocol_id, xfer->hdr.seq, @@ -691,23 +566,12 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo) return 0; } -static int scmi_mailbox_check(struct device_node *np, int idx) -{ - return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", - idx, NULL); -} - -static int scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, - int prot_id, bool tx) +static int scmi_chan_setup(struct scmi_info *info, struct device *dev, + int prot_id, bool tx) { int ret, idx; - struct resource res; - resource_size_t size; - struct device_node *shmem, *np = dev->of_node; struct scmi_chan_info *cinfo; - struct mbox_client *cl; struct idr *idr; - const char *desc = tx ? "Tx" : "Rx"; /* Transmit channel is first entry i.e. index 0 */ idx = tx ? 0 : 1; @@ -718,7 +582,7 @@ static int scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, if (cinfo) return 0; - if (scmi_mailbox_check(np, idx)) { + if (!info->desc->ops->chan_available(dev, idx)) { cinfo = idr_find(idr, SCMI_PROTOCOL_BASE); if (unlikely(!cinfo)) /* Possible only if platform has no Rx */ return -EINVAL; @@ -731,36 +595,9 @@ static int scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, cinfo->dev = dev; - cl = &cinfo->cl; - cl->dev = dev; - cl->rx_callback = scmi_rx_callback; - cl->tx_prepare = tx ? scmi_tx_prepare : NULL; - cl->tx_block = false; - cl->knows_txdone = tx; - - shmem = of_parse_phandle(np, "shmem", idx); - ret = of_address_to_resource(shmem, 0, &res); - of_node_put(shmem); - if (ret) { - dev_err(dev, "failed to get SCMI %s payload memory\n", desc); + ret = info->desc->ops->chan_setup(cinfo, info->dev, tx); + if (ret) return ret; - } - - size = resource_size(&res); - cinfo->payload = devm_ioremap(info->dev, res.start, size); - if (!cinfo->payload) { - dev_err(dev, "failed to ioremap SCMI %s payload\n", desc); - return -EADDRNOTAVAIL; - } - - cinfo->chan = mbox_request_channel(cl, idx); - if (IS_ERR(cinfo->chan)) { - ret = PTR_ERR(cinfo->chan); - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to request SCMI %s mailbox\n", - desc); - return ret; - } idr_alloc: ret = idr_alloc(idr, cinfo, prot_id, prot_id + 1, GFP_KERNEL); @@ -774,12 +611,12 @@ idr_alloc: } static inline int -scmi_mbox_txrx_setup(struct scmi_info *info, struct device *dev, int prot_id) +scmi_txrx_setup(struct scmi_info *info, struct device *dev, int prot_id) { - int ret = scmi_mbox_chan_setup(info, dev, prot_id, true); + int ret = scmi_chan_setup(info, dev, prot_id, true); if (!ret) /* Rx is optional, hence no error check */ - scmi_mbox_chan_setup(info, dev, prot_id, false); + scmi_chan_setup(info, dev, prot_id, false); return ret; } @@ -797,7 +634,7 @@ scmi_create_protocol_device(struct device_node *np, struct scmi_info *info, return; } - if (scmi_mbox_txrx_setup(info, &sdev->dev, prot_id)) { + if (scmi_txrx_setup(info, &sdev->dev, prot_id)) { dev_err(&sdev->dev, "failed to setup transport\n"); scmi_device_destroy(sdev); return; @@ -850,12 +687,6 @@ static int scmi_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *child, *np = dev->of_node; - /* Only mailbox method supported, check for the presence of one */ - if (scmi_mailbox_check(np, 0)) { - dev_err(dev, "no mailbox found in %pOF\n", np); - return -EINVAL; - } - desc = of_device_get_match_data(dev); if (!desc) return -EINVAL; @@ -880,7 +711,7 @@ static int scmi_probe(struct platform_device *pdev) handle->dev = info->dev; handle->version = &info->version; - ret = scmi_mbox_txrx_setup(info, dev, SCMI_PROTOCOL_BASE); + ret = scmi_txrx_setup(info, dev, SCMI_PROTOCOL_BASE); if (ret) return ret; @@ -915,19 +746,9 @@ static int scmi_probe(struct platform_device *pdev) return 0; } -static int scmi_mbox_free_channel(int id, void *p, void *data) +void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id) { - struct scmi_chan_info *cinfo = p; - struct idr *idr = data; - - if (!IS_ERR_OR_NULL(cinfo->chan)) { - mbox_free_channel(cinfo->chan); - cinfo->chan = NULL; - } - idr_remove(idr, id); - - return 0; } static int scmi_remove(struct platform_device *pdev) @@ -947,11 +768,11 @@ static int scmi_remove(struct platform_device *pdev) return ret; /* Safe to free channels since no more users */ - ret = idr_for_each(idr, scmi_mbox_free_channel, idr); + ret = idr_for_each(idr, info->desc->ops->chan_free, idr); idr_destroy(&info->tx_idr); idr = &info->rx_idr; - ret = idr_for_each(idr, scmi_mbox_free_channel, idr); + ret = idr_for_each(idr, info->desc->ops->chan_free, idr); idr_destroy(&info->rx_idr); return ret; @@ -1003,15 +824,9 @@ static struct attribute *versions_attrs[] = { }; ATTRIBUTE_GROUPS(versions); -static const struct scmi_desc scmi_generic_desc = { - .max_rx_timeout_ms = 30, /* We may increase this if required */ - .max_msg = 20, /* Limited by MBOX_TX_QUEUE_LEN */ - .max_msg_size = 128, -}; - /* Each compatible listed below must have descriptor associated with it */ static const struct of_device_id scmi_of_match[] = { - { .compatible = "arm,scmi", .data = &scmi_generic_desc }, + { .compatible = "arm,scmi", .data = &scmi_mailbox_desc }, { /* Sentinel */ }, }; diff --git a/drivers/firmware/arm_scmi/mailbox.c b/drivers/firmware/arm_scmi/mailbox.c new file mode 100644 index 000000000000..73077bbc4ad9 --- /dev/null +++ b/drivers/firmware/arm_scmi/mailbox.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * System Control and Management Interface (SCMI) Message Mailbox Transport + * driver. + * + * Copyright (C) 2019 ARM Ltd. + */ + +#include +#include +#include +#include +#include +#include + +#include "common.h" + +/** + * struct scmi_mailbox - Structure representing a SCMI mailbox transport + * + * @cl: Mailbox Client + * @chan: Transmit/Receive mailbox channel + * @cinfo: SCMI channel info + * @shmem: Transmit/Receive shared memory area + */ +struct scmi_mailbox { + struct mbox_client cl; + struct mbox_chan *chan; + struct scmi_chan_info *cinfo; + struct scmi_shared_mem __iomem *shmem; +}; + +#define client_to_scmi_mailbox(c) container_of(c, struct scmi_mailbox, cl) + +static void tx_prepare(struct mbox_client *cl, void *m) +{ + struct scmi_mailbox *smbox = client_to_scmi_mailbox(cl); + + shmem_tx_prepare(smbox->shmem, m); +} + +static void rx_callback(struct mbox_client *cl, void *m) +{ + struct scmi_mailbox *smbox = client_to_scmi_mailbox(cl); + + scmi_rx_callback(smbox->cinfo, shmem_read_header(smbox->shmem)); +} + +static bool mailbox_chan_available(struct device *dev, int idx) +{ + return !of_parse_phandle_with_args(dev->of_node, "mboxes", + "#mbox-cells", idx, NULL); +} + +static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, + bool tx) +{ + const char *desc = tx ? "Tx" : "Rx"; + struct device *cdev = cinfo->dev; + struct scmi_mailbox *smbox; + struct device_node *shmem; + int ret, idx = tx ? 0 : 1; + struct mbox_client *cl; + resource_size_t size; + struct resource res; + + smbox = devm_kzalloc(dev, sizeof(*smbox), GFP_KERNEL); + if (!smbox) + return -ENOMEM; + + shmem = of_parse_phandle(cdev->of_node, "shmem", idx); + ret = of_address_to_resource(shmem, 0, &res); + of_node_put(shmem); + if (ret) { + dev_err(cdev, "failed to get SCMI %s shared memory\n", desc); + return ret; + } + + size = resource_size(&res); + smbox->shmem = devm_ioremap(dev, res.start, size); + if (!smbox->shmem) { + dev_err(dev, "failed to ioremap SCMI %s shared memory\n", desc); + return -EADDRNOTAVAIL; + } + + cl = &smbox->cl; + cl->dev = cdev; + cl->tx_prepare = tx ? tx_prepare : NULL; + cl->rx_callback = rx_callback; + cl->tx_block = false; + cl->knows_txdone = tx; + + smbox->chan = mbox_request_channel(cl, tx ? 0 : 1); + if (IS_ERR(smbox->chan)) { + ret = PTR_ERR(smbox->chan); + if (ret != -EPROBE_DEFER) + dev_err(cdev, "failed to request SCMI %s mailbox\n", + tx ? "Tx" : "Rx"); + return ret; + } + + cinfo->transport_info = smbox; + smbox->cinfo = cinfo; + + return 0; +} + +static int mailbox_chan_free(int id, void *p, void *data) +{ + struct scmi_chan_info *cinfo = p; + struct scmi_mailbox *smbox = cinfo->transport_info; + + if (!IS_ERR(smbox->chan)) { + mbox_free_channel(smbox->chan); + cinfo->transport_info = NULL; + smbox->chan = NULL; + smbox->cinfo = NULL; + } + + scmi_free_channel(cinfo, data, id); + + return 0; +} + +static int mailbox_send_message(struct scmi_chan_info *cinfo, + struct scmi_xfer *xfer) +{ + struct scmi_mailbox *smbox = cinfo->transport_info; + int ret; + + ret = mbox_send_message(smbox->chan, xfer); + + /* mbox_send_message returns non-negative value on success, so reset */ + if (ret > 0) + ret = 0; + + return ret; +} + +static void mailbox_mark_txdone(struct scmi_chan_info *cinfo, int ret) +{ + struct scmi_mailbox *smbox = cinfo->transport_info; + + /* + * NOTE: we might prefer not to need the mailbox ticker to manage the + * transfer queueing since the protocol layer queues things by itself. + * Unfortunately, we have to kick the mailbox framework after we have + * received our message. + */ + mbox_client_txdone(smbox->chan, ret); +} + +static void mailbox_fetch_response(struct scmi_chan_info *cinfo, + struct scmi_xfer *xfer) +{ + struct scmi_mailbox *smbox = cinfo->transport_info; + + shmem_fetch_response(smbox->shmem, xfer); +} + +static bool +mailbox_poll_done(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer) +{ + struct scmi_mailbox *smbox = cinfo->transport_info; + + return shmem_poll_done(smbox->shmem, xfer); +} + +static struct scmi_transport_ops scmi_mailbox_ops = { + .chan_available = mailbox_chan_available, + .chan_setup = mailbox_chan_setup, + .chan_free = mailbox_chan_free, + .send_message = mailbox_send_message, + .mark_txdone = mailbox_mark_txdone, + .fetch_response = mailbox_fetch_response, + .poll_done = mailbox_poll_done, +}; + +const struct scmi_desc scmi_mailbox_desc = { + .ops = &scmi_mailbox_ops, + .max_rx_timeout_ms = 30, /* We may increase this if required */ + .max_msg = 20, /* Limited by MBOX_TX_QUEUE_LEN */ + .max_msg_size = 128, +}; diff --git a/drivers/firmware/arm_scmi/shmem.c b/drivers/firmware/arm_scmi/shmem.c new file mode 100644 index 000000000000..ca0ffd302ea2 --- /dev/null +++ b/drivers/firmware/arm_scmi/shmem.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * For transport using shared mem structure. + * + * Copyright (C) 2019 ARM Ltd. + */ + +#include +#include +#include + +#include "common.h" + +/* + * SCMI specification requires all parameters, message headers, return + * arguments or any protocol data to be expressed in little endian + * format only. + */ +struct scmi_shared_mem { + __le32 reserved; + __le32 channel_status; +#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR BIT(1) +#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE BIT(0) + __le32 reserved1[2]; + __le32 flags; +#define SCMI_SHMEM_FLAG_INTR_ENABLED BIT(0) + __le32 length; + __le32 msg_header; + u8 msg_payload[0]; +}; + +void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem, + struct scmi_xfer *xfer) +{ + /* + * Ideally channel must be free by now unless OS timeout last + * request and platform continued to process the same, wait + * until it releases the shared memory, otherwise we may endup + * overwriting its response with new message payload or vice-versa + */ + spin_until_cond(ioread32(&shmem->channel_status) & + SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE); + /* Mark channel busy + clear error */ + iowrite32(0x0, &shmem->channel_status); + iowrite32(xfer->hdr.poll_completion ? 0 : SCMI_SHMEM_FLAG_INTR_ENABLED, + &shmem->flags); + iowrite32(sizeof(shmem->msg_header) + xfer->tx.len, &shmem->length); + iowrite32(pack_scmi_header(&xfer->hdr), &shmem->msg_header); + if (xfer->tx.buf) + memcpy_toio(shmem->msg_payload, xfer->tx.buf, xfer->tx.len); +} + +u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem) +{ + return ioread32(&shmem->msg_header); +} + +void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem, + struct scmi_xfer *xfer) +{ + xfer->hdr.status = ioread32(shmem->msg_payload); + /* Skip the length of header and status in shmem area i.e 8 bytes */ + xfer->rx.len = min_t(size_t, xfer->rx.len, + ioread32(&shmem->length) - 8); + + /* Take a copy to the rx buffer.. */ + memcpy_fromio(xfer->rx.buf, shmem->msg_payload + 4, xfer->rx.len); +} + +bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem, + struct scmi_xfer *xfer) +{ + u16 xfer_id; + + xfer_id = MSG_XTRACT_TOKEN(ioread32(&shmem->msg_header)); + + if (xfer->hdr.seq != xfer_id) + return false; + + return ioread32(&shmem->channel_status) & + (SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR | + SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE); +} From 046e14afb3561523efd0047c35c20793ae5f8848 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 5 Feb 2020 15:43:36 +0200 Subject: [PATCH 0046/4444] gpio: Avoid kernel.h inclusion where it's possible Inclusion of kernel.h increases the mess with the header dependencies. Avoid kernel.h inclusion where it's possible. Besides that, clean up a bit other inclusions inside GPIO subsystem headers. It includes: - removal pin control bits (forward declaration and header) from linux/gpio.h - removal of.h from asm-generic/gpio.h - use of explicit headers in gpio/consumer.h - add FIXME note with regard to gpio.h inclusion in of_gpio,h Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200205134336.20197-1-andriy.shevchenko@linux.intel.com Signed-off-by: Linus Walleij --- include/asm-generic/gpio.h | 4 ++-- include/linux/gpio.h | 2 -- include/linux/gpio/consumer.h | 5 ++++- include/linux/of_gpio.h | 9 ++++++--- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 19eadac415c4..aea9aee1f3e9 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -2,10 +2,8 @@ #ifndef _ASM_GENERIC_GPIO_H #define _ASM_GENERIC_GPIO_H -#include #include #include -#include #ifdef CONFIG_GPIOLIB @@ -140,6 +138,8 @@ static inline void gpio_unexport(unsigned gpio) #else /* !CONFIG_GPIOLIB */ +#include + static inline bool gpio_is_valid(int number) { /* only non-negative numbers are valid */ diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 2157717c2136..008ad3ee56b7 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -102,11 +102,9 @@ void devm_gpio_free(struct device *dev, unsigned int gpio); #include #include #include -#include struct device; struct gpio_chip; -struct pinctrl_dev; static inline bool gpio_is_valid(int number) { diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index bf2d017dd7b7..0a72fccf60ff 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -2,9 +2,10 @@ #ifndef __LINUX_GPIO_CONSUMER_H #define __LINUX_GPIO_CONSUMER_H +#include #include +#include #include -#include struct device; @@ -189,6 +190,8 @@ struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev, #else /* CONFIG_GPIOLIB */ +#include + static inline int gpiod_count(struct device *dev, const char *con_id) { return 0; diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h index 16967390a3fe..f821095218b0 100644 --- a/include/linux/of_gpio.h +++ b/include/linux/of_gpio.h @@ -11,9 +11,8 @@ #define __LINUX_OF_GPIO_H #include -#include -#include -#include +#include +#include /* FIXME: Shouldn't be here */ #include struct device_node; @@ -34,6 +33,8 @@ enum of_gpio_flags { #ifdef CONFIG_OF_GPIO +#include + /* * OF GPIO chip for memory mapped banks */ @@ -63,6 +64,8 @@ extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc); #else /* CONFIG_OF_GPIO */ +#include + /* Drivers may not strictly depend on the GPIO support, so let them link. */ static inline int of_get_named_gpio_flags(struct device_node *np, const char *list_name, int index, enum of_gpio_flags *flags) From 408324a3c5383716939eea8096a0f999a0665f7e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 11 Dec 2019 14:52:22 +0100 Subject: [PATCH 0047/4444] ARM: shmobile: Enable ARM_GLOBAL_TIMER on Cortex-A9 MPCore SoCs SH-Mobile AG5 and R-Car H1 SoCs are based on the Cortex-A9 MPCore, which includes a global timer. Enable the ARM global timer on these SoCs, which will be used for: - the scheduler clock, improving scheduler accuracy from 10 ms to 3 or 4 ns, - delay loops, allowing removal of calls to shmobile_init_delay() from the corresponding machine vectors. Note that when using an old DTB lacking the global timer, the kernel will still work. However, loops-per-jiffies will no longer be preset, and the delay loop will need to be calibrated during boot. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20191211135222.26770-5-geert+renesas@glider.be --- arch/arm/mach-shmobile/setup-r8a7779.c | 1 - arch/arm/mach-shmobile/setup-sh73a0.c | 1 - drivers/soc/renesas/Kconfig | 2 ++ 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c index b13ec9088ce5..86406e3f9b22 100644 --- a/arch/arm/mach-shmobile/setup-r8a7779.c +++ b/arch/arm/mach-shmobile/setup-r8a7779.c @@ -72,7 +72,6 @@ static const char *const r8a7779_compat_dt[] __initconst = { DT_MACHINE_START(R8A7779_DT, "Generic R8A7779 (Flattened Device Tree)") .smp = smp_ops(r8a7779_smp_ops), .map_io = r8a7779_map_io, - .init_early = shmobile_init_delay, .init_irq = r8a7779_init_irq_dt, .init_late = shmobile_init_late, .dt_compat = r8a7779_compat_dt, diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c index cc08aa752244..eb4a62fa4289 100644 --- a/arch/arm/mach-shmobile/setup-sh73a0.c +++ b/arch/arm/mach-shmobile/setup-sh73a0.c @@ -56,7 +56,6 @@ static const char *const sh73a0_boards_compat_dt[] __initconst = { DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)") .smp = smp_ops(sh73a0_smp_ops), .map_io = sh73a0_map_io, - .init_early = shmobile_init_delay, .init_machine = sh73a0_generic_init, .init_late = shmobile_init_late, .dt_compat = sh73a0_boards_compat_dt, diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index ba2b8b51d2d9..de5cfe3fddd3 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -116,6 +116,7 @@ config ARCH_R8A7779 bool "R-Car H1 (R8A77790)" select ARCH_RCAR_GEN1 select ARM_ERRATA_754322 + select ARM_GLOBAL_TIMER select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP select SYSC_R8A7779 @@ -163,6 +164,7 @@ config ARCH_SH73A0 bool "SH-Mobile AG5 (R8A73A00)" select ARCH_RMOBILE select ARM_ERRATA_754322 + select ARM_GLOBAL_TIMER select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP select RENESAS_INTC_IRQPIN From 516f68943a6ad4aadfa384e4ce3751e03e1afbda Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 15 Jan 2020 06:12:25 +0100 Subject: [PATCH 0048/4444] ARM: dts: renesas: Add missing ethernet PHY reset GPIO on Gen2 reference boards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ethernet PHY reset GPIO was missing and the kernel was depending solely on the bootloader to bring the PHY out of reset. Fix this to get rid of the dependency on bootloader. Signed-off-by: Marek Vasut Tested-by: Niklas Söderlund Link: https://lore.kernel.org/r/20200115051225.7346-1-marek.vasut@gmail.com Signed-off-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7790-lager.dts | 1 + arch/arm/boot/dts/r8a7790-stout.dts | 1 + arch/arm/boot/dts/r8a7791-koelsch.dts | 1 + arch/arm/boot/dts/r8a7791-porter.dts | 1 + arch/arm/boot/dts/r8a7793-gose.dts | 1 + arch/arm/boot/dts/r8a7794-alt.dts | 1 + arch/arm/boot/dts/r8a7794-silk.dts | 1 + 7 files changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index 097fd9317c6e..69745def44d4 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -674,6 +674,7 @@ interrupt-parent = <&irqc0>; interrupts = <0 IRQ_TYPE_LEVEL_LOW>; micrel,led-mode = <1>; + reset-gpios = <&gpio5 31 GPIO_ACTIVE_LOW>; }; }; diff --git a/arch/arm/boot/dts/r8a7790-stout.dts b/arch/arm/boot/dts/r8a7790-stout.dts index a315ba749aa4..4138efb2766d 100644 --- a/arch/arm/boot/dts/r8a7790-stout.dts +++ b/arch/arm/boot/dts/r8a7790-stout.dts @@ -203,6 +203,7 @@ interrupt-parent = <&irqc0>; interrupts = <1 IRQ_TYPE_LEVEL_LOW>; micrel,led-mode = <1>; + reset-gpios = <&gpio3 31 GPIO_ACTIVE_LOW>; }; }; diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts index 2b096d5e06fb..687167b70cb6 100644 --- a/arch/arm/boot/dts/r8a7791-koelsch.dts +++ b/arch/arm/boot/dts/r8a7791-koelsch.dts @@ -633,6 +633,7 @@ interrupt-parent = <&irqc0>; interrupts = <0 IRQ_TYPE_LEVEL_LOW>; micrel,led-mode = <1>; + reset-gpios = <&gpio5 22 GPIO_ACTIVE_LOW>; }; }; diff --git a/arch/arm/boot/dts/r8a7791-porter.dts b/arch/arm/boot/dts/r8a7791-porter.dts index f9ece7ab2010..a8e0335148a5 100644 --- a/arch/arm/boot/dts/r8a7791-porter.dts +++ b/arch/arm/boot/dts/r8a7791-porter.dts @@ -307,6 +307,7 @@ interrupt-parent = <&irqc0>; interrupts = <0 IRQ_TYPE_LEVEL_LOW>; micrel,led-mode = <1>; + reset-gpios = <&gpio5 22 GPIO_ACTIVE_LOW>; }; }; diff --git a/arch/arm/boot/dts/r8a7793-gose.dts b/arch/arm/boot/dts/r8a7793-gose.dts index 22ca7cd1e7d2..cfe06a74ce89 100644 --- a/arch/arm/boot/dts/r8a7793-gose.dts +++ b/arch/arm/boot/dts/r8a7793-gose.dts @@ -591,6 +591,7 @@ interrupt-parent = <&irqc0>; interrupts = <0 IRQ_TYPE_LEVEL_LOW>; micrel,led-mode = <1>; + reset-gpios = <&gpio5 22 GPIO_ACTIVE_LOW>; }; }; diff --git a/arch/arm/boot/dts/r8a7794-alt.dts b/arch/arm/boot/dts/r8a7794-alt.dts index f79fce74cd9c..935935c1dbac 100644 --- a/arch/arm/boot/dts/r8a7794-alt.dts +++ b/arch/arm/boot/dts/r8a7794-alt.dts @@ -343,6 +343,7 @@ interrupt-parent = <&irqc0>; interrupts = <8 IRQ_TYPE_LEVEL_LOW>; micrel,led-mode = <1>; + reset-gpios = <&gpio1 24 GPIO_ACTIVE_LOW>; }; }; diff --git a/arch/arm/boot/dts/r8a7794-silk.dts b/arch/arm/boot/dts/r8a7794-silk.dts index 2c16ad854300..9aaa96ea9943 100644 --- a/arch/arm/boot/dts/r8a7794-silk.dts +++ b/arch/arm/boot/dts/r8a7794-silk.dts @@ -394,6 +394,7 @@ interrupt-parent = <&irqc0>; interrupts = <8 IRQ_TYPE_LEVEL_LOW>; micrel,led-mode = <1>; + reset-gpios = <&gpio1 24 GPIO_ACTIVE_LOW>; }; }; From 4e28626dbc2cac7d27f91a3171f6fd34626280b3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 31 Dec 2019 15:16:42 +0100 Subject: [PATCH 0049/4444] ARM: dts: renesas: Group tuples in operating-points properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To improve human readability and enable automatic validation, the tuples in the "operating-points" properties of CPU nodes should be grouped. Fix this by grouping the tuples of these properties using angle brackets in the DTS files for all Renesas SoCs that don't already do so. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20191231141642.31609-1-geert+renesas@glider.be --- arch/arm/boot/dts/r8a73a4-ape6evm.dts | 7 ++----- arch/arm/boot/dts/sh73a0-kzm9g.dts | 9 +++------ 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts index a5351ddbf506..b088e8e351d5 100644 --- a/arch/arm/boot/dts/r8a73a4-ape6evm.dts +++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts @@ -157,11 +157,8 @@ &cpu0 { cpu0-supply = <&vdd_dvfs>; - operating-points = < - /* kHz uV */ - 1950000 1115000 - 1462500 995000 - >; + operating-points = <1950000 1115000>, /* kHz uV */ + <1462500 995000>; voltage-tolerance = <1>; /* 1% */ }; diff --git a/arch/arm/boot/dts/sh73a0-kzm9g.dts b/arch/arm/boot/dts/sh73a0-kzm9g.dts index 1916f31a30ff..5a8d92a061df 100644 --- a/arch/arm/boot/dts/sh73a0-kzm9g.dts +++ b/arch/arm/boot/dts/sh73a0-kzm9g.dts @@ -25,12 +25,9 @@ cpus { cpu@0 { cpu0-supply = <&vdd_dvfs>; - operating-points = < - /* kHz uV */ - 1196000 1315000 - 598000 1175000 - 398667 1065000 - >; + operating-points = <1196000 1315000>, /* kHz uV */ + < 598000 1175000>, + < 398667 1065000>; voltage-tolerance = <1>; /* 1% */ }; }; From b214f94e0f5f00c11308d8b9ef4d396252edd91b Mon Sep 17 00:00:00 2001 From: Chris Brandt Date: Mon, 10 Feb 2020 07:31:53 -0500 Subject: [PATCH 0050/4444] ARM: dts: r7s72100: Add SPIBSC clocks Add clocks for SPIBSC blocks. Also modify the flash node for the GR-PEACH board at the same time because now that the SPIBSC clock is identified, if it is not used by any driver, it will be turned off at the end of kernel boot. That would not work out so well for an XIP system such as GR-PEACH. Signed-off-by: Chris Brandt Link: https://lore.kernel.org/r/20200210123153.8257-1-chris.brandt@renesas.com Signed-off-by: Geert Uytterhoeven --- arch/arm/boot/dts/r7s72100-gr-peach.dts | 3 +++ arch/arm/boot/dts/r7s72100.dtsi | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/r7s72100-gr-peach.dts b/arch/arm/boot/dts/r7s72100-gr-peach.dts index fe1a4aa4d7cb..2562cc9b5356 100644 --- a/arch/arm/boot/dts/r7s72100-gr-peach.dts +++ b/arch/arm/boot/dts/r7s72100-gr-peach.dts @@ -41,6 +41,9 @@ bank-width = <4>; device-width = <1>; + clocks = <&mstp9_clks R7S72100_CLK_SPIBSC0>; + power-domains = <&cpg_clocks>; + #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/r7s72100.dtsi b/arch/arm/boot/dts/r7s72100.dtsi index 75b2796ebfca..0a567d8ebc66 100644 --- a/arch/arm/boot/dts/r7s72100.dtsi +++ b/arch/arm/boot/dts/r7s72100.dtsi @@ -467,11 +467,12 @@ #clock-cells = <1>; compatible = "renesas,r7s72100-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0xfcfe0438 4>; - clocks = <&p0_clk>, <&p0_clk>, <&p0_clk>, <&p0_clk>; + clocks = <&p0_clk>, <&p0_clk>, <&p0_clk>, <&p0_clk>, <&b_clk>, <&b_clk>; clock-indices = < R7S72100_CLK_I2C0 R7S72100_CLK_I2C1 R7S72100_CLK_I2C2 R7S72100_CLK_I2C3 + R7S72100_CLK_SPIBSC0 R7S72100_CLK_SPIBSC1 >; - clock-output-names = "i2c0", "i2c1", "i2c2", "i2c3"; + clock-output-names = "i2c0", "i2c1", "i2c2", "i2c3", "spibsc0", "spibsc1"; }; mstp10_clks: mstp10_clks@fcfe043c { From 6e26901a00c04436e9e7a323772b71348aeab651 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 24 Jan 2020 14:31:37 +0100 Subject: [PATCH 0051/4444] clk: renesas: rcar-gen3: Add CCREE clocks Add the CryptoCell module clocks and their parents for the CryptoCell instances in the various Renesas R-Car Gen3 SoCs that do not have support for them yet in their clock drivers (M3-W/W+, M3-N, E3, D3). The R-Car H3 clock driver already supports these clocks. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200124133137.15921-1-geert+renesas@glider.be --- drivers/clk/renesas/r8a7796-cpg-mssr.c | 2 ++ drivers/clk/renesas/r8a77965-cpg-mssr.c | 4 +++- drivers/clk/renesas/r8a77990-cpg-mssr.c | 2 ++ drivers/clk/renesas/r8a77995-cpg-mssr.c | 2 ++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index e8420d3ada94..1155d6636848 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -105,6 +105,7 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = { DEF_GEN3_SD("sd3", R8A7796_CLK_SD3, CLK_SDSRC, 0x26c), DEF_FIXED("cl", R8A7796_CLK_CL, CLK_PLL1_DIV2, 48, 1), + DEF_FIXED("cr", R8A7796_CLK_CR, CLK_PLL1_DIV4, 2, 1), DEF_FIXED("cp", R8A7796_CLK_CP, CLK_EXTAL, 2, 1), DEF_FIXED("cpex", R8A7796_CLK_CPEX, CLK_EXTAL, 2, 1), @@ -132,6 +133,7 @@ static struct mssr_mod_clk r8a7796_mod_clks[] __initdata = { DEF_MOD("sys-dmac2", 217, R8A7796_CLK_S3D1), DEF_MOD("sys-dmac1", 218, R8A7796_CLK_S3D1), DEF_MOD("sys-dmac0", 219, R8A7796_CLK_S0D3), + DEF_MOD("sceg-pub", 229, R8A7796_CLK_CR), DEF_MOD("cmt3", 300, R8A7796_CLK_R), DEF_MOD("cmt2", 301, R8A7796_CLK_R), DEF_MOD("cmt1", 302, R8A7796_CLK_R), diff --git a/drivers/clk/renesas/r8a77965-cpg-mssr.c b/drivers/clk/renesas/r8a77965-cpg-mssr.c index b3af4da2ca74..9530480880f1 100644 --- a/drivers/clk/renesas/r8a77965-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77965-cpg-mssr.c @@ -99,7 +99,8 @@ static const struct cpg_core_clk r8a77965_core_clks[] __initconst = { DEF_GEN3_SD("sd2", R8A77965_CLK_SD2, CLK_SDSRC, 0x268), DEF_GEN3_SD("sd3", R8A77965_CLK_SD3, CLK_SDSRC, 0x26c), - DEF_FIXED("cl", R8A77965_CLK_CL, CLK_PLL1_DIV2, 48, 1), + DEF_FIXED("cl", R8A77965_CLK_CL, CLK_PLL1_DIV2, 48, 1), + DEF_FIXED("cr", R8A77965_CLK_CR, CLK_PLL1_DIV4, 2, 1), DEF_FIXED("cp", R8A77965_CLK_CP, CLK_EXTAL, 2, 1), DEF_FIXED("cpex", R8A77965_CLK_CPEX, CLK_EXTAL, 2, 1), @@ -127,6 +128,7 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = { DEF_MOD("sys-dmac2", 217, R8A77965_CLK_S3D1), DEF_MOD("sys-dmac1", 218, R8A77965_CLK_S3D1), DEF_MOD("sys-dmac0", 219, R8A77965_CLK_S0D3), + DEF_MOD("sceg-pub", 229, R8A77965_CLK_CR), DEF_MOD("cmt3", 300, R8A77965_CLK_R), DEF_MOD("cmt2", 301, R8A77965_CLK_R), diff --git a/drivers/clk/renesas/r8a77990-cpg-mssr.c b/drivers/clk/renesas/r8a77990-cpg-mssr.c index ceabf55c21c2..8eda2e3e2480 100644 --- a/drivers/clk/renesas/r8a77990-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77990-cpg-mssr.c @@ -105,6 +105,7 @@ static const struct cpg_core_clk r8a77990_core_clks[] __initconst = { DEF_GEN3_SD("sd3", R8A77990_CLK_SD3, CLK_SDSRC, 0x026c), DEF_FIXED("cl", R8A77990_CLK_CL, CLK_PLL1, 48, 1), + DEF_FIXED("cr", R8A77990_CLK_CR, CLK_PLL1D2, 2, 1), DEF_FIXED("cp", R8A77990_CLK_CP, CLK_EXTAL, 2, 1), DEF_FIXED("cpex", R8A77990_CLK_CPEX, CLK_EXTAL, 4, 1), @@ -135,6 +136,7 @@ static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = { DEF_MOD("sys-dmac2", 217, R8A77990_CLK_S3D1), DEF_MOD("sys-dmac1", 218, R8A77990_CLK_S3D1), DEF_MOD("sys-dmac0", 219, R8A77990_CLK_S3D1), + DEF_MOD("sceg-pub", 229, R8A77990_CLK_CR), DEF_MOD("cmt3", 300, R8A77990_CLK_R), DEF_MOD("cmt2", 301, R8A77990_CLK_R), diff --git a/drivers/clk/renesas/r8a77995-cpg-mssr.c b/drivers/clk/renesas/r8a77995-cpg-mssr.c index 962bb337f2e7..056ebf3e70e2 100644 --- a/drivers/clk/renesas/r8a77995-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77995-cpg-mssr.c @@ -91,6 +91,7 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = { DEF_FIXED("s3d4", R8A77995_CLK_S3D4, CLK_S3, 4, 1), DEF_FIXED("cl", R8A77995_CLK_CL, CLK_PLL1, 48, 1), + DEF_FIXED("cr", R8A77995_CLK_CR, CLK_PLL1D2, 2, 1), DEF_FIXED("cp", R8A77995_CLK_CP, CLK_EXTAL, 2, 1), DEF_FIXED("cpex", R8A77995_CLK_CPEX, CLK_EXTAL, 4, 1), @@ -122,6 +123,7 @@ static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = { DEF_MOD("sys-dmac2", 217, R8A77995_CLK_S3D1), DEF_MOD("sys-dmac1", 218, R8A77995_CLK_S3D1), DEF_MOD("sys-dmac0", 219, R8A77995_CLK_S3D1), + DEF_MOD("sceg-pub", 229, R8A77995_CLK_CR), DEF_MOD("cmt3", 300, R8A77995_CLK_R), DEF_MOD("cmt2", 301, R8A77995_CLK_R), DEF_MOD("cmt1", 302, R8A77995_CLK_R), From 9e6f3b44dc75666bd1861f49aea0f8dfa8c67499 Mon Sep 17 00:00:00 2001 From: Dirk Behme Date: Mon, 3 Feb 2020 08:28:59 +0100 Subject: [PATCH 0052/4444] clk: renesas: r8a7795: Add RPC clocks Describe the RPCSRC internal clock and the RPC[D2] clocks derived from it, as well as the RPC-IF module clock, in the R-Car H3 (R8A7795) CPG/MSSR driver. Inspired by commit 94e3935b5756 ("clk: renesas: r8a77980: Add RPC clocks"). Signed-off-by: Dirk Behme Link: https://lore.kernel.org/r/20200203072901.31548-1-dirk.behme@de.bosch.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7795-cpg-mssr.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index fbc8c75f4314..ff5b3020cb03 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -44,6 +44,7 @@ enum clk_ids { CLK_S3, CLK_SDSRC, CLK_SSPSRC, + CLK_RPCSRC, CLK_RINT, /* Module Clocks */ @@ -70,6 +71,12 @@ static struct cpg_core_clk r8a7795_core_clks[] __initdata = { DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), + + DEF_BASE("rpc", R8A7795_CLK_RPC, CLK_TYPE_GEN3_RPC, + CLK_RPCSRC), + DEF_BASE("rpcd2", R8A7795_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, + R8A7795_CLK_RPC), DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), @@ -242,6 +249,7 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = { DEF_MOD("can-fd", 914, R8A7795_CLK_S3D2), DEF_MOD("can-if1", 915, R8A7795_CLK_S3D4), DEF_MOD("can-if0", 916, R8A7795_CLK_S3D4), + DEF_MOD("rpc-if", 917, R8A7795_CLK_RPCD2), DEF_MOD("i2c6", 918, R8A7795_CLK_S0D6), DEF_MOD("i2c5", 919, R8A7795_CLK_S0D6), DEF_MOD("i2c-dvfs", 926, R8A7795_CLK_CP), From 715286f51d13f125de6dbc13f2d707a7893bf95d Mon Sep 17 00:00:00 2001 From: Dirk Behme Date: Mon, 3 Feb 2020 08:29:00 +0100 Subject: [PATCH 0053/4444] clk: renesas: r8a7796: Add RPC clocks Describe the RPCSRC internal clock and the RPC[D2] clocks derived from it, as well as the RPC-IF module clock, in the R-Car M3-W/M3-W+ (R8A7796) CPG/MSSR driver. Inspired by commit 94e3935b5756 ("clk: renesas: r8a77980: Add RPC clocks"). Signed-off-by: Dirk Behme Link: https://lore.kernel.org/r/20200203072901.31548-2-dirk.behme@de.bosch.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7796-cpg-mssr.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index 1155d6636848..e8d466dbc7f9 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -46,6 +46,7 @@ enum clk_ids { CLK_S3, CLK_SDSRC, CLK_SSPSRC, + CLK_RPCSRC, CLK_RINT, /* Module Clocks */ @@ -72,6 +73,12 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = { DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), + + DEF_BASE("rpc", R8A7796_CLK_RPC, CLK_TYPE_GEN3_RPC, + CLK_RPCSRC), + DEF_BASE("rpcd2", R8A7796_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, + R8A7796_CLK_RPC), DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), @@ -217,6 +224,7 @@ static struct mssr_mod_clk r8a7796_mod_clks[] __initdata = { DEF_MOD("can-fd", 914, R8A7796_CLK_S3D2), DEF_MOD("can-if1", 915, R8A7796_CLK_S3D4), DEF_MOD("can-if0", 916, R8A7796_CLK_S3D4), + DEF_MOD("rpc-if", 917, R8A7796_CLK_RPCD2), DEF_MOD("i2c6", 918, R8A7796_CLK_S0D6), DEF_MOD("i2c5", 919, R8A7796_CLK_S0D6), DEF_MOD("i2c-dvfs", 926, R8A7796_CLK_CP), From 808eab15f39be1ed9502244d2aa4f35209f9d0d5 Mon Sep 17 00:00:00 2001 From: Dirk Behme Date: Mon, 3 Feb 2020 08:29:01 +0100 Subject: [PATCH 0054/4444] clk: renesas: r8a77965: Add RPC clocks Describe the RPCSRC internal clock and the RPC[D2] clocks derived from it, as well as the RPC-IF module clock, in the R-Car M3-N (R8A77965) CPG/MSSR driver. Inspired by commit 94e3935b5756 ("clk: renesas: r8a77980: Add RPC clocks"). Signed-off-by: Dirk Behme Link: https://lore.kernel.org/r/20200203072901.31548-3-dirk.behme@de.bosch.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a77965-cpg-mssr.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/clk/renesas/r8a77965-cpg-mssr.c b/drivers/clk/renesas/r8a77965-cpg-mssr.c index 9530480880f1..7a05a2fc1cc6 100644 --- a/drivers/clk/renesas/r8a77965-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77965-cpg-mssr.c @@ -43,6 +43,7 @@ enum clk_ids { CLK_S3, CLK_SDSRC, CLK_SSPSRC, + CLK_RPCSRC, CLK_RINT, /* Module Clocks */ @@ -68,6 +69,12 @@ static const struct cpg_core_clk r8a77965_core_clks[] __initconst = { DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), + + DEF_BASE("rpc", R8A77965_CLK_RPC, CLK_TYPE_GEN3_RPC, + CLK_RPCSRC), + DEF_BASE("rpcd2", R8A77965_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, + R8A77965_CLK_RPC), DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), @@ -217,6 +224,7 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = { DEF_MOD("can-fd", 914, R8A77965_CLK_S3D2), DEF_MOD("can-if1", 915, R8A77965_CLK_S3D4), DEF_MOD("can-if0", 916, R8A77965_CLK_S3D4), + DEF_MOD("rpc-if", 917, R8A77965_CLK_RPCD2), DEF_MOD("i2c6", 918, R8A77965_CLK_S0D6), DEF_MOD("i2c5", 919, R8A77965_CLK_S0D6), DEF_MOD("i2c-dvfs", 926, R8A77965_CLK_CP), From 264716935ed2c10adddbf6fe65214534346062fe Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 10 Jan 2020 14:19:15 +0100 Subject: [PATCH 0055/4444] pinctrl: sh-pfc: checker: Move data before code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure the checker to move all data definitions to the top, before the code. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20200110131927.1029-2-geert+renesas@glider.be --- drivers/pinctrl/sh-pfc/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index 82209116955b..a565effbff12 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -726,6 +726,9 @@ static int sh_pfc_suspend_init(struct sh_pfc *pfc) { return 0; } #endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */ #ifdef DEBUG +static unsigned int sh_pfc_errors __initdata = 0; +static unsigned int sh_pfc_warnings __initdata = 0; + static bool __init is0s(const u16 *enum_ids, unsigned int n) { unsigned int i; @@ -737,9 +740,6 @@ static bool __init is0s(const u16 *enum_ids, unsigned int n) return true; } -static unsigned int sh_pfc_errors __initdata = 0; -static unsigned int sh_pfc_warnings __initdata = 0; - static void __init sh_pfc_check_cfg_reg(const char *drvname, const struct pinmux_cfg_reg *cfg_reg) { From 41f3df3498de2d28ed5202adf736e14d4ff83b75 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 18 Oct 2019 19:13:19 +0200 Subject: [PATCH 0056/4444] ARM: dts: ux500: Fix up DSI controller nodes These nodes should be named dsi-controller@* so fix it up. Cc: Stephan Gerhold Signed-off-by: Linus Walleij --- arch/arm/boot/dts/ste-dbx5x0.dtsi | 6 +++--- arch/arm/boot/dts/ste-href-tvk1281618-r2.dtsi | 2 +- arch/arm/boot/dts/ste-href-tvk1281618-r3.dtsi | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi index 6671f74c9f03..3e10da3f8fd3 100644 --- a/arch/arm/boot/dts/ste-dbx5x0.dtsi +++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi @@ -1097,7 +1097,7 @@ ranges; status = "disabled"; - dsi0: dsi@a0351000 { + dsi0: dsi-controller@a0351000 { compatible = "ste,mcde-dsi"; reg = <0xa0351000 0x1000>; clocks = <&prcmu_clk PRCMU_DSI0CLK>, <&prcmu_clk PRCMU_DSI0ESCCLK>; @@ -1105,7 +1105,7 @@ #address-cells = <1>; #size-cells = <0>; }; - dsi1: dsi@a0352000 { + dsi1: dsi-controller@a0352000 { compatible = "ste,mcde-dsi"; reg = <0xa0352000 0x1000>; clocks = <&prcmu_clk PRCMU_DSI1CLK>, <&prcmu_clk PRCMU_DSI1ESCCLK>; @@ -1113,7 +1113,7 @@ #address-cells = <1>; #size-cells = <0>; }; - dsi2: dsi@a0353000 { + dsi2: dsi-controller@a0353000 { compatible = "ste,mcde-dsi"; reg = <0xa0353000 0x1000>; /* This DSI port only has the Low Power / Energy Save clock */ diff --git a/arch/arm/boot/dts/ste-href-tvk1281618-r2.dtsi b/arch/arm/boot/dts/ste-href-tvk1281618-r2.dtsi index e024520f4d47..de82b9db956f 100644 --- a/arch/arm/boot/dts/ste-href-tvk1281618-r2.dtsi +++ b/arch/arm/boot/dts/ste-href-tvk1281618-r2.dtsi @@ -66,7 +66,7 @@ mcde@a0350000 { status = "okay"; - dsi@a0351000 { + dsi-controller@a0351000 { panel { compatible = "samsung,s6d16d0"; reg = <0>; diff --git a/arch/arm/boot/dts/ste-href-tvk1281618-r3.dtsi b/arch/arm/boot/dts/ste-href-tvk1281618-r3.dtsi index cb3677f0a1cb..9f285c7cf914 100644 --- a/arch/arm/boot/dts/ste-href-tvk1281618-r3.dtsi +++ b/arch/arm/boot/dts/ste-href-tvk1281618-r3.dtsi @@ -45,7 +45,7 @@ mcde@a0350000 { status = "okay"; - dsi@a0351000 { + dsi-controller@a0351000 { panel { compatible = "sony,acx424akp"; reg = <0>; From ab7f98c0c5468b22931025e4cb4b0b1019f018c7 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 19 Jan 2020 20:11:38 +0100 Subject: [PATCH 0057/4444] ARM: dts: stm32: Add Ethernet0 RMII pins A pinmux entry on stm32mp1 Add pinmux entry for ethernet0 RMII . Signed-off-by: Marek Vasut Cc: Alexandre Torgue Cc: Maxime Coquelin Cc: Patrice Chotard Cc: Patrick Delaunay Cc: linux-stm32@st-md-mailman.stormreply.com To: linux-arm-kernel@lists.infradead.org Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp15-pinctrl.dtsi | 34 ++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi index 0237d4ddaa92..f40f66a692a1 100644 --- a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi +++ b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi @@ -162,6 +162,40 @@ }; }; + ethernet0_rmii_pins_a: rmii-0 { + pins1 { + pinmux = , /* ETH1_RMII_TXD0 */ + , /* ETH1_RMII_TXD1 */ + , /* ETH1_RMII_TX_EN */ + , /* ETH1_RMII_REF_CLK */ + , /* ETH1_MDIO */ + ; /* ETH1_MDC */ + bias-disable; + drive-push-pull; + slew-rate = <2>; + }; + pins2 { + pinmux = , /* ETH1_RMII_RXD0 */ + , /* ETH1_RMII_RXD1 */ + ; /* ETH1_RMII_CRS_DV */ + bias-disable; + }; + }; + + ethernet0_rmii_pins_sleep_a: rmii-sleep-0 { + pins1 { + pinmux = , /* ETH1_RMII_TXD0 */ + , /* ETH1_RMII_TXD1 */ + , /* ETH1_RMII_TX_EN */ + , /* ETH1_MDIO */ + , /* ETH1_MDC */ + , /* ETH1_RMII_RXD0 */ + , /* ETH1_RMII_RXD1 */ + , /* ETH1_RMII_REF_CLK */ + ; /* ETH1_RMII_CRS_DV */ + }; + }; + fmc_pins_a: fmc-0 { pins1 { pinmux = , /* FMC_NOE */ From 80ab128332ee78a0f16bb00a678bb39227f55466 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 19 Jan 2020 20:11:39 +0100 Subject: [PATCH 0058/4444] ARM: dts: stm32: Add SAI2A pins B pinmux entry on stm32mp1 Add pinmux entry for SAI2A with alternative pin configuration. This is useful in combination with sai2b_pins_b e.g. for codecs like SGTL5000. Signed-off-by: Marek Vasut Cc: Alexandre Torgue Cc: Maxime Coquelin Cc: Patrice Chotard Cc: Patrick Delaunay Cc: linux-stm32@st-md-mailman.stormreply.com To: linux-arm-kernel@lists.infradead.org Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp15-pinctrl.dtsi | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi index f40f66a692a1..2927a812bb26 100644 --- a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi +++ b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi @@ -719,6 +719,26 @@ }; }; + + sai2a_pins_b: sai2a-2 { + pins1 { + pinmux = , /* SAI2_SD_A */ + , /* SAI2_FS_A */ + ; /* SAI2_SCK_A */ + slew-rate = <0>; + drive-push-pull; + bias-disable; + }; + }; + + sai2a_sleep_pins_b: sai2a-sleep-3 { + pins { + pinmux = , /* SAI2_SD_A */ + , /* SAI2_FS_A */ + ; /* SAI2_SCK_A */ + }; + }; + sai2b_pins_a: sai2b-0 { pins1 { pinmux = , /* SAI2_SCK_B */ From 4d7c53a684da4ef7730016a75609a46c8e739a17 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 19 Jan 2020 20:11:40 +0100 Subject: [PATCH 0059/4444] ARM: dts: stm32: Add USART3 pins A pinmux entry on stm32mp1 Add pinmux for USART3. Signed-off-by: Marek Vasut Cc: Alexandre Torgue Cc: Maxime Coquelin Cc: Patrice Chotard Cc: Patrick Delaunay Cc: linux-stm32@st-md-mailman.stormreply.com To: linux-arm-kernel@lists.infradead.org Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp15-pinctrl.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi index 2927a812bb26..ac6fb333fee6 100644 --- a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi +++ b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi @@ -1054,6 +1054,19 @@ }; }; + usart3_pins_a: usart3-0 { + pins1 { + pinmux = ; /* USART3_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* USART3_RX */ + bias-disable; + }; + }; + uart4_pins_a: uart4-0 { pins1 { pinmux = ; /* UART4_TX */ From a7959919709e7ebe023eec362b8ae8db838588d4 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 19 Jan 2020 20:11:41 +0100 Subject: [PATCH 0060/4444] ARM: dts: stm32: Add UART8 pins A pinmux entry on stm32mp1 Add pinmux for UART8. Signed-off-by: Marek Vasut Cc: Alexandre Torgue Cc: Maxime Coquelin Cc: Patrice Chotard Cc: Patrick Delaunay Cc: linux-stm32@st-md-mailman.stormreply.com To: linux-arm-kernel@lists.infradead.org Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp15-pinctrl.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi index ac6fb333fee6..024a86e626b2 100644 --- a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi +++ b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi @@ -1107,6 +1107,19 @@ bias-disable; }; }; + + uart8_pins_a: uart8-0 { + pins1 { + pinmux = ; /* UART8_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART8_RX */ + bias-disable; + }; + }; }; &pinctrl_z { From 238086efd1499a890eb0ba2e7cd68236f141fbca Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 19 Jan 2020 20:11:42 +0100 Subject: [PATCH 0061/4444] ARM: dts: stm32: Add missing ETHCK clock to ethernet node on stm32mp1 Add missing 'eth-ck' clock to the ethernet node on stm32mp1. These clock are used to generate external clock signal for the PHY in case 'st,eth_ref_clk_sel' is specified. Signed-off-by: Marek Vasut Cc: Alexandre Torgue Cc: Christophe ROULLIER Cc: Maxime Coquelin Cc: Patrice Chotard Cc: Patrick Delaunay Cc: linux-stm32@st-md-mailman.stormreply.com To: linux-arm-kernel@lists.infradead.org Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp151.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp151.dtsi b/arch/arm/boot/dts/stm32mp151.dtsi index fb41d0778b00..e0ecc5ee7d83 100644 --- a/arch/arm/boot/dts/stm32mp151.dtsi +++ b/arch/arm/boot/dts/stm32mp151.dtsi @@ -1369,10 +1369,12 @@ clock-names = "stmmaceth", "mac-clk-tx", "mac-clk-rx", + "eth-ck", "ethstp"; clocks = <&rcc ETHMAC>, <&rcc ETHTX>, <&rcc ETHRX>, + <&rcc ETHCK_K>, <&rcc ETHSTP>; st,syscon = <&syscfg 0x4>; snps,mixed-burst; From 34e0c7847dcfb60e2d2ec568f7be7e25bb59df34 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 19 Jan 2020 20:11:43 +0100 Subject: [PATCH 0062/4444] ARM: dts: stm32: Add DH Electronics DHCOM STM32MP1 SoM and PDK2 board Add support for DH Electronics DHCOM SoM and PDK2 rev. 400 carrier board. This is an SoM with STM32MP157C and an evaluation kit. The baseboard provides Ethernet, UART, USB, CAN and optional display. Signed-off-by: Marek Vasut Cc: Alexandre Torgue Cc: Maxime Coquelin Cc: Patrice Chotard Cc: Patrick Delaunay Cc: linux-stm32@st-md-mailman.stormreply.com To: linux-arm-kernel@lists.infradead.org Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/stm32mp157c-dhcom-pdk2.dts | 265 +++++++++++++ arch/arm/boot/dts/stm32mp157c-dhcom-som.dtsi | 368 +++++++++++++++++++ 3 files changed, 634 insertions(+) create mode 100644 arch/arm/boot/dts/stm32mp157c-dhcom-pdk2.dts create mode 100644 arch/arm/boot/dts/stm32mp157c-dhcom-som.dtsi diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index d6546d2676b9..527bfa4a4240 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1016,6 +1016,7 @@ dtb-$(CONFIG_ARCH_STM32) += \ stm32h743i-disco.dtb \ stm32mp157a-avenger96.dtb \ stm32mp157a-dk1.dtb \ + stm32mp157c-dhcom-pdk2.dtb \ stm32mp157c-dk2.dtb \ stm32mp157c-ed1.dtb \ stm32mp157c-ev1.dtb diff --git a/arch/arm/boot/dts/stm32mp157c-dhcom-pdk2.dts b/arch/arm/boot/dts/stm32mp157c-dhcom-pdk2.dts new file mode 100644 index 000000000000..af99e132e1b1 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157c-dhcom-pdk2.dts @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2019 Marek Vasut + */ + +#include "stm32mp157c-dhcom-som.dtsi" +#include + +/ { + model = "STMicroelectronics STM32MP157C DHCOM Premium Developer Kit (2)"; + compatible = "dh,stm32mp157c-dhcom-pdk2", "st,stm32mp157"; + + aliases { + serial0 = &uart4; + serial1 = &usart3; + serial2 = &uart8; + ethernet0 = ðernet0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + clk_ext_audio_codec: clock-codec { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + }; + + display_bl: display-bl { + compatible = "pwm-backlight"; + pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>; + brightness-levels = <0 16 22 30 40 55 75 102 138 188 255>; + default-brightness-level = <8>; + enable-gpios = <&gpioi 0 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + ethernet_vio: vioregulator { + compatible = "regulator-fixed"; + regulator-name = "vio"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpiog 3 GPIO_ACTIVE_LOW>; + regulator-always-on; + regulator-boot-on; + }; + + panel { + compatible = "edt,etm0700g0edh6"; + backlight = <&display_bl>; + + port { + lcd_panel_in: endpoint { + remote-endpoint = <&lcd_display_out>; + }; + }; + }; + + sound { + compatible = "audio-graph-card"; + routing = + "MIC_IN", "Capture", + "Capture", "Mic Bias", + "Playback", "HP_OUT"; + dais = <&sai2a_port &sai2b_port>; + status = "okay"; + }; +}; + +&cec { + pinctrl-names = "default"; + pinctrl-0 = <&cec_pins_a>; + status = "okay"; +}; + +ðernet0 { + status = "okay"; + pinctrl-0 = <ðernet0_rmii_pins_a>; + pinctrl-1 = <ðernet0_rmii_pins_sleep_a>; + pinctrl-names = "default", "sleep"; + phy-mode = "rmii"; + max-speed = <100>; + phy-handle = <&phy0>; + st,eth-ref-clk-sel; + phy-reset-gpios = <&gpioh 15 GPIO_ACTIVE_LOW>; + + mdio0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + + phy0: ethernet-phy@1 { + reg = <1>; + }; + }; +}; + +&i2c5 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c5_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + /* spare dmas for other usage */ + /delete-property/dmas; + /delete-property/dma-names; + + sgtl5000: codec@a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + #sound-dai-cells = <0>; + clocks = <&clk_ext_audio_codec>; + VDDA-supply = <&v3v3>; + VDDIO-supply = <&vdd>; + + sgtl5000_port: port { + #address-cells = <1>; + #size-cells = <0>; + + sgtl5000_tx_endpoint: endpoint@0 { + reg = <0>; + remote-endpoint = <&sai2a_endpoint>; + frame-master; + bitclock-master; + }; + + sgtl5000_rx_endpoint: endpoint@1 { + reg = <1>; + remote-endpoint = <&sai2b_endpoint>; + frame-master; + bitclock-master; + }; + }; + + }; + + polytouch@38 { + compatible = "edt,edt-ft5x06"; + reg = <0x38>; + interrupt-parent = <&gpiog>; + interrupts = <2 IRQ_TYPE_EDGE_FALLING>; /* GPIO E */ + linux,wakeup; + }; +}; + +<dc { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <<dc_pins_b>; + pinctrl-1 = <<dc_pins_sleep_b>; + status = "okay"; + + port { + lcd_display_out: endpoint { + remote-endpoint = <&lcd_panel_in>; + }; + }; +}; + +&m_can1 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&m_can1_pins_a>; + pinctrl-1 = <&m_can1_sleep_pins_a>; + status = "okay"; +}; + +&sai2 { + clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>; + clock-names = "pclk", "x8k", "x11k"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sai2a_pins_b &sai2b_pins_b>; + pinctrl-1 = <&sai2a_sleep_pins_b &sai2b_sleep_pins_b>; + status = "okay"; + + sai2a: audio-controller@4400b004 { + #clock-cells = <0>; + dma-names = "tx"; + clocks = <&rcc SAI2_K>; + clock-names = "sai_ck"; + status = "okay"; + + sai2a_port: port { + sai2a_endpoint: endpoint { + remote-endpoint = <&sgtl5000_tx_endpoint>; + format = "i2s"; + mclk-fs = <512>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <16>; + }; + }; + }; + + sai2b: audio-controller@4400b024 { + dma-names = "rx"; + st,sync = <&sai2a 2>; + clocks = <&rcc SAI2_K>, <&sai2a>; + clock-names = "sai_ck", "MCLK"; + status = "okay"; + + sai2b_port: port { + sai2b_endpoint: endpoint { + remote-endpoint = <&sgtl5000_rx_endpoint>; + format = "i2s"; + mclk-fs = <512>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <16>; + }; + }; + }; +}; + +&timers2 { + /* spare dmas for other usage (un-delete to enable pwm capture) */ + /delete-property/dmas; + /delete-property/dma-names; + status = "okay"; + pwm2: pwm { + pinctrl-0 = <&pwm2_pins_a>; + pinctrl-names = "default"; + status = "okay"; + }; + timer@1 { + status = "okay"; + }; +}; + +&usart3 { + pinctrl-names = "default"; + pinctrl-0 = <&usart3_pins_a>; + status = "okay"; +}; + +&uart8 { + pinctrl-names = "default"; + pinctrl-0 = <&uart8_pins_a>; + status = "okay"; +}; + +&usbh_ehci { + phys = <&usbphyc_port0>; + status = "okay"; +}; + +&usbotg_hs { + dr_mode = "peripheral"; + phys = <&usbphyc_port1 0>; + phy-names = "usb2-phy"; + status = "okay"; +}; + +&usbphyc { + status = "okay"; +}; + +&usbphyc_port0 { + phy-supply = <&vdd_usb>; + vdda1v1-supply = <®11>; + vdda1v8-supply = <®18>; +}; + +&usbphyc_port1 { + phy-supply = <&vdd_usb>; + vdda1v1-supply = <®11>; + vdda1v8-supply = <®18>; +}; diff --git a/arch/arm/boot/dts/stm32mp157c-dhcom-som.dtsi b/arch/arm/boot/dts/stm32mp157c-dhcom-som.dtsi new file mode 100644 index 000000000000..f81dc3134135 --- /dev/null +++ b/arch/arm/boot/dts/stm32mp157c-dhcom-som.dtsi @@ -0,0 +1,368 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) 2019 Marek Vasut + */ +/dts-v1/; + +#include "stm32mp157.dtsi" +#include "stm32mp15xc.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxaa-pinctrl.dtsi" +#include +#include + +/ { + memory@c0000000 { + device_type = "memory"; + reg = <0xC0000000 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + mcuram2: mcuram2@10000000 { + compatible = "shared-dma-pool"; + reg = <0x10000000 0x40000>; + no-map; + }; + + vdev0vring0: vdev0vring0@10040000 { + compatible = "shared-dma-pool"; + reg = <0x10040000 0x1000>; + no-map; + }; + + vdev0vring1: vdev0vring1@10041000 { + compatible = "shared-dma-pool"; + reg = <0x10041000 0x1000>; + no-map; + }; + + vdev0buffer: vdev0buffer@10042000 { + compatible = "shared-dma-pool"; + reg = <0x10042000 0x4000>; + no-map; + }; + + mcuram: mcuram@30000000 { + compatible = "shared-dma-pool"; + reg = <0x30000000 0x40000>; + no-map; + }; + + retram: retram@38000000 { + compatible = "shared-dma-pool"; + reg = <0x38000000 0x10000>; + no-map; + }; + }; +}; + +&adc { + vdd-supply = <&vdd>; + vdda-supply = <&vdda>; + vref-supply = <&vdda>; + status = "okay"; + + adc1: adc@0 { + st,min-sample-time-nsecs = <5000>; + st,adc-channels = <0>; + status = "okay"; + }; + + adc2: adc@100 { + st,adc-channels = <1>; + st,min-sample-time-nsecs = <5000>; + status = "okay"; + }; +}; + +&dac { + pinctrl-names = "default"; + pinctrl-0 = <&dac_ch1_pins_a &dac_ch2_pins_a>; + vref-supply = <&vdda>; + status = "okay"; + + dac1: dac@1 { + status = "okay"; + }; + dac2: dac@2 { + status = "okay"; + }; +}; + +&dts { + status = "okay"; +}; + +&gpu { + status = "okay"; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + /* spare dmas for other usage */ + /delete-property/dmas; + /delete-property/dma-names; + + rtc@32 { + compatible = "microcrystal,rv8803"; + reg = <0x32>; + }; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; + + regulators { + compatible = "st,stpmic1-regulators"; + ldo1-supply = <&v3v3>; + ldo2-supply = <&v3v3>; + ldo3-supply = <&vdd_ddr>; + ldo5-supply = <&v3v3>; + ldo6-supply = <&v3v3>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; + }; + + vdda: ldo1 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + interrupts = ; + }; + + v2v8: ldo2 { + regulator-name = "v2v8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + interrupts = ; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + interrupts = ; + }; + + vdd_sd: ldo5 { + regulator-name = "vdd_sd"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + interrupts = ; + regulator-boot-on; + }; + + v1v8: ldo6 { + regulator-name = "v1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + interrupts = ; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + regulator-over-current-protection; + }; + + bst_out: boost { + regulator-name = "bst_out"; + interrupts = ; + }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + interrupts = ; + }; + + vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + interrupts = ; + regulator-active-discharge; + }; + }; + + onkey { + compatible = "st,stpmic1-onkey"; + interrupts = , ; + interrupt-names = "onkey-falling", "onkey-rising"; + power-off-time-sec = <10>; + status = "okay"; + }; + + watchdog { + compatible = "st,stpmic1-wdt"; + status = "disabled"; + }; + }; + + touchscreen@49 { + compatible = "ti,tsc2004"; + reg = <0x49>; + vio-supply = <&v3v3>; + interrupts-extended = <&gpioh 3 IRQ_TYPE_EDGE_FALLING>; + }; + + eeprom@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + pagesize = <16>; + }; +}; + +&ipcc { + status = "okay"; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; +}; + +&m4_rproc { + memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, + <&vdev0vring1>, <&vdev0buffer>; + mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>; + mbox-names = "vq0", "vq1", "shutdown"; + interrupt-parent = <&exti>; + interrupts = <68 1>; + status = "okay"; +}; + +&pwr_regulators { + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; +}; + +&qspi { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>; + pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a &qspi_bk2_sleep_pins_a>; + reg = <0x58003000 0x1000>, <0x70000000 0x4000000>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + flash0: mx66l51235l@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-rx-bus-width = <4>; + spi-max-frequency = <108000000>; + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&rng1 { + status = "okay"; +}; + +&rtc { + status = "okay"; +}; + +&sdmmc1 { + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; + pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_a>; + pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_a>; + broken-cd; + st,sig-dir; + st,neg-edge; + st,use-ckin; + bus-width = <4>; + vmmc-supply = <&vdd_sd>; + status = "okay"; +}; + +&sdmmc2 { + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>; + pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_a>; + pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_a>; + non-removable; + no-sd; + no-sdio; + st,neg-edge; + bus-width = <8>; + vmmc-supply = <&v3v3>; + vqmmc-supply = <&v3v3>; + mmc-ddr-3_3v; + status = "okay"; +}; + +&sdmmc3 { + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc3_b4_pins_a>; + pinctrl-1 = <&sdmmc3_b4_od_pins_a>; + pinctrl-2 = <&sdmmc3_b4_sleep_pins_a>; + broken-cd; + st,neg-edge; + bus-width = <4>; + vmmc-supply = <&v3v3>; + vqmmc-supply = <&v3v3>; + mmc-ddr-3_3v; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_a>; + status = "okay"; +}; From 8714b26e28630b77faf824574b5b1350cc41c945 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Thu, 30 Jan 2020 14:53:04 +0100 Subject: [PATCH 0063/4444] ARM: dts: stm32: remove useless properties in stm32mp157a-avenger96 stmpic node Theses 3 properties are not coded in driver so remove them from the DTS. Signed-off-by: Benjamin Gaignard Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157a-avenger96.dts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm/boot/dts/stm32mp157a-avenger96.dts b/arch/arm/boot/dts/stm32mp157a-avenger96.dts index cbfa4075907e..4a658a797eef 100644 --- a/arch/arm/boot/dts/stm32mp157a-avenger96.dts +++ b/arch/arm/boot/dts/stm32mp157a-avenger96.dts @@ -135,10 +135,6 @@ #interrupt-cells = <2>; status = "okay"; - st,main-control-register = <0x04>; - st,vin-control-register = <0xc0>; - st,usb-control-register = <0x30>; - regulators { compatible = "st,stpmic1-regulators"; From 82ac8a81f985ad6a05c3f39aedb275eafbc40d3e Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Tue, 4 Feb 2020 14:26:04 +0100 Subject: [PATCH 0064/4444] ARM: dts: stm32: add USB OTG full support on stm32mp151 Using the st,stm32mp15-hsotg compatible allows to use USB OTG with Dual Role mode support. Signed-off-by: Amelie Delaunay Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp151.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/stm32mp151.dtsi b/arch/arm/boot/dts/stm32mp151.dtsi index e0ecc5ee7d83..12cbcdaa3bca 100644 --- a/arch/arm/boot/dts/stm32mp151.dtsi +++ b/arch/arm/boot/dts/stm32mp151.dtsi @@ -1044,7 +1044,7 @@ }; usbotg_hs: usb-otg@49000000 { - compatible = "snps,dwc2"; + compatible = "st,stm32mp15-hsotg", "snps,dwc2"; reg = <0x49000000 0x10000>; clocks = <&rcc USBO_K>; clock-names = "otg"; @@ -1055,6 +1055,7 @@ g-np-tx-fifo-size = <32>; g-tx-fifo-size = <128 128 64 64 64 64 32 32>; dr_mode = "otg"; + usb33d-supply = <&usb33>; status = "disabled"; }; From 9879e2165758933caa3b4a3803432e9a9d602961 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Tue, 4 Feb 2020 14:26:05 +0100 Subject: [PATCH 0065/4444] ARM: dts: stm32: add USB OTG pinctrl to stm32mp15 Add pinctrl definition for USB High-Speed OTG ID pin and USB Full-Speed OTG DP and DM lines that can be used on stm32mp15. Signed-off-by: Amelie Delaunay Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp15-pinctrl.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi index 024a86e626b2..73c07f0dfad2 100644 --- a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi +++ b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi @@ -1120,6 +1120,19 @@ bias-disable; }; }; + + usbotg_hs_pins_a: usbotg-hs-0 { + pins { + pinmux = ; /* OTG_ID */ + }; + }; + + usbotg_fs_dp_dm_pins_a: usbotg-fs-dp-dm-0 { + pins { + pinmux = , /* OTG_FS_DM */ + ; /* OTG_FS_DP */ + }; + }; }; &pinctrl_z { From c5fae093511b4a5cf9f1e3a0e9e472424c85b521 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Tue, 4 Feb 2020 14:26:06 +0100 Subject: [PATCH 0066/4444] ARM: dts: stm32: enable USB OTG Dual Role on stm32mp157c-ev1 Now that st,stm32mp15-hsotg is used, dual role is supported. ID pin is managed to detect the current role. On stm32mp157c-ev1, Host mode requires a vbus-supply property. Charge pump for vbus is provided by PMIC VBUS_OTG. Signed-off-by: Amelie Delaunay Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157c-ed1.dts | 4 ++++ arch/arm/boot/dts/stm32mp157c-ev1.dts | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/stm32mp157c-ed1.dts index 1fc43251d697..c84f14b17371 100644 --- a/arch/arm/boot/dts/stm32mp157c-ed1.dts +++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts @@ -355,6 +355,10 @@ status = "okay"; }; +&usbotg_hs { + vbus-supply = <&vbus_otg>; +}; + &usbphyc_port0 { phy-supply = <&vdd_usb>; vdda1v1-supply = <®11>; diff --git a/arch/arm/boot/dts/stm32mp157c-ev1.dts b/arch/arm/boot/dts/stm32mp157c-ev1.dts index 228e35e16884..8f1fe0781d9f 100644 --- a/arch/arm/boot/dts/stm32mp157c-ev1.dts +++ b/arch/arm/boot/dts/stm32mp157c-ev1.dts @@ -353,7 +353,8 @@ }; &usbotg_hs { - dr_mode = "peripheral"; + pinctrl-0 = <&usbotg_hs_pins_a>; + pinctrl-names = "default"; phys = <&usbphyc_port1 0>; phy-names = "usb2-phy"; status = "okay"; From cc775a83db657def8b0329da27467ae2188593a8 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Tue, 4 Feb 2020 15:10:53 +0100 Subject: [PATCH 0067/4444] ARM: dts: stm32: add resets property on all DMA nodes on stm32mp151 resets property is well-managed in DMA drivers. In previous products, there were no reset lines, that's why they are missing here in dma1, dma2, dmamux and mdma nodes. Signed-off-by: Amelie Delaunay Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp151.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp151.dtsi b/arch/arm/boot/dts/stm32mp151.dtsi index 12cbcdaa3bca..938e7fd58621 100644 --- a/arch/arm/boot/dts/stm32mp151.dtsi +++ b/arch/arm/boot/dts/stm32mp151.dtsi @@ -959,6 +959,7 @@ , ; clocks = <&rcc DMA1>; + resets = <&rcc DMA1_R>; #dma-cells = <4>; st,mem2mem; dma-requests = <8>; @@ -976,6 +977,7 @@ , ; clocks = <&rcc DMA2>; + resets = <&rcc DMA2_R>; #dma-cells = <4>; st,mem2mem; dma-requests = <8>; @@ -989,6 +991,7 @@ dma-masters = <&dma1 &dma2>; dma-channels = <16>; clocks = <&rcc DMAMUX>; + resets = <&rcc DMAMUX_R>; }; adc: adc@48003000 { @@ -1281,6 +1284,7 @@ reg = <0x58000000 0x1000>; interrupts = ; clocks = <&rcc MDMA>; + resets = <&rcc MDMA_R>; #dma-cells = <5>; dma-channels = <32>; dma-requests = <48>; From 8ab014ce5eaf13d9f701130944cf381555c050f1 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Mon, 10 Feb 2020 14:43:30 +0100 Subject: [PATCH 0068/4444] ARM: dts: stm32: Correct stmfx node name on stm32746g-eval board Change stmfx node name to fit with yaml requirements. Signed-off-by: Benjamin Gaignard Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32746g-eval.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/stm32746g-eval.dts b/arch/arm/boot/dts/stm32746g-eval.dts index fcc804e3c158..4ea3f98dd275 100644 --- a/arch/arm/boot/dts/stm32746g-eval.dts +++ b/arch/arm/boot/dts/stm32746g-eval.dts @@ -165,7 +165,7 @@ interrupts = <8 IRQ_TYPE_EDGE_RISING>; interrupt-parent = <&gpioi>; - stmfx_pinctrl: stmfx-pin-controller { + stmfx_pinctrl: pinctrl { compatible = "st,stmfx-0300-pinctrl"; gpio-controller; #gpio-cells = <2>; From fccd6a577bb334286a8eac73b9ccdb01cacbb859 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Mon, 10 Feb 2020 14:43:31 +0100 Subject: [PATCH 0069/4444] ARM: dts: stm32: Correct stmfx node name on stm32mp157c-ev1 board Change stmfx node name to fit with yaml requirements. Signed-off-by: Benjamin Gaignard Signed-off-by: Alexandre Torgue --- arch/arm/boot/dts/stm32mp157c-ev1.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/stm32mp157c-ev1.dts b/arch/arm/boot/dts/stm32mp157c-ev1.dts index 8f1fe0781d9f..82ae94d8fc28 100644 --- a/arch/arm/boot/dts/stm32mp157c-ev1.dts +++ b/arch/arm/boot/dts/stm32mp157c-ev1.dts @@ -210,7 +210,7 @@ interrupt-parent = <&gpioi>; vdd-supply = <&v3v3>; - stmfx_pinctrl: stmfx-pin-controller { + stmfx_pinctrl: pinctrl { compatible = "st,stmfx-0300-pinctrl"; gpio-controller; #gpio-cells = <2>; From e77a63a7424dba472e92b6d99bda381cb5b28d74 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 21 Jan 2020 11:37:07 +0100 Subject: [PATCH 0070/4444] ARM: at91: Drop unneeded select of COMMON_CLK Support for AT91/Microchip SoCs depends on ARCH_MULTIPLATFORM or ARM_SINGLE_ARMV7M, which both select COMMON_CLK. Hence there is no need for COMMON_CLK_AT91 to select COMMON_CLK. Signed-off-by: Geert Uytterhoeven Cc: Nicolas Ferre Cc: Alexandre Belloni Cc: Ludovic Desroches Link: https://lore.kernel.org/r/20200121103722.1781-5-geert+renesas@glider.be Signed-off-by: Alexandre Belloni --- arch/arm/mach-at91/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 7979420bd48b..ccd7e80ce943 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -153,7 +153,6 @@ config HAVE_AT91_USB_CLK config COMMON_CLK_AT91 bool - select COMMON_CLK select MFD_SYSCON config HAVE_AT91_SMD From ec2daf6e33f9f9113ba085b6ff88592907b6f1ce Mon Sep 17 00:00:00 2001 From: Jon Flatley Date: Fri, 24 Jan 2020 15:18:32 -0800 Subject: [PATCH 0071/4444] platform: chrome: Add cros-usbpd-notify driver ChromiumOS uses ACPI device with HID "GOOG0003" for power delivery related events. The existing cros-usbpd-charger driver relies on these events without ever actually receiving them on ACPI platforms. This is because in the ChromeOS kernel trees, the GOOG0003 device is owned by an ACPI driver that offers firmware updates to USB-C chargers. Introduce a new platform driver under cros-ec, the ChromeOS embedded controller, that handles these PD events and dispatches them appropriately over a notifier chain to all drivers that use them. On platforms that don't have the ACPI device defined, the driver gets instantiated for ECs which support the EC_FEATURE_USB_PD feature bit, and the notification events will get delivered using the MKBP event handling mechanism. Co-Developed-by: Prashant Malani Reviewed-by: Gwendal Grignou Reviewed-by: Benson Leung Signed-off-by: Jon Flatley Signed-off-by: Prashant Malani Acked-By: Enric Balletbo i Serra Signed-off-by: Benson Leung --- drivers/platform/chrome/Kconfig | 14 ++ drivers/platform/chrome/Makefile | 1 + drivers/platform/chrome/cros_usbpd_notify.c | 169 ++++++++++++++++++ .../linux/platform_data/cros_usbpd_notify.h | 17 ++ 4 files changed, 201 insertions(+) create mode 100644 drivers/platform/chrome/cros_usbpd_notify.c create mode 100644 include/linux/platform_data/cros_usbpd_notify.h diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig index 5f57282a28da..15fc8b8a2db8 100644 --- a/drivers/platform/chrome/Kconfig +++ b/drivers/platform/chrome/Kconfig @@ -226,6 +226,20 @@ config CROS_USBPD_LOGGER To compile this driver as a module, choose M here: the module will be called cros_usbpd_logger. +config CROS_USBPD_NOTIFY + tristate "ChromeOS Type-C power delivery event notifier" + depends on MFD_CROS_EC_DEV + default MFD_CROS_EC_DEV + help + If you say Y here, you get support for Type-C PD event notifications + from the ChromeOS EC. On ACPI platorms this driver will bind to the + GOOG0003 ACPI device, and on platforms which don't have this device it + will get initialized on ECs which support the feature + EC_FEATURE_USB_PD. + + To compile this driver as a module, choose M here: the + module will be called cros_usbpd_notify. + source "drivers/platform/chrome/wilco_ec/Kconfig" endif # CHROMEOS_PLATFORMS diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile index aacd5920d8a1..f6465f8ef0b5 100644 --- a/drivers/platform/chrome/Makefile +++ b/drivers/platform/chrome/Makefile @@ -22,5 +22,6 @@ obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o obj-$(CONFIG_CROS_EC_SENSORHUB) += cros_ec_sensorhub.o obj-$(CONFIG_CROS_EC_SYSFS) += cros_ec_sysfs.o obj-$(CONFIG_CROS_USBPD_LOGGER) += cros_usbpd_logger.o +obj-$(CONFIG_CROS_USBPD_NOTIFY) += cros_usbpd_notify.o obj-$(CONFIG_WILCO_EC) += wilco_ec/ diff --git a/drivers/platform/chrome/cros_usbpd_notify.c b/drivers/platform/chrome/cros_usbpd_notify.c new file mode 100644 index 000000000000..3851bbd6e9a3 --- /dev/null +++ b/drivers/platform/chrome/cros_usbpd_notify.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2020 Google LLC + * + * This driver serves as the receiver of cros_ec PD host events. + */ + +#include +#include +#include +#include +#include + +#define DRV_NAME "cros-usbpd-notify" +#define ACPI_DRV_NAME "GOOG0003" + +static BLOCKING_NOTIFIER_HEAD(cros_usbpd_notifier_list); + +/** + * cros_usbpd_register_notify - Register a notifier callback for PD events. + * @nb: Notifier block pointer to register + * + * On ACPI platforms this corresponds to host events on the ECPD + * "GOOG0003" ACPI device. On non-ACPI platforms this will filter mkbp events + * for USB PD events. + * + * Return: 0 on success or negative error code. + */ +int cros_usbpd_register_notify(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&cros_usbpd_notifier_list, + nb); +} +EXPORT_SYMBOL_GPL(cros_usbpd_register_notify); + +/** + * cros_usbpd_unregister_notify - Unregister notifier callback for PD events. + * @nb: Notifier block pointer to unregister + * + * Unregister a notifier callback that was previously registered with + * cros_usbpd_register_notify(). + */ +void cros_usbpd_unregister_notify(struct notifier_block *nb) +{ + blocking_notifier_chain_unregister(&cros_usbpd_notifier_list, nb); +} +EXPORT_SYMBOL_GPL(cros_usbpd_unregister_notify); + +#ifdef CONFIG_ACPI + +static int cros_usbpd_notify_add_acpi(struct acpi_device *adev) +{ + return 0; +} + +static void cros_usbpd_notify_acpi(struct acpi_device *adev, u32 event) +{ + blocking_notifier_call_chain(&cros_usbpd_notifier_list, event, NULL); +} + +static const struct acpi_device_id cros_usbpd_notify_acpi_device_ids[] = { + { ACPI_DRV_NAME, 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, cros_usbpd_notify_acpi_device_ids); + +static struct acpi_driver cros_usbpd_notify_acpi_driver = { + .name = DRV_NAME, + .class = DRV_NAME, + .ids = cros_usbpd_notify_acpi_device_ids, + .ops = { + .add = cros_usbpd_notify_add_acpi, + .notify = cros_usbpd_notify_acpi, + }, +}; + +#endif /* CONFIG_ACPI */ + +static int cros_usbpd_notify_plat(struct notifier_block *nb, + unsigned long queued_during_suspend, + void *data) +{ + struct cros_ec_device *ec_dev = (struct cros_ec_device *)data; + u32 host_event = cros_ec_get_host_event(ec_dev); + + if (!host_event) + return NOTIFY_BAD; + + if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_PD_MCU)) { + blocking_notifier_call_chain(&cros_usbpd_notifier_list, + host_event, NULL); + return NOTIFY_OK; + } + return NOTIFY_DONE; +} + +static int cros_usbpd_notify_probe_plat(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct cros_ec_dev *ecdev = dev_get_drvdata(dev->parent); + struct notifier_block *nb; + int ret; + + nb = devm_kzalloc(dev, sizeof(*nb), GFP_KERNEL); + if (!nb) + return -ENOMEM; + + nb->notifier_call = cros_usbpd_notify_plat; + dev_set_drvdata(dev, nb); + + ret = blocking_notifier_chain_register(&ecdev->ec_dev->event_notifier, + nb); + if (ret < 0) { + dev_err(dev, "Failed to register notifier\n"); + return ret; + } + + return 0; +} + +static int cros_usbpd_notify_remove_plat(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct cros_ec_dev *ecdev = dev_get_drvdata(dev->parent); + struct notifier_block *nb = + (struct notifier_block *)dev_get_drvdata(dev); + + blocking_notifier_chain_unregister(&ecdev->ec_dev->event_notifier, nb); + + return 0; +} + +static struct platform_driver cros_usbpd_notify_plat_driver = { + .driver = { + .name = DRV_NAME, + }, + .probe = cros_usbpd_notify_probe_plat, + .remove = cros_usbpd_notify_remove_plat, +}; + +static int __init cros_usbpd_notify_init(void) +{ + int ret; + + ret = platform_driver_register(&cros_usbpd_notify_plat_driver); + if (ret < 0) + return ret; + +#ifdef CONFIG_ACPI + acpi_bus_register_driver(&cros_usbpd_notify_acpi_driver); +#endif + return 0; +} + +static void __exit cros_usbpd_notify_exit(void) +{ +#ifdef CONFIG_ACPI + acpi_bus_unregister_driver(&cros_usbpd_notify_acpi_driver); +#endif + platform_driver_unregister(&cros_usbpd_notify_plat_driver); +} + +module_init(cros_usbpd_notify_init); +module_exit(cros_usbpd_notify_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ChromeOS power delivery notifier device"); +MODULE_AUTHOR("Jon Flatley "); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/include/linux/platform_data/cros_usbpd_notify.h b/include/linux/platform_data/cros_usbpd_notify.h new file mode 100644 index 000000000000..4f2791722b6d --- /dev/null +++ b/include/linux/platform_data/cros_usbpd_notify.h @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * ChromeOS EC Power Delivery Notifier Driver + * + * Copyright 2020 Google LLC + */ + +#ifndef __LINUX_PLATFORM_DATA_CROS_USBPD_NOTIFY_H +#define __LINUX_PLATFORM_DATA_CROS_USBPD_NOTIFY_H + +#include + +int cros_usbpd_register_notify(struct notifier_block *nb); + +void cros_usbpd_unregister_notify(struct notifier_block *nb); + +#endif /* __LINUX_PLATFORM_DATA_CROS_USBPD_NOTIFY_H */ From f2437e48ac7ae0e99b8e76d88aaf24a9b2e6d3e2 Mon Sep 17 00:00:00 2001 From: Jon Flatley Date: Fri, 24 Jan 2020 15:18:38 -0800 Subject: [PATCH 0072/4444] power: supply: cros-ec-usbpd-charger: Fix host events There's a bug on ACPI platforms where host events from the ECPD ACPI device never make their way to the cros-ec-usbpd-charger driver. This makes it so the only time the charger driver updates its state is when user space accesses its sysfs attributes. Now that these events have been unified into a single notifier chain on both ACPI and non-ACPI platforms, update the charger driver to use this new notifier. Reviewed-by: Benson Leung Co-Developed-by: Prashant Malani Signed-off-by: Jon Flatley Signed-off-by: Prashant Malani Reviewed-by: Sebastian Reichel Signed-off-by: Benson Leung --- drivers/power/supply/Kconfig | 2 +- drivers/power/supply/cros_usbpd-charger.c | 50 ++++++++--------------- 2 files changed, 19 insertions(+), 33 deletions(-) diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index 9a5591ab90d0..a6e191b4ff48 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -659,7 +659,7 @@ config CHARGER_RT9455 config CHARGER_CROS_USBPD tristate "ChromeOS EC based USBPD charger" - depends on CROS_EC + depends on CROS_USBPD_NOTIFY default n help Say Y here to enable ChromeOS EC based USBPD charger diff --git a/drivers/power/supply/cros_usbpd-charger.c b/drivers/power/supply/cros_usbpd-charger.c index 30c3d37511c9..2a45e84447fe 100644 --- a/drivers/power/supply/cros_usbpd-charger.c +++ b/drivers/power/supply/cros_usbpd-charger.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -517,32 +518,21 @@ static int cros_usbpd_charger_property_is_writeable(struct power_supply *psy, } static int cros_usbpd_charger_ec_event(struct notifier_block *nb, - unsigned long queued_during_suspend, + unsigned long host_event, void *_notify) { - struct cros_ec_device *ec_device; - struct charger_data *charger; - u32 host_event; + struct charger_data *charger = container_of(nb, struct charger_data, + notifier); - charger = container_of(nb, struct charger_data, notifier); - ec_device = charger->ec_device; - - host_event = cros_ec_get_host_event(ec_device); - if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_PD_MCU)) { - cros_usbpd_charger_power_changed(charger->ports[0]->psy); - return NOTIFY_OK; - } else { - return NOTIFY_DONE; - } + cros_usbpd_charger_power_changed(charger->ports[0]->psy); + return NOTIFY_OK; } static void cros_usbpd_charger_unregister_notifier(void *data) { struct charger_data *charger = data; - struct cros_ec_device *ec_device = charger->ec_device; - blocking_notifier_chain_unregister(&ec_device->event_notifier, - &charger->notifier); + cros_usbpd_unregister_notify(&charger->notifier); } static int cros_usbpd_charger_probe(struct platform_device *pd) @@ -676,21 +666,17 @@ static int cros_usbpd_charger_probe(struct platform_device *pd) goto fail; } - if (ec_device->mkbp_event_supported) { - /* Get PD events from the EC */ - charger->notifier.notifier_call = cros_usbpd_charger_ec_event; - ret = blocking_notifier_chain_register( - &ec_device->event_notifier, - &charger->notifier); - if (ret < 0) { - dev_warn(dev, "failed to register notifier\n"); - } else { - ret = devm_add_action_or_reset(dev, - cros_usbpd_charger_unregister_notifier, - charger); - if (ret < 0) - goto fail; - } + /* Get PD events from the EC */ + charger->notifier.notifier_call = cros_usbpd_charger_ec_event; + ret = cros_usbpd_register_notify(&charger->notifier); + if (ret < 0) { + dev_warn(dev, "failed to register notifier\n"); + } else { + ret = devm_add_action_or_reset(dev, + cros_usbpd_charger_unregister_notifier, + charger); + if (ret < 0) + goto fail; } return 0; From b9631bc2013479ca52c42d1f2cea9051abe9828e Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 31 Jan 2020 11:37:09 +0100 Subject: [PATCH 0073/4444] ARM: dts: exynos: Fix broken reboot on some Odroid U2/X2/U3 boards The bootloader on Odroid U2/X2/U3 boards configures main ARM clock to 1GHz. During the system shutdown procedure Linux kernel selects so called 'suspend-opp' for the CPU cores, what means that ARM clock is set to 800MHz and the CPU supply voltage is adjusted to that value. PMIC configuration is preserved during the board reboot. Later when the bootloader tries to enter the 1GHz mode, the voltage value configured by the kernel might be not high enough for the CPU to operate stable. This depends on the individual physical properties of each SoC (usually it is related to the production series) and varies between the boards. Typically most of the Odroid U3 boards work fine, while most of the U2 and X2 hangs during the reboot. This commit switches suspend-opp to 1GHz for the Odroid U2/X2/U3 boards, what finally fixes this issue. Signed-off-by: Marek Szyprowski Tested-by: Andrzej Pietrasiewicz Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos4412-odroid-common.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi index 9c39e82e4ecb..73d6a71da88d 100644 --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi @@ -165,6 +165,15 @@ cpu0-supply = <&buck2_reg>; }; +&cpu0_opp_table { + opp-1000000000 { + opp-suspend; + }; + opp-800000000 { + /delete-property/opp-suspend; + }; +}; + &pinctrl_1 { gpio_power_key: power_key { samsung,pins = "gpx1-3"; From 1c651356f482ff08f6acef197a362f2e71d55a98 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 21 Jan 2020 08:05:10 +0100 Subject: [PATCH 0074/4444] ARM: dts: exynos: Add GPU thermal zone cooling maps for Odroid XU3/XU4/HC1 Add trip points and cooling maps for GPU thermal zone for Odroid XU3/XU4/HC1 boards. Trip points are based on the CPU thermal zone for the those boards. Signed-off-by: Marek Szyprowski Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos5422-odroidhc1.dts | 30 ++++++++++ .../boot/dts/exynos5422-odroidxu3-common.dtsi | 59 +++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/arch/arm/boot/dts/exynos5422-odroidhc1.dts b/arch/arm/boot/dts/exynos5422-odroidhc1.dts index f163206265bb..812659260278 100644 --- a/arch/arm/boot/dts/exynos5422-odroidhc1.dts +++ b/arch/arm/boot/dts/exynos5422-odroidhc1.dts @@ -215,6 +215,36 @@ }; }; }; + gpu_thermal: gpu-thermal { + thermal-sensors = <&tmu_gpu 0>; + trips { + gpu_alert0: gpu-alert-0 { + temperature = <70000>; + hysteresis = <10000>; + type = "active"; + }; + gpu_alert1: gpu-alert-1 { + temperature = <85000>; + hysteresis = <10000>; + type = "active"; + }; + gpu_crit0: gpu-crit-0 { + temperature = <120000>; + hysteresis = <0>; + type = "critical"; + }; + }; + cooling-maps { + map0 { + trip = <&gpu_alert0>; + cooling-device = <&gpu 0 2>; + }; + map1 { + trip = <&gpu_alert1>; + cooling-device = <&gpu 3 6>; + }; + }; + }; }; }; diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi index 1865a708b49f..5da2d81e3be2 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi @@ -357,6 +357,65 @@ }; }; }; + gpu_thermal: gpu-thermal { + thermal-sensors = <&tmu_gpu 0>; + polling-delay-passive = <250>; + polling-delay = <0>; + trips { + gpu_alert0: gpu-alert-0 { + temperature = <50000>; + hysteresis = <5000>; + type = "active"; + }; + gpu_alert1: gpu-alert-1 { + temperature = <60000>; + hysteresis = <5000>; + type = "active"; + }; + gpu_alert2: gpu-alert-2 { + temperature = <70000>; + hysteresis = <5000>; + type = "active"; + }; + gpu_crit0: gpu-crit-0 { + temperature = <120000>; + hysteresis = <0>; + type = "critical"; + }; + gpu_alert3: gpu-alert-3 { + temperature = <70000>; + hysteresis = <10000>; + type = "passive"; + }; + gpu_alert4: gpu-alert-4 { + temperature = <85000>; + hysteresis = <10000>; + type = "passive"; + }; + }; + cooling-maps { + map0 { + trip = <&gpu_alert0>; + cooling-device = <&fan0 0 1>; + }; + map1 { + trip = <&gpu_alert1>; + cooling-device = <&fan0 1 2>; + }; + map2 { + trip = <&gpu_alert2>; + cooling-device = <&fan0 2 3>; + }; + map3 { + trip = <&gpu_alert3>; + cooling-device = <&gpu 0 2>; + }; + map4 { + trip = <&gpu_alert4>; + cooling-device = <&gpu 3 6>; + }; + }; + }; }; }; From ff5cd9accbc724a793904c6e401040c85be89748 Mon Sep 17 00:00:00 2001 From: Alexander Kapshuk Date: Sun, 9 Feb 2020 16:00:57 +0200 Subject: [PATCH 0075/4444] ver_linux: Query ld cache for versions of libc/libcpp run-time Query ld cache for versions of both libc and libcpp run-time, instead of querying /proc/self/maps for libc run-time, and ld cache for libcpp run-time, thus reducing code size and complexity. Signed-off-by: Alexander Kapshuk Link: https://lore.kernel.org/r/20200209140057.20181-1-alexander.kapshuk@gmail.com Signed-off-by: Greg Kroah-Hartman --- scripts/ver_linux | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/scripts/ver_linux b/scripts/ver_linux index 85005d6b7f10..0968a3070eff 100755 --- a/scripts/ver_linux +++ b/scripts/ver_linux @@ -14,6 +14,8 @@ BEGIN { printf("\n") vernum = "[0-9]+([.]?[0-9]+)+" + libc = "libc[.]so[.][0-9]+$" + libcpp = "(libg|stdc)[+]+[.]so[.][0-9]+$" printversion("GNU C", version("gcc -dumpversion")) printversion("GNU Make", version("make --version")) @@ -35,26 +37,14 @@ BEGIN { printversion("Bison", version("bison --version")) printversion("Flex", version("flex --version")) - while (getline <"/proc/self/maps" > 0) { - if (/libc.*\.so$/) { - n = split($0, procmaps, "/") - if (match(procmaps[n], vernum)) { - ver = substr(procmaps[n], RSTART, RLENGTH) - printversion("Linux C Library", ver) - break - } - } + while ("ldconfig -p 2>/dev/null" | getline > 0) { + if ($NF ~ libc && !seen[ver = version("readlink " $NF)]++) + printversion("Linux C Library", ver) + else if ($NF ~ libcpp && !seen[ver = version("readlink " $NF)]++) + printversion("Linux C++ Library", ver) } printversion("Dynamic linker (ldd)", version("ldd --version")) - - while ("ldconfig -p 2>/dev/null" | getline > 0) { - if (/(libg|stdc)[+]+\.so/) { - libcpp = $NF - break - } - } - printversion("Linux C++ Library", version("readlink " libcpp)) printversion("Procps", version("ps --version")) printversion("Net-tools", version("ifconfig --version")) printversion("Kbd", version("loadkeys -V")) From 01c0514ec8226386ce8367dcd8814f86224caaeb Mon Sep 17 00:00:00 2001 From: Alexander Popov Date: Fri, 3 Jan 2020 02:49:07 +0300 Subject: [PATCH 0076/4444] lkdtm/stackleak: Make the test more verbose Make the stack erasing test more verbose about the errors that it can detect. Signed-off-by: Alexander Popov Cc: Kees Cook Link: https://lore.kernel.org/r/20200102234907.585508-1-alex.popov@linux.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/lkdtm/stackleak.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/misc/lkdtm/stackleak.c b/drivers/misc/lkdtm/stackleak.c index d5a084475abc..d1a5c0705be3 100644 --- a/drivers/misc/lkdtm/stackleak.c +++ b/drivers/misc/lkdtm/stackleak.c @@ -16,6 +16,7 @@ void lkdtm_STACKLEAK_ERASING(void) unsigned long *sp, left, found, i; const unsigned long check_depth = STACKLEAK_SEARCH_DEPTH / sizeof(unsigned long); + bool test_failed = false; /* * For the details about the alignment of the poison values, see @@ -34,7 +35,8 @@ void lkdtm_STACKLEAK_ERASING(void) left--; } else { pr_err("FAIL: not enough stack space for the test\n"); - return; + test_failed = true; + goto end; } pr_info("checking unused part of the thread stack (%lu bytes)...\n", @@ -52,22 +54,29 @@ void lkdtm_STACKLEAK_ERASING(void) } if (found <= check_depth) { - pr_err("FAIL: thread stack is not erased (checked %lu bytes)\n", + pr_err("FAIL: the erased part is not found (checked %lu bytes)\n", i * sizeof(unsigned long)); - return; + test_failed = true; + goto end; } - pr_info("first %lu bytes are unpoisoned\n", + pr_info("the erased part begins after %lu not poisoned bytes\n", (i - found) * sizeof(unsigned long)); /* The rest of thread stack should be erased */ for (; i < left; i++) { if (*(sp - i) != STACKLEAK_POISON) { - pr_err("FAIL: thread stack is NOT properly erased\n"); - return; + pr_err("FAIL: bad value number %lu in the erased part: 0x%lx\n", + i, *(sp - i)); + test_failed = true; } } - pr_info("OK: the rest of the thread stack is properly erased\n"); - return; +end: + if (test_failed) { + pr_err("FAIL: the thread stack is NOT properly erased\n"); + dump_stack(); + } else { + pr_info("OK: the rest of the thread stack is properly erased\n"); + } } From e3cdcfcea363edadebf94576c29d33a441fd5a6f Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 10 Feb 2020 08:52:56 +0000 Subject: [PATCH 0077/4444] PCI/ACPI: Move pcie_to_hpx3_type[] from stack to static data Move pcie_to_hpx3_type[] from the stack to static data. This reduces stack usage and also makes the object code slightly smaller. Link: https://lore.kernel.org/r/20200210085256.319424-1-colin.king@canonical.com Signed-off-by: Colin Ian King Signed-off-by: Bjorn Helgaas --- drivers/pci/pci-acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 0c02d500158f..d914f8bc31ea 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -439,7 +439,7 @@ enum hpx_type3_dev_type { static u16 hpx3_device_type(struct pci_dev *dev) { u16 pcie_type = pci_pcie_type(dev); - const int pcie_to_hpx3_type[] = { + static const int pcie_to_hpx3_type[] = { [PCI_EXP_TYPE_ENDPOINT] = HPX_TYPE_ENDPOINT, [PCI_EXP_TYPE_LEG_END] = HPX_TYPE_LEG_END, [PCI_EXP_TYPE_RC_END] = HPX_TYPE_RC_END, From 80363e1b673b242fa5f5578a7b1e3fa03bf4729a Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 3 Jan 2020 11:27:19 -0800 Subject: [PATCH 0078/4444] scsi: tcm_qla2xxx: Make qlt_alloc_qfull_cmd() set cmd->se_cmd.map_tag Reduce code duplication by introducing the tcm_qla2xxx_{get,rel}_cmd() functions. Introduce these functions in the tcm_qla2xxx.c source files such that the qla_target.c source file becomes independent of the SCSI target core header files. This patch fixes a bug, namely by ensuring that qlt_alloc_qfull_cmd() sets cmd->se_cmd.map_tag. Cc: Himanshu Madhani Link: https://lore.kernel.org/r/20200103192719.205158-1-bvanassche@acm.org Acked-by: Himanshu Madhani Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 28 ++++++---------------------- drivers/scsi/qla2xxx/qla_target.h | 2 ++ drivers/scsi/qla2xxx/tcm_qla2xxx.c | 25 +++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 70081b395fb2..243f87df3d2b 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -27,8 +27,6 @@ #include #include #include -#include -#include #include "qla_def.h" #include "qla_target.h" @@ -3816,7 +3814,7 @@ void qlt_free_cmd(struct qla_tgt_cmd *cmd) return; } cmd->jiffies_at_free = get_jiffies_64(); - target_free_tag(sess->se_sess, &cmd->se_cmd); + cmd->vha->hw->tgt.tgt_ops->rel_cmd(cmd); } EXPORT_SYMBOL(qlt_free_cmd); @@ -4150,7 +4148,7 @@ out_term: qlt_send_term_exchange(qpair, NULL, &cmd->atio, 1, 0); qlt_decr_num_pend_cmds(vha); - target_free_tag(sess->se_sess, &cmd->se_cmd); + cmd->vha->hw->tgt.tgt_ops->rel_cmd(cmd); spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); ha->tgt.tgt_ops->put_sess(sess); @@ -4277,24 +4275,18 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha, struct fc_port *sess, struct atio_from_isp *atio) { - struct se_session *se_sess = sess->se_sess; struct qla_tgt_cmd *cmd; - int tag, cpu; - tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); - if (tag < 0) + cmd = vha->hw->tgt.tgt_ops->get_cmd(sess); + if (!cmd) return NULL; - cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag]; - memset(cmd, 0, sizeof(struct qla_tgt_cmd)); cmd->cmd_type = TYPE_TGT_CMD; memcpy(&cmd->atio, atio, sizeof(*atio)); cmd->state = QLA_TGT_STATE_NEW; cmd->tgt = vha->vha_tgt.qla_tgt; qlt_incr_num_pend_cmds(vha); cmd->vha = vha; - cmd->se_cmd.map_tag = tag; - cmd->se_cmd.map_cpu = cpu; cmd->sess = sess; cmd->loop_id = sess->loop_id; cmd->conf_compl_supported = sess->conf_compl_supported; @@ -5352,9 +5344,7 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; struct qla_hw_data *ha = vha->hw; struct fc_port *sess; - struct se_session *se_sess; struct qla_tgt_cmd *cmd; - int tag, cpu; unsigned long flags; if (unlikely(tgt->tgt_stop)) { @@ -5384,10 +5374,8 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, if (!sess) return; - se_sess = sess->se_sess; - - tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); - if (tag < 0) { + cmd = ha->tgt.tgt_ops->get_cmd(sess); + if (!cmd) { ql_dbg(ql_dbg_io, vha, 0x3009, "qla_target(%d): %s: Allocation of cmd failed\n", vha->vp_idx, __func__); @@ -5402,9 +5390,6 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, return; } - cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag]; - memset(cmd, 0, sizeof(struct qla_tgt_cmd)); - qlt_incr_num_pend_cmds(vha); INIT_LIST_HEAD(&cmd->cmd_list); memcpy(&cmd->atio, atio, sizeof(*atio)); @@ -5414,7 +5399,6 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, cmd->reset_count = ha->base_qpair->chip_reset; cmd->q_full = 1; cmd->qpair = ha->base_qpair; - cmd->se_cmd.map_cpu = cpu; if (qfull) { cmd->q_full = 1; diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 6539499e9e95..3cf8590feeac 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -671,6 +671,8 @@ struct qla_tgt_func_tmpl { void (*handle_data)(struct qla_tgt_cmd *); int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, u64, uint16_t, uint32_t); + struct qla_tgt_cmd *(*get_cmd)(struct fc_port *); + void (*rel_cmd)(struct qla_tgt_cmd *); void (*free_cmd)(struct qla_tgt_cmd *); void (*free_mcmd)(struct qla_tgt_mgmt_cmd *); void (*free_session)(struct fc_port *); diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index abe7f79bb789..1f0a185b2a95 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -268,6 +268,29 @@ static void tcm_qla2xxx_complete_free(struct work_struct *work) transport_generic_free_cmd(&cmd->se_cmd, 0); } +static struct qla_tgt_cmd *tcm_qla2xxx_get_cmd(struct fc_port *sess) +{ + struct se_session *se_sess = sess->se_sess; + struct qla_tgt_cmd *cmd; + int tag, cpu; + + tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); + if (tag < 0) + return NULL; + + cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag]; + memset(cmd, 0, sizeof(struct qla_tgt_cmd)); + cmd->se_cmd.map_tag = tag; + cmd->se_cmd.map_cpu = cpu; + + return cmd; +} + +static void tcm_qla2xxx_rel_cmd(struct qla_tgt_cmd *cmd) +{ + target_free_tag(cmd->sess->se_sess, &cmd->se_cmd); +} + /* * Called from qla_target_template->free_cmd(), and will call * tcm_qla2xxx_release_cmd via normal struct target_core_fabric_ops @@ -1549,6 +1572,8 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = { .handle_cmd = tcm_qla2xxx_handle_cmd, .handle_data = tcm_qla2xxx_handle_data, .handle_tmr = tcm_qla2xxx_handle_tmr, + .get_cmd = tcm_qla2xxx_get_cmd, + .rel_cmd = tcm_qla2xxx_rel_cmd, .free_cmd = tcm_qla2xxx_free_cmd, .free_mcmd = tcm_qla2xxx_free_mcmd, .free_session = tcm_qla2xxx_free_session, From 0ab710458da113a71c461c4df27e7f1353d9f864 Mon Sep 17 00:00:00 2001 From: Bharath Ravi Date: Sat, 25 Jan 2020 01:19:25 -0500 Subject: [PATCH 0079/4444] scsi: iscsi: Perform connection failure entirely in kernel space Connection failure processing depends on a daemon being present to (at least) stop the connection and start recovery. This is a problem on a multipath scenario, where if the daemon failed for whatever reason, the SCSI path is never marked as down, multipath won't perform the failover and IO to the device will be forever waiting for that connection to come back. This patch performs the connection failure entirely inside the kernel. This way, the failover can happen and pending IO can continue even if the daemon is dead. Once the daemon comes alive again, it can execute recovery procedures if applicable. Cc: Mike Christie Cc: Lee Duncan Cc: Bart Van Assche Link: https://lore.kernel.org/r/20200125061925.191601-1-krisman@collabora.com Co-developed-by: Dave Clausen Co-developed-by: Nick Black Co-developed-by: Vaibhav Nagarnaik Co-developed-by: Anatol Pomazau Co-developed-by: Tahsin Erdogan Co-developed-by: Frank Mayhar Co-developed-by: Junho Ryu Co-developed-by: Khazhismel Kumykov Reviewed-by: Reviewed-by: Khazhismel Kumykov Co-developed-by: Gabriel Krisman Bertazi Reviewed-by: Lee Duncan Signed-off-by: Bharath Ravi Signed-off-by: Dave Clausen Signed-off-by: Nick Black Signed-off-by: Vaibhav Nagarnaik Signed-off-by: Anatol Pomazau Signed-off-by: Tahsin Erdogan Signed-off-by: Frank Mayhar Signed-off-by: Junho Ryu Signed-off-by: Khazhismel Kumykov Signed-off-by: Gabriel Krisman Bertazi Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_iscsi.c | 68 +++++++++++++++++++++++++++++ include/scsi/scsi_transport_iscsi.h | 1 + 2 files changed, 69 insertions(+) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index dfc726fa34e3..f3f0ecdb09a2 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -86,6 +86,12 @@ struct iscsi_internal { struct transport_container session_cont; }; +/* Worker to perform connection failure on unresponsive connections + * completely in kernel space. + */ +static void stop_conn_work_fn(struct work_struct *work); +static DECLARE_WORK(stop_conn_work, stop_conn_work_fn); + static atomic_t iscsi_session_nr; /* sysfs session id for next new session */ static struct workqueue_struct *iscsi_eh_timer_workq; @@ -1611,6 +1617,7 @@ static DEFINE_MUTEX(rx_queue_mutex); static LIST_HEAD(sesslist); static DEFINE_SPINLOCK(sesslock); static LIST_HEAD(connlist); +static LIST_HEAD(connlist_err); static DEFINE_SPINLOCK(connlock); static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn) @@ -2254,6 +2261,7 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid) mutex_init(&conn->ep_mutex); INIT_LIST_HEAD(&conn->conn_list); + INIT_LIST_HEAD(&conn->conn_list_err); conn->transport = transport; conn->cid = cid; @@ -2307,6 +2315,7 @@ int iscsi_destroy_conn(struct iscsi_cls_conn *conn) spin_lock_irqsave(&connlock, flags); list_del(&conn->conn_list); + list_del(&conn->conn_list_err); spin_unlock_irqrestore(&connlock, flags); transport_unregister_device(&conn->dev); @@ -2421,6 +2430,51 @@ int iscsi_offload_mesg(struct Scsi_Host *shost, } EXPORT_SYMBOL_GPL(iscsi_offload_mesg); +static void stop_conn_work_fn(struct work_struct *work) +{ + struct iscsi_cls_conn *conn, *tmp; + unsigned long flags; + LIST_HEAD(recovery_list); + + spin_lock_irqsave(&connlock, flags); + if (list_empty(&connlist_err)) { + spin_unlock_irqrestore(&connlock, flags); + return; + } + list_splice_init(&connlist_err, &recovery_list); + spin_unlock_irqrestore(&connlock, flags); + + list_for_each_entry_safe(conn, tmp, &recovery_list, conn_list_err) { + uint32_t sid = iscsi_conn_get_sid(conn); + struct iscsi_cls_session *session; + + mutex_lock(&rx_queue_mutex); + + session = iscsi_session_lookup(sid); + if (session) { + if (system_state != SYSTEM_RUNNING) { + session->recovery_tmo = 0; + conn->transport->stop_conn(conn, + STOP_CONN_TERM); + } else { + conn->transport->stop_conn(conn, + STOP_CONN_RECOVER); + } + } + + list_del_init(&conn->conn_list_err); + + mutex_unlock(&rx_queue_mutex); + + /* we don't want to hold rx_queue_mutex for too long, + * for instance if many conns failed at the same time, + * since this stall other iscsi maintenance operations. + * Give other users a chance to proceed. + */ + cond_resched(); + } +} + void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error) { struct nlmsghdr *nlh; @@ -2428,6 +2482,12 @@ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error) struct iscsi_uevent *ev; struct iscsi_internal *priv; int len = nlmsg_total_size(sizeof(*ev)); + unsigned long flags; + + spin_lock_irqsave(&connlock, flags); + list_add(&conn->conn_list_err, &connlist_err); + spin_unlock_irqrestore(&connlock, flags); + queue_work(system_unbound_wq, &stop_conn_work); priv = iscsi_if_transport_lookup(conn->transport); if (!priv) @@ -2757,11 +2817,19 @@ static int iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) { struct iscsi_cls_conn *conn; + unsigned long flags; conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid); if (!conn) return -EINVAL; + spin_lock_irqsave(&connlock, flags); + if (!list_empty(&conn->conn_list_err)) { + spin_unlock_irqrestore(&connlock, flags); + return -EAGAIN; + } + spin_unlock_irqrestore(&connlock, flags); + ISCSI_DBG_TRANS_CONN(conn, "Destroying transport conn\n"); if (transport->destroy_conn) transport->destroy_conn(conn); diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 325ae731d9ad..2129dc9e2dec 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -190,6 +190,7 @@ extern void iscsi_ping_comp_event(uint32_t host_no, struct iscsi_cls_conn { struct list_head conn_list; /* item in connlist */ + struct list_head conn_list_err; /* item in connlist_err */ void *dd_data; /* LLD private data */ struct iscsi_transport *transport; uint32_t cid; /* connection id */ From 77d331802a44e727084a15706384908daaabeb6f Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 26 Jan 2020 15:47:57 +0000 Subject: [PATCH 0080/4444] scsi: megaraid_sas: fix indentation issue There are two statements that are indented one level too deeply, remove the extraneous tabs. [mkp: fix typo spotted by Bart] Link: https://lore.kernel.org/r/20200126154757.42530-1-colin.king@canonical.com Reviewed-by: Bart Van Assche Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index fd4b5ac6ac5b..5bebdd397580 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -8224,8 +8224,8 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, "return -EBUSY from %s %d cmd 0x%x opcode 0x%x cmd->cmd_status_drv 0x%x\n", __func__, __LINE__, cmd->frame->hdr.cmd, opcode, cmd->cmd_status_drv); - error = -EBUSY; - goto out; + error = -EBUSY; + goto out; } cmd->sync_cmd = 0; From 7742ca797aa79f280853ffd3e7d2e2af3cd317a5 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Wed, 29 Jan 2020 18:52:48 +0800 Subject: [PATCH 0081/4444] scsi: ufs: ufs-mediatek: ensure UniPro is not powered down before linkup MediaTek Chipsets can enter proprietary UniPro low-power mode during suspend while link is in hibern8 state. Make sure leaving low-power mode before every link startup to prevent lockup in any possible error recovery path. At the same time, re-factor related funcitons to improve code readability. Link: https://lore.kernel.org/r/20200129105251.12466-2-stanley.chu@mediatek.com Reviewed-by: Alim Akhtar Reviewed-by: Bean Huo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-mediatek.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 53eae5fe2ade..7ac838cc15d1 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -30,6 +30,11 @@ #define ufs_mtk_device_reset_ctrl(high, res) \ ufs_mtk_smc(UFS_MTK_SIP_DEVICE_RESET, high, res) +#define ufs_mtk_unipro_powerdown(hba, powerdown) \ + ufshcd_dme_set(hba, \ + UIC_ARG_MIB_SEL(VS_UNIPROPOWERDOWNCONTROL, 0), \ + powerdown) + static void ufs_mtk_cfg_unipro_cg(struct ufs_hba *hba, bool enable) { u32 tmp; @@ -290,6 +295,8 @@ static int ufs_mtk_pre_link(struct ufs_hba *hba) int ret; u32 tmp; + ufs_mtk_unipro_powerdown(hba, 0); + /* disable deep stall */ ret = ufshcd_dme_get(hba, UIC_ARG_MIB(VS_SAVEPOWERCONTROL), &tmp); if (ret) @@ -390,9 +397,7 @@ static int ufs_mtk_link_set_hpm(struct ufs_hba *hba) if (err) return err; - err = ufshcd_dme_set(hba, - UIC_ARG_MIB_SEL(VS_UNIPROPOWERDOWNCONTROL, 0), - 0); + err = ufs_mtk_unipro_powerdown(hba, 0); if (err) return err; @@ -413,14 +418,10 @@ static int ufs_mtk_link_set_lpm(struct ufs_hba *hba) { int err; - err = ufshcd_dme_set(hba, - UIC_ARG_MIB_SEL(VS_UNIPROPOWERDOWNCONTROL, 0), - 1); + err = ufs_mtk_unipro_powerdown(hba, 1); if (err) { /* Resume UniPro state for following error recovery */ - ufshcd_dme_set(hba, - UIC_ARG_MIB_SEL(VS_UNIPROPOWERDOWNCONTROL, 0), - 0); + ufs_mtk_unipro_powerdown(hba, 0); return err; } From 2a06ff207445ddb7aa643751f85c54e7e3895fb4 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Wed, 29 Jan 2020 18:52:49 +0800 Subject: [PATCH 0082/4444] scsi: ufs: ufs-mediatek: support linkoff state during suspend If system suspend or runtime suspend mode is configured as linkoff state, phy can be powered off and reference clock can be gated in MediaTek Chipsets. At the same time, remove redundant reference clock control in suspend and resume callbacks because such control can be well-handled in setup_clocks callback. Link: https://lore.kernel.org/r/20200129105251.12466-3-stanley.chu@mediatek.com Reviewed-by: Alim Akhtar Reviewed-by: Bean Huo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-mediatek.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 7ac838cc15d1..d78897a14905 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -167,7 +167,7 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on, switch (status) { case PRE_CHANGE: - if (!on) { + if (!on && !ufshcd_is_link_active(hba)) { ufs_mtk_setup_ref_clk(hba, on); ret = phy_power_off(host->mphy); } @@ -437,10 +437,11 @@ static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) err = ufs_mtk_link_set_lpm(hba); if (err) return -EAGAIN; - phy_power_off(host->mphy); - ufs_mtk_setup_ref_clk(hba, false); } + if (!ufshcd_is_link_active(hba)) + phy_power_off(host->mphy); + return 0; } @@ -449,9 +450,10 @@ static int ufs_mtk_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) struct ufs_mtk_host *host = ufshcd_get_variant(hba); int err; - if (ufshcd_is_link_hibern8(hba)) { - ufs_mtk_setup_ref_clk(hba, true); + if (!ufshcd_is_link_active(hba)) phy_power_on(host->mphy); + + if (ufshcd_is_link_hibern8(hba)) { err = ufs_mtk_link_set_hpm(hba); if (err) return err; From 5a244e0ea67b293abb1d26c825db2ddde5f2862f Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Wed, 29 Jan 2020 18:52:50 +0800 Subject: [PATCH 0083/4444] scsi: ufs: fix Auto-Hibern8 error detection Auto-Hibern8 may be disabled by some vendors or sysfs in runtime even if Auto-Hibern8 capability is supported by host. If Auto-Hibern8 capability is supported by host but not actually enabled, Auto-Hibern8 error shall not happen. To fix this, provide a way to detect if Auto-Hibern8 is actually enabled first, and bypass Auto-Hibern8 disabling case in ufshcd_is_auto_hibern8_error(). Fixes: 821744403913 ("scsi: ufs: Add error-handling of Auto-Hibernate") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20200129105251.12466-4-stanley.chu@mediatek.com Reviewed-by: Bean Huo Reviewed-by: Alim Akhtar Reviewed-by: Asutosh Das Reviewed-by: Can Guo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 3 ++- drivers/scsi/ufs/ufshcd.h | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index abd0e6b05f79..214a3f373dd8 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5479,7 +5479,8 @@ static irqreturn_t ufshcd_update_uic_error(struct ufs_hba *hba) static bool ufshcd_is_auto_hibern8_error(struct ufs_hba *hba, u32 intr_mask) { - if (!ufshcd_is_auto_hibern8_supported(hba)) + if (!ufshcd_is_auto_hibern8_supported(hba) || + !ufshcd_is_auto_hibern8_enabled(hba)) return false; if (!(intr_mask & UFSHCD_UIC_HIBERN8_MASK)) diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 2ae6c7c8528c..81c71a3e3474 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -55,6 +55,7 @@ #include #include #include +#include #include "unipro.h" #include @@ -773,6 +774,11 @@ static inline bool ufshcd_is_auto_hibern8_supported(struct ufs_hba *hba) return (hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT); } +static inline bool ufshcd_is_auto_hibern8_enabled(struct ufs_hba *hba) +{ + return FIELD_GET(UFSHCI_AHIBERN8_TIMER_MASK, hba->ahit) ? true : false; +} + #define ufshcd_writel(hba, val, reg) \ writel((val), (hba)->mmio_base + (reg)) #define ufshcd_readl(hba, reg) \ From 722adbbd706569bc547aeb2adcd706f55b2ac6f8 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Wed, 29 Jan 2020 18:52:51 +0800 Subject: [PATCH 0084/4444] scsi: ufs: ufs-mediatek: gate ref-clk during Auto-Hibern8 In current UFS driver design, hba->uic_link_state will not be changed after link enters Hibern8 state by Auto-Hibern8 mechanism. In this case, reference clock gating will be skipped unless special handling is implemented in vendor's callbacks. Support reference clock gating during Auto-Hibern8 period in MediaTek Chipsets: If link state is already in Hibern8 while Auto-Hibern8 feature is enabled, gate reference clock in setup_clocks callback. Link: https://lore.kernel.org/r/20200129105251.12466-5-stanley.chu@mediatek.com Reviewed-by: Alim Akhtar Reviewed-by: Bean Huo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-mediatek.c | 38 +++++++++++++++++++++++---------- drivers/scsi/ufs/ufs-mediatek.h | 12 +++++++++++ 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index d78897a14905..0ce08872d671 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -143,6 +143,17 @@ out: return 0; } +static u32 ufs_mtk_link_get_state(struct ufs_hba *hba) +{ + u32 val; + + ufshcd_writel(hba, 0x20, REG_UFS_DEBUG_SEL); + val = ufshcd_readl(hba, REG_UFS_PROBE); + val = val >> 28; + + return val; +} + /** * ufs_mtk_setup_clocks - enables/disable clocks * @hba: host controller instance @@ -155,7 +166,7 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on, enum ufs_notify_change_status status) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); - int ret = -EINVAL; + int ret = 0; /* * In case ufs_mtk_init() is not yet done, simply ignore. @@ -165,19 +176,24 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on, if (!host) return 0; - switch (status) { - case PRE_CHANGE: - if (!on && !ufshcd_is_link_active(hba)) { + if (!on && status == PRE_CHANGE) { + if (!ufshcd_is_link_active(hba)) { ufs_mtk_setup_ref_clk(hba, on); ret = phy_power_off(host->mphy); + } else { + /* + * Gate ref-clk if link state is in Hibern8 + * triggered by Auto-Hibern8. + */ + if (!ufshcd_can_hibern8_during_gating(hba) && + ufshcd_is_auto_hibern8_enabled(hba) && + ufs_mtk_link_get_state(hba) == + VS_LINK_HIBERN8) + ufs_mtk_setup_ref_clk(hba, on); } - break; - case POST_CHANGE: - if (on) { - ret = phy_power_on(host->mphy); - ufs_mtk_setup_ref_clk(hba, on); - } - break; + } else if (on && status == POST_CHANGE) { + ret = phy_power_on(host->mphy); + ufs_mtk_setup_ref_clk(hba, on); } return ret; diff --git a/drivers/scsi/ufs/ufs-mediatek.h b/drivers/scsi/ufs/ufs-mediatek.h index fccdd979d6fb..492414e5f481 100644 --- a/drivers/scsi/ufs/ufs-mediatek.h +++ b/drivers/scsi/ufs/ufs-mediatek.h @@ -53,6 +53,18 @@ #define VS_SAVEPOWERCONTROL 0xD0A6 #define VS_UNIPROPOWERDOWNCONTROL 0xD0A8 +/* + * Vendor specific link state + */ +enum { + VS_LINK_DISABLED = 0, + VS_LINK_DOWN = 1, + VS_LINK_UP = 2, + VS_LINK_HIBERN8 = 3, + VS_LINK_LOST = 4, + VS_LINK_CFG = 5, +}; + /* * SiP commands */ From 3d8b24a0f438d812d14849bd42516f54e80b57e8 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sun, 19 Jan 2020 15:14:28 +0800 Subject: [PATCH 0085/4444] scsi: core: remove .for_blk_mq Not in use anymore. Remove the flag. Cc: Sathya Prakash Cc: Chaitra P B Cc: Suganath Prabu Subramani Cc: Kashyap Desai Cc: Sumit Saxena Cc: Shivasharan S Cc: Ewan D. Milne Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Bart Van Assche Link: https://lore.kernel.org/r/20200119071432.18558-3-ming.lei@redhat.com Reviewed-by: Christoph Hellwig Signed-off-by: Ming Lei Signed-off-by: Martin K. Petersen --- drivers/scsi/virtio_scsi.c | 1 - include/scsi/scsi_host.h | 3 --- 2 files changed, 4 deletions(-) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index bfec84aacd90..0e0910c5b942 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -742,7 +742,6 @@ static struct scsi_host_template virtscsi_host_template = { .dma_boundary = UINT_MAX, .map_queues = virtscsi_map_queues, .track_queue_depth = 1, - .force_blk_mq = 1, }; #define virtscsi_config_get(vdev, fld) \ diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index f577647bf5f2..7a97fb8104cf 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -426,9 +426,6 @@ struct scsi_host_template { /* True if the controller does not support WRITE SAME */ unsigned no_write_same:1; - /* True if the low-level driver supports blk-mq only */ - unsigned force_blk_mq:1; - /* * Countdown for host blocking with no commands outstanding. */ From 2494c2868d6e0eaaefd42f4fd2d260a8c35d240d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 22 Jan 2020 20:23:40 -0800 Subject: [PATCH 0086/4444] scsi: qla2xxx: Check locking assumptions at runtime in qla2x00_abort_srb() Document the locking assumptions this function relies on and also verify these locking assumptions at runtime. Cc: Quinn Tran Cc: Daniel Wagner Link: https://lore.kernel.org/r/20200123042345.23886-2-bvanassche@acm.org Acked-by: Himanshu Madhani Reviewed-by: Martin Wilck Reviewed-by: Roman Bolshakov Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index b520a980d1dc..79387ac8936f 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1700,6 +1700,8 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, bool ret_cmd; uint32_t ratov_j; + lockdep_assert_held(qp->qp_lock_ptr); + if (qla2x00_chip_is_down(vha)) { sp->done(sp, res); return; From 39c4f1a965a9244c3ba60695e8ff8da065ec6ac4 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 27 Jan 2020 16:23:01 -0800 Subject: [PATCH 0087/4444] scsi: lpfc: Fix RQ buffer leakage when no IOCBs available The driver is occasionally seeing the following SLI Port error, requiring reset and reinit: Port Status Event: ... error 1=0x52004a01, error 2=0x218 The failure means an RQ timeout. That is, the adapter had received asynchronous receive frames, ran out of buffer slots to place the frames, and the driver did not replenish the buffer slots before a timeout occurred. The driver should not be so slow in replenishing buffers that a timeout can occur. When the driver received all the frames of a sequence, it allocates an IOCB to put the frames in. In a situation where there was no IOCB available for the frame of a sequence, the RQ buffer corresponding to the first frame of the sequence was not returned to the FW. Eventually, with enough traffic encountering the situation, the timeout occurred. Fix by releasing the buffer back to firmware whenever there is no IOCB for the first frame. [mkp: typo] Link: https://lore.kernel.org/r/20200128002312.16346-2-jsmart2021@gmail.com Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_sli.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 64002b0cb02d..ab6f58bc80a4 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -17950,6 +17950,10 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) list_add_tail(&iocbq->list, &first_iocbq->list); } } + /* Free the sequence's header buffer */ + if (!first_iocbq) + lpfc_in_buf_free(vport->phba, &seq_dmabuf->dbuf); + return first_iocbq; } From 0ab384a49c548baf132ccef249f78d9c6c506380 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 27 Jan 2020 16:23:02 -0800 Subject: [PATCH 0088/4444] scsi: lpfc: Fix lpfc_io_buf resource leak in lpfc_get_scsi_buf_s4 error path If a call to lpfc_get_cmd_rsp_buf_per_hdwq returns NULL (memory allocation failure), a previously allocated lpfc_io_buf resource is leaked. Fix by releasing the lpfc_io_buf resource in the failure path. Fixes: d79c9e9d4b3d ("scsi: lpfc: Support dynamic unbounded SGL lists on G7 hardware.") Cc: # v5.4+ Link: https://lore.kernel.org/r/20200128002312.16346-3-jsmart2021@gmail.com Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_scsi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 2c7e0b22db2f..96ac4a154c58 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -671,8 +671,10 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, lpfc_cmd->prot_data_type = 0; #endif tmp = lpfc_get_cmd_rsp_buf_per_hdwq(phba, lpfc_cmd); - if (!tmp) + if (!tmp) { + lpfc_release_io_buf(phba, lpfc_cmd, lpfc_cmd->hdwq); return NULL; + } lpfc_cmd->fcp_cmnd = tmp->fcp_cmnd; lpfc_cmd->fcp_rsp = tmp->fcp_rsp; From 835214f5d5f516a38069bc077c879c7da00d6108 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 27 Jan 2020 16:23:03 -0800 Subject: [PATCH 0089/4444] scsi: lpfc: Fix broken Credit Recovery after driver load When driver is set to enable bb credit recovery, the switch displayed the setting as inactive. If the link bounces, it switches to Active. During link up processing, the driver currently does a MBX_READ_SPARAM followed by a MBX_CONFIG_LINK. These mbox commands are queued to be executed, one at a time and the completion is processed by the worker thread. Since the MBX_READ_SPARAM is done BEFORE the MBX_CONFIG_LINK, the BB_SC_N bit is never set the the returned values. BB Credit recovery status only gets set after the driver requests the feature in CONFIG_LINK, which is done after the link up. Thus the ordering of READ_SPARAM needs to follow the CONFIG_LINK. Fix by reordering so that READ_SPARAM is done after CONFIG_LINK. Added a HBA_DEFER_FLOGI flag so that any FLOGI handling waits until after the READ_SPARAM is done so that the proper BB credit value is set in the FLOGI payload. Fixes: 6bfb16208298 ("scsi: lpfc: Fix configuration of BB credit recovery in service parameters") Cc: # v5.4+ Link: https://lore.kernel.org/r/20200128002312.16346-4-jsmart2021@gmail.com Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 1 + drivers/scsi/lpfc/lpfc_hbadisc.c | 59 +++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 04d73e2be373..3f2cb17c4574 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -749,6 +749,7 @@ struct lpfc_hba { * capability */ #define HBA_FLOGI_ISSUED 0x100000 /* FLOGI was issued */ +#define HBA_DEFER_FLOGI 0x800000 /* Defer FLOGI till read_sparm cmpl */ uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/ struct lpfc_dmabuf slim2p; diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index dcc8999c6a68..6a2bdae0e52a 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1163,13 +1163,16 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } /* Start discovery by sending a FLOGI. port_state is identically - * LPFC_FLOGI while waiting for FLOGI cmpl + * LPFC_FLOGI while waiting for FLOGI cmpl. Check if sending + * the FLOGI is being deferred till after MBX_READ_SPARAM completes. */ - if (vport->port_state != LPFC_FLOGI) - lpfc_initial_flogi(vport); - else if (vport->fc_flag & FC_PT2PT) - lpfc_disc_start(vport); - + if (vport->port_state != LPFC_FLOGI) { + if (!(phba->hba_flag & HBA_DEFER_FLOGI)) + lpfc_initial_flogi(vport); + } else { + if (vport->fc_flag & FC_PT2PT) + lpfc_disc_start(vport); + } return; out: @@ -3094,6 +3097,14 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free(pmb, phba->mbox_mem_pool); + + /* Check if sending the FLOGI is being deferred to after we get + * up to date CSPs from MBX_READ_SPARAM. + */ + if (phba->hba_flag & HBA_DEFER_FLOGI) { + lpfc_initial_flogi(vport); + phba->hba_flag &= ~HBA_DEFER_FLOGI; + } return; out: @@ -3224,6 +3235,23 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) } lpfc_linkup(phba); + sparam_mbox = NULL; + + if (!(phba->hba_flag & HBA_FCOE_MODE)) { + cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!cfglink_mbox) + goto out; + vport->port_state = LPFC_LOCAL_CFG_LINK; + lpfc_config_link(phba, cfglink_mbox); + cfglink_mbox->vport = vport; + cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link; + rc = lpfc_sli_issue_mbox(phba, cfglink_mbox, MBX_NOWAIT); + if (rc == MBX_NOT_FINISHED) { + mempool_free(cfglink_mbox, phba->mbox_mem_pool); + goto out; + } + } + sparam_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!sparam_mbox) goto out; @@ -3244,20 +3272,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) goto out; } - if (!(phba->hba_flag & HBA_FCOE_MODE)) { - cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); - if (!cfglink_mbox) - goto out; - vport->port_state = LPFC_LOCAL_CFG_LINK; - lpfc_config_link(phba, cfglink_mbox); - cfglink_mbox->vport = vport; - cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link; - rc = lpfc_sli_issue_mbox(phba, cfglink_mbox, MBX_NOWAIT); - if (rc == MBX_NOT_FINISHED) { - mempool_free(cfglink_mbox, phba->mbox_mem_pool); - goto out; - } - } else { + if (phba->hba_flag & HBA_FCOE_MODE) { vport->port_state = LPFC_VPORT_UNKNOWN; /* * Add the driver's default FCF record at FCF index 0 now. This @@ -3314,6 +3329,10 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) } /* Reset FCF roundrobin bmask for new discovery */ lpfc_sli4_clear_fcf_rr_bmask(phba); + } else { + if (phba->bbcredit_support && phba->cfg_enable_bbcr && + !(phba->link_flag & LS_LOOPBACK_MODE)) + phba->hba_flag |= HBA_DEFER_FLOGI; } /* Prepare for LINK up registrations */ From 792f3b90be2aeedf5e076bbe6c5808e693f51c23 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 27 Jan 2020 16:23:04 -0800 Subject: [PATCH 0090/4444] scsi: lpfc: Fix registration of ELS type support in fdmi Adjust FC4 Types in FDMI settings The driver sets FDMI information registring ELS as a FC4 type. ELS is a fc3 type and should not be registered. Fix by removing ELS type bit when we register for FDMI Port attributes. Link: https://lore.kernel.org/r/20200128002312.16346-5-jsmart2021@gmail.com Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_ct.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 58b35a1442c1..fa70e2001b8e 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -2453,7 +2453,6 @@ lpfc_fdmi_port_attr_fc4type(struct lpfc_vport *vport, ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; memset(ae, 0, 32); - ae->un.AttrTypes[3] = 0x02; /* Type 0x1 - ELS */ ae->un.AttrTypes[2] = 0x01; /* Type 0x8 - FCP */ ae->un.AttrTypes[7] = 0x01; /* Type 0x20 - CT */ @@ -2771,7 +2770,6 @@ lpfc_fdmi_port_attr_active_fc4type(struct lpfc_vport *vport, ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; memset(ae, 0, 32); - ae->un.AttrTypes[3] = 0x02; /* Type 0x1 - ELS */ ae->un.AttrTypes[2] = 0x01; /* Type 0x8 - FCP */ ae->un.AttrTypes[7] = 0x01; /* Type 0x20 - CT */ From 821bc882accaaaf1bbecf5c0ecef659443e3e8cb Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 27 Jan 2020 16:23:05 -0800 Subject: [PATCH 0091/4444] scsi: lpfc: Fix release of hwq to clear the eq relationship When performing reset testing, the eq's list for related hwqs was getting corrupted. In cases where there is not a 1:1 eq to hwq, the eq is shared. The eq maintains a list of hwqs utilizing it in case of cpu offlining and polling. During the reset, the hwqs are being torn down so they can be recreated. The recreation was getting confused by seeing a non-null eq assignment on the eq and the eq list became corrupt. Correct by clearing the hdwq eq assignment when the hwq is cleaned up. Link: https://lore.kernel.org/r/20200128002312.16346-6-jsmart2021@gmail.com Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 5a605773dd0a..9fd238d49117 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -9235,6 +9235,7 @@ lpfc_sli4_release_hdwq(struct lpfc_hba *phba) /* Free the CQ/WQ corresponding to the Hardware Queue */ lpfc_sli4_queue_free(hdwq[idx].io_cq); lpfc_sli4_queue_free(hdwq[idx].io_wq); + hdwq[idx].hba_eq = NULL; hdwq[idx].io_cq = NULL; hdwq[idx].io_wq = NULL; if (phba->cfg_xpsgl && !phba->nvmet_support) From a99c80742af4b58bfd2d16cada8ee73cb9618649 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 27 Jan 2020 16:23:06 -0800 Subject: [PATCH 0092/4444] scsi: lpfc: Fix compiler warning on frame size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The following error is see from the compiler: drivers/scsi/lpfc/lpfc_init.c: In function ‘lpfc_cpuhp_get_eq’: drivers/scsi/lpfc/lpfc_init.c:12660:1: error: the frame size of 1032 bytes is larger than 1024 bytes [-Werror=frame-larger-than=] The issue is due to allocating a cpumask on the stack. Fix by converting to a dynamical allocation of the cpu mask. Link: https://lore.kernel.org/r/20200128002312.16346-7-jsmart2021@gmail.com Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 9fd238d49117..9a6191818a23 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -11106,15 +11106,19 @@ found_any: * @cpu: cpu going offline * @eqlist: */ -static void +static int lpfc_cpuhp_get_eq(struct lpfc_hba *phba, unsigned int cpu, struct list_head *eqlist) { const struct cpumask *maskp; struct lpfc_queue *eq; - cpumask_t tmp; + struct cpumask *tmp; u16 idx; + tmp = kzalloc(cpumask_size(), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + for (idx = 0; idx < phba->cfg_irq_chann; idx++) { maskp = pci_irq_get_affinity(phba->pcidev, idx); if (!maskp) @@ -11124,7 +11128,7 @@ lpfc_cpuhp_get_eq(struct lpfc_hba *phba, unsigned int cpu, * then we don't need to poll the eq attached * to it. */ - if (!cpumask_and(&tmp, maskp, cpumask_of(cpu))) + if (!cpumask_and(tmp, maskp, cpumask_of(cpu))) continue; /* get the cpus that are online and are affini- * tized to this irq vector. If the count is @@ -11132,8 +11136,8 @@ lpfc_cpuhp_get_eq(struct lpfc_hba *phba, unsigned int cpu, * down this vector. Since this cpu has not * gone offline yet, we need >1. */ - cpumask_and(&tmp, maskp, cpu_online_mask); - if (cpumask_weight(&tmp) > 1) + cpumask_and(tmp, maskp, cpu_online_mask); + if (cpumask_weight(tmp) > 1) continue; /* Now that we have an irq to shutdown, get the eq @@ -11144,6 +11148,8 @@ lpfc_cpuhp_get_eq(struct lpfc_hba *phba, unsigned int cpu, eq = phba->sli4_hba.hba_eq_hdl[idx].eq; list_add(&eq->_poll_list, eqlist); } + kfree(tmp); + return 0; } static void __lpfc_cpuhp_remove(struct lpfc_hba *phba) @@ -11314,7 +11320,9 @@ static int lpfc_cpu_offline(unsigned int cpu, struct hlist_node *node) lpfc_irq_rebalance(phba, cpu, true); - lpfc_cpuhp_get_eq(phba, cpu, &eqlist); + retval = lpfc_cpuhp_get_eq(phba, cpu, &eqlist); + if (retval) + return retval; /* start polling on these eq's */ list_for_each_entry_safe(eq, next, &eqlist, _poll_list) { From 4cb9e1ddaa145be9ed67b6a7de98ca705a43f998 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 27 Jan 2020 16:23:07 -0800 Subject: [PATCH 0093/4444] scsi: lpfc: Fix coverity errors in fmdi attribute handling Coverity reported a memory corruption error for the fdmi attributes routines: CID 15768 [Memory Corruption] Out-of-bounds access on FDMI Sloppy coding of the fmdi structures. In both the lpfc_fdmi_attr_def and lpfc_fdmi_reg_port_list structures, a field was placed at the start of payload that may have variable content. The field was given an arbitrary type (uint32_t). The code then uses the field name to derive an address, which it used in things such as memset and memcpy. The memset sizes or memcpy lengths were larger than the arbitrary type, thus coverity reported an error. Fix by replacing the arbitrary fields with the real field structures describing the payload. Link: https://lore.kernel.org/r/20200128002312.16346-8-jsmart2021@gmail.com Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_ct.c | 137 ++++++++++++++++++------------------ drivers/scsi/lpfc/lpfc_hw.h | 36 +++++----- 2 files changed, 85 insertions(+), 88 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index fa70e2001b8e..8db27e84263e 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -2073,8 +2073,8 @@ lpfc_fdmi_hba_attr_wwnn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, sizeof(struct lpfc_name)); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); memcpy(&ae->un.AttrWWN, &vport->fc_sparam.nodeName, sizeof(struct lpfc_name)); @@ -2090,8 +2090,8 @@ lpfc_fdmi_hba_attr_manufacturer(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); /* This string MUST be consistent with other FC platforms * supported by Broadcom. @@ -2115,8 +2115,8 @@ lpfc_fdmi_hba_attr_sn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strncpy(ae->un.AttrString, phba->SerialNumber, sizeof(ae->un.AttrString)); @@ -2137,8 +2137,8 @@ lpfc_fdmi_hba_attr_model(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strncpy(ae->un.AttrString, phba->ModelName, sizeof(ae->un.AttrString)); @@ -2158,8 +2158,8 @@ lpfc_fdmi_hba_attr_description(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strncpy(ae->un.AttrString, phba->ModelDesc, sizeof(ae->un.AttrString)); @@ -2181,8 +2181,8 @@ lpfc_fdmi_hba_attr_hdw_ver(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t i, j, incr, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); /* Convert JEDEC ID to ascii for hardware version */ incr = vp->rev.biuRev; @@ -2211,8 +2211,8 @@ lpfc_fdmi_hba_attr_drvr_ver(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strncpy(ae->un.AttrString, lpfc_release_version, sizeof(ae->un.AttrString)); @@ -2233,8 +2233,8 @@ lpfc_fdmi_hba_attr_rom_ver(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); if (phba->sli_rev == LPFC_SLI_REV4) lpfc_decode_firmware_rev(phba, ae->un.AttrString, 1); @@ -2258,8 +2258,8 @@ lpfc_fdmi_hba_attr_fmw_ver(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); lpfc_decode_firmware_rev(phba, ae->un.AttrString, 1); len = strnlen(ae->un.AttrString, @@ -2278,8 +2278,8 @@ lpfc_fdmi_hba_attr_os_ver(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); snprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s %s %s", init_utsname()->sysname, @@ -2301,7 +2301,7 @@ lpfc_fdmi_hba_attr_ct_len(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; ae->un.AttrInt = cpu_to_be32(LPFC_MAX_CT_SIZE); size = FOURBYTES + sizeof(uint32_t); @@ -2317,8 +2317,8 @@ lpfc_fdmi_hba_attr_symbolic_name(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); len = lpfc_vport_symbolic_node_name(vport, ae->un.AttrString, 256); @@ -2336,7 +2336,7 @@ lpfc_fdmi_hba_attr_vendor_info(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; /* Nothing is defined for this currently */ ae->un.AttrInt = cpu_to_be32(0); @@ -2353,7 +2353,7 @@ lpfc_fdmi_hba_attr_num_ports(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; /* Each driver instance corresponds to a single port */ ae->un.AttrInt = cpu_to_be32(1); @@ -2370,8 +2370,8 @@ lpfc_fdmi_hba_attr_fabric_wwnn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, sizeof(struct lpfc_name)); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); memcpy(&ae->un.AttrWWN, &vport->fabric_nodename, sizeof(struct lpfc_name)); @@ -2389,8 +2389,8 @@ lpfc_fdmi_hba_attr_bios_ver(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strlcat(ae->un.AttrString, phba->BIOSVersion, sizeof(ae->un.AttrString)); @@ -2410,7 +2410,7 @@ lpfc_fdmi_hba_attr_bios_state(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; /* Driver doesn't have access to this information */ ae->un.AttrInt = cpu_to_be32(0); @@ -2427,8 +2427,8 @@ lpfc_fdmi_hba_attr_vendor_id(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strncpy(ae->un.AttrString, "EMULEX", sizeof(ae->un.AttrString)); @@ -2450,8 +2450,8 @@ lpfc_fdmi_port_attr_fc4type(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 32); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); ae->un.AttrTypes[2] = 0x01; /* Type 0x8 - FCP */ ae->un.AttrTypes[7] = 0x01; /* Type 0x20 - CT */ @@ -2475,7 +2475,7 @@ lpfc_fdmi_port_attr_support_speed(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; ae->un.AttrInt = 0; if (!(phba->hba_flag & HBA_FCOE_MODE)) { @@ -2529,7 +2529,7 @@ lpfc_fdmi_port_attr_speed(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; if (!(phba->hba_flag & HBA_FCOE_MODE)) { switch (phba->fc_linkspeed) { @@ -2599,7 +2599,7 @@ lpfc_fdmi_port_attr_max_frame(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; hsp = (struct serv_parm *)&vport->fc_sparam; ae->un.AttrInt = (((uint32_t) hsp->cmn.bbRcvSizeMsb & 0x0F) << 8) | @@ -2619,8 +2619,8 @@ lpfc_fdmi_port_attr_os_devname(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); snprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "/sys/class/scsi_host/host%d", shost->host_no); @@ -2640,8 +2640,8 @@ lpfc_fdmi_port_attr_host_name(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); scnprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s", vport->phba->os_host_name); @@ -2661,8 +2661,8 @@ lpfc_fdmi_port_attr_wwnn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, sizeof(struct lpfc_name)); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); memcpy(&ae->un.AttrWWN, &vport->fc_sparam.nodeName, sizeof(struct lpfc_name)); @@ -2679,8 +2679,8 @@ lpfc_fdmi_port_attr_wwpn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, sizeof(struct lpfc_name)); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); memcpy(&ae->un.AttrWWN, &vport->fc_sparam.portName, sizeof(struct lpfc_name)); @@ -2697,8 +2697,8 @@ lpfc_fdmi_port_attr_symbolic_name(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); len = lpfc_vport_symbolic_port_name(vport, ae->un.AttrString, 256); len += (len & 3) ? (4 - (len & 3)) : 4; @@ -2716,7 +2716,7 @@ lpfc_fdmi_port_attr_port_type(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) ae->un.AttrInt = cpu_to_be32(LPFC_FDMI_PORTTYPE_NLPORT); else @@ -2734,7 +2734,7 @@ lpfc_fdmi_port_attr_class(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; ae->un.AttrInt = cpu_to_be32(FC_COS_CLASS2 | FC_COS_CLASS3); size = FOURBYTES + sizeof(uint32_t); ad->AttrLen = cpu_to_be16(size); @@ -2749,8 +2749,8 @@ lpfc_fdmi_port_attr_fabric_wwpn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, sizeof(struct lpfc_name)); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); memcpy(&ae->un.AttrWWN, &vport->fabric_portname, sizeof(struct lpfc_name)); @@ -2767,8 +2767,8 @@ lpfc_fdmi_port_attr_active_fc4type(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 32); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); ae->un.AttrTypes[2] = 0x01; /* Type 0x8 - FCP */ ae->un.AttrTypes[7] = 0x01; /* Type 0x20 - CT */ @@ -2790,7 +2790,7 @@ lpfc_fdmi_port_attr_port_state(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; /* Link Up - operational */ ae->un.AttrInt = cpu_to_be32(LPFC_FDMI_PORTSTATE_ONLINE); size = FOURBYTES + sizeof(uint32_t); @@ -2806,7 +2806,7 @@ lpfc_fdmi_port_attr_num_disc(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; vport->fdmi_num_disc = lpfc_find_map_node(vport); ae->un.AttrInt = cpu_to_be32(vport->fdmi_num_disc); size = FOURBYTES + sizeof(uint32_t); @@ -2822,7 +2822,7 @@ lpfc_fdmi_port_attr_nportid(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; ae->un.AttrInt = cpu_to_be32(vport->fc_myDID); size = FOURBYTES + sizeof(uint32_t); ad->AttrLen = cpu_to_be16(size); @@ -2837,8 +2837,8 @@ lpfc_fdmi_smart_attr_service(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strncpy(ae->un.AttrString, "Smart SAN Initiator", sizeof(ae->un.AttrString)); @@ -2858,8 +2858,8 @@ lpfc_fdmi_smart_attr_guid(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); memcpy(&ae->un.AttrString, &vport->fc_sparam.nodeName, sizeof(struct lpfc_name)); @@ -2879,8 +2879,8 @@ lpfc_fdmi_smart_attr_version(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strncpy(ae->un.AttrString, "Smart SAN Version 2.0", sizeof(ae->un.AttrString)); @@ -2901,8 +2901,8 @@ lpfc_fdmi_smart_attr_model(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strncpy(ae->un.AttrString, phba->ModelName, sizeof(ae->un.AttrString)); @@ -2921,7 +2921,7 @@ lpfc_fdmi_smart_attr_port_info(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; /* SRIOV (type 3) is not supported */ if (vport->vpi) @@ -2941,7 +2941,7 @@ lpfc_fdmi_smart_attr_qos(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; ae->un.AttrInt = cpu_to_be32(0); size = FOURBYTES + sizeof(uint32_t); ad->AttrLen = cpu_to_be16(size); @@ -2956,7 +2956,7 @@ lpfc_fdmi_smart_attr_security(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; ae->un.AttrInt = cpu_to_be32(1); size = FOURBYTES + sizeof(uint32_t); ad->AttrLen = cpu_to_be16(size); @@ -3104,7 +3104,8 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /* Registered Port List */ /* One entry (port) per adapter */ rh->rpl.EntryCnt = cpu_to_be32(1); - memcpy(&rh->rpl.pe, &phba->pport->fc_sparam.portName, + memcpy(&rh->rpl.pe.PortName, + &phba->pport->fc_sparam.portName, sizeof(struct lpfc_name)); /* point to the HBA attribute block */ diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 436cdc8c5ef4..b5642c872593 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1340,25 +1340,8 @@ struct fc_rdp_res_frame { /* lpfc_sli_ct_request defines the CT_IU preamble for FDMI commands */ #define SLI_CT_FDMI_Subtypes 0x10 /* Management Service Subtype */ -/* - * Registered Port List Format - */ -struct lpfc_fdmi_reg_port_list { - uint32_t EntryCnt; - uint32_t pe; /* Variable-length array */ -}; - - /* Definitions for HBA / Port attribute entries */ -struct lpfc_fdmi_attr_def { /* Defined in TLV format */ - /* Structure is in Big Endian format */ - uint32_t AttrType:16; - uint32_t AttrLen:16; - uint32_t AttrValue; /* Marks start of Value (ATTRIBUTE_ENTRY) */ -}; - - /* Attribute Entry */ struct lpfc_fdmi_attr_entry { union { @@ -1369,7 +1352,13 @@ struct lpfc_fdmi_attr_entry { } un; }; -#define LPFC_FDMI_MAX_AE_SIZE sizeof(struct lpfc_fdmi_attr_entry) +struct lpfc_fdmi_attr_def { /* Defined in TLV format */ + /* Structure is in Big Endian format */ + uint32_t AttrType:16; + uint32_t AttrLen:16; + /* Marks start of Value (ATTRIBUTE_ENTRY) */ + struct lpfc_fdmi_attr_entry AttrValue; +} __packed; /* * HBA Attribute Block @@ -1393,13 +1382,20 @@ struct lpfc_fdmi_hba_ident { struct lpfc_name PortName; }; +/* + * Registered Port List Format + */ +struct lpfc_fdmi_reg_port_list { + uint32_t EntryCnt; + struct lpfc_fdmi_port_entry pe; +} __packed; + /* * Register HBA(RHBA) */ struct lpfc_fdmi_reg_hba { struct lpfc_fdmi_hba_ident hi; - struct lpfc_fdmi_reg_port_list rpl; /* variable-length array */ -/* struct lpfc_fdmi_attr_block ab; */ + struct lpfc_fdmi_reg_port_list rpl; }; /* From 6cde2e3e2813f598a39c8e5688480b76b2f40b10 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 27 Jan 2020 16:23:08 -0800 Subject: [PATCH 0094/4444] scsi: lpfc: Remove handler for obsolete ELS - Read Port Status (RPS) There was report of an odd "Fix me..." log message, which was tracked down to the lpfc_els_rcv_rps() routine. This was in handling of a very old and obsolete ELS - Read Port Status. The RPS ELS was defined in FC-LS-1, but deprecated in FC-LS-2, and removed from all later FC-LS revisions. It was replaced by the Read Diagnostic Parameters (RDP) ELS and the Link Error Status Block descriptor. There should be no support for the RSP ELS. Remove support from driver. Link: https://lore.kernel.org/r/20200128002312.16346-9-jsmart2021@gmail.com Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 1 - drivers/scsi/lpfc/lpfc_els.c | 193 +---------------------------------- drivers/scsi/lpfc/lpfc_hw.h | 20 ---- 3 files changed, 5 insertions(+), 209 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 3f2cb17c4574..cebbad1b3e55 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -262,7 +262,6 @@ struct lpfc_stats { uint32_t elsRcvPRLI; uint32_t elsRcvLIRR; uint32_t elsRcvRLS; - uint32_t elsRcvRPS; uint32_t elsRcvRPL; uint32_t elsRcvRRQ; uint32_t elsRcvRTV; diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 42a2bf38eaea..371599d67eb4 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -7134,109 +7134,13 @@ lpfc_els_rsp_rls_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_els_free_iocb(phba, elsiocb); } -/** - * lpfc_els_rsp_rps_acc - Completion callbk func for MBX_READ_LNK_STAT mbox cmd - * @phba: pointer to lpfc hba data structure. - * @pmb: pointer to the driver internal queue element for mailbox command. - * - * This routine is the completion callback function for the MBX_READ_LNK_STAT - * mailbox command. This callback function is to actually send the Accept - * (ACC) response to a Read Port Status (RPS) unsolicited IOCB event. It - * collects the link statistics from the completion of the MBX_READ_LNK_STAT - * mailbox command, constructs the RPS response with the link statistics - * collected, and then invokes the lpfc_sli_issue_iocb() routine to send ACC - * response to the RPS. - * - * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp - * will be incremented by 1 for holding the ndlp and the reference to ndlp - * will be stored into the context1 field of the IOCB for the completion - * callback function to the RPS Accept Response ELS IOCB command. - * - **/ -static void -lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) -{ - MAILBOX_t *mb; - IOCB_t *icmd; - RPS_RSP *rps_rsp; - uint8_t *pcmd; - struct lpfc_iocbq *elsiocb; - struct lpfc_nodelist *ndlp; - uint16_t status; - uint16_t oxid; - uint16_t rxid; - uint32_t cmdsize; - - mb = &pmb->u.mb; - - ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; - rxid = (uint16_t)((unsigned long)(pmb->ctx_buf) & 0xffff); - oxid = (uint16_t)(((unsigned long)(pmb->ctx_buf) >> 16) & 0xffff); - pmb->ctx_ndlp = NULL; - pmb->ctx_buf = NULL; - - if (mb->mbxStatus) { - mempool_free(pmb, phba->mbox_mem_pool); - return; - } - - cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t); - mempool_free(pmb, phba->mbox_mem_pool); - elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize, - lpfc_max_els_tries, ndlp, - ndlp->nlp_DID, ELS_CMD_ACC); - - /* Decrement the ndlp reference count from previous mbox command */ - lpfc_nlp_put(ndlp); - - if (!elsiocb) - return; - - icmd = &elsiocb->iocb; - icmd->ulpContext = rxid; - icmd->unsli3.rcvsli3.ox_id = oxid; - - pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); - *((uint32_t *) (pcmd)) = ELS_CMD_ACC; - pcmd += sizeof(uint32_t); /* Skip past command */ - rps_rsp = (RPS_RSP *)pcmd; - - if (phba->fc_topology != LPFC_TOPOLOGY_LOOP) - status = 0x10; - else - status = 0x8; - if (phba->pport->fc_flag & FC_FABRIC) - status |= 0x4; - - rps_rsp->rsvd1 = 0; - rps_rsp->portStatus = cpu_to_be16(status); - rps_rsp->linkFailureCnt = cpu_to_be32(mb->un.varRdLnk.linkFailureCnt); - rps_rsp->lossSyncCnt = cpu_to_be32(mb->un.varRdLnk.lossSyncCnt); - rps_rsp->lossSignalCnt = cpu_to_be32(mb->un.varRdLnk.lossSignalCnt); - rps_rsp->primSeqErrCnt = cpu_to_be32(mb->un.varRdLnk.primSeqErrCnt); - rps_rsp->invalidXmitWord = cpu_to_be32(mb->un.varRdLnk.invalidXmitWord); - rps_rsp->crcCnt = cpu_to_be32(mb->un.varRdLnk.crcCnt); - /* Xmit ELS RPS ACC response tag */ - lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS, - "0118 Xmit ELS RPS ACC response tag x%x xri x%x, " - "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n", - elsiocb->iotag, elsiocb->iocb.ulpContext, - ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, - ndlp->nlp_rpi); - elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; - phba->fc_stat.elsXmitACC++; - if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == IOCB_ERROR) - lpfc_els_free_iocb(phba, elsiocb); - return; -} - /** * lpfc_els_rcv_rls - Process an unsolicited rls iocb * @vport: pointer to a host virtual N_Port data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @ndlp: pointer to a node-list data structure. * - * This routine processes Read Port Status (RPL) IOCB received as an + * This routine processes Read Link Status (RLS) IOCB received as an * ELS unsolicited event. It first checks the remote port state. If the * remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE * state, it invokes the lpfc_els_rsl_reject() routine to send the reject @@ -7258,7 +7162,7 @@ lpfc_els_rcv_rls(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) - /* reject the unsolicited RPS request and done with it */ + /* reject the unsolicited RLS request and done with it */ goto reject_out; mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC); @@ -7306,7 +7210,7 @@ reject_out: * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp * will be incremented by 1 for holding the ndlp and the reference to ndlp * will be stored into the context1 field of the IOCB for the completion - * callback function to the RPS Accept Response ELS IOCB command. + * callback function to the RTV Accept Response ELS IOCB command. * * Return codes * 0 - Successfully processed rtv iocb (currently always return 0) @@ -7325,7 +7229,7 @@ lpfc_els_rcv_rtv(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) - /* reject the unsolicited RPS request and done with it */ + /* reject the unsolicited RTV request and done with it */ goto reject_out; cmdsize = sizeof(struct RTV_RSP) + sizeof(uint32_t); @@ -7378,84 +7282,7 @@ reject_out: return 0; } -/* lpfc_els_rcv_rps - Process an unsolicited rps iocb - * @vport: pointer to a host virtual N_Port data structure. - * @cmdiocb: pointer to lpfc command iocb data structure. - * @ndlp: pointer to a node-list data structure. - * - * This routine processes Read Port Status (RPS) IOCB received as an - * ELS unsolicited event. It first checks the remote port state. If the - * remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE - * state, it invokes the lpfc_els_rsp_reject() routine to send the reject - * response. Otherwise, it issue the MBX_READ_LNK_STAT mailbox command - * for reading the HBA link statistics. It is for the callback function, - * lpfc_els_rsp_rps_acc(), set to the MBX_READ_LNK_STAT mailbox command - * to actually sending out RPS Accept (ACC) response. - * - * Return codes - * 0 - Successfully processed rps iocb (currently always return 0) - **/ -static int -lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, - struct lpfc_nodelist *ndlp) -{ - struct lpfc_hba *phba = vport->phba; - uint32_t *lp; - uint8_t flag; - LPFC_MBOXQ_t *mbox; - struct lpfc_dmabuf *pcmd; - RPS *rps; - struct ls_rjt stat; - - if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && - (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) - /* reject the unsolicited RPS request and done with it */ - goto reject_out; - - pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; - lp = (uint32_t *) pcmd->virt; - flag = (be32_to_cpu(*lp++) & 0xf); - rps = (RPS *) lp; - - if ((flag == 0) || - ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) || - ((flag == 2) && (memcmp(&rps->un.portName, &vport->fc_portname, - sizeof(struct lpfc_name)) == 0))) { - - printk("Fix me....\n"); - dump_stack(); - mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC); - if (mbox) { - lpfc_read_lnk_stat(phba, mbox); - mbox->ctx_buf = (void *)((unsigned long) - ((cmdiocb->iocb.unsli3.rcvsli3.ox_id << 16) | - cmdiocb->iocb.ulpContext)); /* rx_id */ - mbox->ctx_ndlp = lpfc_nlp_get(ndlp); - mbox->vport = vport; - mbox->mbox_cmpl = lpfc_els_rsp_rps_acc; - if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) - != MBX_NOT_FINISHED) - /* Mbox completion will send ELS Response */ - return 0; - /* Decrement reference count used for the failed mbox - * command. - */ - lpfc_nlp_put(ndlp); - mempool_free(mbox, phba->mbox_mem_pool); - } - } - -reject_out: - /* issue rejection response */ - stat.un.b.lsRjtRsvd0 = 0; - stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; - stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; - stat.un.b.vendorUnique = 0; - lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); - return 0; -} - -/* lpfc_issue_els_rrq - Process an unsolicited rps iocb +/* lpfc_issue_els_rrq - Process an unsolicited rrq iocb * @vport: pointer to a host virtual N_Port data structure. * @ndlp: pointer to a node-list data structure. * @did: DID of the target. @@ -8632,16 +8459,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, if (newnode) lpfc_nlp_put(ndlp); break; - case ELS_CMD_RPS: - lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, - "RCV RPS: did:x%x/ste:x%x flg:x%x", - did, vport->port_state, ndlp->nlp_flag); - - phba->fc_stat.elsRcvRPS++; - lpfc_els_rcv_rps(vport, elsiocb, ndlp); - if (newnode) - lpfc_nlp_put(ndlp); - break; case ELS_CMD_RPL: lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, "RCV RPL: did:x%x/ste:x%x flg:x%x", diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index b5642c872593..9a5979075646 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -597,7 +597,6 @@ struct fc_vft_header { #define ELS_CMD_ADISC 0x52000000 #define ELS_CMD_FARP 0x54000000 #define ELS_CMD_FARPR 0x55000000 -#define ELS_CMD_RPS 0x56000000 #define ELS_CMD_RPL 0x57000000 #define ELS_CMD_FAN 0x60000000 #define ELS_CMD_RSCN 0x61040000 @@ -639,7 +638,6 @@ struct fc_vft_header { #define ELS_CMD_ADISC 0x52 #define ELS_CMD_FARP 0x54 #define ELS_CMD_FARPR 0x55 -#define ELS_CMD_RPS 0x56 #define ELS_CMD_RPL 0x57 #define ELS_CMD_FAN 0x60 #define ELS_CMD_RSCN 0x0461 @@ -919,24 +917,6 @@ typedef struct _RNID { /* Structure is in Big Endian format */ } un; } __packed RNID; -typedef struct _RPS { /* Structure is in Big Endian format */ - union { - uint32_t portNum; - struct lpfc_name portName; - } un; -} RPS; - -typedef struct _RPS_RSP { /* Structure is in Big Endian format */ - uint16_t rsvd1; - uint16_t portStatus; - uint32_t linkFailureCnt; - uint32_t lossSyncCnt; - uint32_t lossSignalCnt; - uint32_t primSeqErrCnt; - uint32_t invalidXmitWord; - uint32_t crcCnt; -} RPS_RSP; - struct RLS { /* Structure is in Big Endian format */ uint32_t rls; #define rls_rsvd_SHIFT 24 From f6770e7d2329f0b05223fffea9eb821fd2dd038a Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 27 Jan 2020 16:23:09 -0800 Subject: [PATCH 0095/4444] scsi: lpfc: Clean up hba max_lun_queue_depth checks The current code does some odd +1 over maximum xri count checks and requires that the lun_queue_count can't be bigger than maximum xri count divided by 8. These items are bogus. Clean the code up to cap lun_queue_count to maximum xri count. Link: https://lore.kernel.org/r/20200128002312.16346-10-jsmart2021@gmail.com Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 3 --- drivers/scsi/lpfc/lpfc_init.c | 17 ++++------------- drivers/scsi/lpfc/lpfc_sli.c | 9 --------- 3 files changed, 4 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 46f56f30f77e..48b6c98ec922 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -3869,9 +3869,6 @@ LPFC_VPORT_ATTR_R(enable_da_id, 1, 0, 1, /* # lun_queue_depth: This parameter is used to limit the number of outstanding # commands per FCP LUN. Value range is [1,512]. Default value is 30. -# If this parameter value is greater than 1/8th the maximum number of exchanges -# supported by the HBA port, then the lun queue depth will be reduced to -# 1/8th the maximum number of exchanges. */ LPFC_VPORT_ATTR_R(lun_queue_depth, 30, 1, 512, "Max number of FCP commands we can queue to a specific LUN"); diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 9a6191818a23..6d571e0b74f0 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -512,21 +512,12 @@ lpfc_config_port_post(struct lpfc_hba *phba) lpfc_sli_read_link_ste(phba); /* Reset the DFT_HBA_Q_DEPTH to the max xri */ - i = (mb->un.varRdConfig.max_xri + 1); - if (phba->cfg_hba_queue_depth > i) { + if (phba->cfg_hba_queue_depth > mb->un.varRdConfig.max_xri) { lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, "3359 HBA queue depth changed from %d to %d\n", - phba->cfg_hba_queue_depth, i); - phba->cfg_hba_queue_depth = i; - } - - /* Reset the DFT_LUN_Q_DEPTH to (max xri >> 3) */ - i = (mb->un.varRdConfig.max_xri >> 3); - if (phba->pport->cfg_lun_queue_depth > i) { - lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, - "3360 LUN queue depth changed from %d to %d\n", - phba->pport->cfg_lun_queue_depth, i); - phba->pport->cfg_lun_queue_depth = i; + phba->cfg_hba_queue_depth, + mb->un.varRdConfig.max_xri); + phba->cfg_hba_queue_depth = mb->un.varRdConfig.max_xri; } phba->lmt = mb->un.varRdConfig.lmt; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index ab6f58bc80a4..a5fd043e9be4 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -7371,15 +7371,6 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) phba->vpd.rev.fcphHigh, phba->vpd.rev.fcphLow, phba->vpd.rev.feaLevelHigh, phba->vpd.rev.feaLevelLow); - /* Reset the DFT_LUN_Q_DEPTH to (max xri >> 3) */ - rc = (phba->sli4_hba.max_cfg_param.max_xri >> 3); - if (phba->pport->cfg_lun_queue_depth > rc) { - lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, - "3362 LUN queue depth changed from %d to %d\n", - phba->pport->cfg_lun_queue_depth, rc); - phba->pport->cfg_lun_queue_depth = rc; - } - if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == LPFC_SLI_INTF_IF_TYPE_0) { lpfc_set_features(phba, mboxq, LPFC_SET_UE_RECOVERY); From ad6203f975263752e9738a33eacbc92f5bb6f636 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 27 Jan 2020 16:23:11 -0800 Subject: [PATCH 0096/4444] scsi: lpfc: Update lpfc version to 12.6.0.4 Update lpfc version to 12.6.0.4 Link: https://lore.kernel.org/r/20200128002312.16346-12-jsmart2021@gmail.com Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 9563c49f36ab..25193146ef20 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -20,7 +20,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "12.6.0.3" +#define LPFC_DRIVER_VERSION "12.6.0.4" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ From 145e5a8a5cbd0c608dfe653c92edb70a580bdbf6 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 27 Jan 2020 16:23:12 -0800 Subject: [PATCH 0097/4444] scsi: lpfc: Copyright updates for 12.6.0.4 patches Update copyrights to 2020 for files modified in the 12.6.0.4 patch set. Link: https://lore.kernel.org/r/20200128002312.16346-13-jsmart2021@gmail.com Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 2 +- drivers/scsi/lpfc/lpfc_attr.c | 2 +- drivers/scsi/lpfc/lpfc_ct.c | 2 +- drivers/scsi/lpfc/lpfc_els.c | 2 +- drivers/scsi/lpfc/lpfc_hbadisc.c | 2 +- drivers/scsi/lpfc/lpfc_hw.h | 2 +- drivers/scsi/lpfc/lpfc_init.c | 2 +- drivers/scsi/lpfc/lpfc_scsi.c | 2 +- drivers/scsi/lpfc/lpfc_sli.c | 2 +- drivers/scsi/lpfc/lpfc_version.h | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index cebbad1b3e55..6abc837b9a33 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 48b6c98ec922..4317c9ce7eca 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 8db27e84263e..2aa578d20f8c 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 371599d67eb4..8a38e6f7f853 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 6a2bdae0e52a..e8937071c748 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 9a5979075646..68f62ae6ef4f 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 6d571e0b74f0..9d03e9b71efb 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 96ac4a154c58..0fc9a242bc65 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index a5fd043e9be4..86ac10ecd65a 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 25193146ef20..c4ab006e6ecc 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * From f0df2e05a2d93e5feda871db0401399f5836abaa Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 10 Feb 2020 18:06:52 +0100 Subject: [PATCH 0098/4444] dt-bindings: interconnect: sunxi: Add A64 MBUS compatible A64 contains MBUS controller. Add a compatible for it. Acked-by: Rob Herring Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- .../devicetree/bindings/arm/sunxi/allwinner,sun4i-a10-mbus.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/sunxi/allwinner,sun4i-a10-mbus.yaml b/Documentation/devicetree/bindings/arm/sunxi/allwinner,sun4i-a10-mbus.yaml index 9370e64992dd..aa0738b4d534 100644 --- a/Documentation/devicetree/bindings/arm/sunxi/allwinner,sun4i-a10-mbus.yaml +++ b/Documentation/devicetree/bindings/arm/sunxi/allwinner,sun4i-a10-mbus.yaml @@ -30,6 +30,7 @@ properties: enum: - allwinner,sun5i-a13-mbus - allwinner,sun8i-h3-mbus + - allwinner,sun50i-a64-mbus reg: maxItems: 1 From fc7c2bfb08c36d26b9cad391636566fcdb75fef0 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 10 Feb 2020 18:06:54 +0100 Subject: [PATCH 0099/4444] arm64: dts: allwinner: a64: Add MBUS controller node A64 contains MBUS, which is the bus used by DMA devices to access system memory. MBUS controller is responsible for arbitration between channels based on set priority and can do some other things as well, like report bandwidth used. It also maps RAM region to different address than CPU. Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index 862b47dc9dc9..251c91724de1 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -1061,6 +1061,14 @@ status = "disabled"; }; + mbus: dram-controller@1c62000 { + compatible = "allwinner,sun50i-a64-mbus"; + reg = <0x01c62000 0x1000>; + clocks = <&ccu 112>; + dma-ranges = <0x00000000 0x40000000 0xc0000000>; + #interconnect-cells = <1>; + }; + csi: csi@1cb0000 { compatible = "allwinner,sun50i-a64-csi"; reg = <0x01cb0000 0x1000>; From a7f3e0bbf2c14abc60fb2e51c26b16fa642bf052 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 10 Feb 2020 18:06:55 +0100 Subject: [PATCH 0100/4444] media: dt-bindings: media: Add Allwinner A64 deinterlace compatible Allwinner A64 SoC also contains deinterlace core, compatible to H3. Add compatible string for it. Acked-by: Rob Herring Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- .../bindings/media/allwinner,sun8i-h3-deinterlace.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/media/allwinner,sun8i-h3-deinterlace.yaml b/Documentation/devicetree/bindings/media/allwinner,sun8i-h3-deinterlace.yaml index 2e40f700e84f..8707df613f6c 100644 --- a/Documentation/devicetree/bindings/media/allwinner,sun8i-h3-deinterlace.yaml +++ b/Documentation/devicetree/bindings/media/allwinner,sun8i-h3-deinterlace.yaml @@ -17,7 +17,11 @@ description: |- properties: compatible: - const: allwinner,sun8i-h3-deinterlace + oneOf: + - const: allwinner,sun8i-h3-deinterlace + - items: + - const: allwinner,sun50i-a64-deinterlace + - const: allwinner,sun8i-h3-deinterlace reg: maxItems: 1 From dd00d78d0f41ec1932d90f23741dbf79b8d8544e Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 10 Feb 2020 18:06:56 +0100 Subject: [PATCH 0101/4444] arm64: dts: allwinner: a64: Add deinterlace core node A64 contains deinterlace core, compatible to the one found in H3. It can be used in combination with VPU unit to decode and process interlaced videos. Add a node for it. Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index 251c91724de1..72b1b34879c6 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -1114,6 +1114,20 @@ #phy-cells = <0>; }; + deinterlace: deinterlace@1e00000 { + compatible = "allwinner,sun50i-a64-deinterlace", + "allwinner,sun8i-h3-deinterlace"; + reg = <0x01e00000 0x20000>; + clocks = <&ccu CLK_BUS_DEINTERLACE>, + <&ccu CLK_DEINTERLACE>, + <&ccu CLK_DRAM_DEINTERLACE>; + clock-names = "bus", "mod", "ram"; + resets = <&ccu RST_BUS_DEINTERLACE>; + interrupts = ; + interconnects = <&mbus 9>; + interconnect-names = "dma-mem"; + }; + hdmi: hdmi@1ee0000 { compatible = "allwinner,sun50i-a64-dw-hdmi", "allwinner,sun8i-a83t-dw-hdmi"; From 1de8493069b8f510e586242c1b4329cd3c9b6fb9 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 10 Feb 2020 18:06:53 +0100 Subject: [PATCH 0102/4444] clk: sunxi-ng: a64: Export MBUS clock MBUS clock will be referenced in MBUS controller node. Export it. Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun50i-a64.h | 4 ---- include/dt-bindings/clock/sun50i-a64-ccu.h | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.h b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h index 116e6f826d04..54d1f96f4b68 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.h +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h @@ -55,10 +55,6 @@ /* All the DRAM gates are exported */ -/* Some more module clocks are exported */ - -#define CLK_MBUS 112 - /* And the DSI and GPU module clock is exported */ #define CLK_NUMBER (CLK_GPU + 1) diff --git a/include/dt-bindings/clock/sun50i-a64-ccu.h b/include/dt-bindings/clock/sun50i-a64-ccu.h index e512a1c9b0fc..318eb15c414c 100644 --- a/include/dt-bindings/clock/sun50i-a64-ccu.h +++ b/include/dt-bindings/clock/sun50i-a64-ccu.h @@ -131,7 +131,7 @@ #define CLK_AVS 109 #define CLK_HDMI 110 #define CLK_HDMI_DDC 111 - +#define CLK_MBUS 112 #define CLK_DSI_DPHY 113 #define CLK_GPU 114 From 221a690420fdad808eb0b39eebb19d4eda95568c Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 10 Feb 2020 18:40:07 +0100 Subject: [PATCH 0103/4444] arm64: dts: allwinner: h6: orangepi-3: Add eMMC node OrangePi 3 can optionally have 8 GiB eMMC (soldered on board). Because those pins are dedicated to eMMC exclusively, node can be added for both variants (with and without eMMC). Kernel will then scan bus for presence of eMMC and act accordingly. Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts index c311eee52a35..1e0abd9d047f 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts @@ -144,6 +144,15 @@ }; }; +&mmc2 { + vmmc-supply = <®_cldo1>; + vqmmc-supply = <®_bldo2>; + cap-mmc-hw-reset; + non-removable; + bus-width = <8>; + status = "okay"; +}; + &ohci0 { status = "okay"; }; From 8673e944b50ec6e5afd4f599cf12b2798b629f3d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 5 Feb 2020 11:48:28 +0200 Subject: [PATCH 0104/4444] platform/chrome: wilco_ec: Platform data shouldn't include kernel.h Replace with appropriate types.h. Also there is no need to include device.h, but mutex.h. For the pointers to unknown structures use forward declarations. In the *.c files we need to include all headers that provide APIs being used in the module. Signed-off-by: Andy Shevchenko Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/wilco_ec/properties.c | 3 +++ drivers/platform/chrome/wilco_ec/sysfs.c | 4 ++++ include/linux/platform_data/wilco-ec.h | 8 ++++++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/platform/chrome/wilco_ec/properties.c b/drivers/platform/chrome/wilco_ec/properties.c index 62f27610dd33..c2bf4c95c5d2 100644 --- a/drivers/platform/chrome/wilco_ec/properties.c +++ b/drivers/platform/chrome/wilco_ec/properties.c @@ -3,8 +3,11 @@ * Copyright 2019 Google LLC */ +#include +#include #include #include +#include #include /* Operation code; what the EC should do with the property */ diff --git a/drivers/platform/chrome/wilco_ec/sysfs.c b/drivers/platform/chrome/wilco_ec/sysfs.c index f0d174b6bb21..3c587b4054a5 100644 --- a/drivers/platform/chrome/wilco_ec/sysfs.c +++ b/drivers/platform/chrome/wilco_ec/sysfs.c @@ -8,8 +8,12 @@ * See Documentation/ABI/testing/sysfs-platform-wilco-ec for more information. */ +#include +#include #include +#include #include +#include #define CMD_KB_CMOS 0x7C #define SUB_CMD_KB_CMOS_AUTO_ON 0x03 diff --git a/include/linux/platform_data/wilco-ec.h b/include/linux/platform_data/wilco-ec.h index afede15a95bf..25f46a939637 100644 --- a/include/linux/platform_data/wilco-ec.h +++ b/include/linux/platform_data/wilco-ec.h @@ -8,8 +8,8 @@ #ifndef WILCO_EC_H #define WILCO_EC_H -#include -#include +#include +#include /* Message flags for using the mailbox() interface */ #define WILCO_EC_FLAG_NO_RESPONSE BIT(0) /* EC does not respond */ @@ -17,6 +17,10 @@ /* Normal commands have a maximum 32 bytes of data */ #define EC_MAILBOX_DATA_SIZE 32 +struct device; +struct resource; +struct platform_device; + /** * struct wilco_ec_device - Wilco Embedded Controller handle. * @dev: Device handle. From 42cd0ab476e2daffc23982c37822a78f9a53cdd5 Mon Sep 17 00:00:00 2001 From: Yicheng Li Date: Mon, 3 Feb 2020 14:53:56 -0800 Subject: [PATCH 0105/4444] platform/chrome: cros_ec: Query EC protocol version if EC transitions between RO/RW RO and RW of EC may have different EC protocol version. If EC transitions between RO and RW, but AP does not reboot (this is true for fingerprint microcontroller / cros_fp, but not true for main ec / cros_ec), the AP still uses the protocol version queried before transition, which can cause problems. In the case of fingerprint microcontroller, this causes AP to send the wrong version of EC_CMD_GET_NEXT_EVENT to RO in the interrupt handler, which in turn prevents RO to clear the interrupt line to AP, in an infinite loop. Once an EC_HOST_EVENT_INTERFACE_READY is received, we know that there might have been a transition between RO and RW, so re-query the protocol. Signed-off-by: Yicheng Li Tested-by: Marek Szyprowski Reviewed-by: Gwendal Grignou Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec.c | 30 +++++++++++++++++++++ include/linux/platform_data/cros_ec_proto.h | 4 +++ 2 files changed, 34 insertions(+) diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c index 6fc8f2c3ac51..7ee43b2e0654 100644 --- a/drivers/platform/chrome/cros_ec.c +++ b/drivers/platform/chrome/cros_ec.c @@ -138,6 +138,24 @@ static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event) return ret; } +static int cros_ec_ready_event(struct notifier_block *nb, + unsigned long queued_during_suspend, + void *_notify) +{ + struct cros_ec_device *ec_dev = container_of(nb, struct cros_ec_device, + notifier_ready); + u32 host_event = cros_ec_get_host_event(ec_dev); + + if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_INTERFACE_READY)) { + mutex_lock(&ec_dev->lock); + cros_ec_query_all(ec_dev); + mutex_unlock(&ec_dev->lock); + return NOTIFY_OK; + } + + return NOTIFY_DONE; +} + /** * cros_ec_register() - Register a new ChromeOS EC, using the provided info. * @ec_dev: Device to register. @@ -237,6 +255,18 @@ int cros_ec_register(struct cros_ec_device *ec_dev) dev_dbg(ec_dev->dev, "Error %d clearing sleep event to ec", err); + if (ec_dev->mkbp_event_supported) { + /* + * Register the notifier for EC_HOST_EVENT_INTERFACE_READY + * event. + */ + ec_dev->notifier_ready.notifier_call = cros_ec_ready_event; + err = blocking_notifier_chain_register(&ec_dev->event_notifier, + &ec_dev->notifier_ready); + if (err) + return err; + } + dev_info(dev, "Chrome EC device registered\n"); return 0; diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h index ba5914770191..383243326676 100644 --- a/include/linux/platform_data/cros_ec_proto.h +++ b/include/linux/platform_data/cros_ec_proto.h @@ -125,6 +125,9 @@ struct cros_ec_command { * @host_event_wake_mask: Mask of host events that cause wake from suspend. * @last_event_time: exact time from the hard irq when we got notified of * a new event. + * @notifier_ready: The notifier_block to let the kernel re-query EC + * communication protocol when the EC sends + * EC_HOST_EVENT_INTERFACE_READY. * @ec: The platform_device used by the mfd driver to interface with the * main EC. * @pd: The platform_device used by the mfd driver to interface with the @@ -166,6 +169,7 @@ struct cros_ec_device { u32 host_event_wake_mask; u32 last_resume_result; ktime_t last_event_time; + struct notifier_block notifier_ready; /* The platform devices used by the mfd driver */ struct platform_device *ec; From 99b4f439a1c62d6a122636c5cd55ee3671dd96f4 Mon Sep 17 00:00:00 2001 From: Yu-Hsuan Hsu Date: Sun, 26 Jan 2020 00:29:17 +0800 Subject: [PATCH 0106/4444] ASoC: cros_ec_codec: Support setting bclk ratio Support setting bclk ratio from machine drivers. Signed-off-by: Yu-Hsuan Hsu Reviewed-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200125162917.247485-1-yuhsuan@chromium.org Signed-off-by: Mark Brown --- sound/soc/codecs/cros_ec_codec.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c index 6a24f570c5e8..d3dc42aa6825 100644 --- a/sound/soc/codecs/cros_ec_codec.c +++ b/sound/soc/codecs/cros_ec_codec.c @@ -45,6 +45,9 @@ struct cros_ec_codec_priv { /* DMIC */ atomic_t dmic_probed; + /* I2S_RX */ + uint32_t i2s_rx_bclk_ratio; + /* WoV */ bool wov_enabled; uint8_t *wov_audio_shm_p; @@ -259,6 +262,7 @@ static int i2s_rx_hw_params(struct snd_pcm_substream *substream, snd_soc_component_get_drvdata(component); struct ec_param_ec_codec_i2s_rx p; enum ec_codec_i2s_rx_sample_depth depth; + uint32_t bclk; int ret; if (params_rate(params) != 48000) @@ -284,15 +288,29 @@ static int i2s_rx_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - dev_dbg(component->dev, "set bclk to %u\n", - snd_soc_params_to_bclk(params)); + if (priv->i2s_rx_bclk_ratio) + bclk = params_rate(params) * priv->i2s_rx_bclk_ratio; + else + bclk = snd_soc_params_to_bclk(params); + + dev_dbg(component->dev, "set bclk to %u\n", bclk); p.cmd = EC_CODEC_I2S_RX_SET_BCLK; - p.set_bclk_param.bclk = snd_soc_params_to_bclk(params); + p.set_bclk_param.bclk = bclk; return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX, (uint8_t *)&p, sizeof(p), NULL, 0); } +static int i2s_rx_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) +{ + struct snd_soc_component *component = dai->component; + struct cros_ec_codec_priv *priv = + snd_soc_component_get_drvdata(component); + + priv->i2s_rx_bclk_ratio = ratio; + return 0; +} + static int i2s_rx_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct snd_soc_component *component = dai->component; @@ -340,6 +358,7 @@ static int i2s_rx_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) static const struct snd_soc_dai_ops i2s_rx_dai_ops = { .hw_params = i2s_rx_hw_params, .set_fmt = i2s_rx_set_fmt, + .set_bclk_ratio = i2s_rx_set_bclk_ratio, }; static int i2s_rx_event(struct snd_soc_dapm_widget *w, From f40ed2e8db8d51c0b8155bee3a293528d9f7a956 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 29 Jan 2020 16:36:01 -0600 Subject: [PATCH 0107/4444] ASoC: Intel: sof_pcm512x: add support for SOF platforms with pcm512x Add support for multiple platforms, e.g. Apollolake based, using the pcm512x audio codec. The SOF developers and CI rely on the Up^2 and Hifiberry DAC+ boards based on this codec for tests. Signed-off-by: Kai Vehmanen Signed-off-by: Pan Xiuli Signed-off-by: Ranjani Sridharan Signed-off-by: Guennadi Liakhovetski Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200129223603.2569-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 14 + sound/soc/intel/boards/Makefile | 2 + sound/soc/intel/boards/sof_pcm512x.c | 428 +++++++++++++++++++++++++++ 3 files changed, 444 insertions(+) create mode 100644 sound/soc/intel/boards/sof_pcm512x.c diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 9ca2567d0059..755e1de19df9 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -457,6 +457,20 @@ config SND_SOC_INTEL_SOF_RT5682_MACH with rt5682 codec. Say Y if you have such a device. If unsure select "N". + +config SND_SOC_INTEL_SOF_PCM512x_MACH + tristate "SOF with TI PCM512x codec" + depends on I2C && ACPI + depends on (SND_SOC_SOF_HDA_AUDIO_CODEC && (MFD_INTEL_LPSS || COMPILE_TEST)) ||\ + (SND_SOC_SOF_BAYTRAIL && (X86_INTEL_LPSS || COMPILE_TEST)) + select SND_SOC_PCM512x_I2C + select SND_HDA_CODEC_HDMI if SND_SOC_SOF_HDA_AUDIO_CODEC + help + This adds support for ASoC machine driver for SOF platforms + with TI PCM512x I2S audio codec. + Say Y or m if you have such a device. + If unsure select "N". + endif ## SND_SOC_SOF_HDA_LINK || SND_SOC_SOF_BAYTRAIL if (SND_SOC_SOF_COMETLAKE_LP && SND_SOC_SOF_HDA_LINK) diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index b74ddd49bd39..781e7ec58e47 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -7,6 +7,7 @@ snd-soc-sst-bdw-rt5677-mach-objs := bdw-rt5677.o snd-soc-sst-broadwell-objs := broadwell.o snd-soc-sst-bxt-da7219_max98357a-objs := bxt_da7219_max98357a.o hda_dsp_common.o snd-soc-sst-bxt-rt298-objs := bxt_rt298.o hda_dsp_common.o +snd-soc-sst-sof-pcm512x-objs := sof_pcm512x.o hda_dsp_common.o snd-soc-sst-glk-rt5682_max98357a-objs := glk_rt5682_max98357a.o hda_dsp_common.o snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o @@ -37,6 +38,7 @@ obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON) += snd-soc-sst-bxt-da7219_max98357a.o obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o +obj-$(CONFIG_SND_SOC_INTEL_SOF_PCM512x_MACH) += snd-soc-sst-sof-pcm512x.o obj-$(CONFIG_SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH) += snd-soc-sst-glk-rt5682_max98357a.o obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5650_MACH) += snd-soc-sst-bdw-rt5650-mach.o diff --git a/sound/soc/intel/boards/sof_pcm512x.c b/sound/soc/intel/boards/sof_pcm512x.c new file mode 100644 index 000000000000..626153bd71e7 --- /dev/null +++ b/sound/soc/intel/boards/sof_pcm512x.c @@ -0,0 +1,428 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright(c) 2018-2020 Intel Corporation. + +/* + * Intel SOF Machine Driver for Intel platforms with TI PCM512x codec, + * e.g. Up or Up2 with Hifiberry DAC+ HAT + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../codecs/pcm512x.h" +#include "../common/soc-intel-quirks.h" +#include "hda_dsp_common.h" + +#define NAME_SIZE 32 + +#define SOF_PCM512X_SSP_CODEC(quirk) ((quirk) & GENMASK(3, 0)) +#define SOF_PCM512X_SSP_CODEC_MASK (GENMASK(3, 0)) + +/* Default: SSP5 */ +static unsigned long sof_pcm512x_quirk = SOF_PCM512X_SSP_CODEC(5); + +static bool is_legacy_cpu; + +struct sof_hdmi_pcm { + struct list_head head; + struct snd_soc_dai *codec_dai; + int device; +}; + +struct sof_card_private { + struct list_head hdmi_pcm_list; +}; + +static int sof_pcm512x_quirk_cb(const struct dmi_system_id *id) +{ + sof_pcm512x_quirk = (unsigned long)id->driver_data; + return 1; +} + +static const struct dmi_system_id sof_pcm512x_quirk_table[] = { + { + .callback = sof_pcm512x_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), + DMI_MATCH(DMI_PRODUCT_NAME, "UP-CHT01"), + }, + .driver_data = (void *)(SOF_PCM512X_SSP_CODEC(2)), + }, + {} +}; + +static int sof_hdmi_init(struct snd_soc_pcm_runtime *rtd) +{ + struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_dai *dai = rtd->codec_dai; + struct sof_hdmi_pcm *pcm; + + pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); + if (!pcm) + return -ENOMEM; + + /* dai_link id is 1:1 mapped to the PCM device */ + pcm->device = rtd->dai_link->id; + pcm->codec_dai = dai; + + list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); + + return 0; +} + +static int sof_pcm512x_codec_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *codec = rtd->codec_dai->component; + + snd_soc_component_update_bits(codec, PCM512x_GPIO_EN, 0x08, 0x08); + snd_soc_component_update_bits(codec, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02); + snd_soc_component_update_bits(codec, PCM512x_GPIO_CONTROL_1, + 0x08, 0x08); + + return 0; +} + +static int aif1_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_component *codec = rtd->codec_dai->component; + + snd_soc_component_update_bits(codec, PCM512x_GPIO_CONTROL_1, + 0x08, 0x08); + + return 0; +} + +static void aif1_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_component *codec = rtd->codec_dai->component; + + snd_soc_component_update_bits(codec, PCM512x_GPIO_CONTROL_1, + 0x08, 0x00); +} + +static const struct snd_soc_ops sof_pcm512x_ops = { + .startup = aif1_startup, + .shutdown = aif1_shutdown, +}; + +static struct snd_soc_dai_link_component platform_component[] = { + { + /* name might be overridden during probe */ + .name = "0000:00:1f.3" + } +}; + +#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) +static int sof_card_late_probe(struct snd_soc_card *card) +{ + struct sof_card_private *ctx = snd_soc_card_get_drvdata(card); + struct sof_hdmi_pcm *pcm; + + /* HDMI is not supported by SOF on Baytrail/CherryTrail */ + if (is_legacy_cpu) + return 0; + + if (list_empty(&ctx->hdmi_pcm_list)) + return -EINVAL; + + pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm, head); + + return hda_dsp_hdmi_build_controls(card, pcm->codec_dai->component); +} +#else +static int sof_card_late_probe(struct snd_soc_card *card) +{ + return 0; +} +#endif + +static const struct snd_kcontrol_new sof_controls[] = { + SOC_DAPM_PIN_SWITCH("Ext Spk"), +}; + +static const struct snd_soc_dapm_widget sof_widgets[] = { + SND_SOC_DAPM_SPK("Ext Spk", NULL), +}; + +static const struct snd_soc_dapm_widget dmic_widgets[] = { + SND_SOC_DAPM_MIC("SoC DMIC", NULL), +}; + +static const struct snd_soc_dapm_route sof_map[] = { + /* Speaker */ + {"Ext Spk", NULL, "OUTR"}, + {"Ext Spk", NULL, "OUTL"}, +}; + +static const struct snd_soc_dapm_route dmic_map[] = { + /* digital mics */ + {"DMic", NULL, "SoC DMIC"}, +}; + +static int dmic_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets, + ARRAY_SIZE(dmic_widgets)); + if (ret) { + dev_err(card->dev, "DMic widget addition failed: %d\n", ret); + /* Don't need to add routes if widget addition failed */ + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map, + ARRAY_SIZE(dmic_map)); + + if (ret) + dev_err(card->dev, "DMic map addition failed: %d\n", ret); + + return ret; +} + +/* sof audio machine driver for pcm512x codec */ +static struct snd_soc_card sof_audio_card_pcm512x = { + .name = "pcm512x", + .owner = THIS_MODULE, + .controls = sof_controls, + .num_controls = ARRAY_SIZE(sof_controls), + .dapm_widgets = sof_widgets, + .num_dapm_widgets = ARRAY_SIZE(sof_widgets), + .dapm_routes = sof_map, + .num_dapm_routes = ARRAY_SIZE(sof_map), + .fully_routed = true, + .late_probe = sof_card_late_probe, +}; + +SND_SOC_DAILINK_DEF(pcm512x_component, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-104C5122:00", "pcm512x-hifi"))); +SND_SOC_DAILINK_DEF(dmic_component, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); + +static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, + int ssp_codec, + int dmic_be_num, + int hdmi_num) +{ + struct snd_soc_dai_link_component *idisp_components; + struct snd_soc_dai_link_component *cpus; + struct snd_soc_dai_link *links; + int i, id = 0; + + links = devm_kcalloc(dev, sof_audio_card_pcm512x.num_links, + sizeof(struct snd_soc_dai_link), GFP_KERNEL); + cpus = devm_kcalloc(dev, sof_audio_card_pcm512x.num_links, + sizeof(struct snd_soc_dai_link_component), GFP_KERNEL); + if (!links || !cpus) + goto devm_err; + + /* codec SSP */ + links[id].name = devm_kasprintf(dev, GFP_KERNEL, + "SSP%d-Codec", ssp_codec); + if (!links[id].name) + goto devm_err; + + links[id].id = id; + links[id].codecs = pcm512x_component; + links[id].num_codecs = ARRAY_SIZE(pcm512x_component); + links[id].platforms = platform_component; + links[id].num_platforms = ARRAY_SIZE(platform_component); + links[id].init = sof_pcm512x_codec_init; + links[id].ops = &sof_pcm512x_ops; + links[id].nonatomic = true; + links[id].dpcm_playback = 1; + /* + * capture only supported with specific versions of the Hifiberry DAC+ + * links[id].dpcm_capture = 1; + */ + links[id].no_pcm = 1; + links[id].cpus = &cpus[id]; + links[id].num_cpus = 1; + if (is_legacy_cpu) { + links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "ssp%d-port", + ssp_codec); + if (!links[id].cpus->dai_name) + goto devm_err; + } else { + links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "SSP%d Pin", + ssp_codec); + if (!links[id].cpus->dai_name) + goto devm_err; + } + id++; + + /* dmic */ + if (dmic_be_num > 0) { + /* at least we have dmic01 */ + links[id].name = "dmic01"; + links[id].cpus = &cpus[id]; + links[id].cpus->dai_name = "DMIC01 Pin"; + links[id].init = dmic_init; + if (dmic_be_num > 1) { + /* set up 2 BE links at most */ + links[id + 1].name = "dmic16k"; + links[id + 1].cpus = &cpus[id + 1]; + links[id + 1].cpus->dai_name = "DMIC16k Pin"; + dmic_be_num = 2; + } + } + + for (i = 0; i < dmic_be_num; i++) { + links[id].id = id; + links[id].num_cpus = 1; + links[id].codecs = dmic_component; + links[id].num_codecs = ARRAY_SIZE(dmic_component); + links[id].platforms = platform_component; + links[id].num_platforms = ARRAY_SIZE(platform_component); + links[id].ignore_suspend = 1; + links[id].dpcm_capture = 1; + links[id].no_pcm = 1; + id++; + } + + /* HDMI */ + if (hdmi_num > 0) { + idisp_components = devm_kcalloc(dev, hdmi_num, + sizeof(struct snd_soc_dai_link_component), + GFP_KERNEL); + if (!idisp_components) + goto devm_err; + } + for (i = 1; i <= hdmi_num; i++) { + links[id].name = devm_kasprintf(dev, GFP_KERNEL, + "iDisp%d", i); + if (!links[id].name) + goto devm_err; + + links[id].id = id; + links[id].cpus = &cpus[id]; + links[id].num_cpus = 1; + links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "iDisp%d Pin", i); + if (!links[id].cpus->dai_name) + goto devm_err; + + idisp_components[i - 1].name = "ehdaudio0D2"; + idisp_components[i - 1].dai_name = devm_kasprintf(dev, + GFP_KERNEL, + "intel-hdmi-hifi%d", + i); + if (!idisp_components[i - 1].dai_name) + goto devm_err; + + links[id].codecs = &idisp_components[i - 1]; + links[id].num_codecs = 1; + links[id].platforms = platform_component; + links[id].num_platforms = ARRAY_SIZE(platform_component); + links[id].init = sof_hdmi_init; + links[id].dpcm_playback = 1; + links[id].no_pcm = 1; + id++; + } + + return links; +devm_err: + return NULL; +} + +static int sof_audio_probe(struct platform_device *pdev) +{ + struct snd_soc_dai_link *dai_links; + struct snd_soc_acpi_mach *mach; + struct sof_card_private *ctx; + int dmic_be_num, hdmi_num; + int ret, ssp_codec; + + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + hdmi_num = 0; + if (soc_intel_is_byt() || soc_intel_is_cht()) { + is_legacy_cpu = true; + dmic_be_num = 0; + /* default quirk for legacy cpu */ + sof_pcm512x_quirk = SOF_PCM512X_SSP_CODEC(2); + } else { + dmic_be_num = 2; +#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) + hdmi_num = 3; +#endif + } + + dmi_check_system(sof_pcm512x_quirk_table); + + dev_dbg(&pdev->dev, "sof_pcm512x_quirk = %lx\n", sof_pcm512x_quirk); + + ssp_codec = sof_pcm512x_quirk & SOF_PCM512X_SSP_CODEC_MASK; + + /* compute number of dai links */ + sof_audio_card_pcm512x.num_links = 1 + dmic_be_num + hdmi_num; + + dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, + dmic_be_num, hdmi_num); + if (!dai_links) + return -ENOMEM; + + sof_audio_card_pcm512x.dai_link = dai_links; + + INIT_LIST_HEAD(&ctx->hdmi_pcm_list); + + sof_audio_card_pcm512x.dev = &pdev->dev; + mach = (&pdev->dev)->platform_data; + + /* set platform name for each dailink */ + ret = snd_soc_fixup_dai_links_platform_name(&sof_audio_card_pcm512x, + mach->mach_params.platform); + if (ret) + return ret; + + snd_soc_card_set_drvdata(&sof_audio_card_pcm512x, ctx); + + return devm_snd_soc_register_card(&pdev->dev, + &sof_audio_card_pcm512x); +} + +static int sof_pcm512x_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct snd_soc_component *component = NULL; + + for_each_card_components(card, component) { + if (!strcmp(component->name, pcm512x_component[0].name)) { + snd_soc_component_set_jack(component, NULL, NULL); + break; + } + } + + return 0; +} + +static struct platform_driver sof_audio = { + .probe = sof_audio_probe, + .remove = sof_pcm512x_remove, + .driver = { + .name = "sof_pcm512x", + .pm = &snd_soc_pm_ops, + }, +}; +module_platform_driver(sof_audio) + +MODULE_DESCRIPTION("ASoC Intel(R) SOF + PCM512x Machine driver"); +MODULE_AUTHOR("Pierre-Louis Bossart"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:sof_pcm512x"); From 341eb6b787c3883561bc76a7a234bf8ba48b7186 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 29 Jan 2020 16:36:02 -0600 Subject: [PATCH 0108/4444] ASoC: Intel: BXT: switch pcm512x based boards to sof_pcm512x Switch over Broxton platforms with the pcm512x codec from the legacy bxt-pcm512x to the new sof_pcm512x machine driver. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200129223603.2569-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-bxt-match.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c index 4a5adae1d785..f5092bc48364 100644 --- a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c @@ -65,7 +65,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_bxt_machines[] = { }, { .id = "104C5122", - .drv_name = "bxt-pcm512x", + .drv_name = "sof_pcm512x", .sof_fw_filename = "sof-apl.ri", .sof_tplg_filename = "sof-apl-pcm512x.tplg", }, From 9d19426ed8f8cb5d468659caddeeeef4b147669b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 29 Jan 2020 16:36:03 -0600 Subject: [PATCH 0109/4444] ASoC: Intel: CHT: add support for pcm512x boards Add support for Cherrytrail boards, using the pcm512x audio codec using the new sof_pcm512x machine driver. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200129223603.2569-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-cht-match.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-cht-match.c b/sound/soc/intel/common/soc-acpi-intel-cht-match.c index d0fb43c2b9f6..2752dc955733 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cht-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cht-match.c @@ -174,6 +174,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cherrytrail_machines[] = { .sof_fw_filename = "sof-cht.ri", .sof_tplg_filename = "sof-cht-cx2072x.tplg", }, + { + .id = "104C5122", + .drv_name = "sof_pcm512x", + .sof_fw_filename = "sof-cht.ri", + .sof_tplg_filename = "sof-cht-src-50khz-pcm512x.tplg", + }, + #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) /* * This is always last in the table so that it is selected only when From d2cff470452df5eba8107f267bdb6de159ba09e2 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sun, 2 Feb 2020 07:39:17 +0000 Subject: [PATCH 0110/4444] ASoC: Remove unused including Remove including that don't need it. Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20200202073917.195880-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/mt6660.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/mt6660.c b/sound/soc/codecs/mt6660.c index a36c416caad4..1a3515df1764 100644 --- a/sound/soc/codecs/mt6660.c +++ b/sound/soc/codecs/mt6660.c @@ -4,7 +4,6 @@ #include #include -#include #include #include #include From 918d0aba86ed8c1f4ff7f39e39e5c1b46fff2bc2 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Mon, 3 Feb 2020 23:01:44 -0700 Subject: [PATCH 0111/4444] ASoC: wcd934x: Remove some unnecessary NULL checks Clang warns: ../sound/soc/codecs/wcd934x.c:1886:11: warning: address of array 'wcd->rx_chs' will always evaluate to 'true' [-Wpointer-bool-conversion] if (wcd->rx_chs) { ~~ ~~~~~^~~~~~ ../sound/soc/codecs/wcd934x.c:1894:11: warning: address of array 'wcd->tx_chs' will always evaluate to 'true' [-Wpointer-bool-conversion] if (wcd->tx_chs) { ~~ ~~~~~^~~~~~ 2 warnings generated. Arrays that are in the middle of a struct are never NULL so they don't need a check like this. Fixes: a61f3b4f476e ("ASoC: wcd934x: add support to wcd9340/wcd9341 codec") Link: https://github.com/ClangBuiltLinux/linux/issues/854 Signed-off-by: Nathan Chancellor Link: https://lore.kernel.org/r/20200204060143.23393-1-natechancellor@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd934x.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 158e878abd6c..e780ecd554d2 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -1883,20 +1883,16 @@ static int wcd934x_set_channel_map(struct snd_soc_dai *dai, return -EINVAL; } - if (wcd->rx_chs) { - wcd->num_rx_port = rx_num; - for (i = 0; i < rx_num; i++) { - wcd->rx_chs[i].ch_num = rx_slot[i]; - INIT_LIST_HEAD(&wcd->rx_chs[i].list); - } + wcd->num_rx_port = rx_num; + for (i = 0; i < rx_num; i++) { + wcd->rx_chs[i].ch_num = rx_slot[i]; + INIT_LIST_HEAD(&wcd->rx_chs[i].list); } - if (wcd->tx_chs) { - wcd->num_tx_port = tx_num; - for (i = 0; i < tx_num; i++) { - wcd->tx_chs[i].ch_num = tx_slot[i]; - INIT_LIST_HEAD(&wcd->tx_chs[i].list); - } + wcd->num_tx_port = tx_num; + for (i = 0; i < tx_num; i++) { + wcd->tx_chs[i].ch_num = tx_slot[i]; + INIT_LIST_HEAD(&wcd->tx_chs[i].list); } return 0; From bbf53b95ed9521625e5867522cc057bd8f1320b1 Mon Sep 17 00:00:00 2001 From: Derek Fang Date: Thu, 6 Feb 2020 14:22:13 +0800 Subject: [PATCH 0112/4444] ASoC: rl6231: Add new supports on rl6231 1. Increases the max limit of PLL input frequency on RL6231 shared support. 2. Add a new pll preset map. Signed-off-by: Derek Fang Link: https://lore.kernel.org/r/1580970133-14089-1-git-send-email-derek.fang@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rl6231.c | 1 + sound/soc/codecs/rl6231.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rl6231.c b/sound/soc/codecs/rl6231.c index a887d5ccb10d..d181c217d835 100644 --- a/sound/soc/codecs/rl6231.c +++ b/sound/soc/codecs/rl6231.c @@ -102,6 +102,7 @@ struct pll_calc_map { static const struct pll_calc_map pll_preset_table[] = { {19200000, 4096000, 23, 14, 1, false}, {19200000, 24576000, 3, 30, 3, false}, + {3840000, 24576000, 3, 30, 0, true}, }; static unsigned int find_best_div(unsigned int in, diff --git a/sound/soc/codecs/rl6231.h b/sound/soc/codecs/rl6231.h index 31a9643b0afd..6d8ed0377296 100644 --- a/sound/soc/codecs/rl6231.h +++ b/sound/soc/codecs/rl6231.h @@ -10,7 +10,7 @@ #ifndef __RL6231_H__ #define __RL6231_H__ -#define RL6231_PLL_INP_MAX 40000000 +#define RL6231_PLL_INP_MAX 50000000 #define RL6231_PLL_INP_MIN 256000 #define RL6231_PLL_N_MAX 0x1ff #define RL6231_PLL_K_MAX 0x1f From b5848c814cdb6ea87f77559a143c464101330c7e Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Wed, 5 Feb 2020 02:28:56 +0000 Subject: [PATCH 0113/4444] ASoC: rt5682: Add the field "is_sdw" of private data The field "is_sdw" is used for distinguishing the driver whether is run in soundwire mode or not. That will run the separated setting in runtime to make sure the driver can be run with the same build between i2s mode and soundwire mode. Signed-off-by: Oder Chiou Link: https://lore.kernel.org/r/980b97e1ab9c4fab8bd345ec2158f1fd@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 148 +++++++++++++++++++++----------------- sound/soc/codecs/rt5682.h | 6 ++ 2 files changed, 90 insertions(+), 64 deletions(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index ae6f6121bc1b..82a636620131 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -56,6 +56,7 @@ struct rt5682_priv { struct delayed_work jack_detect_work; struct delayed_work jd_check_work; struct mutex calibrate_mutex; + bool is_sdw; int sysclk; int sysclk_src; @@ -805,10 +806,11 @@ static const struct snd_kcontrol_new rt5682_if1_45_adc_swap_mux = static const struct snd_kcontrol_new rt5682_if1_67_adc_swap_mux = SOC_DAPM_ENUM("IF1 67 ADC Swap Mux", rt5682_if1_67_adc_enum); -static void rt5682_reset(struct regmap *regmap) +static void rt5682_reset(struct rt5682_priv *rt5682) { - regmap_write(regmap, RT5682_RESET, 0); - regmap_write(regmap, RT5682_I2C_MODE, 1); + regmap_write(rt5682->regmap, RT5682_RESET, 0); + if (!rt5682->is_sdw) + regmap_write(rt5682->regmap, RT5682_I2C_MODE, 1); } /** * rt5682_sel_asrc_clk_src - select ASRC clock source for a set of filters @@ -871,6 +873,8 @@ static int rt5682_button_detect(struct snd_soc_component *component) static void rt5682_enable_push_button_irq(struct snd_soc_component *component, bool enable) { + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + if (enable) { snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1, RT5682_SAR_BUTT_DET_MASK, RT5682_SAR_BUTT_DET_EN); @@ -880,8 +884,15 @@ static void rt5682_enable_push_button_irq(struct snd_soc_component *component, snd_soc_component_update_bits(component, RT5682_4BTN_IL_CMD_2, RT5682_4BTN_IL_MASK | RT5682_4BTN_IL_RST_MASK, RT5682_4BTN_IL_EN | RT5682_4BTN_IL_NOR); - snd_soc_component_update_bits(component, RT5682_IRQ_CTRL_3, - RT5682_IL_IRQ_MASK, RT5682_IL_IRQ_EN); + if (rt5682->is_sdw) + snd_soc_component_update_bits(component, + RT5682_IRQ_CTRL_3, + RT5682_IL_IRQ_MASK | RT5682_IL_IRQ_TYPE_MASK, + RT5682_IL_IRQ_EN | RT5682_IL_IRQ_PUL); + else + snd_soc_component_update_bits(component, + RT5682_IRQ_CTRL_3, RT5682_IL_IRQ_MASK, + RT5682_IL_IRQ_EN); } else { snd_soc_component_update_bits(component, RT5682_IRQ_CTRL_3, RT5682_IL_IRQ_MASK, RT5682_IL_IRQ_DIS); @@ -999,62 +1010,69 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component, rt5682->hs_jack = hs_jack; - if (!hs_jack) { - regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, - RT5682_JD1_EN_MASK, RT5682_JD1_DIS); - regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, - RT5682_POW_JDH | RT5682_POW_JDL, 0); - cancel_delayed_work_sync(&rt5682->jack_detect_work); - return 0; - } + if (!rt5682->is_sdw) { + if (!hs_jack) { + regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, + RT5682_JD1_EN_MASK, RT5682_JD1_DIS); + regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, + RT5682_POW_JDH | RT5682_POW_JDL, 0); + cancel_delayed_work_sync(&rt5682->jack_detect_work); + return 0; + } - switch (rt5682->pdata.jd_src) { - case RT5682_JD1: - snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_2, - RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL); - snd_soc_component_write(component, RT5682_CBJ_CTRL_1, 0xd042); - snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_3, - RT5682_CBJ_IN_BUF_EN, RT5682_CBJ_IN_BUF_EN); - snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1, - RT5682_SAR_POW_MASK, RT5682_SAR_POW_EN); - regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, - RT5682_GP1_PIN_MASK, RT5682_GP1_PIN_IRQ); - regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, + switch (rt5682->pdata.jd_src) { + case RT5682_JD1: + snd_soc_component_update_bits(component, + RT5682_CBJ_CTRL_2, RT5682_EXT_JD_SRC, + RT5682_EXT_JD_SRC_MANUAL); + snd_soc_component_write(component, RT5682_CBJ_CTRL_1, + 0xd042); + snd_soc_component_update_bits(component, + RT5682_CBJ_CTRL_3, RT5682_CBJ_IN_BUF_EN, + RT5682_CBJ_IN_BUF_EN); + snd_soc_component_update_bits(component, + RT5682_SAR_IL_CMD_1, RT5682_SAR_POW_MASK, + RT5682_SAR_POW_EN); + regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, + RT5682_GP1_PIN_MASK, RT5682_GP1_PIN_IRQ); + regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, RT5682_POW_IRQ | RT5682_POW_JDH | RT5682_POW_ANA, RT5682_POW_IRQ | RT5682_POW_JDH | RT5682_POW_ANA); - regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_2, - RT5682_PWR_JDH | RT5682_PWR_JDL, - RT5682_PWR_JDH | RT5682_PWR_JDL); - regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, - RT5682_JD1_EN_MASK | RT5682_JD1_POL_MASK, - RT5682_JD1_EN | RT5682_JD1_POL_NOR); - regmap_update_bits(rt5682->regmap, RT5682_4BTN_IL_CMD_4, - 0x7f7f, (rt5682->pdata.btndet_delay << 8 | - rt5682->pdata.btndet_delay)); - regmap_update_bits(rt5682->regmap, RT5682_4BTN_IL_CMD_5, - 0x7f7f, (rt5682->pdata.btndet_delay << 8 | - rt5682->pdata.btndet_delay)); - regmap_update_bits(rt5682->regmap, RT5682_4BTN_IL_CMD_6, - 0x7f7f, (rt5682->pdata.btndet_delay << 8 | - rt5682->pdata.btndet_delay)); - regmap_update_bits(rt5682->regmap, RT5682_4BTN_IL_CMD_7, - 0x7f7f, (rt5682->pdata.btndet_delay << 8 | - rt5682->pdata.btndet_delay)); - mod_delayed_work(system_power_efficient_wq, - &rt5682->jack_detect_work, msecs_to_jiffies(250)); - break; + regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_2, + RT5682_PWR_JDH | RT5682_PWR_JDL, + RT5682_PWR_JDH | RT5682_PWR_JDL); + regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, + RT5682_JD1_EN_MASK | RT5682_JD1_POL_MASK, + RT5682_JD1_EN | RT5682_JD1_POL_NOR); + regmap_update_bits(rt5682->regmap, RT5682_4BTN_IL_CMD_4, + 0x7f7f, (rt5682->pdata.btndet_delay << 8 | + rt5682->pdata.btndet_delay)); + regmap_update_bits(rt5682->regmap, RT5682_4BTN_IL_CMD_5, + 0x7f7f, (rt5682->pdata.btndet_delay << 8 | + rt5682->pdata.btndet_delay)); + regmap_update_bits(rt5682->regmap, RT5682_4BTN_IL_CMD_6, + 0x7f7f, (rt5682->pdata.btndet_delay << 8 | + rt5682->pdata.btndet_delay)); + regmap_update_bits(rt5682->regmap, RT5682_4BTN_IL_CMD_7, + 0x7f7f, (rt5682->pdata.btndet_delay << 8 | + rt5682->pdata.btndet_delay)); + mod_delayed_work(system_power_efficient_wq, + &rt5682->jack_detect_work, + msecs_to_jiffies(250)); + break; - case RT5682_JD_NULL: - regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, - RT5682_JD1_EN_MASK, RT5682_JD1_DIS); - regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, - RT5682_POW_JDH | RT5682_POW_JDL, 0); - break; + case RT5682_JD_NULL: + regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, + RT5682_JD1_EN_MASK, RT5682_JD1_DIS); + regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, + RT5682_POW_JDH | RT5682_POW_JDL, 0); + break; - default: - dev_warn(component->dev, "Wrong JD source\n"); - break; + default: + dev_warn(component->dev, "Wrong JD source\n"); + break; + } } return 0; @@ -1134,11 +1152,13 @@ static void rt5682_jack_detect_handler(struct work_struct *work) SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3); - if (rt5682->jack_type & (SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3)) - schedule_delayed_work(&rt5682->jd_check_work, 0); - else - cancel_delayed_work_sync(&rt5682->jd_check_work); + if (!rt5682->is_sdw) { + if (rt5682->jack_type & (SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3)) + schedule_delayed_work(&rt5682->jd_check_work, 0); + else + cancel_delayed_work_sync(&rt5682->jd_check_work); + } mutex_unlock(&rt5682->calibrate_mutex); } @@ -2332,7 +2352,7 @@ static void rt5682_remove(struct snd_soc_component *component) { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); - rt5682_reset(rt5682->regmap); + rt5682_reset(rt5682); } #ifdef CONFIG_PM @@ -2474,7 +2494,7 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682) mutex_lock(&rt5682->calibrate_mutex); - rt5682_reset(rt5682->regmap); + rt5682_reset(rt5682); regmap_write(rt5682->regmap, RT5682_I2C_CTRL, 0x000f); regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0xa2af); usleep_range(15000, 20000); @@ -2586,7 +2606,7 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, return -ENODEV; } - rt5682_reset(rt5682->regmap); + rt5682_reset(rt5682); mutex_init(&rt5682->calibrate_mutex); rt5682_calibrate(rt5682); @@ -2676,7 +2696,7 @@ static void rt5682_i2c_shutdown(struct i2c_client *client) { struct rt5682_priv *rt5682 = i2c_get_clientdata(client); - rt5682_reset(rt5682->regmap); + rt5682_reset(rt5682); } #ifdef CONFIG_OF diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h index 18faaa2a49a0..4d3a8c41546e 100644 --- a/sound/soc/codecs/rt5682.h +++ b/sound/soc/codecs/rt5682.h @@ -1091,11 +1091,17 @@ #define RT5682_JD1_POL_MASK (0x1 << 13) #define RT5682_JD1_POL_NOR (0x0 << 13) #define RT5682_JD1_POL_INV (0x1 << 13) +#define RT5682_JD1_IRQ_MASK (0x1 << 10) +#define RT5682_JD1_IRQ_LEV (0x0 << 10) +#define RT5682_JD1_IRQ_PUL (0x1 << 10) /* IRQ Control 3 (0x00b8) */ #define RT5682_IL_IRQ_MASK (0x1 << 7) #define RT5682_IL_IRQ_DIS (0x0 << 7) #define RT5682_IL_IRQ_EN (0x1 << 7) +#define RT5682_IL_IRQ_TYPE_MASK (0x1 << 4) +#define RT5682_IL_IRQ_LEV (0x0 << 4) +#define RT5682_IL_IRQ_PUL (0x1 << 4) /* GPIO Control 1 (0x00c0) */ #define RT5682_GP1_PIN_MASK (0x3 << 14) From 028476c861e3eb660d8d104ef39fccb34c04a0d5 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Mon, 3 Feb 2020 11:08:09 +0100 Subject: [PATCH 0114/4444] ASoC: stm32: sai: manage error when getting reset controller Return an error when the SAI driver fails to get a reset controller. Also add an error trace, except on probe defer status. Signed-off-by: Etienne Carriere Signed-off-by: Olivier Moysan Link: https://lore.kernel.org/r/20200203100814.22944-2-olivier.moysan@st.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_sai.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c index e20267504b16..b824ba6cb028 100644 --- a/sound/soc/stm/stm32_sai.c +++ b/sound/soc/stm/stm32_sai.c @@ -197,12 +197,16 @@ static int stm32_sai_probe(struct platform_device *pdev) return sai->irq; /* reset */ - rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); - if (!IS_ERR(rst)) { - reset_control_assert(rst); - udelay(2); - reset_control_deassert(rst); + rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); + if (IS_ERR(rst)) { + if (PTR_ERR(rst) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Reset controller error %ld\n", + PTR_ERR(rst)); + return PTR_ERR(rst); } + reset_control_assert(rst); + udelay(2); + reset_control_deassert(rst); /* Enable peripheral clock to allow register access */ ret = clk_prepare_enable(sai->pclk); From 7889c0082e6400ae5d07345e5573548d0999b840 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Mon, 3 Feb 2020 11:08:10 +0100 Subject: [PATCH 0115/4444] ASoC: stm32: spdifrx: manage error when getting reset controller Return an error when the SPDIFRX driver fails to get a reset controller. Also add an error trace, except on probe defer status. Signed-off-by: Etienne Carriere Signed-off-by: Olivier Moysan Link: https://lore.kernel.org/r/20200203100814.22944-3-olivier.moysan@st.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_spdifrx.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c index 3769d9ce5dbe..9f80ddf34443 100644 --- a/sound/soc/stm/stm32_spdifrx.c +++ b/sound/soc/stm/stm32_spdifrx.c @@ -978,12 +978,16 @@ static int stm32_spdifrx_probe(struct platform_device *pdev) return ret; } - rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); - if (!IS_ERR(rst)) { - reset_control_assert(rst); - udelay(2); - reset_control_deassert(rst); + rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); + if (IS_ERR(rst)) { + if (PTR_ERR(rst) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Reset controller error %ld\n", + PTR_ERR(rst)); + return PTR_ERR(rst); } + reset_control_assert(rst); + udelay(2); + reset_control_deassert(rst); ret = devm_snd_soc_register_component(&pdev->dev, &stm32_spdifrx_component, From 158ecc65c05314cd02fcf67fa54ebef537358e5c Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Mon, 3 Feb 2020 11:08:11 +0100 Subject: [PATCH 0116/4444] ASoC: stm32: i2s: manage error when getting reset controller Return an error when the i2s driver fails to get a reset controller. Also add an error trace, except on probe defer status. Signed-off-by: Etienne Carriere Signed-off-by: Olivier Moysan Link: https://lore.kernel.org/r/20200203100814.22944-4-olivier.moysan@st.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_i2s.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index 3e7226a53e53..cdcc00d9a67e 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -866,12 +866,16 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, } /* Reset */ - rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); - if (!IS_ERR(rst)) { - reset_control_assert(rst); - udelay(2); - reset_control_deassert(rst); + rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); + if (IS_ERR(rst)) { + if (PTR_ERR(rst) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Reset controller error %ld\n", + PTR_ERR(rst)); + return PTR_ERR(rst); } + reset_control_assert(rst); + udelay(2); + reset_control_deassert(rst); return 0; } From 5183e85423070d088aaf1ed07ab260e03d5a4e20 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Mon, 3 Feb 2020 11:08:12 +0100 Subject: [PATCH 0117/4444] ASoC: stm32: sai: improve error management on probe deferral Do not print an error trace when deferring probe for SAI driver. Signed-off-by: Etienne Carriere Signed-off-by: Olivier Moysan Link: https://lore.kernel.org/r/20200203100814.22944-5-olivier.moysan@st.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_sai.c | 12 +++++++++--- sound/soc/stm/stm32_sai_sub.c | 11 ++++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c index b824ba6cb028..058757c721f0 100644 --- a/sound/soc/stm/stm32_sai.c +++ b/sound/soc/stm/stm32_sai.c @@ -174,20 +174,26 @@ static int stm32_sai_probe(struct platform_device *pdev) if (!STM_SAI_IS_F4(sai)) { sai->pclk = devm_clk_get(&pdev->dev, "pclk"); if (IS_ERR(sai->pclk)) { - dev_err(&pdev->dev, "missing bus clock pclk\n"); + if (PTR_ERR(sai->pclk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "missing bus clock pclk: %ld\n", + PTR_ERR(sai->pclk)); return PTR_ERR(sai->pclk); } } sai->clk_x8k = devm_clk_get(&pdev->dev, "x8k"); if (IS_ERR(sai->clk_x8k)) { - dev_err(&pdev->dev, "missing x8k parent clock\n"); + if (PTR_ERR(sai->clk_x8k) != -EPROBE_DEFER) + dev_err(&pdev->dev, "missing x8k parent clock: %ld\n", + PTR_ERR(sai->clk_x8k)); return PTR_ERR(sai->clk_x8k); } sai->clk_x11k = devm_clk_get(&pdev->dev, "x11k"); if (IS_ERR(sai->clk_x11k)) { - dev_err(&pdev->dev, "missing x11k parent clock\n"); + if (PTR_ERR(sai->clk_x11k) != -EPROBE_DEFER) + dev_err(&pdev->dev, "missing x11k parent clock: %ld\n", + PTR_ERR(sai->clk_x11k)); return PTR_ERR(sai->clk_x11k); } diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 30bcd5d3a32a..0bbf9ed5e48b 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -1380,7 +1380,9 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, sai->regmap = devm_regmap_init_mmio(&pdev->dev, base, sai->regmap_config); if (IS_ERR(sai->regmap)) { - dev_err(&pdev->dev, "Failed to initialize MMIO\n"); + if (PTR_ERR(sai->regmap) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Regmap init error %ld\n", + PTR_ERR(sai->regmap)); return PTR_ERR(sai->regmap); } @@ -1471,7 +1473,9 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, of_node_put(args.np); sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck"); if (IS_ERR(sai->sai_ck)) { - dev_err(&pdev->dev, "Missing kernel clock sai_ck\n"); + if (PTR_ERR(sai->sai_ck) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Missing kernel clock sai_ck: %ld\n", + PTR_ERR(sai->sai_ck)); return PTR_ERR(sai->sai_ck); } @@ -1553,7 +1557,8 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) ret = devm_snd_dmaengine_pcm_register(&pdev->dev, conf, 0); if (ret) { - dev_err(&pdev->dev, "Could not register pcm dma\n"); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "PCM DMA register error %d\n", ret); return ret; } From d49bd5ed24163a1a1c81d40e84295731ddd17b1c Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Mon, 3 Feb 2020 11:08:13 +0100 Subject: [PATCH 0118/4444] ASoC: stm32: spdifrx: improve error management on probe deferral Do not print an error trace when deferring probe for SPDIFRX driver. Signed-off-by: Etienne Carriere Signed-off-by: Olivier Moysan Link: https://lore.kernel.org/r/20200203100814.22944-6-olivier.moysan@st.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_spdifrx.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c index 9f80ddf34443..49766afdae61 100644 --- a/sound/soc/stm/stm32_spdifrx.c +++ b/sound/soc/stm/stm32_spdifrx.c @@ -406,7 +406,9 @@ static int stm32_spdifrx_dma_ctrl_register(struct device *dev, spdifrx->ctrl_chan = dma_request_chan(dev, "rx-ctrl"); if (IS_ERR(spdifrx->ctrl_chan)) { - dev_err(dev, "dma_request_slave_channel failed\n"); + if (PTR_ERR(spdifrx->ctrl_chan) != -EPROBE_DEFER) + dev_err(dev, "dma_request_slave_channel error %ld\n", + PTR_ERR(spdifrx->ctrl_chan)); return PTR_ERR(spdifrx->ctrl_chan); } @@ -929,7 +931,9 @@ static int stm32_spdifrx_parse_of(struct platform_device *pdev, spdifrx->kclk = devm_clk_get(&pdev->dev, "kclk"); if (IS_ERR(spdifrx->kclk)) { - dev_err(&pdev->dev, "Could not get kclk\n"); + if (PTR_ERR(spdifrx->kclk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Could not get kclk: %ld\n", + PTR_ERR(spdifrx->kclk)); return PTR_ERR(spdifrx->kclk); } @@ -967,7 +971,9 @@ static int stm32_spdifrx_probe(struct platform_device *pdev) spdifrx->base, spdifrx->regmap_conf); if (IS_ERR(spdifrx->regmap)) { - dev_err(&pdev->dev, "Regmap init failed\n"); + if (PTR_ERR(spdifrx->regmap) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Regmap init error %ld\n", + PTR_ERR(spdifrx->regmap)); return PTR_ERR(spdifrx->regmap); } @@ -1003,7 +1009,8 @@ static int stm32_spdifrx_probe(struct platform_device *pdev) pcm_config = &stm32_spdifrx_pcm_config; ret = devm_snd_dmaengine_pcm_register(&pdev->dev, pcm_config, 0); if (ret) { - dev_err(&pdev->dev, "PCM DMA register returned %d\n", ret); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "PCM DMA register error %d\n", ret); goto error; } From 04dd656e8d506c12f5e97a24089b2991f5f00984 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Mon, 3 Feb 2020 11:08:14 +0100 Subject: [PATCH 0119/4444] ASoC: stm32: i2s: improve error management on probe deferral Do not print an error trace when deferring probe for I2S driver. Signed-off-by: Etienne Carriere Signed-off-by: Olivier Moysan Link: https://lore.kernel.org/r/20200203100814.22944-7-olivier.moysan@st.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_i2s.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index cdcc00d9a67e..2478405727c3 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -831,25 +831,33 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, /* Get clocks */ i2s->pclk = devm_clk_get(&pdev->dev, "pclk"); if (IS_ERR(i2s->pclk)) { - dev_err(&pdev->dev, "Could not get pclk\n"); + if (PTR_ERR(i2s->pclk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Could not get pclk: %ld\n", + PTR_ERR(i2s->pclk)); return PTR_ERR(i2s->pclk); } i2s->i2sclk = devm_clk_get(&pdev->dev, "i2sclk"); if (IS_ERR(i2s->i2sclk)) { - dev_err(&pdev->dev, "Could not get i2sclk\n"); + if (PTR_ERR(i2s->i2sclk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Could not get i2sclk: %ld\n", + PTR_ERR(i2s->i2sclk)); return PTR_ERR(i2s->i2sclk); } i2s->x8kclk = devm_clk_get(&pdev->dev, "x8k"); if (IS_ERR(i2s->x8kclk)) { - dev_err(&pdev->dev, "missing x8k parent clock\n"); + if (PTR_ERR(i2s->x8kclk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Could not get x8k parent clock: %ld\n", + PTR_ERR(i2s->x8kclk)); return PTR_ERR(i2s->x8kclk); } i2s->x11kclk = devm_clk_get(&pdev->dev, "x11k"); if (IS_ERR(i2s->x11kclk)) { - dev_err(&pdev->dev, "missing x11k parent clock\n"); + if (PTR_ERR(i2s->x11kclk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Could not get x11k parent clock: %ld\n", + PTR_ERR(i2s->x11kclk)); return PTR_ERR(i2s->x11kclk); } @@ -907,7 +915,9 @@ static int stm32_i2s_probe(struct platform_device *pdev) i2s->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "pclk", i2s->base, i2s->regmap_conf); if (IS_ERR(i2s->regmap)) { - dev_err(&pdev->dev, "regmap init failed\n"); + if (PTR_ERR(i2s->regmap) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Regmap init error %ld\n", + PTR_ERR(i2s->regmap)); return PTR_ERR(i2s->regmap); } @@ -918,8 +928,11 @@ static int stm32_i2s_probe(struct platform_device *pdev) ret = devm_snd_dmaengine_pcm_register(&pdev->dev, &stm32_i2s_pcm_config, 0); - if (ret) + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "PCM DMA register error %d\n", ret); return ret; + } /* Set SPI/I2S in i2s mode */ ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, From 3025571edd9df653e1ad649f0638368a39d1bbb5 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 8 Feb 2020 22:07:20 +0000 Subject: [PATCH 0120/4444] ASoC: Intel: mrfld: return error codes when an error occurs Currently function sst_platform_get_resources always returns zero and error return codes set by the function are never returned. Fix this by returning the error return code in variable ret rather than the hard coded zero. Addresses-Coverity: ("Unused value") Fixes: f533a035e4da ("ASoC: Intel: mrfld - create separate module for pci part") Signed-off-by: Colin Ian King Acked-by: Cezary Rojewski Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200208220720.36657-1-colin.king@canonical.com Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst/sst_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/atom/sst/sst_pci.c b/sound/soc/intel/atom/sst/sst_pci.c index d952719bc098..5862fe968083 100644 --- a/sound/soc/intel/atom/sst/sst_pci.c +++ b/sound/soc/intel/atom/sst/sst_pci.c @@ -99,7 +99,7 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx) dev_dbg(ctx->dev, "DRAM Ptr %p\n", ctx->dram); do_release_regions: pci_release_regions(pci); - return 0; + return ret; } /* From 1646484ed2430e37f00945db4755449d54354b57 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 8 Feb 2020 22:15:29 +0000 Subject: [PATCH 0121/4444] ASoC: rt5659: remove redundant assignment to variable idx Variable idx is being assigned with a value that is never idx, it is assigned a new value a couple of statements later. The assignment is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20200208221529.37105-1-colin.king@canonical.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5659.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index e66d08398f74..89e0f58512fa 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c @@ -1604,7 +1604,7 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct rt5659_priv *rt5659 = snd_soc_component_get_drvdata(component); - int pd, idx = -EINVAL; + int pd, idx; pd = rl6231_get_pre_div(rt5659->regmap, RT5659_ADDA_CLK_1, RT5659_I2S_PD1_SFT); From 0d4416446897a91bb19ba837b97b607caea59a8f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 10 Feb 2020 10:30:27 +0100 Subject: [PATCH 0122/4444] spi: pxa2xx: Enable support for compile-testing m68k/allmodconfig: WARNING: unmet direct dependencies detected for SPI_PXA2XX Depends on [n]: SPI [=y] && SPI_MASTER [=y] && (ARCH_PXA || ARCH_MMP || PCI [=n] || ACPI) Selected by [m]: - SND_SOC_INTEL_BDW_RT5677_MACH [=m] && SOUND [=m] && !UML && SND [=m] && SND_SOC [=m] && SND_SOC_INTEL_MACH [=y] && (SND_SOC_INTEL_HASWELL [=n] || SND_SOC_SOF_BROADWELL [=m]) && I2C [=m] && (I2C_DESIGNWARE_PLATFORM [=m] || COMPILE_TEST [=y]) && (GPIOLIB [=y] || COMPILE_TEST [=y]) && (X86_INTEL_LPSS || COMPILE_TEST [=y]) && SPI_MASTER [=y] This happens because SND_SOC_INTEL_BDW_RT5677_MACH selects SPI_PXA2XX, and the former depends on COMPILE_TEST, while the latter does not. Fix this by enabling compile-testing for SPI_PXA2XX. Fixes: 630db1549356f644 ("ASoC: Intel: bdw-rt5677: fix Kconfig dependencies") Signed-off-by: Geert Uytterhoeven Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200210093027.6672-1-geert@linux-m68k.org Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index d6ed0c355954..912cd6e35726 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -551,7 +551,7 @@ config SPI_PPC4xx config SPI_PXA2XX tristate "PXA2xx SSP SPI master" - depends on (ARCH_PXA || ARCH_MMP || PCI || ACPI) + depends on ARCH_PXA || ARCH_MMP || PCI || ACPI || COMPILE_TEST select PXA_SSP if ARCH_PXA || ARCH_MMP help This enables using a PXA2xx or Sodaville SSP port as a SPI master From 9da9ace29ba556d5a2ae6d044070daba5b7d3638 Mon Sep 17 00:00:00 2001 From: Paul Olaru Date: Mon, 10 Feb 2020 11:58:14 +0200 Subject: [PATCH 0123/4444] ASoC: SOF: Rename i.MX8 platform to i.MX8X i.MX8 and i.MX8X platforms are very similar and were treated the same. Anyhow, we need to account for the differences somehow. Current supported platform is i.MX8QXP which is from i.MX8X family. Rename i.MX8 platform to i.MX8X to prepare for future i.MX8 platforms. Signed-off-by: Paul Olaru Signed-off-by: Daniel Baluta Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200210095817.13226-2-daniel.baluta@oss.nxp.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx8.c | 10 +++++----- sound/soc/sof/sof-of-dev.c | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index b2556f5e2871..9ffc2a955e4f 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -138,7 +138,7 @@ static int imx8_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) /* * DSP control. */ -static int imx8_run(struct snd_sof_dev *sdev) +static int imx8x_run(struct snd_sof_dev *sdev) { struct imx8_priv *dsp_priv = (struct imx8_priv *)sdev->private; int ret; @@ -360,13 +360,13 @@ static struct snd_soc_dai_driver imx8_dai[] = { }, }; -/* i.MX8 ops */ -struct snd_sof_dsp_ops sof_imx8_ops = { +/* i.MX8X ops */ +struct snd_sof_dsp_ops sof_imx8x_ops = { /* probe and remove */ .probe = imx8_probe, .remove = imx8_remove, /* DSP core boot */ - .run = imx8_run, + .run = imx8x_run, /* Block IO */ .block_read = sof_block_read, @@ -398,6 +398,6 @@ struct snd_sof_dsp_ops sof_imx8_ops = { SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP }; -EXPORT_SYMBOL(sof_imx8_ops); +EXPORT_SYMBOL(sof_imx8x_ops); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c index 39ea8af6213f..2da1bd859d98 100644 --- a/sound/soc/sof/sof-of-dev.c +++ b/sound/soc/sof/sof-of-dev.c @@ -19,9 +19,9 @@ extern struct snd_sof_dsp_ops sof_imx8_ops; static struct sof_dev_desc sof_of_imx8qxp_desc = { .default_fw_path = "imx/sof", .default_tplg_path = "imx/sof-tplg", - .default_fw_filename = "sof-imx8.ri", + .default_fw_filename = "sof-imx8x.ri", .nocodec_tplg_filename = "sof-imx8-nocodec.tplg", - .ops = &sof_imx8_ops, + .ops = &sof_imx8x_ops, }; #endif From acfa52027bb64b8f93324da2277ff662c7a95679 Mon Sep 17 00:00:00 2001 From: Paul Olaru Date: Mon, 10 Feb 2020 11:58:15 +0200 Subject: [PATCH 0124/4444] ASoC: SOF: imx8: Add ops for i.MX8QM i.MX8QM and i.MX8QXP are mostly identical platforms with minor hardware differences. One of these differences affects the firmware boot process, requiring the run operation to differ. All other ops are reused. Signed-off-by: Paul Olaru Signed-off-by: Daniel Baluta Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200210095817.13226-3-daniel.baluta@oss.nxp.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx8.c | 51 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index 9ffc2a955e4f..b692752b2178 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -178,6 +178,24 @@ static int imx8x_run(struct snd_sof_dev *sdev) return 0; } +static int imx8_run(struct snd_sof_dev *sdev) +{ + struct imx8_priv *dsp_priv = (struct imx8_priv *)sdev->private; + int ret; + + ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP, + IMX_SC_C_OFS_SEL, 0); + if (ret < 0) { + dev_err(sdev->dev, "Error system address offset source select\n"); + return ret; + } + + imx_sc_pm_cpu_start(dsp_priv->sc_ipc, IMX_SC_R_DSP, true, + RESET_VECTOR_VADDR); + + return 0; +} + static int imx8_probe(struct snd_sof_dev *sdev) { struct platform_device *pdev = @@ -360,6 +378,39 @@ static struct snd_soc_dai_driver imx8_dai[] = { }, }; +/* i.MX8 ops */ +struct snd_sof_dsp_ops sof_imx8_ops = { + /* probe and remove */ + .probe = imx8_probe, + .remove = imx8_remove, + /* DSP core boot */ + .run = imx8_run, + + /* Block IO */ + .block_read = sof_block_read, + .block_write = sof_block_write, + + /* ipc */ + .send_msg = imx8_send_msg, + .fw_ready = sof_fw_ready, + .get_mailbox_offset = imx8_get_mailbox_offset, + .get_window_offset = imx8_get_window_offset, + + .ipc_msg_data = imx8_ipc_msg_data, + .ipc_pcm_params = imx8_ipc_pcm_params, + + /* module loading */ + .load_module = snd_sof_parse_module_memcpy, + .get_bar_index = imx8_get_bar_index, + /* firmware loading */ + .load_firmware = snd_sof_load_firmware_memcpy, + + /* DAI drivers */ + .drv = imx8_dai, + .num_drv = 1, /* we have only 1 ESAI interface on i.MX8 */ +}; +EXPORT_SYMBOL(sof_imx8_ops); + /* i.MX8X ops */ struct snd_sof_dsp_ops sof_imx8x_ops = { /* probe and remove */ From f831ebf2faa598793a7ec327847c61dbeabba601 Mon Sep 17 00:00:00 2001 From: Paul Olaru Date: Mon, 10 Feb 2020 11:58:16 +0200 Subject: [PATCH 0125/4444] ASoC: SOF: Add i.MX8QM device descriptor Add SOF device and DT descriptors for i.MX8QM platform. Signed-off-by: Paul Olaru Signed-off-by: Daniel Baluta Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200210095817.13226-4-daniel.baluta@oss.nxp.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-of-dev.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c index 2da1bd859d98..16e49f2ee629 100644 --- a/sound/soc/sof/sof-of-dev.c +++ b/sound/soc/sof/sof-of-dev.c @@ -13,6 +13,7 @@ #include "ops.h" extern struct snd_sof_dsp_ops sof_imx8_ops; +extern struct snd_sof_dsp_ops sof_imx8x_ops; /* platform specific devices */ #if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8) @@ -23,6 +24,14 @@ static struct sof_dev_desc sof_of_imx8qxp_desc = { .nocodec_tplg_filename = "sof-imx8-nocodec.tplg", .ops = &sof_imx8x_ops, }; + +static struct sof_dev_desc sof_of_imx8qm_desc = { + .default_fw_path = "imx/sof", + .default_tplg_path = "imx/sof-tplg", + .default_fw_filename = "sof-imx8.ri", + .nocodec_tplg_filename = "sof-imx8-nocodec.tplg", + .ops = &sof_imx8_ops, +}; #endif static const struct dev_pm_ops sof_of_pm = { @@ -103,6 +112,7 @@ static int sof_of_remove(struct platform_device *pdev) static const struct of_device_id sof_of_ids[] = { #if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8) { .compatible = "fsl,imx8qxp-dsp", .data = &sof_of_imx8qxp_desc}, + { .compatible = "fsl,imx8qm-dsp", .data = &sof_of_imx8qm_desc}, #endif { } }; From ea00d95200d02ece71f5814d41b14f2eb16d598b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 7 Feb 2020 10:13:51 +0100 Subject: [PATCH 0126/4444] ASoC: Use imply for SND_SOC_ALL_CODECS Currently SND_SOC_ALL_CODECS selects the config symbols for all codec drivers. As "select" bypasses dependencies, lots of "select" statements need explicit dependencies, which are hard to get right, and hard to maintain[*]. Fix this by using "imply" instead, which is a weak version of "select", and which obeys dependencies of target symbols. Add dependencies to invisible symbols that are currently selected only if their dependencies are fulfilled. [*] See e.g. commit 13426feaf46c48fc ("ASoC: wcd934x: Add missing COMMON_CLK dependency to SND_SOC_ALL_CODECS"). Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200207091351.18133-1-geert@linux-m68k.org Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 520 ++++++++++++++++++++------------------- 1 file changed, 263 insertions(+), 257 deletions(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 7e90f5d83097..7a14b1c416b5 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -14,262 +14,262 @@ menu "CODEC drivers" config SND_SOC_ALL_CODECS tristate "Build all ASoC CODEC drivers" depends on COMPILE_TEST - select SND_SOC_88PM860X if MFD_88PM860X - select SND_SOC_L3 - select SND_SOC_AB8500_CODEC if ABX500_CORE - select SND_SOC_AC97_CODEC - select SND_SOC_AD1836 if SPI_MASTER - select SND_SOC_AD193X_SPI if SPI_MASTER - select SND_SOC_AD193X_I2C if I2C - select SND_SOC_AD1980 if SND_SOC_AC97_BUS - select SND_SOC_AD73311 - select SND_SOC_ADAU1373 if I2C - select SND_SOC_ADAU1761_I2C if I2C - select SND_SOC_ADAU1761_SPI if SPI - select SND_SOC_ADAU1781_I2C if I2C - select SND_SOC_ADAU1781_SPI if SPI - select SND_SOC_ADAV801 if SPI_MASTER - select SND_SOC_ADAV803 if I2C - select SND_SOC_ADAU1977_SPI if SPI_MASTER - select SND_SOC_ADAU1977_I2C if I2C - select SND_SOC_ADAU1701 if I2C - select SND_SOC_ADAU7002 - select SND_SOC_ADAU7118_I2C if I2C - select SND_SOC_ADAU7118_HW - select SND_SOC_ADS117X - select SND_SOC_AK4104 if SPI_MASTER - select SND_SOC_AK4118 if I2C - select SND_SOC_AK4458 if I2C - select SND_SOC_AK4535 if I2C - select SND_SOC_AK4554 - select SND_SOC_AK4613 if I2C - select SND_SOC_AK4641 if I2C - select SND_SOC_AK4642 if I2C - select SND_SOC_AK4671 if I2C - select SND_SOC_AK5386 - select SND_SOC_AK5558 if I2C - select SND_SOC_ALC5623 if I2C - select SND_SOC_ALC5632 if I2C - select SND_SOC_BT_SCO - select SND_SOC_BD28623 - select SND_SOC_CQ0093VC - select SND_SOC_CROS_EC_CODEC if CROS_EC - select SND_SOC_CS35L32 if I2C - select SND_SOC_CS35L33 if I2C - select SND_SOC_CS35L34 if I2C - select SND_SOC_CS35L35 if I2C - select SND_SOC_CS35L36 if I2C - select SND_SOC_CS42L42 if I2C - select SND_SOC_CS42L51_I2C if I2C - select SND_SOC_CS42L52 if I2C && INPUT - select SND_SOC_CS42L56 if I2C && INPUT - select SND_SOC_CS42L73 if I2C - select SND_SOC_CS4265 if I2C - select SND_SOC_CS4270 if I2C - select SND_SOC_CS4271_I2C if I2C - select SND_SOC_CS4271_SPI if SPI_MASTER - select SND_SOC_CS42XX8_I2C if I2C - select SND_SOC_CS43130 if I2C - select SND_SOC_CS4341 if SND_SOC_I2C_AND_SPI - select SND_SOC_CS4349 if I2C - select SND_SOC_CS47L15 if MFD_CS47L15 - select SND_SOC_CS47L24 if MFD_CS47L24 - select SND_SOC_CS47L35 if MFD_CS47L35 - select SND_SOC_CS47L85 if MFD_CS47L85 - select SND_SOC_CS47L90 if MFD_CS47L90 - select SND_SOC_CS47L92 if MFD_CS47L92 - select SND_SOC_CS53L30 if I2C - select SND_SOC_CX20442 if TTY - select SND_SOC_CX2072X if I2C - select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI - select SND_SOC_DA7213 if I2C - select SND_SOC_DA7218 if I2C - select SND_SOC_DA7219 if I2C - select SND_SOC_DA732X if I2C - select SND_SOC_DA9055 if I2C - select SND_SOC_DMIC if GPIOLIB - select SND_SOC_ES8316 if I2C - select SND_SOC_ES8328_SPI if SPI_MASTER - select SND_SOC_ES8328_I2C if I2C - select SND_SOC_ES7134 - select SND_SOC_ES7241 - select SND_SOC_GTM601 - select SND_SOC_HDAC_HDMI - select SND_SOC_HDAC_HDA - select SND_SOC_ICS43432 - select SND_SOC_INNO_RK3036 - select SND_SOC_ISABELLE if I2C - select SND_SOC_JZ4740_CODEC - select SND_SOC_JZ4725B_CODEC - select SND_SOC_JZ4770_CODEC - select SND_SOC_LM4857 if I2C - select SND_SOC_LM49453 if I2C - select SND_SOC_LOCHNAGAR_SC if MFD_LOCHNAGAR - select SND_SOC_MAX98088 if I2C - select SND_SOC_MAX98090 if I2C - select SND_SOC_MAX98095 if I2C - select SND_SOC_MAX98357A if GPIOLIB - select SND_SOC_MAX98371 if I2C - select SND_SOC_MAX98504 if I2C - select SND_SOC_MAX9867 if I2C - select SND_SOC_MAX98925 if I2C - select SND_SOC_MAX98926 if I2C - select SND_SOC_MAX98927 if I2C - select SND_SOC_MAX98373 if I2C - select SND_SOC_MAX9850 if I2C - select SND_SOC_MAX9860 if I2C - select SND_SOC_MAX9759 - select SND_SOC_MAX9768 if I2C - select SND_SOC_MAX9877 if I2C - select SND_SOC_MC13783 if MFD_MC13XXX - select SND_SOC_ML26124 if I2C - select SND_SOC_MT6351 if MTK_PMIC_WRAP - select SND_SOC_MT6358 if MTK_PMIC_WRAP - select SND_SOC_MT6660 if I2C - select SND_SOC_NAU8540 if I2C - select SND_SOC_NAU8810 if I2C - select SND_SOC_NAU8822 if I2C - select SND_SOC_NAU8824 if I2C - select SND_SOC_NAU8825 if I2C - select SND_SOC_HDMI_CODEC - select SND_SOC_PCM1681 if I2C - select SND_SOC_PCM1789_I2C if I2C - select SND_SOC_PCM179X_I2C if I2C - select SND_SOC_PCM179X_SPI if SPI_MASTER - select SND_SOC_PCM186X_I2C if I2C - select SND_SOC_PCM186X_SPI if SPI_MASTER - select SND_SOC_PCM3008 - select SND_SOC_PCM3060_I2C if I2C - select SND_SOC_PCM3060_SPI if SPI_MASTER - select SND_SOC_PCM3168A_I2C if I2C - select SND_SOC_PCM3168A_SPI if SPI_MASTER - select SND_SOC_PCM5102A - select SND_SOC_PCM512x_I2C if I2C - select SND_SOC_PCM512x_SPI if SPI_MASTER - select SND_SOC_RK3328 - select SND_SOC_RT274 if I2C - select SND_SOC_RT286 if I2C - select SND_SOC_RT298 if I2C - select SND_SOC_RT1011 if I2C - select SND_SOC_RT1015 if I2C - select SND_SOC_RT1305 if I2C - select SND_SOC_RT1308 if I2C - select SND_SOC_RT5514 if I2C - select SND_SOC_RT5616 if I2C - select SND_SOC_RT5631 if I2C - select SND_SOC_RT5640 if I2C - select SND_SOC_RT5645 if I2C - select SND_SOC_RT5651 if I2C - select SND_SOC_RT5659 if I2C - select SND_SOC_RT5660 if I2C - select SND_SOC_RT5663 if I2C - select SND_SOC_RT5665 if I2C - select SND_SOC_RT5668 if I2C - select SND_SOC_RT5670 if I2C - select SND_SOC_RT5677 if I2C && SPI_MASTER - select SND_SOC_RT5682 if I2C - select SND_SOC_RT700_SDW if SOUNDWIRE - select SND_SOC_RT711_SDW if SOUNDWIRE - select SND_SOC_RT715_SDW if SOUNDWIRE - select SND_SOC_RT1308_SDW if SOUNDWIRE - select SND_SOC_SGTL5000 if I2C - select SND_SOC_SI476X if MFD_SI476X_CORE - select SND_SOC_SIMPLE_AMPLIFIER - select SND_SOC_SIRF_AUDIO_CODEC - select SND_SOC_SPDIF - select SND_SOC_SSM2305 - select SND_SOC_SSM2518 if I2C - select SND_SOC_SSM2602_SPI if SPI_MASTER - select SND_SOC_SSM2602_I2C if I2C - select SND_SOC_SSM4567 if I2C - select SND_SOC_STA32X if I2C - select SND_SOC_STA350 if I2C - select SND_SOC_STA529 if I2C - select SND_SOC_STAC9766 if SND_SOC_AC97_BUS - select SND_SOC_STI_SAS - select SND_SOC_TAS2552 if I2C - select SND_SOC_TAS2562 if I2C - select SND_SOC_TAS2770 if I2C - select SND_SOC_TAS5086 if I2C - select SND_SOC_TAS571X if I2C - select SND_SOC_TAS5720 if I2C - select SND_SOC_TAS6424 if I2C - select SND_SOC_TDA7419 if I2C - select SND_SOC_TFA9879 if I2C - select SND_SOC_TLV320AIC23_I2C if I2C - select SND_SOC_TLV320AIC23_SPI if SPI_MASTER - select SND_SOC_TLV320AIC26 if SPI_MASTER - select SND_SOC_TLV320AIC31XX if I2C - select SND_SOC_TLV320AIC32X4_I2C if I2C && COMMON_CLK - select SND_SOC_TLV320AIC32X4_SPI if SPI_MASTER && COMMON_CLK - select SND_SOC_TLV320AIC3X if I2C - select SND_SOC_TPA6130A2 if I2C - select SND_SOC_TLV320DAC33 if I2C - select SND_SOC_TSCS42XX if I2C - select SND_SOC_TSCS454 if I2C - select SND_SOC_TS3A227E if I2C - select SND_SOC_TWL4030 if TWL4030_CORE - select SND_SOC_TWL6040 if TWL6040_CORE - select SND_SOC_UDA1334 if GPIOLIB - select SND_SOC_UDA134X - select SND_SOC_UDA1380 if I2C - select SND_SOC_WCD9335 if SLIMBUS - select SND_SOC_WCD934X if MFD_WCD934X && COMMON_CLK - select SND_SOC_WL1273 if MFD_WL1273_CORE - select SND_SOC_WM0010 if SPI_MASTER - select SND_SOC_WM1250_EV1 if I2C - select SND_SOC_WM2000 if I2C - select SND_SOC_WM2200 if I2C - select SND_SOC_WM5100 if I2C - select SND_SOC_WM5102 if MFD_WM5102 - select SND_SOC_WM5110 if MFD_WM5110 - select SND_SOC_WM8350 if MFD_WM8350 - select SND_SOC_WM8400 if MFD_WM8400 - select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8523 if I2C - select SND_SOC_WM8524 if GPIOLIB - select SND_SOC_WM8580 if I2C - select SND_SOC_WM8711 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8727 - select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8737 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8741 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8770 if SPI_MASTER - select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8782 - select SND_SOC_WM8804_I2C if I2C - select SND_SOC_WM8804_SPI if SPI_MASTER - select SND_SOC_WM8900 if I2C - select SND_SOC_WM8903 if I2C - select SND_SOC_WM8904 if I2C - select SND_SOC_WM8940 if I2C - select SND_SOC_WM8955 if I2C - select SND_SOC_WM8960 if I2C - select SND_SOC_WM8961 if I2C - select SND_SOC_WM8962 if I2C && INPUT - select SND_SOC_WM8971 if I2C - select SND_SOC_WM8974 if I2C - select SND_SOC_WM8978 if I2C - select SND_SOC_WM8983 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8985 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8990 if I2C - select SND_SOC_WM8991 if I2C - select SND_SOC_WM8993 if I2C - select SND_SOC_WM8994 if MFD_WM8994 - select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8996 if I2C - select SND_SOC_WM8997 if MFD_WM8997 - select SND_SOC_WM8998 if MFD_WM8998 - select SND_SOC_WM9081 if I2C - select SND_SOC_WM9090 if I2C - select SND_SOC_WM9705 if (SND_SOC_AC97_BUS || SND_SOC_AC97_BUS_NEW) - select SND_SOC_WM9712 if (SND_SOC_AC97_BUS || SND_SOC_AC97_BUS_NEW) - select SND_SOC_WM9713 if (SND_SOC_AC97_BUS || SND_SOC_AC97_BUS_NEW) - select SND_SOC_WSA881X if SOUNDWIRE + imply SND_SOC_88PM860X + imply SND_SOC_L3 + imply SND_SOC_AB8500_CODEC + imply SND_SOC_AC97_CODEC + imply SND_SOC_AD1836 + imply SND_SOC_AD193X_SPI + imply SND_SOC_AD193X_I2C + imply SND_SOC_AD1980 + imply SND_SOC_AD73311 + imply SND_SOC_ADAU1373 + imply SND_SOC_ADAU1761_I2C + imply SND_SOC_ADAU1761_SPI + imply SND_SOC_ADAU1781_I2C + imply SND_SOC_ADAU1781_SPI + imply SND_SOC_ADAV801 + imply SND_SOC_ADAV803 + imply SND_SOC_ADAU1977_SPI + imply SND_SOC_ADAU1977_I2C + imply SND_SOC_ADAU1701 + imply SND_SOC_ADAU7002 + imply SND_SOC_ADAU7118_I2C + imply SND_SOC_ADAU7118_HW + imply SND_SOC_ADS117X + imply SND_SOC_AK4104 + imply SND_SOC_AK4118 + imply SND_SOC_AK4458 + imply SND_SOC_AK4535 + imply SND_SOC_AK4554 + imply SND_SOC_AK4613 + imply SND_SOC_AK4641 + imply SND_SOC_AK4642 + imply SND_SOC_AK4671 + imply SND_SOC_AK5386 + imply SND_SOC_AK5558 + imply SND_SOC_ALC5623 + imply SND_SOC_ALC5632 + imply SND_SOC_BT_SCO + imply SND_SOC_BD28623 + imply SND_SOC_CQ0093VC + imply SND_SOC_CROS_EC_CODEC + imply SND_SOC_CS35L32 + imply SND_SOC_CS35L33 + imply SND_SOC_CS35L34 + imply SND_SOC_CS35L35 + imply SND_SOC_CS35L36 + imply SND_SOC_CS42L42 + imply SND_SOC_CS42L51_I2C + imply SND_SOC_CS42L52 + imply SND_SOC_CS42L56 + imply SND_SOC_CS42L73 + imply SND_SOC_CS4265 + imply SND_SOC_CS4270 + imply SND_SOC_CS4271_I2C + imply SND_SOC_CS4271_SPI + imply SND_SOC_CS42XX8_I2C + imply SND_SOC_CS43130 + imply SND_SOC_CS4341 + imply SND_SOC_CS4349 + imply SND_SOC_CS47L15 + imply SND_SOC_CS47L24 + imply SND_SOC_CS47L35 + imply SND_SOC_CS47L85 + imply SND_SOC_CS47L90 + imply SND_SOC_CS47L92 + imply SND_SOC_CS53L30 + imply SND_SOC_CX20442 + imply SND_SOC_CX2072X + imply SND_SOC_DA7210 + imply SND_SOC_DA7213 + imply SND_SOC_DA7218 + imply SND_SOC_DA7219 + imply SND_SOC_DA732X + imply SND_SOC_DA9055 + imply SND_SOC_DMIC + imply SND_SOC_ES8316 + imply SND_SOC_ES8328_SPI + imply SND_SOC_ES8328_I2C + imply SND_SOC_ES7134 + imply SND_SOC_ES7241 + imply SND_SOC_GTM601 + imply SND_SOC_HDAC_HDMI + imply SND_SOC_HDAC_HDA + imply SND_SOC_ICS43432 + imply SND_SOC_INNO_RK3036 + imply SND_SOC_ISABELLE + imply SND_SOC_JZ4740_CODEC + imply SND_SOC_JZ4725B_CODEC + imply SND_SOC_JZ4770_CODEC + imply SND_SOC_LM4857 + imply SND_SOC_LM49453 + imply SND_SOC_LOCHNAGAR_SC + imply SND_SOC_MAX98088 + imply SND_SOC_MAX98090 + imply SND_SOC_MAX98095 + imply SND_SOC_MAX98357A + imply SND_SOC_MAX98371 + imply SND_SOC_MAX98504 + imply SND_SOC_MAX9867 + imply SND_SOC_MAX98925 + imply SND_SOC_MAX98926 + imply SND_SOC_MAX98927 + imply SND_SOC_MAX98373 + imply SND_SOC_MAX9850 + imply SND_SOC_MAX9860 + imply SND_SOC_MAX9759 + imply SND_SOC_MAX9768 + imply SND_SOC_MAX9877 + imply SND_SOC_MC13783 + imply SND_SOC_ML26124 + imply SND_SOC_MT6351 + imply SND_SOC_MT6358 + imply SND_SOC_MT6660 + imply SND_SOC_NAU8540 + imply SND_SOC_NAU8810 + imply SND_SOC_NAU8822 + imply SND_SOC_NAU8824 + imply SND_SOC_NAU8825 + imply SND_SOC_HDMI_CODEC + imply SND_SOC_PCM1681 + imply SND_SOC_PCM1789_I2C + imply SND_SOC_PCM179X_I2C + imply SND_SOC_PCM179X_SPI + imply SND_SOC_PCM186X_I2C + imply SND_SOC_PCM186X_SPI + imply SND_SOC_PCM3008 + imply SND_SOC_PCM3060_I2C + imply SND_SOC_PCM3060_SPI + imply SND_SOC_PCM3168A_I2C + imply SND_SOC_PCM3168A_SPI + imply SND_SOC_PCM5102A + imply SND_SOC_PCM512x_I2C + imply SND_SOC_PCM512x_SPI + imply SND_SOC_RK3328 + imply SND_SOC_RT274 + imply SND_SOC_RT286 + imply SND_SOC_RT298 + imply SND_SOC_RT1011 + imply SND_SOC_RT1015 + imply SND_SOC_RT1305 + imply SND_SOC_RT1308 + imply SND_SOC_RT5514 + imply SND_SOC_RT5616 + imply SND_SOC_RT5631 + imply SND_SOC_RT5640 + imply SND_SOC_RT5645 + imply SND_SOC_RT5651 + imply SND_SOC_RT5659 + imply SND_SOC_RT5660 + imply SND_SOC_RT5663 + imply SND_SOC_RT5665 + imply SND_SOC_RT5668 + imply SND_SOC_RT5670 + imply SND_SOC_RT5677 + imply SND_SOC_RT5682 + imply SND_SOC_RT700_SDW + imply SND_SOC_RT711_SDW + imply SND_SOC_RT715_SDW + imply SND_SOC_RT1308_SDW + imply SND_SOC_SGTL5000 + imply SND_SOC_SI476X + imply SND_SOC_SIMPLE_AMPLIFIER + imply SND_SOC_SIRF_AUDIO_CODEC + imply SND_SOC_SPDIF + imply SND_SOC_SSM2305 + imply SND_SOC_SSM2518 + imply SND_SOC_SSM2602_SPI + imply SND_SOC_SSM2602_I2C + imply SND_SOC_SSM4567 + imply SND_SOC_STA32X + imply SND_SOC_STA350 + imply SND_SOC_STA529 + imply SND_SOC_STAC9766 + imply SND_SOC_STI_SAS + imply SND_SOC_TAS2552 + imply SND_SOC_TAS2562 + imply SND_SOC_TAS2770 + imply SND_SOC_TAS5086 + imply SND_SOC_TAS571X + imply SND_SOC_TAS5720 + imply SND_SOC_TAS6424 + imply SND_SOC_TDA7419 + imply SND_SOC_TFA9879 + imply SND_SOC_TLV320AIC23_I2C + imply SND_SOC_TLV320AIC23_SPI + imply SND_SOC_TLV320AIC26 + imply SND_SOC_TLV320AIC31XX + imply SND_SOC_TLV320AIC32X4_I2C + imply SND_SOC_TLV320AIC32X4_SPI + imply SND_SOC_TLV320AIC3X + imply SND_SOC_TPA6130A2 + imply SND_SOC_TLV320DAC33 + imply SND_SOC_TSCS42XX + imply SND_SOC_TSCS454 + imply SND_SOC_TS3A227E + imply SND_SOC_TWL4030 + imply SND_SOC_TWL6040 + imply SND_SOC_UDA1334 + imply SND_SOC_UDA134X + imply SND_SOC_UDA1380 + imply SND_SOC_WCD9335 + imply SND_SOC_WCD934X + imply SND_SOC_WL1273 + imply SND_SOC_WM0010 + imply SND_SOC_WM1250_EV1 + imply SND_SOC_WM2000 + imply SND_SOC_WM2200 + imply SND_SOC_WM5100 + imply SND_SOC_WM5102 + imply SND_SOC_WM5110 + imply SND_SOC_WM8350 + imply SND_SOC_WM8400 + imply SND_SOC_WM8510 + imply SND_SOC_WM8523 + imply SND_SOC_WM8524 + imply SND_SOC_WM8580 + imply SND_SOC_WM8711 + imply SND_SOC_WM8727 + imply SND_SOC_WM8728 + imply SND_SOC_WM8731 + imply SND_SOC_WM8737 + imply SND_SOC_WM8741 + imply SND_SOC_WM8750 + imply SND_SOC_WM8753 + imply SND_SOC_WM8770 + imply SND_SOC_WM8776 + imply SND_SOC_WM8782 + imply SND_SOC_WM8804_I2C + imply SND_SOC_WM8804_SPI + imply SND_SOC_WM8900 + imply SND_SOC_WM8903 + imply SND_SOC_WM8904 + imply SND_SOC_WM8940 + imply SND_SOC_WM8955 + imply SND_SOC_WM8960 + imply SND_SOC_WM8961 + imply SND_SOC_WM8962 + imply SND_SOC_WM8971 + imply SND_SOC_WM8974 + imply SND_SOC_WM8978 + imply SND_SOC_WM8983 + imply SND_SOC_WM8985 + imply SND_SOC_WM8988 + imply SND_SOC_WM8990 + imply SND_SOC_WM8991 + imply SND_SOC_WM8993 + imply SND_SOC_WM8994 + imply SND_SOC_WM8995 + imply SND_SOC_WM8996 + imply SND_SOC_WM8997 + imply SND_SOC_WM8998 + imply SND_SOC_WM9081 + imply SND_SOC_WM9090 + imply SND_SOC_WM9705 + imply SND_SOC_WM9712 + imply SND_SOC_WM9713 + imply SND_SOC_WSA881X help Normally ASoC codec drivers are only built if a machine driver which uses them is also built since they are only usable with a machine @@ -283,6 +283,7 @@ config SND_SOC_ALL_CODECS config SND_SOC_88PM860X tristate + depends on MFD_88PM860X config SND_SOC_ARIZONA tristate @@ -1301,11 +1302,13 @@ config SND_SOC_TSCS454 Add support for Tempo Semiconductor's TSCS454 audio CODEC. config SND_SOC_TWL4030 - select MFD_TWL4030_AUDIO tristate + depends on TWL4030_CORE + select MFD_TWL4030_AUDIO config SND_SOC_TWL6040 tristate + depends on TWL6040_CORE config SND_SOC_UDA1334 tristate "NXP UDA1334 DAC" @@ -1366,9 +1369,12 @@ config SND_SOC_WM5110 config SND_SOC_WM8350 tristate + depends on MFD_WM8350 config SND_SOC_WM8400 tristate + # FIXME nothing selects SND_SOC_WM8400?? + depends on MFD_WM8400 config SND_SOC_WM8510 tristate "Wolfson Microelectronics WM8510 CODEC" From 2619e03703475b7e0a6f73f85e642859cd25dfc8 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 10 Feb 2020 16:09:49 +0200 Subject: [PATCH 0127/4444] ASoC: ti: Add udma-pcm platform driver for UDMA Platform driver glue for platforms using UDMA (am654 and j721e). Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20200210140950.11090-2-peter.ujfalusi@ti.com Signed-off-by: Mark Brown --- sound/soc/ti/Kconfig | 4 ++++ sound/soc/ti/Makefile | 2 ++ sound/soc/ti/udma-pcm.c | 43 +++++++++++++++++++++++++++++++++++++++++ sound/soc/ti/udma-pcm.h | 18 +++++++++++++++++ 4 files changed, 67 insertions(+) create mode 100644 sound/soc/ti/udma-pcm.c create mode 100644 sound/soc/ti/udma-pcm.h diff --git a/sound/soc/ti/Kconfig b/sound/soc/ti/Kconfig index 29f61053ab62..bf85a160a523 100644 --- a/sound/soc/ti/Kconfig +++ b/sound/soc/ti/Kconfig @@ -10,6 +10,10 @@ config SND_SOC_TI_SDMA_PCM tristate select SND_SOC_GENERIC_DMAENGINE_PCM +config SND_SOC_TI_UDMA_PCM + tristate + select SND_SOC_GENERIC_DMAENGINE_PCM + comment "Texas Instruments DAI support for:" config SND_SOC_DAVINCI_ASP tristate "daVinci Audio Serial Port (ASP) or McBSP support" diff --git a/sound/soc/ti/Makefile b/sound/soc/ti/Makefile index 08c44d56ef3e..ea48c6679cc7 100644 --- a/sound/soc/ti/Makefile +++ b/sound/soc/ti/Makefile @@ -3,9 +3,11 @@ # Platform drivers snd-soc-ti-edma-objs := edma-pcm.o snd-soc-ti-sdma-objs := sdma-pcm.o +snd-soc-ti-udma-objs := udma-pcm.o obj-$(CONFIG_SND_SOC_TI_EDMA_PCM) += snd-soc-ti-edma.o obj-$(CONFIG_SND_SOC_TI_SDMA_PCM) += snd-soc-ti-sdma.o +obj-$(CONFIG_SND_SOC_TI_UDMA_PCM) += snd-soc-ti-udma.o # CPU DAI drivers snd-soc-davinci-asp-objs := davinci-i2s.o diff --git a/sound/soc/ti/udma-pcm.c b/sound/soc/ti/udma-pcm.c new file mode 100644 index 000000000000..39830caaaf7c --- /dev/null +++ b/sound/soc/ti/udma-pcm.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com + * Author: Peter Ujfalusi + */ + +#include +#include +#include +#include +#include +#include + +#include "udma-pcm.h" + +static const struct snd_pcm_hardware udma_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP | + SNDRV_PCM_INFO_INTERLEAVED, + .buffer_bytes_max = SIZE_MAX, + .period_bytes_min = 32, + .period_bytes_max = SZ_64K, + .periods_min = 2, + .periods_max = UINT_MAX, +}; + +static const struct snd_dmaengine_pcm_config udma_dmaengine_pcm_config = { + .pcm_hardware = &udma_pcm_hardware, + .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, +}; + +int udma_pcm_platform_register(struct device *dev) +{ + return devm_snd_dmaengine_pcm_register(dev, &udma_dmaengine_pcm_config, + 0); +} +EXPORT_SYMBOL_GPL(udma_pcm_platform_register); + +MODULE_AUTHOR("Peter Ujfalusi "); +MODULE_DESCRIPTION("UDMA PCM ASoC platform driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/ti/udma-pcm.h b/sound/soc/ti/udma-pcm.h new file mode 100644 index 000000000000..54111e7312c1 --- /dev/null +++ b/sound/soc/ti/udma-pcm.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com + */ + +#ifndef __UDMA_PCM_H__ +#define __UDMA_PCM_H__ + +#if IS_ENABLED(CONFIG_SND_SOC_TI_UDMA_PCM) +int udma_pcm_platform_register(struct device *dev); +#else +static inline int udma_pcm_platform_register(struct device *dev) +{ + return 0; +} +#endif /* CONFIG_SND_SOC_TI_UDMA_PCM */ + +#endif /* __UDMA_PCM_H__ */ From fb0c3c6e2007da156d023e91da42c173ea33b102 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 10 Feb 2020 16:09:50 +0200 Subject: [PATCH 0128/4444] ASoC: ti: davinci-mcasp: Add support for platforms using UDMA k3 devices including am654 and j721e are using UDMA Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20200210140950.11090-3-peter.ujfalusi@ti.com Signed-off-by: Mark Brown --- sound/soc/ti/Kconfig | 4 +++- sound/soc/ti/davinci-mcasp.c | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/sound/soc/ti/Kconfig b/sound/soc/ti/Kconfig index bf85a160a523..c5408c129f34 100644 --- a/sound/soc/ti/Kconfig +++ b/sound/soc/ti/Kconfig @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only menu "Audio support for Texas Instruments SoCs" -depends on DMA_OMAP || TI_EDMA || COMPILE_TEST +depends on DMA_OMAP || TI_EDMA || TI_K3_UDMA || COMPILE_TEST config SND_SOC_TI_EDMA_PCM tristate @@ -28,6 +28,7 @@ config SND_SOC_DAVINCI_MCASP tristate "Multichannel Audio Serial Port (McASP) support" select SND_SOC_TI_EDMA_PCM select SND_SOC_TI_SDMA_PCM + select SND_SOC_TI_UDMA_PCM help Say Y or M here if you want to have support for McASP IP found in various Texas Instruments SoCs like: @@ -35,6 +36,7 @@ config SND_SOC_DAVINCI_MCASP - Sitara line of SoCs (AM335x, AM438x, etc) - DRA7x devices - Keystone devices + - K3 devices (am654, j721e) config SND_SOC_DAVINCI_VCIF tristate "daVinci Voice Interface (VCIF) support" diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index e1e937eb1dc1..d9c3a3210a24 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -38,6 +38,7 @@ #include "edma-pcm.h" #include "sdma-pcm.h" +#include "udma-pcm.h" #include "davinci-mcasp.h" #define MCASP_MAX_AFIFO_DEPTH 64 @@ -1875,6 +1876,7 @@ nodata: enum { PCM_EDMA, PCM_SDMA, + PCM_UDMA, }; static const char *sdma_prefix = "ti,omap"; @@ -1912,6 +1914,8 @@ static int davinci_mcasp_get_dma_type(struct davinci_mcasp *mcasp) dev_dbg(mcasp->dev, "DMA controller compatible = \"%s\"\n", tmp); if (!strncmp(tmp, sdma_prefix, strlen(sdma_prefix))) return PCM_SDMA; + else if (strstr(tmp, "udmap")) + return PCM_UDMA; return PCM_EDMA; } @@ -2371,6 +2375,9 @@ static int davinci_mcasp_probe(struct platform_device *pdev) case PCM_SDMA: ret = sdma_pcm_platform_register(&pdev->dev, "tx", "rx"); break; + case PCM_UDMA: + ret = udma_pcm_platform_register(&pdev->dev); + break; default: dev_err(&pdev->dev, "No DMA controller found (%d)\n", ret); case -EPROBE_DEFER: From c8b60c6d93b8104f5a8d9fbb4f52ad88df918a44 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 6 Feb 2020 11:17:52 +0800 Subject: [PATCH 0129/4444] ASoC: mediatek: mt8173-rt5650: support HDMI jack reporting Uses hdmi-codec to support HDMI jack reporting. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200206102509.3.I253f51edff62df1d88005de12ba601aa029b1e99@changeid Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8173/mt8173-rt5650.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650.c b/sound/soc/mediatek/mt8173/mt8173-rt5650.c index ef6f23675286..849b050a54d1 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "../../codecs/rt5645.h" #define MCLK_FOR_CODECS 12288000 @@ -98,7 +99,7 @@ static const struct snd_soc_ops mt8173_rt5650_ops = { .hw_params = mt8173_rt5650_hw_params, }; -static struct snd_soc_jack mt8173_rt5650_jack; +static struct snd_soc_jack mt8173_rt5650_jack, mt8173_rt5650_hdmi_jack; static int mt8173_rt5650_init(struct snd_soc_pcm_runtime *runtime) { @@ -144,6 +145,19 @@ static int mt8173_rt5650_init(struct snd_soc_pcm_runtime *runtime) &mt8173_rt5650_jack); } +static int mt8173_rt5650_hdmi_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, + &mt8173_rt5650_hdmi_jack, NULL, 0); + if (ret) + return ret; + + return hdmi_codec_set_jack_detect(rtd->codec_dai->component, + &mt8173_rt5650_hdmi_jack); +} + enum { DAI_LINK_PLAYBACK, DAI_LINK_CAPTURE, @@ -222,6 +236,7 @@ static struct snd_soc_dai_link mt8173_rt5650_dais[] = { .name = "HDMI BE", .no_pcm = 1, .dpcm_playback = 1, + .init = mt8173_rt5650_hdmi_init, SND_SOC_DAILINK_REG(hdmi_be), }, }; From da22a95313197a349c557b98e3bee4e2b04d4f9d Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Mon, 10 Feb 2020 23:04:21 +0800 Subject: [PATCH 0130/4444] ASoC: wcd934x: Remove set but not unused variable 'hph_comp_ctrl7' sound/soc/codecs/wcd934x.c: In function wcd934x_codec_hphdelay_lutbypass: sound/soc/codecs/wcd934x.c:3395:6: warning: variable hph_comp_ctrl7 set but not used [-Wunused-but-set-variable] commit da3e83f8bb86 ("ASoC: wcd934x: add audio routings") involved this unused variable. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20200210150421.34680-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd934x.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index e780ecd554d2..aefaadfba8a1 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -3388,18 +3388,15 @@ static void wcd934x_codec_hphdelay_lutbypass(struct snd_soc_component *comp, { u8 hph_dly_mask; u16 hph_lut_bypass_reg = 0; - u16 hph_comp_ctrl7 = 0; switch (interp_idx) { case INTERP_HPHL: hph_dly_mask = 1; hph_lut_bypass_reg = WCD934X_CDC_TOP_HPHL_COMP_LUT; - hph_comp_ctrl7 = WCD934X_CDC_COMPANDER1_CTL7; break; case INTERP_HPHR: hph_dly_mask = 2; hph_lut_bypass_reg = WCD934X_CDC_TOP_HPHR_COMP_LUT; - hph_comp_ctrl7 = WCD934X_CDC_COMPANDER2_CTL7; break; default: return; From f4d95de415b286090c1bf739c20a5ea2aefda834 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 10 Feb 2020 09:24:22 +0000 Subject: [PATCH 0131/4444] ASoC: ti: davinci-mcasp: remove redundant assignment to variable ret The assignment to ret is redundant as it is not used in the error return path and hence can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20200210092423.327499-1-colin.king@canonical.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-mcasp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index d9c3a3210a24..734ffe925c4d 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -1765,10 +1765,8 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of( } else if (match) { pdata = devm_kmemdup(&pdev->dev, match->data, sizeof(*pdata), GFP_KERNEL); - if (!pdata) { - ret = -ENOMEM; - return pdata; - } + if (!pdata) + return NULL; } else { /* control shouldn't reach here. something is wrong */ ret = -EINVAL; From f9eb06cd0cdd50a3125bc9c62cdc997dc461eae7 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 6 Feb 2020 11:17:50 +0800 Subject: [PATCH 0132/4444] drm/mediatek: exit earlier if failed to register audio driver Exits earlier if register_audio_driver() returns errors. Signed-off-by: Tzung-Bi Shih Acked-by: CK Hu Link: https://lore.kernel.org/r/20200206102509.1.Ieba8d422486264eb7aaa3aa257620a1b0c74c6db@changeid Signed-off-by: Mark Brown --- drivers/gpu/drm/mediatek/mtk_hdmi.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 5e4a4dbda443..fcec06e63e0c 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -1659,7 +1659,7 @@ static const struct hdmi_codec_ops mtk_hdmi_audio_codec_ops = { .get_eld = mtk_hdmi_audio_get_eld, }; -static void mtk_hdmi_register_audio_driver(struct device *dev) +static int mtk_hdmi_register_audio_driver(struct device *dev) { struct hdmi_codec_pdata codec_data = { .ops = &mtk_hdmi_audio_codec_ops, @@ -1672,9 +1672,10 @@ static void mtk_hdmi_register_audio_driver(struct device *dev) PLATFORM_DEVID_AUTO, &codec_data, sizeof(codec_data)); if (IS_ERR(pdev)) - return; + return PTR_ERR(pdev); DRM_INFO("%s driver bound to HDMI\n", HDMI_CODEC_DRV_NAME); + return 0; } static int mtk_drm_hdmi_probe(struct platform_device *pdev) @@ -1708,7 +1709,11 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev) return ret; } - mtk_hdmi_register_audio_driver(dev); + ret = mtk_hdmi_register_audio_driver(dev); + if (ret) { + dev_err(dev, "Failed to register audio driver: %d\n", ret); + return ret; + } hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs; hdmi->bridge.of_node = pdev->dev.of_node; From 5d3c644773925c3568617435e42a9404a114c428 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 6 Feb 2020 11:17:51 +0800 Subject: [PATCH 0133/4444] drm/mediatek: support HDMI jack status reporting 1. Provides a callback (i.e. mtk_hdmi_audio_hook_plugged_cb) to hdmi-codec. When ASoC machine driver calls hdmi_codec_set_jack_detect(), the callback will be invoked to save plugged_cb and codec_dev parameters. +---------+ set_jack_ +------------+ plugged_cb +----------+ | machine | ----------> | hdmi-codec | ----------> | mtk-hdmi | +---------+ detect() +------------+ codec_dev +----------+ 2. When there is any jack status changes, mtk-hdmi will call the plugged_cb() to notify hdmi-codec. And then hdmi-codec will call snd_soc_jack_report(). +----------+ plugged_cb +------------+ | mtk-hdmi | ----------> | hdmi-codec | -> snd_soc_jack_report() +----------+ codec_dev +------------+ connector_status Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200206102509.2.I230fd59de28e73934a91cb01424e25b9e84727f4@changeid Signed-off-by: Mark Brown --- drivers/gpu/drm/mediatek/mtk_hdmi.c | 34 ++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index fcec06e63e0c..03aeb73005ef 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -169,6 +169,8 @@ struct mtk_hdmi { bool audio_enable; bool powered; bool enabled; + hdmi_codec_plugged_cb plugged_cb; + struct device *codec_dev; }; static inline struct mtk_hdmi *hdmi_ctx_from_bridge(struct drm_bridge *b) @@ -1194,13 +1196,23 @@ static void mtk_hdmi_clk_disable_audio(struct mtk_hdmi *hdmi) clk_disable_unprepare(hdmi->clk[MTK_HDMI_CLK_AUD_SPDIF]); } +static enum drm_connector_status +mtk_hdmi_update_plugged_status(struct mtk_hdmi *hdmi) +{ + bool connected = mtk_cec_hpd_high(hdmi->cec_dev); + + if (hdmi->plugged_cb && hdmi->codec_dev) + hdmi->plugged_cb(hdmi->codec_dev, connected); + + return connected ? + connector_status_connected : connector_status_disconnected; +} + static enum drm_connector_status hdmi_conn_detect(struct drm_connector *conn, bool force) { struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn); - - return mtk_cec_hpd_high(hdmi->cec_dev) ? - connector_status_connected : connector_status_disconnected; + return mtk_hdmi_update_plugged_status(hdmi); } static void hdmi_conn_destroy(struct drm_connector *conn) @@ -1651,20 +1663,36 @@ static int mtk_hdmi_audio_get_eld(struct device *dev, void *data, uint8_t *buf, return 0; } +static int mtk_hdmi_audio_hook_plugged_cb(struct device *dev, void *data, + hdmi_codec_plugged_cb fn, + struct device *codec_dev) +{ + struct mtk_hdmi *hdmi = data; + + hdmi->plugged_cb = fn; + hdmi->codec_dev = codec_dev; + mtk_hdmi_update_plugged_status(hdmi); + + return 0; +} + static const struct hdmi_codec_ops mtk_hdmi_audio_codec_ops = { .hw_params = mtk_hdmi_audio_hw_params, .audio_startup = mtk_hdmi_audio_startup, .audio_shutdown = mtk_hdmi_audio_shutdown, .digital_mute = mtk_hdmi_audio_digital_mute, .get_eld = mtk_hdmi_audio_get_eld, + .hook_plugged_cb = mtk_hdmi_audio_hook_plugged_cb, }; static int mtk_hdmi_register_audio_driver(struct device *dev) { + struct mtk_hdmi *hdmi = dev_get_drvdata(dev); struct hdmi_codec_pdata codec_data = { .ops = &mtk_hdmi_audio_codec_ops, .max_i2s_channels = 2, .i2s = 1, + .data = hdmi, }; struct platform_device *pdev; From 3f06501ea4d2d8add203e66d225274f106cb4029 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 29 Jan 2020 16:07:18 -0600 Subject: [PATCH 0134/4444] ASoC: SOF: Do not reset hw_params for streams that ignored suspend Setting the prepared flag to false marks the streams for the hw_params to be reset upon resuming. In the case of the D0i3-compatible streams that ignored suspend to keep the pipeline active in the DSP during suspend, this should not be done. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200129220726.31792-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-audio.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 0d8f65b9ae25..345e42ee4783 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -39,6 +39,13 @@ int sof_set_hw_params_upon_resume(struct device *dev) */ list_for_each_entry(spcm, &sdev->pcm_list, list) { for (dir = 0; dir <= SNDRV_PCM_STREAM_CAPTURE; dir++) { + /* + * do not reset hw_params upon resume for streams that + * were kept running during suspend + */ + if (spcm->stream[dir].suspend_ignored) + continue; + substream = spcm->stream[dir].substream; if (!substream || !substream->runtime) continue; From fb9a81192d44ae9f334b1d88651dec427fa751d8 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 29 Jan 2020 16:07:19 -0600 Subject: [PATCH 0135/4444] ASoC: SOF: pm: Unify suspend/resume routines Unify the suspend/resume routines for both the D0I3/D3 DSP targets in sof_suspend()/sof_resume(). Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200129220726.31792-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pm.c | 91 ++++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 52 deletions(-) diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index a0cde053b61a..5b186bceedb9 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -50,6 +50,7 @@ static void sof_cache_debugfs(struct snd_sof_dev *sdev) static int sof_resume(struct device *dev, bool runtime_resume) { struct snd_sof_dev *sdev = dev_get_drvdata(dev); + enum sof_d0_substate old_d0_substate = sdev->d0_substate; int ret; /* do nothing if dsp resume callbacks are not set */ @@ -60,6 +61,17 @@ static int sof_resume(struct device *dev, bool runtime_resume) if (sdev->first_boot) return 0; + /* resume from D0I3 */ + if (!runtime_resume && old_d0_substate == SOF_DSP_D0I3) { + ret = snd_sof_set_d0_substate(sdev, SOF_DSP_D0I0); + if (ret < 0 && ret != -ENOTSUPP) { + dev_err(sdev->dev, + "error: failed to resume from D0I3 %d\n", + ret); + return ret; + } + } + /* * if the runtime_resume flag is set, call the runtime_resume routine * or else call the system resume routine @@ -74,6 +86,10 @@ static int sof_resume(struct device *dev, bool runtime_resume) return ret; } + /* Nothing further to do if resuming from D0I3 */ + if (!runtime_resume && old_d0_substate == SOF_DSP_D0I3) + return 0; + sdev->fw_state = SOF_FW_BOOT_PREPARE; /* load the firmware */ @@ -140,10 +156,7 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) return 0; if (sdev->fw_state != SOF_FW_BOOT_COMPLETE) - goto power_down; - - /* release trace */ - snd_sof_release_trace(sdev); + goto suspend; /* set restore_stream for all streams during system suspend */ if (!runtime_suspend) { @@ -156,6 +169,22 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) } } + if (snd_sof_dsp_d0i3_on_suspend(sdev)) { + /* suspend to D0i3 */ + ret = snd_sof_set_d0_substate(sdev, SOF_DSP_D0I3); + if (ret < 0) { + dev_err(sdev->dev, "error: failed to enter D0I3, %d\n", + ret); + return ret; + } + + /* Skip to platform-specific suspend if DSP is entering D0I3 */ + goto suspend; + } + + /* release trace */ + snd_sof_release_trace(sdev); + #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) /* cache debugfs contents during runtime suspend */ if (runtime_suspend) @@ -179,13 +208,13 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) ret); } -power_down: +suspend: /* return if the DSP was not probed successfully */ if (sdev->fw_state == SOF_FW_BOOT_NOT_STARTED) return 0; - /* power down all DSP cores */ + /* platform-specific suspend */ if (runtime_suspend) ret = snd_sof_dsp_runtime_suspend(sdev); else @@ -195,6 +224,10 @@ power_down: "error: failed to power down DSP during suspend %d\n", ret); + /* Do not reset FW state if DSP is in D0I3 */ + if (sdev->d0_substate == SOF_DSP_D0I3) + return ret; + /* reset FW state */ sdev->fw_state = SOF_FW_BOOT_NOT_STARTED; @@ -275,58 +308,12 @@ EXPORT_SYMBOL(snd_sof_set_d0_substate); int snd_sof_resume(struct device *dev) { - struct snd_sof_dev *sdev = dev_get_drvdata(dev); - int ret; - - if (snd_sof_dsp_d0i3_on_suspend(sdev)) { - /* resume from D0I3 */ - dev_dbg(sdev->dev, "DSP will exit from D0i3...\n"); - ret = snd_sof_set_d0_substate(sdev, SOF_DSP_D0I0); - if (ret == -ENOTSUPP) { - /* fallback to resume from D3 */ - dev_dbg(sdev->dev, "D0i3 not supported, fall back to resume from D3...\n"); - goto d3_resume; - } else if (ret < 0) { - dev_err(sdev->dev, "error: failed to exit from D0I3 %d\n", - ret); - return ret; - } - - /* platform-specific resume from D0i3 */ - return snd_sof_dsp_resume(sdev); - } - -d3_resume: - /* resume from D3 */ return sof_resume(dev, false); } EXPORT_SYMBOL(snd_sof_resume); int snd_sof_suspend(struct device *dev) { - struct snd_sof_dev *sdev = dev_get_drvdata(dev); - int ret; - - if (snd_sof_dsp_d0i3_on_suspend(sdev)) { - /* suspend to D0i3 */ - dev_dbg(sdev->dev, "DSP is trying to enter D0i3...\n"); - ret = snd_sof_set_d0_substate(sdev, SOF_DSP_D0I3); - if (ret == -ENOTSUPP) { - /* fallback to D3 suspend */ - dev_dbg(sdev->dev, "D0i3 not supported, fall back to D3...\n"); - goto d3_suspend; - } else if (ret < 0) { - dev_err(sdev->dev, "error: failed to enter D0I3, %d\n", - ret); - return ret; - } - - /* platform-specific suspend to D0i3 */ - return snd_sof_dsp_suspend(sdev); - } - -d3_suspend: - /* suspend to D3 */ return sof_suspend(dev, false); } EXPORT_SYMBOL(snd_sof_suspend); From 043ae13bbd558971ce91596ce09c03d6ef6a4a0c Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 29 Jan 2020 16:07:20 -0600 Subject: [PATCH 0136/4444] ASoC: SOF: Add system_suspend_target field to struct snd_sof_dev Add the system_suspend_target field to struct snd_sof_dev to track the intended system suspend power target. This will be used as one of the criteria for determining the final DSP power state. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200129220726.31792-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 4 ++-- sound/soc/sof/pcm.c | 2 +- sound/soc/sof/pm.c | 9 ++++++--- sound/soc/sof/sof-priv.h | 12 ++++++++++-- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 4a4d318f97ff..fddf2c48904f 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -481,7 +481,7 @@ int hda_dsp_resume(struct snd_sof_dev *sdev) struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct pci_dev *pci = to_pci_dev(sdev->dev); - if (sdev->s0_suspend) { + if (sdev->system_suspend_target == SOF_SUSPEND_S0IX) { /* restore L1SEN bit */ if (hda->l1_support_changed) snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, @@ -530,7 +530,7 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev) struct pci_dev *pci = to_pci_dev(sdev->dev); int ret; - if (sdev->s0_suspend) { + if (sdev->system_suspend_target == SOF_SUSPEND_S0IX) { /* enable L1SEN to make sure the system can enter S0Ix */ hda->l1_support_changed = snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 29435ba2d329..db3df02c7398 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -372,7 +372,7 @@ static int sof_pcm_trigger(struct snd_soc_component *component, stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_START; break; case SNDRV_PCM_TRIGGER_SUSPEND: - if (sdev->s0_suspend && + if (sdev->system_suspend_target == SOF_SUSPEND_S0IX && spcm->stream[substream->stream].d0i3_compatible) { /* * trap the event, not sending trigger stop to diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 5b186bceedb9..c86ac1e84bd7 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -323,10 +323,13 @@ int snd_sof_prepare(struct device *dev) struct snd_sof_dev *sdev = dev_get_drvdata(dev); #if defined(CONFIG_ACPI) - sdev->s0_suspend = acpi_target_system_state() == ACPI_STATE_S0; + if (acpi_target_system_state() == ACPI_STATE_S0) + sdev->system_suspend_target = SOF_SUSPEND_S0IX; + else + sdev->system_suspend_target = SOF_SUSPEND_S3; #else /* will suspend to S3 by default */ - sdev->s0_suspend = false; + sdev->system_suspend_target = SOF_SUSPEND_S3; #endif return 0; @@ -337,6 +340,6 @@ void snd_sof_complete(struct device *dev) { struct snd_sof_dev *sdev = dev_get_drvdata(dev); - sdev->s0_suspend = false; + sdev->system_suspend_target = SOF_SUSPEND_NONE; } EXPORT_SYMBOL(snd_sof_complete); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index bc2337cf1142..1839cc51957d 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -60,6 +60,13 @@ enum sof_d0_substate { SOF_DSP_D0I3, /* DSP D0i3(low power) substate*/ }; +/* System suspend target state */ +enum sof_system_suspend_state { + SOF_SUSPEND_NONE = 0, + SOF_SUSPEND_S0IX, + SOF_SUSPEND_S3, +}; + struct snd_sof_dev; struct snd_sof_ipc_msg; struct snd_sof_ipc; @@ -325,8 +332,9 @@ struct snd_sof_dev { /* power states related */ enum sof_d0_substate d0_substate; - /* flag to track if the intended power target of suspend is S0ix */ - bool s0_suspend; + + /* Intended power target of system suspend */ + enum sof_system_suspend_state system_suspend_target; /* DSP firmware boot */ wait_queue_head_t boot_wait; From 700d167739a099cdf12ed15c25fec7f4cb563d42 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 29 Jan 2020 16:07:21 -0600 Subject: [PATCH 0137/4444] ASoC: SOF: pm: Introduce DSP power states Add a new enum sof_dsp_power_states for all the possible the DSP device states. The SOF driver currently handles only the D0 and D3 states and support for other states will be added later as needed. Also, add a helper to determine the target DSP power state based on the system suspend target. The snd_sof_dsp_d0i3_on_suspend() function is renamed to snd_sof_stream_suspend_ignored() to be more indicative of what it does and it used to determine the target DSP state during system suspend. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200129220726.31792-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pm.c | 38 +++++++++++++++++++++++++++++++++++++- sound/soc/sof/sof-audio.c | 2 +- sound/soc/sof/sof-audio.h | 2 +- sound/soc/sof/sof-priv.h | 10 ++++++++++ 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index c86ac1e84bd7..bec25cb6beec 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -12,6 +12,42 @@ #include "sof-priv.h" #include "sof-audio.h" +/* + * Helper function to determine the target DSP state during + * system suspend. This function only cares about the device + * D-states. Platform-specific substates, if any, should be + * handled by the platform-specific parts. + */ +static u32 snd_sof_dsp_power_target(struct snd_sof_dev *sdev) +{ + u32 target_dsp_state; + + switch (sdev->system_suspend_target) { + case SOF_SUSPEND_S3: + /* DSP should be in D3 if the system is suspending to S3 */ + target_dsp_state = SOF_DSP_PM_D3; + break; + case SOF_SUSPEND_S0IX: + /* + * Currently, the only criterion for retaining the DSP in D0 + * is that there are streams that ignored the suspend trigger. + * Additional criteria such Soundwire clock-stop mode and + * device suspend latency considerations will be added later. + */ + if (snd_sof_stream_suspend_ignored(sdev)) + target_dsp_state = SOF_DSP_PM_D0; + else + target_dsp_state = SOF_DSP_PM_D3; + break; + default: + /* This case would be during runtime suspend */ + target_dsp_state = SOF_DSP_PM_D3; + break; + } + + return target_dsp_state; +} + static int sof_send_pm_ctx_ipc(struct snd_sof_dev *sdev, int cmd) { struct sof_ipc_pm_ctx pm_ctx; @@ -169,7 +205,7 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) } } - if (snd_sof_dsp_d0i3_on_suspend(sdev)) { + if (snd_sof_dsp_power_target(sdev) == SOF_DSP_PM_D0) { /* suspend to D0i3 */ ret = snd_sof_set_d0_substate(sdev, SOF_DSP_D0I3); if (ret < 0) { diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 345e42ee4783..d16571ca129c 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -11,7 +11,7 @@ #include "sof-audio.h" #include "ops.h" -bool snd_sof_dsp_d0i3_on_suspend(struct snd_sof_dev *sdev) +bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev) { struct snd_sof_pcm *spcm; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index a62fb2da6a6e..a2702afbd9a1 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -202,7 +202,7 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, /* PM */ int sof_restore_pipelines(struct device *dev); int sof_set_hw_params_upon_resume(struct device *dev); -bool snd_sof_dsp_d0i3_on_suspend(struct snd_sof_dev *sdev); +bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev); /* Machine driver enumeration */ int sof_machine_register(struct snd_sof_dev *sdev, void *pdata); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 1839cc51957d..a7c6109acd98 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -54,6 +54,16 @@ extern int sof_core_debug; (IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) || \ IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)) +/* DSP power state */ +enum sof_dsp_power_states { + SOF_DSP_PM_D0, + SOF_DSP_PM_D1, + SOF_DSP_PM_D2, + SOF_DSP_PM_D3_HOT, + SOF_DSP_PM_D3, + SOF_DSP_PM_D3_COLD, +}; + /* DSP D0ix sub-state */ enum sof_d0_substate { SOF_DSP_D0I0 = 0, /* DSP default D0 substate */ From 61e285caf40fef18e8bd7cea5237ee6723609a1c Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 29 Jan 2020 16:07:22 -0600 Subject: [PATCH 0138/4444] ASoC: SOF: Move DSP power state transitions to platform-specific ops The DSP device substates such as D0I0/D0I3 are platform-specific. Therefore, the d0_substate field of struct snd_sof_dev is replaced with the dsp_power_state field which represents the current state of the DSP. This field holds both the device state and the platform-specific substate values. With the DSP device substates being platform-specific, the DSP power state transitions need to be performed in the platform-specific suspend/resume ops as well. In order to achieve this, the ops signature has to be modified to pass the target device state as an argument. The target substate will be determined by the platform-specific ops before performing the transition. For example, in the case of the system suspending to S0IX, the top-level SOF device suspend callback needs to only determine if the DSP will be entering D3 or remain in D0. The target substate in case the device needs to remain in D0 (D0I0 or D0I3) will be determined by the platform-specific suspend op. With the addition of the extended set of power states for the DSP, the set_power_state op for HDA platforms has to be extended to handle only the appropriate state transitions. So, the implementation for the Intel HDA platforms is also modified. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200129220726.31792-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 4 +- sound/soc/sof/intel/hda-dsp.c | 223 +++++++++++++++++++++++++++++++--- sound/soc/sof/intel/hda.h | 10 +- sound/soc/sof/ops.h | 16 +-- sound/soc/sof/pm.c | 92 ++------------ sound/soc/sof/sof-priv.h | 18 ++- 6 files changed, 242 insertions(+), 121 deletions(-) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 34cefbaf2d2a..1d07450aff77 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -286,8 +286,8 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) /* initialize sof device */ sdev->dev = dev; - /* initialize default D0 sub-state */ - sdev->d0_substate = SOF_DSP_D0I0; + /* initialize default DSP power state */ + sdev->dsp_power_state.state = SOF_DSP_PM_D0; sdev->pdata = plat_data; sdev->first_boot = true; diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index fddf2c48904f..8c00e128a7b0 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -338,13 +338,10 @@ static int hda_dsp_send_pm_gate_ipc(struct snd_sof_dev *sdev, u32 flags) sizeof(pm_gate), &reply, sizeof(reply)); } -int hda_dsp_set_power_state(struct snd_sof_dev *sdev, - enum sof_d0_substate d0_substate) +static int hda_dsp_update_d0i3c_register(struct snd_sof_dev *sdev, u8 value) { struct hdac_bus *bus = sof_to_bus(sdev); - u32 flags; int ret; - u8 value; /* Write to D0I3C after Command-In-Progress bit is cleared */ ret = hda_dsp_wait_d0i3c_done(sdev); @@ -354,7 +351,6 @@ int hda_dsp_set_power_state(struct snd_sof_dev *sdev, } /* Update D0I3C register */ - value = d0_substate == SOF_DSP_D0I3 ? SOF_HDA_VS_D0I3C_I3 : 0; snd_hdac_chip_updateb(bus, VS_D0I3C, SOF_HDA_VS_D0I3C_I3, value); /* Wait for cmd in progress to be cleared before exiting the function */ @@ -367,20 +363,160 @@ int hda_dsp_set_power_state(struct snd_sof_dev *sdev, dev_vdbg(bus->dev, "D0I3C updated, register = 0x%x\n", snd_hdac_chip_readb(bus, VS_D0I3C)); - if (d0_substate == SOF_DSP_D0I0) - flags = HDA_PM_PPG;/* prevent power gating in D0 */ - else - flags = HDA_PM_NO_DMA_TRACE;/* disable DMA trace in D0I3*/ + return 0; +} - /* sending pm_gate IPC */ - ret = hda_dsp_send_pm_gate_ipc(sdev, flags); +static int hda_dsp_set_D0_state(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state) +{ + u32 flags = 0; + int ret; + u8 value = 0; + + /* + * Sanity check for illegal state transitions + * The only allowed transitions are: + * 1. D3 -> D0I0 + * 2. D0I0 -> D0I3 + * 3. D0I3 -> D0I0 + */ + switch (sdev->dsp_power_state.state) { + case SOF_DSP_PM_D0: + /* Follow the sequence below for D0 substate transitions */ + break; + case SOF_DSP_PM_D3: + /* Follow regular flow for D3 -> D0 transition */ + return 0; + default: + dev_err(sdev->dev, "error: transition from %d to %d not allowed\n", + sdev->dsp_power_state.state, target_state->state); + return -EINVAL; + } + + /* Set flags and register value for D0 target substate */ + if (target_state->substate == SOF_HDA_DSP_PM_D0I3) { + value = SOF_HDA_VS_D0I3C_I3; + + /* disable DMA trace in D0I3 */ + flags = HDA_PM_NO_DMA_TRACE; + } else { + /* prevent power gating in D0I0 */ + flags = HDA_PM_PPG; + } + + /* update D0I3C register */ + ret = hda_dsp_update_d0i3c_register(sdev, value); if (ret < 0) + return ret; + + /* + * Notify the DSP of the state change. + * If this IPC fails, revert the D0I3C register update in order + * to prevent partial state change. + */ + ret = hda_dsp_send_pm_gate_ipc(sdev, flags); + if (ret < 0) { dev_err(sdev->dev, "error: PM_GATE ipc error %d\n", ret); + goto revert; + } + + return ret; + +revert: + /* fallback to the previous register value */ + value = value ? 0 : SOF_HDA_VS_D0I3C_I3; + + /* + * This can fail but return the IPC error to signal that + * the state change failed. + */ + hda_dsp_update_d0i3c_register(sdev, value); return ret; } +/* + * All DSP power state transitions are initiated by the driver. + * If the requested state change fails, the error is simply returned. + * Further state transitions are attempted only when the set_power_save() op + * is called again either because of a new IPC sent to the DSP or + * during system suspend/resume. + */ +int hda_dsp_set_power_state(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state) +{ + int ret = 0; + + /* Nothing to do if the DSP is already in the requested state */ + if (target_state->state == sdev->dsp_power_state.state && + target_state->substate == sdev->dsp_power_state.substate) + return 0; + + switch (target_state->state) { + case SOF_DSP_PM_D0: + ret = hda_dsp_set_D0_state(sdev, target_state); + break; + case SOF_DSP_PM_D3: + /* The only allowed transition is: D0I0 -> D3 */ + if (sdev->dsp_power_state.state == SOF_DSP_PM_D0 && + sdev->dsp_power_state.substate == SOF_HDA_DSP_PM_D0I0) + break; + + dev_err(sdev->dev, + "error: transition from %d to %d not allowed\n", + sdev->dsp_power_state.state, target_state->state); + return -EINVAL; + default: + dev_err(sdev->dev, "error: target state unsupported %d\n", + target_state->state); + return -EINVAL; + } + if (ret < 0) { + dev_err(sdev->dev, + "failed to set requested target DSP state %d substate %d\n", + target_state->state, target_state->substate); + return ret; + } + + sdev->dsp_power_state = *target_state; + dev_dbg(sdev->dev, "New DSP state %d substate %d\n", + target_state->state, target_state->substate); + return ret; +} + +/* + * Audio DSP states may transform as below:- + * + * D0I3 compatible stream + * Runtime +---------------------+ opened only, timeout + * suspend | +--------------------+ + * +------------+ D0(active) | | + * | | <---------------+ | + * | +--------> | | | + * | |Runtime +--^--+---------^--+--+ The last | | + * | |resume | | | | opened D0I3 | | + * | | | | | | compatible | | + * | | resume| | | | stream closed | | + * | | from | | D3 | | | | + * | | D3 | |suspend | | d0i3 | | + * | | | | | |suspend | | + * | | | | | | | | + * | | | | | | | | + * +-v---+-----------+--v-------+ | | +------+----v----+ + * | | | +-----------> | + * | D3 (suspended) | | | D0I3 +-----+ + * | | +--------------+ | | + * | | resume from | | | + * +-------------------^--------+ d0i3 suspend +----------------+ | + * | | + * | D3 suspend | + * +------------------------------------------------+ + * + * d0i3_suspend = s0_suspend && D0I3 stream opened, + * D3 suspend = !d0i3_suspend, + */ + static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) { struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; @@ -480,8 +616,22 @@ int hda_dsp_resume(struct snd_sof_dev *sdev) { struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct pci_dev *pci = to_pci_dev(sdev->dev); + const struct sof_dsp_power_state target_state = { + .state = SOF_DSP_PM_D0, + .substate = SOF_HDA_DSP_PM_D0I0, + }; + int ret; + + /* resume from D0I3 */ + if (sdev->dsp_power_state.state == SOF_DSP_PM_D0) { + /* Set DSP power state */ + ret = hda_dsp_set_power_state(sdev, &target_state); + if (ret < 0) { + dev_err(sdev->dev, "error: setting dsp state %d substate %d\n", + target_state.state, target_state.substate); + return ret; + } - if (sdev->system_suspend_target == SOF_SUSPEND_S0IX) { /* restore L1SEN bit */ if (hda->l1_support_changed) snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, @@ -495,13 +645,27 @@ int hda_dsp_resume(struct snd_sof_dev *sdev) } /* init hda controller. DSP cores will be powered up during fw boot */ - return hda_resume(sdev, false); + ret = hda_resume(sdev, false); + if (ret < 0) + return ret; + + hda_dsp_set_power_state(sdev, &target_state); + return ret; } int hda_dsp_runtime_resume(struct snd_sof_dev *sdev) { + const struct sof_dsp_power_state target_state = { + .state = SOF_DSP_PM_D0, + }; + int ret; + /* init hda controller. DSP cores will be powered up during fw boot */ - return hda_resume(sdev, true); + ret = hda_resume(sdev, true); + if (ret < 0) + return ret; + + return hda_dsp_set_power_state(sdev, &target_state); } int hda_dsp_runtime_idle(struct snd_sof_dev *sdev) @@ -519,18 +683,41 @@ int hda_dsp_runtime_idle(struct snd_sof_dev *sdev) int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev) { + const struct sof_dsp_power_state target_state = { + .state = SOF_DSP_PM_D3, + }; + int ret; + /* stop hda controller and power dsp off */ - return hda_suspend(sdev, true); + ret = hda_suspend(sdev, true); + if (ret < 0) + return ret; + + return hda_dsp_set_power_state(sdev, &target_state); } -int hda_dsp_suspend(struct snd_sof_dev *sdev) +int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) { struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct hdac_bus *bus = sof_to_bus(sdev); struct pci_dev *pci = to_pci_dev(sdev->dev); + const struct sof_dsp_power_state target_dsp_state = { + .state = target_state, + .substate = target_state == SOF_DSP_PM_D0 ? + SOF_HDA_DSP_PM_D0I3 : 0, + }; int ret; - if (sdev->system_suspend_target == SOF_SUSPEND_S0IX) { + if (target_state == SOF_DSP_PM_D0) { + /* Set DSP power state */ + ret = hda_dsp_set_power_state(sdev, &target_dsp_state); + if (ret < 0) { + dev_err(sdev->dev, "error: setting dsp state %d substate %d\n", + target_dsp_state.state, + target_dsp_state.substate); + return ret; + } + /* enable L1SEN to make sure the system can enter S0Ix */ hda->l1_support_changed = snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, @@ -551,7 +738,7 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev) return ret; } - return 0; + return hda_dsp_set_power_state(sdev, &target_dsp_state); } int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 6191d9192fae..02c2a7eadb1b 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -392,6 +392,12 @@ struct sof_intel_dsp_bdl { #define SOF_HDA_PLAYBACK 0 #define SOF_HDA_CAPTURE 1 +/* HDA DSP D0 substate */ +enum sof_hda_D0_substate { + SOF_HDA_DSP_PM_D0I0, /* default D0 substate */ + SOF_HDA_DSP_PM_D0I3, /* low power D0 substate */ +}; + /* represents DSP HDA controller frontend - i.e. host facing control */ struct sof_intel_hda_dev { @@ -469,9 +475,9 @@ void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev); void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev); int hda_dsp_set_power_state(struct snd_sof_dev *sdev, - enum sof_d0_substate d0_substate); + const struct sof_dsp_power_state *target_state); -int hda_dsp_suspend(struct snd_sof_dev *sdev); +int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state); int hda_dsp_resume(struct snd_sof_dev *sdev); int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev); int hda_dsp_runtime_resume(struct snd_sof_dev *sdev); diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index e929a6e0058f..7f532bcc8e9d 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -146,10 +146,11 @@ static inline int snd_sof_dsp_resume(struct snd_sof_dev *sdev) return 0; } -static inline int snd_sof_dsp_suspend(struct snd_sof_dev *sdev) +static inline int snd_sof_dsp_suspend(struct snd_sof_dev *sdev, + u32 target_state) { if (sof_ops(sdev)->suspend) - return sof_ops(sdev)->suspend(sdev); + return sof_ops(sdev)->suspend(sdev, target_state); return 0; } @@ -193,14 +194,15 @@ static inline int snd_sof_dsp_set_clk(struct snd_sof_dev *sdev, u32 freq) return 0; } -static inline int snd_sof_dsp_set_power_state(struct snd_sof_dev *sdev, - enum sof_d0_substate substate) +static inline int +snd_sof_dsp_set_power_state(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state) { if (sof_ops(sdev)->set_power_state) - return sof_ops(sdev)->set_power_state(sdev, substate); + return sof_ops(sdev)->set_power_state(sdev, target_state); - /* D0 substate is not supported */ - return -ENOTSUPP; + /* D0 substate is not supported, do nothing here. */ + return 0; } /* debug */ diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index bec25cb6beec..c410822d9920 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -86,7 +86,7 @@ static void sof_cache_debugfs(struct snd_sof_dev *sdev) static int sof_resume(struct device *dev, bool runtime_resume) { struct snd_sof_dev *sdev = dev_get_drvdata(dev); - enum sof_d0_substate old_d0_substate = sdev->d0_substate; + u32 old_state = sdev->dsp_power_state.state; int ret; /* do nothing if dsp resume callbacks are not set */ @@ -97,17 +97,6 @@ static int sof_resume(struct device *dev, bool runtime_resume) if (sdev->first_boot) return 0; - /* resume from D0I3 */ - if (!runtime_resume && old_d0_substate == SOF_DSP_D0I3) { - ret = snd_sof_set_d0_substate(sdev, SOF_DSP_D0I0); - if (ret < 0 && ret != -ENOTSUPP) { - dev_err(sdev->dev, - "error: failed to resume from D0I3 %d\n", - ret); - return ret; - } - } - /* * if the runtime_resume flag is set, call the runtime_resume routine * or else call the system resume routine @@ -122,8 +111,8 @@ static int sof_resume(struct device *dev, bool runtime_resume) return ret; } - /* Nothing further to do if resuming from D0I3 */ - if (!runtime_resume && old_d0_substate == SOF_DSP_D0I3) + /* Nothing further to do if resuming from a low-power D0 substate */ + if (!runtime_resume && old_state == SOF_DSP_PM_D0) return 0; sdev->fw_state = SOF_FW_BOOT_PREPARE; @@ -176,15 +165,13 @@ static int sof_resume(struct device *dev, bool runtime_resume) "error: ctx_restore ipc error during resume %d\n", ret); - /* initialize default D0 sub-state */ - sdev->d0_substate = SOF_DSP_D0I0; - return ret; } static int sof_suspend(struct device *dev, bool runtime_suspend) { struct snd_sof_dev *sdev = dev_get_drvdata(dev); + u32 target_state = 0; int ret; /* do nothing if dsp suspend callback is not set */ @@ -205,18 +192,11 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) } } - if (snd_sof_dsp_power_target(sdev) == SOF_DSP_PM_D0) { - /* suspend to D0i3 */ - ret = snd_sof_set_d0_substate(sdev, SOF_DSP_D0I3); - if (ret < 0) { - dev_err(sdev->dev, "error: failed to enter D0I3, %d\n", - ret); - return ret; - } + target_state = snd_sof_dsp_power_target(sdev); - /* Skip to platform-specific suspend if DSP is entering D0I3 */ + /* Skip to platform-specific suspend if DSP is entering D0 */ + if (target_state == SOF_DSP_PM_D0) goto suspend; - } /* release trace */ snd_sof_release_trace(sdev); @@ -254,14 +234,14 @@ suspend: if (runtime_suspend) ret = snd_sof_dsp_runtime_suspend(sdev); else - ret = snd_sof_dsp_suspend(sdev); + ret = snd_sof_dsp_suspend(sdev, target_state); if (ret < 0) dev_err(sdev->dev, "error: failed to power down DSP during suspend %d\n", ret); - /* Do not reset FW state if DSP is in D0I3 */ - if (sdev->d0_substate == SOF_DSP_D0I3) + /* Do not reset FW state if DSP is in D0 */ + if (target_state == SOF_DSP_PM_D0) return ret; /* reset FW state */ @@ -290,58 +270,6 @@ int snd_sof_runtime_resume(struct device *dev) } EXPORT_SYMBOL(snd_sof_runtime_resume); -int snd_sof_set_d0_substate(struct snd_sof_dev *sdev, - enum sof_d0_substate d0_substate) -{ - int ret; - - if (sdev->d0_substate == d0_substate) - return 0; - - /* do platform specific set_state */ - ret = snd_sof_dsp_set_power_state(sdev, d0_substate); - if (ret < 0) - return ret; - - /* update dsp D0 sub-state */ - sdev->d0_substate = d0_substate; - - return 0; -} -EXPORT_SYMBOL(snd_sof_set_d0_substate); - -/* - * Audio DSP states may transform as below:- - * - * D0I3 compatible stream - * Runtime +---------------------+ opened only, timeout - * suspend | +--------------------+ - * +------------+ D0(active) | | - * | | <---------------+ | - * | +--------> | | | - * | |Runtime +--^--+---------^--+--+ The last | | - * | |resume | | | | opened D0I3 | | - * | | | | | | compatible | | - * | | resume| | | | stream closed | | - * | | from | | D3 | | | | - * | | D3 | |suspend | | d0i3 | | - * | | | | | |suspend | | - * | | | | | | | | - * | | | | | | | | - * +-v---+-----------+--v-------+ | | +------+----v----+ - * | | | +-----------> | - * | D3 (suspended) | | | D0I3 +-----+ - * | | +--------------+ | | - * | | resume from | | | - * +-------------------^--------+ d0i3 suspend +----------------+ | - * | | - * | D3 suspend | - * +------------------------------------------------+ - * - * d0i3_suspend = s0_suspend && D0I3 stream opened, - * D3 suspend = !d0i3_suspend, - */ - int snd_sof_resume(struct device *dev) { return sof_resume(dev, false); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index a7c6109acd98..ef33aaadbc31 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -64,10 +64,9 @@ enum sof_dsp_power_states { SOF_DSP_PM_D3_COLD, }; -/* DSP D0ix sub-state */ -enum sof_d0_substate { - SOF_DSP_D0I0 = 0, /* DSP default D0 substate */ - SOF_DSP_D0I3, /* DSP D0i3(low power) substate*/ +struct sof_dsp_power_state { + u32 state; + u32 substate; /* platform-specific */ }; /* System suspend target state */ @@ -186,14 +185,15 @@ struct snd_sof_dsp_ops { int (*post_fw_run)(struct snd_sof_dev *sof_dev); /* optional */ /* DSP PM */ - int (*suspend)(struct snd_sof_dev *sof_dev); /* optional */ + int (*suspend)(struct snd_sof_dev *sof_dev, + u32 target_state); /* optional */ int (*resume)(struct snd_sof_dev *sof_dev); /* optional */ int (*runtime_suspend)(struct snd_sof_dev *sof_dev); /* optional */ int (*runtime_resume)(struct snd_sof_dev *sof_dev); /* optional */ int (*runtime_idle)(struct snd_sof_dev *sof_dev); /* optional */ int (*set_hw_params_upon_resume)(struct snd_sof_dev *sdev); /* optional */ int (*set_power_state)(struct snd_sof_dev *sdev, - enum sof_d0_substate d0_substate); /* optional */ + const struct sof_dsp_power_state *target_state); /* optional */ /* DSP clocking */ int (*set_clk)(struct snd_sof_dev *sof_dev, u32 freq); /* optional */ @@ -340,8 +340,8 @@ struct snd_sof_dev { */ struct snd_soc_component_driver plat_drv; - /* power states related */ - enum sof_d0_substate d0_substate; + /* current DSP power state */ + struct sof_dsp_power_state dsp_power_state; /* Intended power target of system suspend */ enum sof_system_suspend_state system_suspend_target; @@ -435,8 +435,6 @@ int snd_sof_resume(struct device *dev); int snd_sof_suspend(struct device *dev); int snd_sof_prepare(struct device *dev); void snd_sof_complete(struct device *dev); -int snd_sof_set_d0_substate(struct snd_sof_dev *sdev, - enum sof_d0_substate d0_substate); void snd_sof_new_platform_drv(struct snd_sof_dev *sdev); From de23a838d8d61767c6232f229f019eb46401cb93 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 29 Jan 2020 16:07:23 -0600 Subject: [PATCH 0139/4444] ASoC: SOF: audio: Add helper to check if only D0i3 streams are active Add a helper function to check if only D0i3-compatible streams are active. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200129220726.31792-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-audio.c | 33 +++++++++++++++++++++++++++++++++ sound/soc/sof/sof-audio.h | 1 + 2 files changed, 34 insertions(+) diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index d16571ca129c..75f2ef2bd94b 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -11,6 +11,39 @@ #include "sof-audio.h" #include "ops.h" +/* + * helper to determine if there are only D0i3 compatible + * streams active + */ +bool snd_sof_dsp_only_d0i3_compatible_stream_active(struct snd_sof_dev *sdev) +{ + struct snd_pcm_substream *substream; + struct snd_sof_pcm *spcm; + bool d0i3_compatible_active = false; + int dir; + + list_for_each_entry(spcm, &sdev->pcm_list, list) { + for (dir = 0; dir <= SNDRV_PCM_STREAM_CAPTURE; dir++) { + substream = spcm->stream[dir].substream; + if (!substream || !substream->runtime) + continue; + + /* + * substream->runtime being not NULL indicates that + * that the stream is open. No need to check the + * stream state. + */ + if (!spcm->stream[dir].d0i3_compatible) + return false; + + d0i3_compatible_active = true; + } + } + + return d0i3_compatible_active; +} +EXPORT_SYMBOL(snd_sof_dsp_only_d0i3_compatible_stream_active); + bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev) { struct snd_sof_pcm *spcm; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index a2702afbd9a1..eacd10e4da11 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -203,6 +203,7 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, int sof_restore_pipelines(struct device *dev); int sof_set_hw_params_upon_resume(struct device *dev); bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev); +bool snd_sof_dsp_only_d0i3_compatible_stream_active(struct snd_sof_dev *sdev); /* Machine driver enumeration */ int sof_machine_register(struct snd_sof_dev *sdev, void *pdata); From 207bf12f642f39e749ca65d3efca9d48311e629f Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 29 Jan 2020 16:07:24 -0600 Subject: [PATCH 0140/4444] ASoC: SOF: Intel: hda: Amend the DSP state transition diagram Amend the DSP state transition diagram in preparation for introducing the feature to support opportunistic DSP D0I3 state when the system is in S0. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200129220726.31792-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 36 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 8c00e128a7b0..7b8425330ae0 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -488,33 +488,31 @@ int hda_dsp_set_power_state(struct snd_sof_dev *sdev, /* * Audio DSP states may transform as below:- * - * D0I3 compatible stream - * Runtime +---------------------+ opened only, timeout + * Opportunistic D0I3 in S0 + * Runtime +---------------------+ Delayed D0i3 work timeout * suspend | +--------------------+ - * +------------+ D0(active) | | + * +------------+ D0I0(active) | | * | | <---------------+ | - * | +--------> | | | - * | |Runtime +--^--+---------^--+--+ The last | | - * | |resume | | | | opened D0I3 | | - * | | | | | | compatible | | - * | | resume| | | | stream closed | | - * | | from | | D3 | | | | - * | | D3 | |suspend | | d0i3 | | + * | +--------> | New IPC | | + * | |Runtime +--^--+---------^--+--+ (via mailbox) | | + * | |resume | | | | | | + * | | | | | | | | + * | | System| | | | | | + * | | resume| | S3/S0IX | | | | + * | | | | suspend | | S0IX | | * | | | | | |suspend | | * | | | | | | | | * | | | | | | | | * +-v---+-----------+--v-------+ | | +------+----v----+ * | | | +-----------> | - * | D3 (suspended) | | | D0I3 +-----+ - * | | +--------------+ | | - * | | resume from | | | - * +-------------------^--------+ d0i3 suspend +----------------+ | - * | | - * | D3 suspend | - * +------------------------------------------------+ + * | D3 (suspended) | | | D0I3 | + * | | +--------------+ | + * | | System resume | | + * +----------------------------+ +----------------+ * - * d0i3_suspend = s0_suspend && D0I3 stream opened, - * D3 suspend = !d0i3_suspend, + * S0IX suspend: The DSP is in D0I3 if any D0I3-compatible streams + * ignored the suspend trigger. Otherwise the DSP + * is in D3. */ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) From 63e51fd33fef04b634a0c32ae491ab16a19cb17c Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 29 Jan 2020 16:07:25 -0600 Subject: [PATCH 0141/4444] ASoC: SOF: Intel: cnl: Implement feature to support DSP D0i3 in S0 This patch implements support for DSP D0i3 when the system is in S0. The basic idea is to schedule a delayed work after every successful IPC TX that checks if there are only D0I3-compatible streams active and if so transition the DSP to D0I3. With the introduction of DSP D0I3 in S0, we need to ensure that the DSP is in D0I0 before sending any new IPCs. The exception for this would be the compact IPCs that are used to set the DSP in D0I3/D0I0 states. Signed-off-by: Keyon Jie Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200129220726.31792-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/cnl.c | 37 +++++++++++++++++++++++++++------ sound/soc/sof/intel/hda-dsp.c | 39 +++++++++++++++++++++++++++++++++-- sound/soc/sof/intel/hda.c | 5 +++++ sound/soc/sof/intel/hda.h | 11 ++++++++++ sound/soc/sof/ipc.c | 29 ++++++++++++++++++++++++-- sound/soc/sof/sof-priv.h | 3 +++ 6 files changed, 114 insertions(+), 10 deletions(-) diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 9e2d8afe0535..8a59fec72919 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -171,23 +171,48 @@ static bool cnl_compact_ipc_compress(struct snd_sof_ipc_msg *msg, static int cnl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) { + struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; + struct sof_ipc_cmd_hdr *hdr; u32 dr = 0; u32 dd = 0; + /* + * Currently the only compact IPC supported is the PM_GATE + * IPC which is used for transitioning the DSP between the + * D0I0 and D0I3 states. And these are sent only during the + * set_power_state() op. Therefore, there will never be a case + * that a compact IPC results in the DSP exiting D0I3 without + * the host and FW being in sync. + */ if (cnl_compact_ipc_compress(msg, &dr, &dd)) { /* send the message via IPC registers */ snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDD, dd); snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR, CNL_DSP_REG_HIPCIDR_BUSY | dr); - } else { - /* send the message via mailbox */ - sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, - msg->msg_size); - snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR, - CNL_DSP_REG_HIPCIDR_BUSY); + return 0; } + /* send the message via mailbox */ + sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, + msg->msg_size); + snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR, + CNL_DSP_REG_HIPCIDR_BUSY); + + hdr = msg->msg_data; + + /* + * Use mod_delayed_work() to schedule the delayed work + * to avoid scheduling multiple workqueue items when + * IPCs are sent at a high-rate. mod_delayed_work() + * modifies the timer if the work is pending. + * Also, a new delayed work should not be queued after the + * the CTX_SAVE IPC, which is sent before the DSP enters D3. + */ + if (hdr->cmd != (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CTX_SAVE)) + mod_delayed_work(system_wq, &hdev->d0i3_work, + msecs_to_jiffies(SOF_HDA_D0I3_WORK_DELAY_MS)); + return 0; } diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 7b8425330ae0..ee604be715b9 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -17,6 +17,7 @@ #include #include +#include "../sof-audio.h" #include "../ops.h" #include "hda.h" #include "hda-ipc.h" @@ -334,8 +335,9 @@ static int hda_dsp_send_pm_gate_ipc(struct snd_sof_dev *sdev, u32 flags) pm_gate.flags = flags; /* send pm_gate ipc to dsp */ - return sof_ipc_tx_message(sdev->ipc, pm_gate.hdr.cmd, &pm_gate, - sizeof(pm_gate), &reply, sizeof(reply)); + return sof_ipc_tx_message_no_pm(sdev->ipc, pm_gate.hdr.cmd, + &pm_gate, sizeof(pm_gate), &reply, + sizeof(reply)); } static int hda_dsp_update_d0i3c_register(struct snd_sof_dev *sdev, u8 value) @@ -706,6 +708,9 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) }; int ret; + /* cancel any attempt for DSP D0I3 */ + cancel_delayed_work_sync(&hda->d0i3_work); + if (target_state == SOF_DSP_PM_D0) { /* Set DSP power state */ ret = hda_dsp_set_power_state(sdev, &target_dsp_state); @@ -780,3 +785,33 @@ int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) #endif return 0; } + +void hda_dsp_d0i3_work(struct work_struct *work) +{ + struct sof_intel_hda_dev *hdev = container_of(work, + struct sof_intel_hda_dev, + d0i3_work.work); + struct hdac_bus *bus = &hdev->hbus.core; + struct snd_sof_dev *sdev = dev_get_drvdata(bus->dev); + struct sof_dsp_power_state target_state; + int ret; + + target_state.state = SOF_DSP_PM_D0; + + /* DSP can enter D0I3 iff only D0I3-compatible streams are active */ + if (snd_sof_dsp_only_d0i3_compatible_stream_active(sdev)) + target_state.substate = SOF_HDA_DSP_PM_D0I3; + else + target_state.substate = SOF_HDA_DSP_PM_D0I0; + + /* remain in D0I0 */ + if (target_state.substate == SOF_HDA_DSP_PM_D0I0) + return; + + /* This can fail but error cannot be propagated */ + ret = hda_dsp_set_power_state(sdev, &target_state); + if (ret < 0) + dev_err_ratelimited(sdev->dev, + "error: failed to set DSP state %d substate %d\n", + target_state.state, target_state.substate); +} diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 65b86dd044f1..2b8754a76584 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -598,6 +598,8 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) /* set default mailbox offset for FW ready message */ sdev->dsp_box.offset = HDA_DSP_MBOX_UPLINK_OFFSET; + INIT_DELAYED_WORK(&hdev->d0i3_work, hda_dsp_d0i3_work); + return 0; free_ipc_irq: @@ -622,6 +624,9 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) struct pci_dev *pci = to_pci_dev(sdev->dev); const struct sof_intel_dsp_desc *chip = hda->desc; + /* cancel any attempt for DSP D0I3 */ + cancel_delayed_work_sync(&hda->d0i3_work); + #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* codec removal, invoke bus_device_remove */ snd_hdac_ext_bus_device_remove(bus); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 02c2a7eadb1b..a46b66437a3d 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -392,6 +392,13 @@ struct sof_intel_dsp_bdl { #define SOF_HDA_PLAYBACK 0 #define SOF_HDA_CAPTURE 1 +/* + * Time in ms for opportunistic D0I3 entry delay. + * This has been deliberately chosen to be long to avoid race conditions. + * Could be optimized in future. + */ +#define SOF_HDA_D0I3_WORK_DELAY_MS 5000 + /* HDA DSP D0 substate */ enum sof_hda_D0_substate { SOF_HDA_DSP_PM_D0I0, /* default D0 substate */ @@ -420,6 +427,9 @@ struct sof_intel_hda_dev { /* DMIC device */ struct platform_device *dmic_dev; + + /* delayed work to enter D0I3 opportunistically */ + struct delayed_work d0i3_work; }; static inline struct hdac_bus *sof_to_bus(struct snd_sof_dev *s) @@ -487,6 +497,7 @@ void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags); void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags); void hda_ipc_dump(struct snd_sof_dev *sdev); void hda_ipc_irq_dump(struct snd_sof_dev *sdev); +void hda_dsp_d0i3_work(struct work_struct *work); /* * DSP PCM Operations. diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index b63fc529b456..22d296f95761 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -268,7 +268,6 @@ static int sof_ipc_tx_message_unlocked(struct snd_sof_ipc *ipc, u32 header, spin_unlock_irq(&sdev->ipc_lock); if (ret < 0) { - /* So far IPC TX never fails, consider making the above void */ dev_err_ratelimited(sdev->dev, "error: ipc tx failed with error %d\n", ret); @@ -288,6 +287,32 @@ static int sof_ipc_tx_message_unlocked(struct snd_sof_ipc *ipc, u32 header, int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header, void *msg_data, size_t msg_bytes, void *reply_data, size_t reply_bytes) +{ + const struct sof_dsp_power_state target_state = { + .state = SOF_DSP_PM_D0, + }; + int ret; + + /* ensure the DSP is in D0 before sending a new IPC */ + ret = snd_sof_dsp_set_power_state(ipc->sdev, &target_state); + if (ret < 0) { + dev_err(ipc->sdev->dev, "error: resuming DSP %d\n", ret); + return ret; + } + + return sof_ipc_tx_message_no_pm(ipc, header, msg_data, msg_bytes, + reply_data, reply_bytes); +} +EXPORT_SYMBOL(sof_ipc_tx_message); + +/* + * send IPC message from host to DSP without modifying the DSP state. + * This will be used for IPC's that can be handled by the DSP + * even in a low-power D0 substate. + */ +int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, u32 header, + void *msg_data, size_t msg_bytes, + void *reply_data, size_t reply_bytes) { int ret; @@ -305,7 +330,7 @@ int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header, return ret; } -EXPORT_SYMBOL(sof_ipc_tx_message); +EXPORT_SYMBOL(sof_ipc_tx_message_no_pm); /* handle reply message from DSP */ int snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id) diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index ef33aaadbc31..00084471d0de 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -470,6 +470,9 @@ int snd_sof_ipc_valid(struct snd_sof_dev *sdev); int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header, void *msg_data, size_t msg_bytes, void *reply_data, size_t reply_bytes); +int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, u32 header, + void *msg_data, size_t msg_bytes, + void *reply_data, size_t reply_bytes); /* * Trace/debug From 851fd87324430dfe56cd55dfd05a8114ac82d168 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 29 Jan 2020 16:07:26 -0600 Subject: [PATCH 0142/4444] ASoC: SOF: Intel: hda: Allow trace DMA in S0 when DSP is in D0I3 for debug Trace DMA is disabled by default when the DSP is in D0I3. Add a debug option to keep trace DMA enabled when the DSP is in D0I3 during S0. Signed-off-by: Ranjani Sridharan Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200129220726.31792-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index ee604be715b9..14228b4931d6 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -15,6 +15,7 @@ * Hardware interface for generic Intel audio DSP HDA IP */ +#include #include #include #include "../sof-audio.h" @@ -22,6 +23,13 @@ #include "hda.h" #include "hda-ipc.h" +static bool hda_enable_trace_D0I3_S0; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG) +module_param_named(enable_trace_D0I3_S0, hda_enable_trace_D0I3_S0, bool, 0444); +MODULE_PARM_DESC(enable_trace_D0I3_S0, + "SOF HDA enable trace when the DSP is in D0I3 in S0"); +#endif + /* * DSP Core control. */ @@ -399,8 +407,14 @@ static int hda_dsp_set_D0_state(struct snd_sof_dev *sdev, if (target_state->substate == SOF_HDA_DSP_PM_D0I3) { value = SOF_HDA_VS_D0I3C_I3; - /* disable DMA trace in D0I3 */ - flags = HDA_PM_NO_DMA_TRACE; + /* + * Trace DMA is disabled by default when the DSP enters D0I3. + * But it can be kept enabled when the DSP enters D0I3 while the + * system is in S0 for debug. + */ + if (hda_enable_trace_D0I3_S0 && + sdev->system_suspend_target != SOF_SUSPEND_NONE) + flags = HDA_PM_NO_DMA_TRACE; } else { /* prevent power gating in D0I0 */ flags = HDA_PM_PPG; @@ -450,11 +464,26 @@ int hda_dsp_set_power_state(struct snd_sof_dev *sdev, { int ret = 0; - /* Nothing to do if the DSP is already in the requested state */ + /* + * When the DSP is already in D0I3 and the target state is D0I3, + * it could be the case that the DSP is in D0I3 during S0 + * and the system is suspending to S0Ix. Therefore, + * hda_dsp_set_D0_state() must be called to disable trace DMA + * by sending the PM_GATE IPC to the FW. + */ + if (target_state->substate == SOF_HDA_DSP_PM_D0I3 && + sdev->system_suspend_target == SOF_SUSPEND_S0IX) + goto set_state; + + /* + * For all other cases, return without doing anything if + * the DSP is already in the target state. + */ if (target_state->state == sdev->dsp_power_state.state && target_state->substate == sdev->dsp_power_state.substate) return 0; +set_state: switch (target_state->state) { case SOF_DSP_PM_D0: ret = hda_dsp_set_D0_state(sdev, target_state); From fa1f875c120fa44572c561d86022af2f6b0774c7 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 10 Feb 2020 17:14:02 +0200 Subject: [PATCH 0143/4444] ALSA: dmaengine_pcm: Consider DMA cache caused delay in pointer callback Some DMA engines can have big FIFOs which adds to the latency. The DMAengine framework can report the FIFO utilization in bytes. Use this information for the delay reporting. Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20200210151402.29634-1-peter.ujfalusi@ti.com Signed-off-by: Mark Brown --- sound/core/pcm_dmaengine.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index 5749a8a49784..d8be7b488162 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c @@ -247,9 +247,14 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state); if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) { + struct snd_pcm_runtime *runtime = substream->runtime; + buf_size = snd_pcm_lib_buffer_bytes(substream); if (state.residue > 0 && state.residue <= buf_size) pos = buf_size - state.residue; + + runtime->delay = bytes_to_frames(runtime, + state.in_flight_bytes); } return bytes_to_frames(substream->runtime, pos); From 6be021b1f00d11a420981d711adb2fa9b47c37b9 Mon Sep 17 00:00:00 2001 From: James Liao Date: Wed, 15 Jan 2020 13:42:35 +0800 Subject: [PATCH 0144/4444] arm64: dts: mt8183: Enable CPU idle-states Enable mcdi-cpu and mcdi-cluster on MT8183 CPUs. Signed-off-by: James Liao Signed-off-by: Matthias Brugger --- arch/arm64/boot/dts/mediatek/mt8183.dtsi | 30 ++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi index 124f9d3e09f5..504891d2b97b 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi @@ -74,6 +74,7 @@ reg = <0x000>; enable-method = "psci"; capacity-dmips-mhz = <741>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu1: cpu@1 { @@ -82,6 +83,7 @@ reg = <0x001>; enable-method = "psci"; capacity-dmips-mhz = <741>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu2: cpu@2 { @@ -90,6 +92,7 @@ reg = <0x002>; enable-method = "psci"; capacity-dmips-mhz = <741>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu3: cpu@3 { @@ -98,6 +101,7 @@ reg = <0x003>; enable-method = "psci"; capacity-dmips-mhz = <741>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu4: cpu@100 { @@ -106,6 +110,7 @@ reg = <0x100>; enable-method = "psci"; capacity-dmips-mhz = <1024>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu5: cpu@101 { @@ -114,6 +119,7 @@ reg = <0x101>; enable-method = "psci"; capacity-dmips-mhz = <1024>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu6: cpu@102 { @@ -122,6 +128,7 @@ reg = <0x102>; enable-method = "psci"; capacity-dmips-mhz = <1024>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu7: cpu@103 { @@ -130,6 +137,29 @@ reg = <0x103>; enable-method = "psci"; capacity-dmips-mhz = <1024>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + }; + + idle-states { + entry-method = "psci"; + + CPU_SLEEP: cpu-sleep { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x00010001>; + entry-latency-us = <200>; + exit-latency-us = <200>; + min-residency-us = <800>; + }; + + CLUSTER_SLEEP: cluster-sleep { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x01010001>; + entry-latency-us = <250>; + exit-latency-us = <400>; + min-residency-us = <1300>; + }; }; }; From 7a5aaba4a4f45acc8192beb8a4b1bd4a58b67ce3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Feb 2020 12:14:12 +0900 Subject: [PATCH 0145/4444] ASoC: soc-pcm: add snd_soc_runtime_action() ALSA SoC has snd_soc_runtime_activate() / snd_soc_runtime_deactivate(). These increment or decrement DAI/Component activity, but the code difference is only +1 or -1. This patch adds common snd_soc_runtime_action() which can get +1 or -1 as parameter, and use it from snd_soc_runtime_activate/deactivate() to avoid duplicate implementation. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87blq7ceyq.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 73 ++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 44 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index ff1b7c7078e5..4d26558fcbfc 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -82,6 +82,33 @@ static int soc_rtd_trigger(struct snd_soc_pcm_runtime *rtd, return 0; } +static void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, + int stream, int action) +{ + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai; + int i; + + lockdep_assert_held(&rtd->card->pcm_mutex); + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + cpu_dai->playback_active += action; + for_each_rtd_codec_dai(rtd, i, codec_dai) + codec_dai->playback_active += action; + } else { + cpu_dai->capture_active += action; + for_each_rtd_codec_dai(rtd, i, codec_dai) + codec_dai->capture_active += action; + } + + cpu_dai->active += action; + cpu_dai->component->active += action; + for_each_rtd_codec_dai(rtd, i, codec_dai) { + codec_dai->active += action; + codec_dai->component->active += action; + } +} + /** * snd_soc_runtime_activate() - Increment active count for PCM runtime components * @rtd: ASoC PCM runtime that is activated @@ -94,28 +121,7 @@ static int soc_rtd_trigger(struct snd_soc_pcm_runtime *rtd, */ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) { - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct snd_soc_dai *codec_dai; - int i; - - lockdep_assert_held(&rtd->card->pcm_mutex); - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - cpu_dai->playback_active++; - for_each_rtd_codec_dai(rtd, i, codec_dai) - codec_dai->playback_active++; - } else { - cpu_dai->capture_active++; - for_each_rtd_codec_dai(rtd, i, codec_dai) - codec_dai->capture_active++; - } - - cpu_dai->active++; - cpu_dai->component->active++; - for_each_rtd_codec_dai(rtd, i, codec_dai) { - codec_dai->active++; - codec_dai->component->active++; - } + snd_soc_runtime_action(rtd, stream, 1); } /** @@ -130,28 +136,7 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) */ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) { - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct snd_soc_dai *codec_dai; - int i; - - lockdep_assert_held(&rtd->card->pcm_mutex); - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - cpu_dai->playback_active--; - for_each_rtd_codec_dai(rtd, i, codec_dai) - codec_dai->playback_active--; - } else { - cpu_dai->capture_active--; - for_each_rtd_codec_dai(rtd, i, codec_dai) - codec_dai->capture_active--; - } - - cpu_dai->active--; - cpu_dai->component->active--; - for_each_rtd_codec_dai(rtd, i, codec_dai) { - codec_dai->component->active--; - codec_dai->active--; - } + snd_soc_runtime_action(rtd, stream, -1); } /** From 5c25bd641a7b195b5ed71ce9d6955618bae7b7d3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Feb 2020 12:14:18 +0900 Subject: [PATCH 0146/4444] ASoC: soc-pcm: adjustment for DAI member 0 reset commit 3635bf09a89cf ("ASoC: soc-pcm: add symmetry for channels and sample bits") set 0 not only to dai->rate but also to dai->channels and dai->sample_bits if DAI was not active at soc_pcm_close(). and commit d3383420c969c ("ASoC: soc-pcm: move DAIs parameters cleaning into hw_free()") moved it from soc_pcm_close() to soc_pcm_hw_free(). These happen at v3.14. But, maybe because of branch merge conflict or something similar happen then, soc_pcm_close() still has old settings (care only dai->rate, doesn't care dai->channels/sample_bits). This is 100% duplicated operation. This patch removes soc_pcm_close() side operation which supposed to already moved to soc_pcm_hw_free(). Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87a75rceyl.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 4d26558fcbfc..2a4f7ac5f563 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -687,15 +687,6 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) snd_soc_runtime_deactivate(rtd, substream->stream); - /* clear the corresponding DAIs rate when inactive */ - if (!cpu_dai->active) - cpu_dai->rate = 0; - - for_each_rtd_codec_dai(rtd, i, codec_dai) { - if (!codec_dai->active) - codec_dai->rate = 0; - } - snd_soc_dai_digital_mute(cpu_dai, 1, substream->stream); snd_soc_dai_shutdown(cpu_dai, substream); From 09e88f8a5c56ac5258935a5a543868c20a55d4dd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Feb 2020 12:14:22 +0900 Subject: [PATCH 0147/4444] ASoC: soc-pcm: add for_each_dapm_widgets() macro This patch adds new for_each_dapm_widgets() macro and use it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/878slbceyg.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 5 +++++ sound/soc/soc-dapm.c | 8 ++------ sound/soc/soc-pcm.c | 17 +++++++++-------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 2a306c6f3fbc..9439e75945f6 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -693,6 +693,11 @@ struct snd_soc_dapm_widget_list { struct snd_soc_dapm_widget *widgets[0]; }; +#define for_each_dapm_widgets(list, i, widget) \ + for ((i) = 0; \ + (i) < list->num_widgets && (widget = list->widgets[i]); \ + (i)++) + struct snd_soc_dapm_stats { int power_checks; int path_checks; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index bc20ad9abf8b..cc17a3730d3d 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1724,9 +1724,7 @@ static void dapm_widget_update(struct snd_soc_card *card) wlist = dapm_kcontrol_get_wlist(update->kcontrol); - for (wi = 0; wi < wlist->num_widgets; wi++) { - w = wlist->widgets[wi]; - + for_each_dapm_widgets(wlist, wi, w) { if (w->event && (w->event_flags & SND_SOC_DAPM_PRE_REG)) { ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG); if (ret != 0) @@ -1753,9 +1751,7 @@ static void dapm_widget_update(struct snd_soc_card *card) w->name, ret); } - for (wi = 0; wi < wlist->num_widgets; wi++) { - w = wlist->widgets[wi]; - + for_each_dapm_widgets(wlist, wi, w) { if (w->event && (w->event_flags & SND_SOC_DAPM_POST_REG)) { ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG); if (ret != 0) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 2a4f7ac5f563..7a490c05d4e9 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1306,12 +1306,12 @@ static inline struct snd_soc_dapm_widget * static int widget_in_list(struct snd_soc_dapm_widget_list *list, struct snd_soc_dapm_widget *widget) { + struct snd_soc_dapm_widget *w; int i; - for (i = 0; i < list->num_widgets; i++) { - if (widget == list->widgets[i]) + for_each_dapm_widgets(list, i, w) + if (widget == w) return 1; - } return 0; } @@ -1422,12 +1422,13 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, struct snd_soc_card *card = fe->card; struct snd_soc_dapm_widget_list *list = *list_; struct snd_soc_pcm_runtime *be; + struct snd_soc_dapm_widget *widget; int i, new = 0, err; /* Create any new FE <--> BE connections */ - for (i = 0; i < list->num_widgets; i++) { + for_each_dapm_widgets(list, i, widget) { - switch (list->widgets[i]->id) { + switch (widget->id) { case snd_soc_dapm_dai_in: if (stream != SNDRV_PCM_STREAM_PLAYBACK) continue; @@ -1441,10 +1442,10 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, } /* is there a valid BE rtd for this widget */ - be = dpcm_get_be(card, list->widgets[i], stream); + be = dpcm_get_be(card, widget, stream); if (!be) { dev_err(fe->dev, "ASoC: no BE found for %s\n", - list->widgets[i]->name); + widget->name); continue; } @@ -1460,7 +1461,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, err = dpcm_be_connect(fe, be, stream); if (err < 0) { dev_err(fe->dev, "ASoC: can't connect %s\n", - list->widgets[i]->name); + widget->name); break; } else if (err == 0) /* already connected */ continue; From e82ebffce3ec07584bcc2fc4c4d33a43fd9515f5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Feb 2020 12:14:26 +0900 Subject: [PATCH 0148/4444] ASoC: soc-pcm: don't use bit-OR'ed error Current soc-pcm is using bit-OR'ed error ret |= snd_soc_component_close(component, substream); ret |= snd_soc_component_hw_free(component, substream); The driver may return arbitrary error codes so they can conflict. The bit-OR'ed error works only if the return code is always consistent. This patch fixup it, and use *last* ret value. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/877e0vceyc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 7a490c05d4e9..8d8ed4774e9c 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -498,13 +498,16 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_component *component; - int i, ret = 0; + int i, r, ret = 0; for_each_rtd_components(rtd, i, component) { if (component == last) break; - ret |= snd_soc_component_close(component, substream); + r = snd_soc_component_close(component, substream); + if (r < 0) + ret = r; /* use last ret */ + snd_soc_component_module_put_when_close(component); } @@ -798,13 +801,15 @@ static int soc_pcm_components_hw_free(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_component *component; - int i, ret = 0; + int i, r, ret = 0; for_each_rtd_components(rtd, i, component) { if (component == last) break; - ret |= snd_soc_component_hw_free(component, substream); + r = snd_soc_component_hw_free(component, substream); + if (r < 0) + ret = r; /* use last ret */ } return ret; From b56be800f1292c9b79c4f66571c701551bdf9e12 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Feb 2020 12:14:33 +0900 Subject: [PATCH 0149/4444] ASoC: soc-pcm: call snd_soc_dai_startup()/shutdown() once Current soc_pcm_open() calls snd_soc_dai_startup() under loop. Thus, it needs to care about started/not-yet-started codec DAI. But, if soc-dai.c is handling it, soc-pcm.c don't need to care about it. This patch adds started flag to soc-dai.h, and simplify soc-pcm.c. This is one of prepare for cleanup soc-pcm-open() Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/875zgfcey5.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 5 ++++- sound/soc/soc-dai.c | 11 +++++++++-- sound/soc/soc-pcm.c | 7 ++----- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index eaaeb00e9e84..04c23ac0dfff 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -324,7 +324,6 @@ struct snd_soc_dai { /* DAI runtime info */ unsigned int capture_active; /* stream usage count */ unsigned int playback_active; /* stream usage count */ - unsigned int probed:1; unsigned int active; @@ -348,6 +347,10 @@ struct snd_soc_dai { unsigned int rx_mask; struct list_head list; + + /* bit field */ + unsigned int probed:1; + unsigned int started:1; }; static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai, diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 51031e330179..73a829393652 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -295,17 +295,24 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, { int ret = 0; - if (dai->driver->ops->startup) + if (!dai->started && + dai->driver->ops->startup) ret = dai->driver->ops->startup(substream, dai); + if (ret == 0) + dai->started = 1; + return ret; } void snd_soc_dai_shutdown(struct snd_soc_dai *dai, struct snd_pcm_substream *substream) { - if (dai->driver->ops->shutdown) + if (dai->started && + dai->driver->ops->shutdown) dai->driver->ops->shutdown(substream, dai); + + dai->started = 0; } int snd_soc_dai_prepare(struct snd_soc_dai *dai, diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 8d8ed4774e9c..d53afb96b05b 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -568,7 +568,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) if (ret < 0) { pr_err("ASoC: %s startup failed: %d\n", rtd->dai_link->name, ret); - goto machine_err; + goto codec_dai_err; } /* Dynamic PCM DAI links compat checks use dynamic capabilities */ @@ -637,11 +637,8 @@ dynamic: config_err: soc_rtd_shutdown(rtd, substream); -machine_err: - i = rtd->num_codecs; - codec_dai_err: - for_each_rtd_codec_dai_rollback(rtd, i, codec_dai) + for_each_rtd_codec_dai(rtd, i, codec_dai) snd_soc_dai_shutdown(codec_dai, substream); component_err: From 9d789dc047e32fb0f85ff192f883a534017512a2 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 10 Feb 2020 17:33:36 +0200 Subject: [PATCH 0150/4444] ALSA: dmaengine_pcm: Consider DMA cache caused delay in pointer callback Some DMA engines can have big FIFOs which adds to the latency. The DMAengine framework can report the FIFO utilization in bytes. Use this information for the delay reporting. Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20200210153336.10218-1-peter.ujfalusi@ti.com Signed-off-by: Mark Brown --- sound/core/pcm_dmaengine.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index d8be7b488162..6852bb670b4e 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c @@ -240,6 +240,7 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue); snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) { struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; struct dma_tx_state state; enum dma_status status; unsigned int buf_size; @@ -257,7 +258,7 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) state.in_flight_bytes); } - return bytes_to_frames(substream->runtime, pos); + return bytes_to_frames(runtime, pos); } EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); From d49850110434e25b3128a4f2f083812a111bf457 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Fri, 24 Jan 2020 09:41:30 +0100 Subject: [PATCH 0151/4444] dt-bindings: usb: dwc2: add support for STM32MP15 SoCs USB OTG HS and FS Add the specific compatible string for the DWC2 IP found in the STM32MP15 SoCs. STM32MP15 SoCs uses sensing comparators to detect Vbus valid levels and ID pin state. usb33d-supply described the regulator supplying Vbus and ID sensing comparators. Signed-off-by: Amelie Delaunay Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/usb/dwc2.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/dwc2.yaml b/Documentation/devicetree/bindings/usb/dwc2.yaml index 71cf7ba32237..e95ba9373023 100644 --- a/Documentation/devicetree/bindings/usb/dwc2.yaml +++ b/Documentation/devicetree/bindings/usb/dwc2.yaml @@ -58,6 +58,8 @@ properties: - const: st,stm32f4x9-fsotg - const: st,stm32f4x9-hsotg - const: st,stm32f7-hsotg + - const: st,stm32mp15-fsotg + - const: st,stm32mp15-hsotg - const: samsung,s3c6400-hsotg reg: @@ -103,6 +105,10 @@ properties: vusb_a-supply: description: phandle to voltage regulator of analog section. + vusb33d-supply: + description: reference to the VBUS and ID sensing comparators supply, in + order to perform OTG operation, used on STM32MP15 SoCs. + dr_mode: enum: [host, peripheral, otg] From 17ff9478ffa3ade728d0fd7351720bb215dcbf7f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 27 Jan 2020 03:20:21 +0100 Subject: [PATCH 0152/4444] dt-bindings: Add ITE Tech prefix Add vendor prefix for ITE Tech Inc, http://www.ite.com.tw/ Signed-off-by: Marek Vasut Cc: Daniel Vetter Cc: Rob Herring Cc: Sean Cross Cc: devicetree@vger.kernel.org To: dri-devel@lists.freedesktop.org Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 9e67944bec9c..535211eeb1c5 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -469,6 +469,8 @@ patternProperties: description: Intersil "^issi,.*": description: Integrated Silicon Solutions Inc. + "^ite,.*": + description: ITE Tech, Inc. "^itead,.*": description: ITEAD Intelligent Systems Co.Ltd "^iwave,.*": From db1b4b3a7ae19d1abc6d52e9b3dc05b4bb99320f Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 27 Jan 2020 03:58:37 +0000 Subject: [PATCH 0153/4444] dt-bindings: soc: imx: add binding doc for aips bus Add binding doc for fsl,aips-bus Signed-off-by: Peng Fan Signed-off-by: Rob Herring --- .../bindings/soc/imx/fsl,aips-bus.yaml | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/imx/fsl,aips-bus.yaml diff --git a/Documentation/devicetree/bindings/soc/imx/fsl,aips-bus.yaml b/Documentation/devicetree/bindings/soc/imx/fsl,aips-bus.yaml new file mode 100644 index 000000000000..3cbf2d28a188 --- /dev/null +++ b/Documentation/devicetree/bindings/soc/imx/fsl,aips-bus.yaml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/soc/imx/fsl,aips-bus.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: i.MX AHB to IP Bridge + +maintainers: + - Peng Fan + +description: | + This particular peripheral is designed as the bridge between + AHB bus and peripherals with the lower bandwidth IP Slave (IPS) + buses. + +select: + properties: + compatible: + contains: + const: fsl,aips-bus + required: + - compatible + +properties: + compatible: + items: + - const: fsl,aips-bus + - const: simple-bus + + reg: + maxItems: 1 + +required: + - compatible + - reg + +examples: + - | + bus@30000000 { + compatible = "fsl,aips-bus", "simple-bus"; + reg = <0x30000000 0x400000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + }; +... From c03b401250cada0a46cdbbcef665548e576f345f Mon Sep 17 00:00:00 2001 From: Kamlesh Gurudasani Date: Mon, 27 Jan 2020 19:55:33 +0530 Subject: [PATCH 0154/4444] dt-bindings: add vendor prefix for OzzMaker and Waveshare Electronics Add vendor prefix for OzzMaker [1] and Waveshare Electronics [2] Both are display manufacturers [1] https://ozzmaker.com/about/ [2] https://www.waveshare.com/contact_us Signed-off-by: Kamlesh Gurudasani Acked-by: Sam Ravnborg Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 535211eeb1c5..ac6aa3332b28 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -729,6 +729,8 @@ patternProperties: description: OmniVision Technologies "^oxsemi,.*": description: Oxford Semiconductor, Ltd. + "^ozzmaker,.*": + description: OzzMaker "^panasonic,.*": description: Panasonic Corporation "^parade,.*": @@ -1054,6 +1056,8 @@ patternProperties: description: Vision Optical Technology Co., Ltd. "^vxt,.*": description: VXT Ltd + "^waveshare,.*": + description: Waveshare Electronics "^wd,.*": description: Western Digital Corp. "^wetek,.*": From 90aeca875f8a33da7cbcac20b7921ca090127346 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 29 Jan 2020 09:56:13 +0100 Subject: [PATCH 0155/4444] dt-bindings: display: Convert etnaviv to json-schema Convert etnaviv bindings to yaml format. Move bindings file from display to gpu folder. Signed-off-by: Benjamin Gaignard Signed-off-by: Rob Herring --- .../bindings/display/etnaviv/etnaviv-drm.txt | 36 ---------- .../devicetree/bindings/gpu/vivante,gc.yaml | 69 +++++++++++++++++++ 2 files changed, 69 insertions(+), 36 deletions(-) delete mode 100644 Documentation/devicetree/bindings/display/etnaviv/etnaviv-drm.txt create mode 100644 Documentation/devicetree/bindings/gpu/vivante,gc.yaml diff --git a/Documentation/devicetree/bindings/display/etnaviv/etnaviv-drm.txt b/Documentation/devicetree/bindings/display/etnaviv/etnaviv-drm.txt deleted file mode 100644 index 8def11b16a24..000000000000 --- a/Documentation/devicetree/bindings/display/etnaviv/etnaviv-drm.txt +++ /dev/null @@ -1,36 +0,0 @@ -Vivante GPU core devices -======================== - -Required properties: -- compatible: Should be "vivante,gc" - A more specific compatible is not needed, as the cores contain chip - identification registers at fixed locations, which provide all the - necessary information to the driver. -- reg: should be register base and length as documented in the - datasheet -- interrupts: Should contain the cores interrupt line -- clocks: should contain one clock for entry in clock-names - see Documentation/devicetree/bindings/clock/clock-bindings.txt -- clock-names: - - "bus": AXI/master interface clock - - "reg": AHB/slave interface clock - (only required if GPU can gate slave interface independently) - - "core": GPU core clock - - "shader": Shader clock (only required if GPU has feature PIPE_3D) - -Optional properties: -- power-domains: a power domain consumer specifier according to - Documentation/devicetree/bindings/power/power_domain.txt - -example: - -gpu_3d: gpu@130000 { - compatible = "vivante,gc"; - reg = <0x00130000 0x4000>; - interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6QDL_CLK_GPU3D_AXI>, - <&clks IMX6QDL_CLK_GPU3D_CORE>, - <&clks IMX6QDL_CLK_GPU3D_SHADER>; - clock-names = "bus", "core", "shader"; - power-domains = <&gpc 1>; -}; diff --git a/Documentation/devicetree/bindings/gpu/vivante,gc.yaml b/Documentation/devicetree/bindings/gpu/vivante,gc.yaml new file mode 100644 index 000000000000..0bc4b38d5cbb --- /dev/null +++ b/Documentation/devicetree/bindings/gpu/vivante,gc.yaml @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpu/vivante,gc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Vivante GPU Bindings + +description: Vivante GPU core devices + +maintainers: + - Lucas Stach + +properties: + compatible: + const: vivante,gc + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: AXI/master interface clock + - description: GPU core clock + - description: Shader clock (only required if GPU has feature PIPE_3D) + - description: AHB/slave interface clock (only required if GPU can gate slave interface independently) + minItems: 1 + maxItems: 4 + + clock-names: + items: + enum: [ bus, core, shader, reg ] + minItems: 1 + maxItems: 4 + + resets: + maxItems: 1 + + power-domains: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include + #include + gpu@130000 { + compatible = "vivante,gc"; + reg = <0x00130000 0x4000>; + interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6QDL_CLK_GPU3D_AXI>, + <&clks IMX6QDL_CLK_GPU3D_CORE>, + <&clks IMX6QDL_CLK_GPU3D_SHADER>; + clock-names = "bus", "core", "shader"; + power-domains = <&gpc 1>; + }; + +... From d0cff8adce1370c03ddb2ccb4d8c2921e00181c4 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 11 Feb 2020 15:10:10 -0600 Subject: [PATCH 0156/4444] misc: vexpress: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertenly introduced[3] to the codebase from now on. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200211211010.GA32239@embeddedor Signed-off-by: Greg Kroah-Hartman --- drivers/misc/vexpress-syscfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/vexpress-syscfg.c b/drivers/misc/vexpress-syscfg.c index 058fcd7f9f01..a431787c0898 100644 --- a/drivers/misc/vexpress-syscfg.c +++ b/drivers/misc/vexpress-syscfg.c @@ -42,7 +42,7 @@ struct vexpress_syscfg_func { struct vexpress_syscfg *syscfg; struct regmap *regmap; int num_templates; - u32 template[0]; /* Keep it last! */ + u32 template[]; /* Keep it last! */ }; From 6736041f9606f195339cacb4bcce232f1a2a1ed3 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 11 Feb 2020 15:08:22 -0600 Subject: [PATCH 0157/4444] mei: bus: replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertenly introduced[3] to the codebase from now on. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200211210822.GA31368@embeddedor Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus-fixup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c index 9ad9c01ddf41..910f059b3384 100644 --- a/drivers/misc/mei/bus-fixup.c +++ b/drivers/misc/mei/bus-fixup.c @@ -91,7 +91,7 @@ struct mkhi_rule_id { struct mkhi_fwcaps { struct mkhi_rule_id id; u8 len; - u8 data[0]; + u8 data[]; } __packed; struct mkhi_fw_ver_block { @@ -119,7 +119,7 @@ struct mkhi_msg_hdr { struct mkhi_msg { struct mkhi_msg_hdr hdr; - u8 data[0]; + u8 data[]; } __packed; #define MKHI_OSVER_BUF_LEN (sizeof(struct mkhi_msg_hdr) + \ From 3aef021b2df7d8440225a53460c0d34b140297d5 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 11 Feb 2020 18:05:22 +0200 Subject: [PATCH 0158/4444] mei: limit number of bytes in mei header. The MEI message header provides only 9 bits for storing the message size, limiting to 511. In theory the host buffer (hbuf) can contain up to 1020 bytes (limited by byte = 255 * 4) With the current hardware and hbuf size 512, this is not a real issue, but as hardening approach we enforce the limit. Signed-off-by: Tomas Winkler Link: https://lore.kernel.org/r/20200211160522.7562-1-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 4 ++-- drivers/misc/mei/hw.h | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 1e3edbbacb1e..204d807e755b 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1585,7 +1585,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, goto err; } - hbuf_len = mei_slots2data(hbuf_slots); + hbuf_len = mei_slots2data(hbuf_slots) & MEI_MSG_MAX_LEN_MASK; dr_slots = mei_dma_ring_empty_slots(dev); dr_len = mei_slots2data(dr_slots); @@ -1718,7 +1718,7 @@ ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb) goto out; } - hbuf_len = mei_slots2data(hbuf_slots); + hbuf_len = mei_slots2data(hbuf_slots) & MEI_MSG_MAX_LEN_MASK; dr_slots = mei_dma_ring_empty_slots(dev); dr_len = mei_slots2data(dr_slots); diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h index d025a5f8317e..8231b6941adf 100644 --- a/drivers/misc/mei/hw.h +++ b/drivers/misc/mei/hw.h @@ -209,6 +209,9 @@ struct mei_msg_hdr { u32 extension[0]; } __packed; +/* The length is up to 9 bits */ +#define MEI_MSG_MAX_LEN_MASK GENMASK(9, 0) + #define MEI_MSG_HDR_MAX 2 struct mei_bus_message { From ee43b5ab850f901217857d06f8e3c6cc5154fa03 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Wed, 29 Jan 2020 18:20:29 -0500 Subject: [PATCH 0159/4444] ARM: qcom_defconfig: add Broadcom bluetooth options Add Broadcom bluetooth options and serial bus in order to support Bluetooth on the Nexus 5 phone. Signed-off-by: Brian Masney Link: https://lore.kernel.org/r/20200129232031.34538-2-masneyb@onstation.org Signed-off-by: Bjorn Andersson --- arch/arm/configs/qcom_defconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/configs/qcom_defconfig b/arch/arm/configs/qcom_defconfig index cdc75ef7d529..a00765b7225f 100644 --- a/arch/arm/configs/qcom_defconfig +++ b/arch/arm/configs/qcom_defconfig @@ -50,6 +50,9 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_XFRM_MODE_TUNNEL is not set # CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_IPV6 is not set +CONFIG_BT=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_BCM=y CONFIG_CFG80211=m CONFIG_MAC80211=m CONFIG_RFKILL=y @@ -111,6 +114,7 @@ CONFIG_SERIO_LIBPS2=y # CONFIG_LEGACY_PTYS is not set CONFIG_SERIAL_MSM=y CONFIG_SERIAL_MSM_CONSOLE=y +CONFIG_SERIAL_DEV_BUS=y CONFIG_HW_RANDOM=y CONFIG_I2C=y CONFIG_I2C_CHARDEV=y From 31a233a5a17b5405faa7c52700d15cd5b3ef7c52 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 21 Jan 2020 09:18:06 -0800 Subject: [PATCH 0160/4444] arm64: dts: qcom: sdm845: Disable pwrkey on Cheza We don't use the power key from the PMIC on Cheza. Disable this node so that we don't probe the driver for this device. Reviewed-by: Douglas Anderson Cc: Douglas Anderson Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20200121171806.9933-1-swboyd@chromium.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/pm8998.dtsi | 2 +- arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/pm8998.dtsi b/arch/arm64/boot/dts/qcom/pm8998.dtsi index dc2ce23cde05..67283d60e2ac 100644 --- a/arch/arm64/boot/dts/qcom/pm8998.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8998.dtsi @@ -45,7 +45,7 @@ mode-bootloader = <0x2>; mode-recovery = <0x1>; - pwrkey { + pm8998_pwrkey: pwrkey { compatible = "qcom,pm8941-pwrkey"; interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>; debounce = <15625>; diff --git a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi index 7b53b3c7ffe6..a8e9f639a2bb 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi @@ -626,6 +626,10 @@ ap_ts_i2c: &i2c14 { status = "okay"; }; +&pm8998_pwrkey { + status = "disabled"; +}; + &qupv3_id_0 { status = "okay"; }; From 3d60d80a4162bf015f6efb97f6c17629e21530fe Mon Sep 17 00:00:00 2001 From: Sai Prakash Ranjan Date: Fri, 10 Jan 2020 15:48:02 +0530 Subject: [PATCH 0161/4444] arm64: dts: qcom: sc7180: Add iommus property to QUP0 and QUP1 Define iommus property for QUP0 and QUP1 with the proper SID and mask. Below SMMU global faults are seen without this during boot and when using i2c touchscreen. QUP0: arm-smmu 15000000.iommu: Unexpected global fault, this could be serious arm-smmu 15000000.iommu: GFSR 0x00000002, GFSYNR0 0x00000002, GFSYNR1 0x00000043, GFSYNR2 0x00000000 QUP1: arm-smmu 15000000.iommu: Unexpected global fault, this could be serious arm-smmu 15000000.iommu: GFSR 0x00000002, GFSYNR0 0x00000002, GFSYNR1 0x000004c3, GFSYNR2 0x00000000 Fixes: ba3fc6496366 ("arm64: dts: sc7180: Add qupv3_0 and qupv3_1") Tested-by: Stephen Boyd Tested-by: Douglas Anderson Reviewed-by: Stephen Boyd Reviewed-by: Douglas Anderson Signed-off-by: Sai Prakash Ranjan Link: https://lore.kernel.org/r/20200110101802.4491-1-saiprakash.ranjan@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sc7180.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index 8011c5fe2a31..01e431f49c18 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -338,6 +338,7 @@ #address-cells = <2>; #size-cells = <2>; ranges; + iommus = <&apps_smmu 0x43 0x0>; status = "disabled"; i2c0: i2c@880000 { @@ -546,6 +547,7 @@ #address-cells = <2>; #size-cells = <2>; ranges; + iommus = <&apps_smmu 0x4c3 0x0>; status = "disabled"; i2c6: i2c@a80000 { From b418cf634cfd9f53d362f2f1be56405860947e31 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Wed, 29 Jan 2020 14:44:42 -0800 Subject: [PATCH 0162/4444] arm64: dts: sc7180: Add the sleep_clk to gcc-sc7180 node The bindings say that we're supposed to have this in the node. Who am I to argue with the bindings? Fixes: 90db71e48070 ("arm64: dts: sc7180: Add minimal dts/dtsi files for SC7180 soc") Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20200129144432.1.Ie36f0532f67b0221c1e48e7cf6863a2738716a54@changeid Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sc7180.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index 01e431f49c18..cc5a94f1f1ba 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -310,8 +310,9 @@ compatible = "qcom,gcc-sc7180"; reg = <0 0x00100000 0 0x1f0000>; clocks = <&rpmhcc RPMH_CXO_CLK>, - <&rpmhcc RPMH_CXO_CLK_A>; - clock-names = "bi_tcxo", "bi_tcxo_ao"; + <&rpmhcc RPMH_CXO_CLK_A>, + <&sleep_clk>; + clock-names = "bi_tcxo", "bi_tcxo_ao", "sleep_clk"; #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; From aff9cc0847a58647ef010c5c0db0a8a00fb13911 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Mon, 3 Feb 2020 19:05:34 +0530 Subject: [PATCH 0163/4444] drivers: qcom: rpmh: fix macro to accept NULL argument Device argument matches with dev variable declared in RPMH message. Compiler reports error when the argument is NULL since the argument matches the name of the property. Rename dev argument to device to fix this. Signed-off-by: Maulik Shah Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/1580736940-6985-2-git-send-email-mkshah@codeaurora.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rpmh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c index 035091fd44b8..3a4579d056a4 100644 --- a/drivers/soc/qcom/rpmh.c +++ b/drivers/soc/qcom/rpmh.c @@ -23,7 +23,7 @@ #define RPMH_TIMEOUT_MS msecs_to_jiffies(10000) -#define DEFINE_RPMH_MSG_ONSTACK(dev, s, q, name) \ +#define DEFINE_RPMH_MSG_ONSTACK(device, s, q, name) \ struct rpmh_request name = { \ .msg = { \ .state = s, \ @@ -33,7 +33,7 @@ }, \ .cmd = { { 0 } }, \ .completion = q, \ - .dev = dev, \ + .dev = device, \ .needs_free = false, \ } From d5e205079c34aa1f33157627814f707d6057727a Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Mon, 3 Feb 2020 19:05:35 +0530 Subject: [PATCH 0164/4444] drivers: qcom: rpmh: remove rpmh_flush export rpmh_flush() was exported with the idea that an external entity operation during CPU idle would know when to flush the sleep and wake TCS. Since, this is not the case when defining a power domain for the RSC. Remove the function export and instead allow the function to be called internally. Signed-off-by: Maulik Shah Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/1580736940-6985-3-git-send-email-mkshah@codeaurora.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rpmh-internal.h | 1 + drivers/soc/qcom/rpmh.c | 18 ++++++++---------- include/soc/qcom/rpmh.h | 5 ----- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/drivers/soc/qcom/rpmh-internal.h b/drivers/soc/qcom/rpmh-internal.h index a7bbbb67991c..6eec32b97f83 100644 --- a/drivers/soc/qcom/rpmh-internal.h +++ b/drivers/soc/qcom/rpmh-internal.h @@ -110,5 +110,6 @@ int rpmh_rsc_write_ctrl_data(struct rsc_drv *drv, int rpmh_rsc_invalidate(struct rsc_drv *drv); void rpmh_tx_done(const struct tcs_request *msg, int r); +int rpmh_flush(struct rpmh_ctrlr *ctrlr); #endif /* __RPM_INTERNAL_H__ */ diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c index 3a4579d056a4..eb0ded059d2e 100644 --- a/drivers/soc/qcom/rpmh.c +++ b/drivers/soc/qcom/rpmh.c @@ -427,11 +427,10 @@ static int is_req_valid(struct cache_req *req) req->sleep_val != req->wake_val); } -static int send_single(const struct device *dev, enum rpmh_state state, +static int send_single(struct rpmh_ctrlr *ctrlr, enum rpmh_state state, u32 addr, u32 data) { - DEFINE_RPMH_MSG_ONSTACK(dev, state, NULL, rpm_msg); - struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev); + DEFINE_RPMH_MSG_ONSTACK(NULL, state, NULL, rpm_msg); /* Wake sets are always complete and sleep sets are not */ rpm_msg.msg.wait_for_compl = (state == RPMH_WAKE_ONLY_STATE); @@ -445,7 +444,7 @@ static int send_single(const struct device *dev, enum rpmh_state state, /** * rpmh_flush: Flushes the buffered active and sleep sets to TCS * - * @dev: The device making the request + * @ctrlr: controller making request to flush cached data * * Return: -EBUSY if the controller is busy, probably waiting on a response * to a RPMH request sent earlier. @@ -454,10 +453,9 @@ static int send_single(const struct device *dev, enum rpmh_state state, * that is powering down the entire system. Since no other RPMH API would be * executing at this time, it is safe to run lockless. */ -int rpmh_flush(const struct device *dev) +int rpmh_flush(struct rpmh_ctrlr *ctrlr) { struct cache_req *p; - struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev); int ret; if (!ctrlr->dirty) { @@ -480,11 +478,12 @@ int rpmh_flush(const struct device *dev) __func__, p->addr, p->sleep_val, p->wake_val); continue; } - ret = send_single(dev, RPMH_SLEEP_STATE, p->addr, p->sleep_val); + ret = send_single(ctrlr, RPMH_SLEEP_STATE, p->addr, + p->sleep_val); if (ret) return ret; - ret = send_single(dev, RPMH_WAKE_ONLY_STATE, - p->addr, p->wake_val); + ret = send_single(ctrlr, RPMH_WAKE_ONLY_STATE, p->addr, + p->wake_val); if (ret) return ret; } @@ -493,7 +492,6 @@ int rpmh_flush(const struct device *dev) return 0; } -EXPORT_SYMBOL(rpmh_flush); /** * rpmh_invalidate: Invalidate all sleep and active sets diff --git a/include/soc/qcom/rpmh.h b/include/soc/qcom/rpmh.h index 619e07c75da9..f9ec353d24a5 100644 --- a/include/soc/qcom/rpmh.h +++ b/include/soc/qcom/rpmh.h @@ -20,8 +20,6 @@ int rpmh_write_async(const struct device *dev, enum rpmh_state state, int rpmh_write_batch(const struct device *dev, enum rpmh_state state, const struct tcs_cmd *cmd, u32 *n); -int rpmh_flush(const struct device *dev); - int rpmh_invalidate(const struct device *dev); #else @@ -40,9 +38,6 @@ static inline int rpmh_write_batch(const struct device *dev, const struct tcs_cmd *cmd, u32 *n) { return -ENODEV; } -static inline int rpmh_flush(const struct device *dev) -{ return -ENODEV; } - static inline int rpmh_invalidate(const struct device *dev) { return -ENODEV; } From bcd3a145b1606a76058554b6a75da569d7762322 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sat, 18 Jan 2020 17:55:18 +0100 Subject: [PATCH 0165/4444] ARM: dts: qcom: msm8974-honami: Add USB node. This exact node has been included in Amami DTS ever since 2017, turns out it works perfectly fine with Honami, as tested with postmarketOS. Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20200118165518.36036-1-konradybcio@gmail.com Signed-off-by: Bjorn Andersson --- .../dts/qcom-msm8974-sony-xperia-honami.dts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm/boot/dts/qcom-msm8974-sony-xperia-honami.dts b/arch/arm/boot/dts/qcom-msm8974-sony-xperia-honami.dts index 450b8321e0a6..611bae9fe66b 100644 --- a/arch/arm/boot/dts/qcom-msm8974-sony-xperia-honami.dts +++ b/arch/arm/boot/dts/qcom-msm8974-sony-xperia-honami.dts @@ -260,6 +260,31 @@ }; &soc { + usb@f9a55000 { + status = "ok"; + + phys = <&usb_hs1_phy>; + phy-select = <&tcsr 0xb000 0>; + extcon = <&smbb>, <&usb_id>; + vbus-supply = <&chg_otg>; + + hnp-disable; + srp-disable; + adp-disable; + + ulpi { + phy@a { + status = "ok"; + + v1p8-supply = <&pm8941_l6>; + v3p3-supply = <&pm8941_l24>; + + extcon = <&smbb>; + qcom,init-seq = /bits/ 8 <0x1 0x64>; + }; + }; + }; + sdhci@f9824900 { status = "ok"; From 726a117628d6965d38182e5313df7d3033295dfb Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Wed, 29 Jan 2020 18:20:30 -0500 Subject: [PATCH 0166/4444] ARM: dts: qcom: msm8974: add blsp2_uart10 Add blsp2_uart10 node in order to support bluetooth on the Nexus 5 phone. Signed-off-by: Jonathan Marek [masneyb@onstation.org: use constants in interrupts property; patch extracted from much larger out of tree patch.] Signed-off-by: Brian Masney Link: https://lore.kernel.org/r/20200129232031.34538-3-masneyb@onstation.org Signed-off-by: Bjorn Andersson --- arch/arm/boot/dts/qcom-msm8974.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi index 4b161b809dd5..f8e093179c3f 100644 --- a/arch/arm/boot/dts/qcom-msm8974.dtsi +++ b/arch/arm/boot/dts/qcom-msm8974.dtsi @@ -715,6 +715,15 @@ status = "disabled"; }; + blsp2_uart10: serial@f9960000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0xf9960000 0x1000>; + interrupts = ; + clocks = <&gcc GCC_BLSP2_UART4_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>; + clock-names = "core", "iface"; + status = "disabled"; + }; + sdhci@f9824900 { compatible = "qcom,msm8974-sdhci", "qcom,sdhci-msm-v4"; reg = <0xf9824900 0x11c>, <0xf9824000 0x800>; From 231cb93c06aced94150165d64d490359f7ea8a59 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Wed, 29 Jan 2020 18:20:31 -0500 Subject: [PATCH 0167/4444] ARM: dts: qcom: msm8974-hammerhead: add support for bluetooth Add support for the bluetooth found on the Nexus 5 phone. Signed-off-by: Jonathan Marek [masneyb@onstation.org: formatting cleanups; remove sleep clock; patch extracted from much larger out of tree patch.] Signed-off-by: Brian Masney Link: https://lore.kernel.org/r/20200129232031.34538-4-masneyb@onstation.org Signed-off-by: Bjorn Andersson --- .../qcom-msm8974-lge-nexus5-hammerhead.dts | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts b/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts index 3487daf98e81..32b474bfeec3 100644 --- a/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts +++ b/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts @@ -12,6 +12,7 @@ aliases { serial0 = &blsp1_uart1; + serial1 = &blsp2_uart10; }; chosen { @@ -355,6 +356,57 @@ bias-disable; }; }; + + bt_pin: bt { + hostwake { + pins = "gpio42"; + function = "gpio"; + }; + + devwake { + pins = "gpio62"; + function = "gpio"; + }; + + shutdown { + pins = "gpio41"; + function = "gpio"; + }; + }; + + blsp2_uart10_pin_a: blsp2-uart10-pin-active { + tx { + pins = "gpio53"; + function = "blsp_uart10"; + + drive-strength = <2>; + bias-disable; + }; + + rx { + pins = "gpio54"; + function = "blsp_uart10"; + + drive-strength = <2>; + bias-pull-up; + }; + + cts { + pins = "gpio55"; + function = "blsp_uart10"; + + drive-strength = <2>; + bias-pull-up; + }; + + rts { + pins = "gpio56"; + function = "blsp_uart10"; + + drive-strength = <2>; + bias-disable; + }; + }; }; sdhci@f9824900 { @@ -418,6 +470,25 @@ }; }; + serial@f9960000 { + status = "ok"; + + pinctrl-names = "default"; + pinctrl-0 = <&blsp2_uart10_pin_a>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = <3000000>; + + pinctrl-names = "default"; + pinctrl-0 = <&bt_pin>; + + host-wakeup-gpios = <&msmgpio 42 GPIO_ACTIVE_HIGH>; + device-wakeup-gpios = <&msmgpio 62 GPIO_ACTIVE_HIGH>; + shutdown-gpios = <&msmgpio 41 GPIO_ACTIVE_HIGH>; + }; + }; + i2c@f9967000 { status = "ok"; pinctrl-names = "default"; From 8f4a7a00c1019df72cda3002643fb5823ef39183 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Tue, 31 Dec 2019 12:25:11 +0100 Subject: [PATCH 0168/4444] arm64: dts: qcom: msm8916-samsung-a2015: Reserve Samsung firmware memory At the moment, writing large amounts of data to the eMMC causes the device to freeze. The symptoms vary, sometimes the device reboots immediately, but usually it will just get stuck. It turns out that the issue is not actually related to the eMMC: Apparently, Samsung has made some modifications to the TrustZone firmware. These require additional memory which is reserved at 0x85500000-0x86000000. The downstream kernel describes this memory reservation as: /* Additionally Reserved 6MB for TIMA and Increased the TZ app size * by 2MB [total 8 MB ] */ This suggests that it is used for additional TZ apps, although the extra memory is actually 11 MB instead of the 8 MB mentioned in the comment. Writing to the protected memory causes the kernel to crash or freeze. In our case, writing to the eMMC causes the disk cache to fill the available RAM, until the kernel eventually crashes when attempting to use the reserved memory. Add the additional memory as reserved-memory to fix this problem. Fixes: 1329c1ab0730 ("arm64: dts: qcom: Add device tree for Samsung Galaxy A3U/A5U") Reported-by: Michael Srba Tested-by: Michael Srba # a3u Tested-by: Stephan Gerhold # a5u Signed-off-by: Stephan Gerhold Link: https://lore.kernel.org/r/20191231112511.83342-1-stephan@gerhold.net Signed-off-by: Bjorn Andersson --- .../arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi index bd1eb3eeca53..43c5e0f882f1 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi @@ -15,6 +15,14 @@ stdout-path = "serial0"; }; + reserved-memory { + /* Additional memory used by Samsung firmware modifications */ + tz-apps@85500000 { + reg = <0x0 0x85500000 0x0 0xb00000>; + no-map; + }; + }; + soc { sdhci@7824000 { status = "okay"; From 9478bd43a2eb5c72b599368513d10880b296d65f Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 11 Feb 2020 13:39:10 -0600 Subject: [PATCH 0169/4444] ALSA: core: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertenly introduced[3] to the codebase from now on. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200211193910.GA4596@embeddedor Signed-off-by: Takashi Iwai --- sound/core/oss/rate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/core/oss/rate.c b/sound/core/oss/rate.c index 7cd09cef6961..d381f4c967c9 100644 --- a/sound/core/oss/rate.c +++ b/sound/core/oss/rate.c @@ -47,7 +47,7 @@ struct rate_priv { unsigned int pos; rate_f func; snd_pcm_sframes_t old_src_frames, old_dst_frames; - struct rate_channel channels[0]; + struct rate_channel channels[]; }; static void rate_init(struct snd_pcm_plugin *plugin) From 6c8019d08e0e84ecad78f726c737dc6a49b58b57 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 11 Feb 2020 13:42:24 -0600 Subject: [PATCH 0170/4444] ALSA: usb-midi: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertenly introduced[3] to the codebase from now on. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200211194224.GA9383@embeddedor Signed-off-by: Takashi Iwai --- sound/usb/midi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/midi.c b/sound/usb/midi.c index 392e5fda680c..be5c597ed40c 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -91,7 +91,7 @@ struct usb_ms_endpoint_descriptor { __u8 bDescriptorType; __u8 bDescriptorSubtype; __u8 bNumEmbMIDIJack; - __u8 baAssocJackID[0]; + __u8 baAssocJackID[]; } __attribute__ ((packed)); struct snd_usb_midi_in_endpoint; From 76501954cb9ef5b3d614a075870cfce47fbbd6df Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 11 Feb 2020 13:44:03 -0600 Subject: [PATCH 0171/4444] ALSA: hda/ca0132 - Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertenly introduced[3] to the codebase from now on. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200211194403.GA10318@embeddedor Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index ded8bc07d755..a4a39f7d9ae1 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -2698,7 +2698,7 @@ struct dsp_image_seg { u32 magic; u32 chip_addr; u32 count; - u32 data[0]; + u32 data[]; }; static const u32 g_magic_value = 0x4c46584d; From bb80b96422b443ddcb6dbb39261ea3e02a13661d Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 11 Feb 2020 14:07:39 -0600 Subject: [PATCH 0172/4444] ALSA: hda_codec: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertenly introduced[3] to the codebase from now on. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200211200739.GA12948@embeddedor Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 5dc42f932739..97a03685dd8b 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -88,7 +88,7 @@ struct hda_conn_list { struct list_head list; int len; hda_nid_t nid; - hda_nid_t conns[0]; + hda_nid_t conns[]; }; /* look up the cached results */ From 32c5cd478983387620eb9941b42c95877735ed8a Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Tue, 10 Dec 2019 00:43:48 +0100 Subject: [PATCH 0173/4444] dt-bindings: arm: fsl: add LS1028A based boards Add the Freescale LS1028A evaluation boards. Signed-off-by: Michael Walle Reviewed-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index a8e0b4a813ed..46219a83d955 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -395,6 +395,13 @@ properties: - fsl,ls1021a-twr - const: fsl,ls1021a + - description: LS1028A based Boards + items: + - enum: + - fsl,ls1028a-qds + - fsl,ls1028a-rdb + - const: fsl,ls1028a + - description: LS1043A based Boards items: - enum: From e5ede2cc965bdc25e16bb477603dc2509df5a892 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Tue, 10 Dec 2019 00:43:49 +0100 Subject: [PATCH 0174/4444] dt-bindings: arm: fsl: add Kontron sl28 boards Add the Kontron SMARC-sAL28 board, its variants and combination with carriers. Signed-off-by: Michael Walle Reviewed-by: Rob Herring Signed-off-by: Shawn Guo --- .../devicetree/bindings/arm/fsl.yaml | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 46219a83d955..49ab2d83b744 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -402,6 +402,44 @@ properties: - fsl,ls1028a-rdb - const: fsl,ls1028a + - description: Kontron KBox A-230-LS + items: + - const: kontron,kbox-a-230-ls + - const: kontron,sl28-var4 + - const: kontron,sl28 + - const: fsl,ls1028a + - description: + Kontron SMARC-sAL28 board on the SMARC Eval Carrier 2.0 + items: + - enum: + - kontron,sl28-var2-ads2 + - kontron,sl28-var3-ads2 + - kontron,sl28-var4-ads2 + - enum: + - kontron,sl28-var2 + - kontron,sl28-var3 + - kontron,sl28-var4 + - const: kontron,sl28 + - const: fsl,ls1028a + + - description: + Kontron SMARC-sAL28 board (on a generic/undefined carrier) + items: + - enum: + - kontron,sl28-var2 + - kontron,sl28-var3 + - kontron,sl28-var4 + - const: kontron,sl28 + - const: fsl,ls1028a + + - description: + Kontron SMARC-sAL28 board (base). This is used in the base device + tree which is compatible with the overlays provided by the + vendor. + items: + - const: kontron,sl28 + - const: fsl,ls1028a + - description: LS1043A based Boards items: - enum: From 995fc9eea3db9f6725d8e6c151d0abc549e936a2 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 10 Jan 2020 16:23:34 -0300 Subject: [PATCH 0175/4444] ARM: dts: imx6ul-pico: Convert to DRM bindings Documentation/devicetree/bindings/display/mxsfb.txt states that the current display bindings format used in this dts is deprecated. Convert it to the preferred DRM bindings instead. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6ul-pico.dtsi | 39 ++++++++++++------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/arch/arm/boot/dts/imx6ul-pico.dtsi b/arch/arm/boot/dts/imx6ul-pico.dtsi index de9f83189ba8..df1da98ab10f 100644 --- a/arch/arm/boot/dts/imx6ul-pico.dtsi +++ b/arch/arm/boot/dts/imx6ul-pico.dtsi @@ -20,7 +20,7 @@ stdout-path = &uart6; }; - backlight { + backlight: backlight { compatible = "pwm-backlight"; pwms = <&pwm3 0 5000000>; brightness-levels = <0 4 8 16 32 64 128 255>; @@ -72,6 +72,17 @@ regulator-max-microvolt = <3300000>; startup-delay-us = <200000>; }; + + panel { + compatible = "vxt,vl050-8048nt-c01"; + backlight = <&backlight>; + + port { + panel_in: endpoint { + remote-endpoint = <&display_out>; + }; + }; + }; }; &can1 { @@ -154,31 +165,11 @@ &lcdif { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_lcdif_dat &pinctrl_lcdif_ctrl>; - display = <&display0>; status = "okay"; - display0: display0 { - bits-per-pixel = <32>; - bus-width = <24>; - - display-timings { - native-mode = <&timing0>; - - timing0: timing0 { - clock-frequency = <33200000>; - hactive = <800>; - vactive = <480>; - hfront-porch = <210>; - hback-porch = <46>; - hsync-len = <1>; - vback-porch = <22>; - vfront-porch = <23>; - vsync-len = <1>; - hsync-active = <0>; - vsync-active = <0>; - de-active = <1>; - pixelclk-active = <0>; - }; + port { + display_out: endpoint { + remote-endpoint = <&panel_in>; }; }; }; From c9aee09f7bb2c6dc559744c707d96bbbf6a5e15b Mon Sep 17 00:00:00 2001 From: Aapo Vienamo Date: Sun, 12 Jan 2020 16:00:39 +0200 Subject: [PATCH 0176/4444] ARM: mxs: Enable usbphy1 and usb1 on apx4devkit DTS Enable the USB host port on the APx4 development board. Signed-off-by: Aapo Vienamo Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx28-apx4devkit.dts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/imx28-apx4devkit.dts b/arch/arm/boot/dts/imx28-apx4devkit.dts index 3a184d13887b..c5acc19c982d 100644 --- a/arch/arm/boot/dts/imx28-apx4devkit.dts +++ b/arch/arm/boot/dts/imx28-apx4devkit.dts @@ -183,10 +183,20 @@ pinctrl-0 = <&auart2_2pins_a>; status = "okay"; }; + + usbphy1: usbphy@8007e000 { + pinctrl-names = "default"; + pinctrl-0 = <&usb1_pins_a>; + status = "okay"; + }; }; }; ahb@80080000 { + usb1: usb@80090000 { + status = "okay"; + }; + mac0: ethernet@800f0000 { phy-mode = "rmii"; pinctrl-names = "default"; From 92c2701ec1f5aa0eef4af44a2ac80c1c9d8aa112 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 15 Jan 2020 09:39:08 +0800 Subject: [PATCH 0177/4444] arm64: defconfig: Select CONFIG_PINCTRL_IMX8MP by default Enable CONFIG_PINCTRL_IMX8MP by default to support i.MX8MP pinctrl driver. Signed-off-by: Anson Huang Reviewed-by: Abel Vesa Signed-off-by: Shawn Guo --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 0f212889c931..1c744379c9c7 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -409,6 +409,7 @@ CONFIG_PINCTRL_S700=y CONFIG_PINCTRL_S900=y CONFIG_PINCTRL_IMX8MM=y CONFIG_PINCTRL_IMX8MN=y +CONFIG_PINCTRL_IMX8MP=y CONFIG_PINCTRL_IMX8MQ=y CONFIG_PINCTRL_IMX8QXP=y CONFIG_PINCTRL_IPQ8074=y From b568627307dfe1e4f6b0bd8c9a95550ac12351cd Mon Sep 17 00:00:00 2001 From: Hsin-Yi Wang Date: Wed, 12 Feb 2020 14:05:37 +0800 Subject: [PATCH 0178/4444] arm64: dts: mt8173: add arm,no-tick-in-suspend in timer Arch timer stops during system suspend. Add arm,no-tick-in-suspend property in timer. This is a follow up for d8ec7595a013 ("clocksource/drivers/arm_arch_timer: Don't assume clock runs in suspend") Signed-off-by: Hsin-Yi Wang Signed-off-by: Matthias Brugger --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index 8b4e806d5119..1a9ad90bd7a6 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -331,6 +331,7 @@ (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, ; + arm,no-tick-in-suspend; }; soc { From 3f2e4c11e136e2cffd60dbc840b59ff65f017328 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 17 Dec 2019 18:48:55 +0100 Subject: [PATCH 0179/4444] kfifo: provide noirqsave variants of spinlocked in and out helpers Provide variants of spinlocked kfifo_in() and kfifo_out() routines which don't disable interrupts. Signed-off-by: Bartosz Golaszewski Acked-by: Stefani Seibold --- include/linux/kfifo.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h index fc4b0b10210f..123c200ed7cb 100644 --- a/include/linux/kfifo.h +++ b/include/linux/kfifo.h @@ -517,6 +517,26 @@ __kfifo_uint_must_check_helper( \ __ret; \ }) +/** + * kfifo_in_spinlocked_noirqsave - put data into fifo using a spinlock for + * locking, don't disable interrupts + * @fifo: address of the fifo to be used + * @buf: the data to be added + * @n: number of elements to be added + * @lock: pointer to the spinlock to use for locking + * + * This is a variant of kfifo_in_spinlocked() but uses spin_lock/unlock() + * for locking and doesn't disable interrupts. + */ +#define kfifo_in_spinlocked_noirqsave(fifo, buf, n, lock) \ +({ \ + unsigned int __ret; \ + spin_lock(lock); \ + __ret = kfifo_in(fifo, buf, n); \ + spin_unlock(lock); \ + __ret; \ +}) + /* alias for kfifo_in_spinlocked, will be removed in a future release */ #define kfifo_in_locked(fifo, buf, n, lock) \ kfifo_in_spinlocked(fifo, buf, n, lock) @@ -569,6 +589,28 @@ __kfifo_uint_must_check_helper( \ }) \ ) +/** + * kfifo_out_spinlocked_noirqsave - get data from the fifo using a spinlock + * for locking, don't disable interrupts + * @fifo: address of the fifo to be used + * @buf: pointer to the storage buffer + * @n: max. number of elements to get + * @lock: pointer to the spinlock to use for locking + * + * This is a variant of kfifo_out_spinlocked() which uses spin_lock/unlock() + * for locking and doesn't disable interrupts. + */ +#define kfifo_out_spinlocked_noirqsave(fifo, buf, n, lock) \ +__kfifo_uint_must_check_helper( \ +({ \ + unsigned int __ret; \ + spin_lock(lock); \ + __ret = kfifo_out(fifo, buf, n); \ + spin_unlock(lock); \ + __ret; \ +}) \ +) + /* alias for kfifo_out_spinlocked, will be removed in a future release */ #define kfifo_out_locked(fifo, buf, n, lock) \ kfifo_out_spinlocked(fifo, buf, n, lock) From 5195a89e8583bba43ec13871a7226763e401b44e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 17 Dec 2019 11:30:59 +0100 Subject: [PATCH 0180/4444] kfifo: provide kfifo_is_empty_spinlocked() Provide two spinlocked versions of kfifo_is_empty() to be used with spinlocked variants of kfifo_in() and kfifo_out(). Signed-off-by: Bartosz Golaszewski Acked-by: Stefani Seibold --- include/linux/kfifo.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h index 123c200ed7cb..86249476b57f 100644 --- a/include/linux/kfifo.h +++ b/include/linux/kfifo.h @@ -246,6 +246,37 @@ __kfifo_int_must_check_helper(int val) __tmpq->kfifo.in == __tmpq->kfifo.out; \ }) +/** + * kfifo_is_empty_spinlocked - returns true if the fifo is empty using + * a spinlock for locking + * @fifo: address of the fifo to be used + * @lock: spinlock to be used for locking + */ +#define kfifo_is_empty_spinlocked(fifo, lock) \ +({ \ + unsigned long __flags; \ + bool __ret; \ + spin_lock_irqsave(lock, __flags); \ + __ret = kfifo_is_empty(fifo); \ + spin_unlock_irqrestore(lock, __flags); \ + __ret; \ +}) + +/** + * kfifo_is_empty_spinlocked_noirqsave - returns true if the fifo is empty + * using a spinlock for locking, doesn't disable interrupts + * @fifo: address of the fifo to be used + * @lock: spinlock to be used for locking + */ +#define kfifo_is_empty_spinlocked_noirqsave(fifo, lock) \ +({ \ + bool __ret; \ + spin_lock(lock); \ + __ret = kfifo_is_empty(fifo); \ + spin_unlock(lock); \ + __ret; \ +}) + /** * kfifo_is_full - returns true if the fifo is full * @fifo: address of the fifo to be used From dea9c80ee6726986d90260f135c83545427cbc4e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 27 Nov 2019 12:19:21 +0100 Subject: [PATCH 0181/4444] gpiolib: rework the locking mechanism for lineevent kfifo The read_lock mutex is supposed to prevent collisions between reading and writing to the line event kfifo but it's actually only taken when the events are being read from it. Drop the mutex entirely and reuse the spinlock made available to us in the waitqueue struct. Take the lock whenever the fifo is modified or inspected. Drop the call to kfifo_to_user() and instead first extract the new element from kfifo when the lock is taken and only then pass it on to the user after the spinlock is released. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andy Shevchenko --- drivers/gpio/gpiolib.c | 66 +++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 753283486037..43d98309e725 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -787,8 +787,6 @@ out_free_lh: * @irq: the interrupt that trigger in response to events on this GPIO * @wait: wait queue that handles blocking reads of events * @events: KFIFO for the GPIO events - * @read_lock: mutex lock to protect reads from colliding with adding - * new events to the FIFO * @timestamp: cache for the timestamp storing it between hardirq * and IRQ thread, used to bring the timestamp close to the actual * event @@ -801,7 +799,6 @@ struct lineevent_state { int irq; wait_queue_head_t wait; DECLARE_KFIFO(events, struct gpioevent_data, 16); - struct mutex read_lock; u64 timestamp; }; @@ -817,7 +814,7 @@ static __poll_t lineevent_poll(struct file *filep, poll_wait(filep, &le->wait, wait); - if (!kfifo_is_empty(&le->events)) + if (!kfifo_is_empty_spinlocked_noirqsave(&le->events, &le->wait.lock)) events = EPOLLIN | EPOLLRDNORM; return events; @@ -830,43 +827,52 @@ static ssize_t lineevent_read(struct file *filep, loff_t *f_ps) { struct lineevent_state *le = filep->private_data; - unsigned int copied; + struct gpioevent_data event; + ssize_t bytes_read = 0; int ret; - if (count < sizeof(struct gpioevent_data)) + if (count < sizeof(event)) return -EINVAL; do { + spin_lock(&le->wait.lock); if (kfifo_is_empty(&le->events)) { - if (filep->f_flags & O_NONBLOCK) - return -EAGAIN; + if (bytes_read) { + spin_unlock(&le->wait.lock); + return bytes_read; + } - ret = wait_event_interruptible(le->wait, + if (filep->f_flags & O_NONBLOCK) { + spin_unlock(&le->wait.lock); + return -EAGAIN; + } + + ret = wait_event_interruptible_locked(le->wait, !kfifo_is_empty(&le->events)); - if (ret) + if (ret) { + spin_unlock(&le->wait.lock); return ret; + } } - if (mutex_lock_interruptible(&le->read_lock)) - return -ERESTARTSYS; - ret = kfifo_to_user(&le->events, buf, count, &copied); - mutex_unlock(&le->read_lock); + ret = kfifo_out(&le->events, &event, 1); + spin_unlock(&le->wait.lock); + if (ret != 1) { + /* + * This should never happen - we were holding the lock + * from the moment we learned the fifo is no longer + * empty until now. + */ + ret = -EIO; + break; + } - if (ret) - return ret; + if (copy_to_user(buf + bytes_read, &event, sizeof(event))) + return -EFAULT; + bytes_read += sizeof(event); + } while (count >= bytes_read + sizeof(event)); - /* - * If we couldn't read anything from the fifo (a different - * thread might have been faster) we either return -EAGAIN if - * the file descriptor is non-blocking, otherwise we go back to - * sleep and wait for more data to arrive. - */ - if (copied == 0 && (filep->f_flags & O_NONBLOCK)) - return -EAGAIN; - - } while (copied == 0); - - return copied; + return bytes_read; } static int lineevent_release(struct inode *inode, struct file *filep) @@ -968,7 +974,8 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p) return IRQ_NONE; } - ret = kfifo_put(&le->events, ge); + ret = kfifo_in_spinlocked_noirqsave(&le->events, &ge, + 1, &le->wait.lock); if (ret) wake_up_poll(&le->wait, EPOLLIN); @@ -1083,7 +1090,6 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) INIT_KFIFO(le->events); init_waitqueue_head(&le->wait); - mutex_init(&le->read_lock); /* Request a thread to read the events */ ret = request_threaded_irq(le->irq, From 248ae1752e91438cb7cfc8432b88bc34410e8e4e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 29 Nov 2019 11:22:18 +0100 Subject: [PATCH 0182/4444] gpiolib: emit a debug message when adding events to a full kfifo Currently if the line-event kfifo is full, we just silently drop any new events. Add a ratelimited debug message so that we at least have some trace in the kernel log of event overflow. Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 43d98309e725..36afe0b2b150 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -978,6 +978,8 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p) 1, &le->wait.lock); if (ret) wake_up_poll(&le->wait, EPOLLIN); + else + pr_debug_ratelimited("event FIFO is full - event dropped\n"); return IRQ_HANDLED; } From d2ac25798208fb85f866056cd7d8030eb919da99 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 3 Dec 2019 14:08:44 +0100 Subject: [PATCH 0183/4444] gpiolib: provide a dedicated function for setting lineinfo We'll soon be filling out the gpioline_info structure in multiple places. Add a separate function that given a gpio_desc sets all relevant fields. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andy Shevchenko --- drivers/gpio/gpiolib.c | 98 ++++++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 43 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 36afe0b2b150..443321f9cf63 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1147,6 +1147,60 @@ out_free_le: return ret; } +static void gpio_desc_to_lineinfo(struct gpio_desc *desc, + struct gpioline_info *info) +{ + struct gpio_chip *chip = desc->gdev->chip; + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + + if (desc->name) { + strncpy(info->name, desc->name, sizeof(info->name)); + info->name[sizeof(info->name) - 1] = '\0'; + } else { + info->name[0] = '\0'; + } + + if (desc->label) { + strncpy(info->consumer, desc->label, sizeof(info->consumer)); + info->consumer[sizeof(info->consumer) - 1] = '\0'; + } else { + info->consumer[0] = '\0'; + } + + /* + * Userspace only need to know that the kernel is using this GPIO so + * it can't use it. + */ + info->flags = 0; + if (test_bit(FLAG_REQUESTED, &desc->flags) || + test_bit(FLAG_IS_HOGGED, &desc->flags) || + test_bit(FLAG_USED_AS_IRQ, &desc->flags) || + test_bit(FLAG_EXPORT, &desc->flags) || + test_bit(FLAG_SYSFS, &desc->flags) || + !pinctrl_gpio_can_use_line(chip->base + info->line_offset)) + info->flags |= GPIOLINE_FLAG_KERNEL; + if (test_bit(FLAG_IS_OUT, &desc->flags)) + info->flags |= GPIOLINE_FLAG_IS_OUT; + if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) + info->flags |= GPIOLINE_FLAG_ACTIVE_LOW; + if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) + info->flags |= (GPIOLINE_FLAG_OPEN_DRAIN | + GPIOLINE_FLAG_IS_OUT); + if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) + info->flags |= (GPIOLINE_FLAG_OPEN_SOURCE | + GPIOLINE_FLAG_IS_OUT); + if (test_bit(FLAG_BIAS_DISABLE, &desc->flags)) + info->flags |= GPIOLINE_FLAG_BIAS_DISABLE; + if (test_bit(FLAG_PULL_DOWN, &desc->flags)) + info->flags |= GPIOLINE_FLAG_BIAS_PULL_DOWN; + if (test_bit(FLAG_PULL_UP, &desc->flags)) + info->flags |= GPIOLINE_FLAG_BIAS_PULL_UP; + + spin_unlock_irqrestore(&gpio_lock, flags); +} + /* * gpio_ioctl() - ioctl handler for the GPIO chardev */ @@ -1187,49 +1241,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (IS_ERR(desc)) return PTR_ERR(desc); - if (desc->name) { - strncpy(lineinfo.name, desc->name, - sizeof(lineinfo.name)); - lineinfo.name[sizeof(lineinfo.name)-1] = '\0'; - } else { - lineinfo.name[0] = '\0'; - } - if (desc->label) { - strncpy(lineinfo.consumer, desc->label, - sizeof(lineinfo.consumer)); - lineinfo.consumer[sizeof(lineinfo.consumer)-1] = '\0'; - } else { - lineinfo.consumer[0] = '\0'; - } - - /* - * Userspace only need to know that the kernel is using - * this GPIO so it can't use it. - */ - lineinfo.flags = 0; - if (test_bit(FLAG_REQUESTED, &desc->flags) || - test_bit(FLAG_IS_HOGGED, &desc->flags) || - test_bit(FLAG_USED_AS_IRQ, &desc->flags) || - test_bit(FLAG_EXPORT, &desc->flags) || - test_bit(FLAG_SYSFS, &desc->flags) || - !pinctrl_gpio_can_use_line(chip->base + lineinfo.line_offset)) - lineinfo.flags |= GPIOLINE_FLAG_KERNEL; - if (test_bit(FLAG_IS_OUT, &desc->flags)) - lineinfo.flags |= GPIOLINE_FLAG_IS_OUT; - if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) - lineinfo.flags |= GPIOLINE_FLAG_ACTIVE_LOW; - if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) - lineinfo.flags |= (GPIOLINE_FLAG_OPEN_DRAIN | - GPIOLINE_FLAG_IS_OUT); - if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) - lineinfo.flags |= (GPIOLINE_FLAG_OPEN_SOURCE | - GPIOLINE_FLAG_IS_OUT); - if (test_bit(FLAG_BIAS_DISABLE, &desc->flags)) - lineinfo.flags |= GPIOLINE_FLAG_BIAS_DISABLE; - if (test_bit(FLAG_PULL_DOWN, &desc->flags)) - lineinfo.flags |= GPIOLINE_FLAG_BIAS_PULL_DOWN; - if (test_bit(FLAG_PULL_UP, &desc->flags)) - lineinfo.flags |= GPIOLINE_FLAG_BIAS_PULL_UP; + gpio_desc_to_lineinfo(desc, &lineinfo); if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) return -EFAULT; From 51c1064e82e77b39a49889287ca50709303e2f26 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 22 Nov 2019 15:19:21 +0100 Subject: [PATCH 0184/4444] gpiolib: add new ioctl() for monitoring changes in line info Currently there is no way for user-space to be informed about changes in status of GPIO lines e.g. when someone else requests the line or its config changes. We can only periodically re-read the line-info. This is fine for simple one-off user-space tools, but any daemon that provides a centralized access to GPIO chips would benefit hugely from an event driven line info synchronization. This patch adds a new ioctl() that allows user-space processes to reuse the file descriptor associated with the character device for watching any changes in line properties. Every such event contains the updated line information. Currently the events are generated on three types of status changes: when a line is requested, when it's released and when its config is changed. The first two are self-explanatory. For the third one: this will only happen when another user-space process calls the new SET_CONFIG ioctl() as any changes that can happen from within the kernel (i.e. set_transitory() or set_debounce()) are of no interest to user-space. Signed-off-by: Bartosz Golaszewski Reviewed-by: Linus Walleij --- drivers/gpio/gpiolib.c | 188 ++++++++++++++++++++++++++++++++++++-- drivers/gpio/gpiolib.h | 1 + include/uapi/linux/gpio.h | 30 ++++++ 3 files changed, 210 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 443321f9cf63..f73077f26eff 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -546,6 +546,9 @@ static long linehandle_set_config(struct linehandle_state *lh, if (ret) return ret; } + + atomic_notifier_call_chain(&desc->gdev->notifier, + GPIOLINE_CHANGED_CONFIG, desc); } return 0; } @@ -1201,14 +1204,25 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc, spin_unlock_irqrestore(&gpio_lock, flags); } +struct gpio_chardev_data { + struct gpio_device *gdev; + wait_queue_head_t wait; + DECLARE_KFIFO(events, struct gpioline_info_changed, 32); + struct notifier_block lineinfo_changed_nb; + unsigned long *watched_lines; +}; + /* * gpio_ioctl() - ioctl handler for the GPIO chardev */ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - struct gpio_device *gdev = filp->private_data; + struct gpio_chardev_data *priv = filp->private_data; + struct gpio_device *gdev = priv->gdev; struct gpio_chip *chip = gdev->chip; void __user *ip = (void __user *)arg; + struct gpio_desc *desc; + __u32 offset; /* We fail any subsequent ioctl():s when the chip is gone */ if (!chip) @@ -1230,9 +1244,9 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_to_user(ip, &chipinfo, sizeof(chipinfo))) return -EFAULT; return 0; - } else if (cmd == GPIO_GET_LINEINFO_IOCTL) { + } else if (cmd == GPIO_GET_LINEINFO_IOCTL || + cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) { struct gpioline_info lineinfo; - struct gpio_desc *desc; if (copy_from_user(&lineinfo, ip, sizeof(lineinfo))) return -EFAULT; @@ -1245,11 +1259,25 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) return -EFAULT; + + if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) + set_bit(desc_to_gpio(desc), priv->watched_lines); + return 0; } else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) { return linehandle_create(gdev, ip); } else if (cmd == GPIO_GET_LINEEVENT_IOCTL) { return lineevent_create(gdev, ip); + } else if (cmd == GPIO_GET_LINEINFO_UNWATCH_IOCTL) { + if (copy_from_user(&offset, ip, sizeof(offset))) + return -EFAULT; + + desc = gpiochip_get_desc(chip, offset); + if (IS_ERR(desc)) + return PTR_ERR(desc); + + clear_bit(desc_to_gpio(desc), &desc->flags); + return 0; } return -EINVAL; } @@ -1262,6 +1290,101 @@ static long gpio_ioctl_compat(struct file *filp, unsigned int cmd, } #endif +static struct gpio_chardev_data * +to_gpio_chardev_data(struct notifier_block *nb) +{ + return container_of(nb, struct gpio_chardev_data, lineinfo_changed_nb); +} + +static int lineinfo_changed_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct gpio_chardev_data *priv = to_gpio_chardev_data(nb); + struct gpioline_info_changed chg; + struct gpio_desc *desc = data; + int ret; + + if (!test_bit(desc_to_gpio(desc), priv->watched_lines)) + return NOTIFY_DONE; + + memset(&chg, 0, sizeof(chg)); + chg.info.line_offset = gpio_chip_hwgpio(desc); + chg.event_type = action; + chg.timestamp = ktime_get_ns(); + gpio_desc_to_lineinfo(desc, &chg.info); + + ret = kfifo_in_spinlocked(&priv->events, &chg, 1, &priv->wait.lock); + if (ret) + wake_up_poll(&priv->wait, EPOLLIN); + else + pr_debug_ratelimited("lineinfo event FIFO is full - event dropped\n"); + + return NOTIFY_OK; +} + +static __poll_t lineinfo_watch_poll(struct file *filep, + struct poll_table_struct *pollt) +{ + struct gpio_chardev_data *priv = filep->private_data; + __poll_t events = 0; + + poll_wait(filep, &priv->wait, pollt); + + if (!kfifo_is_empty_spinlocked_noirqsave(&priv->events, + &priv->wait.lock)) + events = EPOLLIN | EPOLLRDNORM; + + return events; +} + +static ssize_t lineinfo_watch_read(struct file *filep, char __user *buf, + size_t count, loff_t *off) +{ + struct gpio_chardev_data *priv = filep->private_data; + struct gpioline_info_changed event; + ssize_t bytes_read = 0; + int ret; + + if (count < sizeof(event)) + return -EINVAL; + + do { + spin_lock(&priv->wait.lock); + if (kfifo_is_empty(&priv->events)) { + if (bytes_read) { + spin_unlock(&priv->wait.lock); + return bytes_read; + } + + if (filep->f_flags & O_NONBLOCK) { + spin_unlock(&priv->wait.lock); + return -EAGAIN; + } + + ret = wait_event_interruptible_locked(priv->wait, + !kfifo_is_empty(&priv->events)); + if (ret) { + spin_unlock(&priv->wait.lock); + return ret; + } + } + + ret = kfifo_out(&priv->events, &event, 1); + spin_unlock(&priv->wait.lock); + if (ret != 1) { + ret = -EIO; + break; + /* We should never get here. See lineevent_read(). */ + } + + if (copy_to_user(buf + bytes_read, &event, sizeof(event))) + return -EFAULT; + bytes_read += sizeof(event); + } while (count >= bytes_read + sizeof(event)); + + return bytes_read; +} + /** * gpio_chrdev_open() - open the chardev for ioctl operations * @inode: inode for this chardev @@ -1272,14 +1395,48 @@ static int gpio_chrdev_open(struct inode *inode, struct file *filp) { struct gpio_device *gdev = container_of(inode->i_cdev, struct gpio_device, chrdev); + struct gpio_chardev_data *priv; + int ret = -ENOMEM; /* Fail on open if the backing gpiochip is gone */ if (!gdev->chip) return -ENODEV; - get_device(&gdev->dev); - filp->private_data = gdev; - return nonseekable_open(inode, filp); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->watched_lines = bitmap_zalloc(gdev->chip->ngpio, GFP_KERNEL); + if (!priv->watched_lines) + goto out_free_priv; + + init_waitqueue_head(&priv->wait); + INIT_KFIFO(priv->events); + priv->gdev = gdev; + + priv->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify; + ret = atomic_notifier_chain_register(&gdev->notifier, + &priv->lineinfo_changed_nb); + if (ret) + goto out_free_bitmap; + + get_device(&gdev->dev); + filp->private_data = priv; + + ret = nonseekable_open(inode, filp); + if (ret) + goto out_unregister_notifier; + + return ret; + +out_unregister_notifier: + atomic_notifier_chain_unregister(&gdev->notifier, + &priv->lineinfo_changed_nb); +out_free_bitmap: + bitmap_free(priv->watched_lines); +out_free_priv: + kfree(priv); + return ret; } /** @@ -1290,17 +1447,23 @@ static int gpio_chrdev_open(struct inode *inode, struct file *filp) */ static int gpio_chrdev_release(struct inode *inode, struct file *filp) { - struct gpio_device *gdev = container_of(inode->i_cdev, - struct gpio_device, chrdev); + struct gpio_chardev_data *priv = filp->private_data; + struct gpio_device *gdev = priv->gdev; + bitmap_free(priv->watched_lines); + atomic_notifier_chain_unregister(&gdev->notifier, + &priv->lineinfo_changed_nb); put_device(&gdev->dev); + kfree(priv); + return 0; } - static const struct file_operations gpio_fileops = { .release = gpio_chrdev_release, .open = gpio_chrdev_open, + .poll = lineinfo_watch_poll, + .read = lineinfo_watch_read, .owner = THIS_MODULE, .llseek = no_llseek, .unlocked_ioctl = gpio_ioctl, @@ -1511,6 +1674,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, spin_unlock_irqrestore(&gpio_lock, flags); + ATOMIC_INIT_NOTIFIER_HEAD(&gdev->notifier); + #ifdef CONFIG_PINCTRL INIT_LIST_HEAD(&gdev->pin_ranges); #endif @@ -2843,6 +3008,8 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label) } done: spin_unlock_irqrestore(&gpio_lock, flags); + atomic_notifier_call_chain(&desc->gdev->notifier, + GPIOLINE_CHANGED_REQUESTED, desc); return ret; } @@ -2940,6 +3107,9 @@ static bool gpiod_free_commit(struct gpio_desc *desc) } spin_unlock_irqrestore(&gpio_lock, flags); + atomic_notifier_call_chain(&desc->gdev->notifier, + GPIOLINE_CHANGED_RELEASED, desc); + return ret; } diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 3e0aab2945d8..5ab90746b519 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -56,6 +56,7 @@ struct gpio_device { const char *label; void *data; struct list_head list; + struct atomic_notifier_head notifier; #ifdef CONFIG_PINCTRL /* diff --git a/include/uapi/linux/gpio.h b/include/uapi/linux/gpio.h index 799cf823d493..dca320764e4d 100644 --- a/include/uapi/linux/gpio.h +++ b/include/uapi/linux/gpio.h @@ -59,6 +59,34 @@ struct gpioline_info { /* Maximum number of requested handles */ #define GPIOHANDLES_MAX 64 +/* Possible line status change events */ +enum { + GPIOLINE_CHANGED_REQUESTED = 1, + GPIOLINE_CHANGED_RELEASED, + GPIOLINE_CHANGED_CONFIG, +}; + +/** + * struct gpioline_info_changed - Information about a change in status + * of a GPIO line + * @info: updated line information + * @timestamp: estimate of time of status change occurrence, in nanoseconds + * and GPIOLINE_CHANGED_CONFIG + * @event_type: one of GPIOLINE_CHANGED_REQUESTED, GPIOLINE_CHANGED_RELEASED + * + * Note: struct gpioline_info embedded here has 32-bit alignment on its own, + * but it works fine with 64-bit alignment too. With its 72 byte size, we can + * guarantee there are no implicit holes between it and subsequent members. + * The 20-byte padding at the end makes sure we don't add any implicit padding + * at the end of the structure on 64-bit architectures. + */ +struct gpioline_info_changed { + struct gpioline_info info; + __u64 timestamp; + __u32 event_type; + __u32 padding[5]; /* for future use */ +}; + /* Linerequest flags */ #define GPIOHANDLE_REQUEST_INPUT (1UL << 0) #define GPIOHANDLE_REQUEST_OUTPUT (1UL << 1) @@ -176,6 +204,8 @@ struct gpioevent_data { #define GPIO_GET_CHIPINFO_IOCTL _IOR(0xB4, 0x01, struct gpiochip_info) #define GPIO_GET_LINEINFO_IOCTL _IOWR(0xB4, 0x02, struct gpioline_info) +#define GPIO_GET_LINEINFO_WATCH_IOCTL _IOWR(0xB4, 0x0b, struct gpioline_info) +#define GPIO_GET_LINEINFO_UNWATCH_IOCTL _IOWR(0xB4, 0x0c, __u32) #define GPIO_GET_LINEHANDLE_IOCTL _IOWR(0xB4, 0x03, struct gpiohandle_request) #define GPIO_GET_LINEEVENT_IOCTL _IOWR(0xB4, 0x04, struct gpioevent_request) From 33f0c47b8fb4724792b16351a32b24902a5d3b07 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 27 Nov 2019 10:17:54 +0100 Subject: [PATCH 0185/4444] tools: gpio: implement gpio-watch Add a simple program that allows to test the new LINECHANGED_FD ioctl(). Signed-off-by: Bartosz Golaszewski Reviewed-by: Andy Shevchenko --- tools/gpio/.gitignore | 1 + tools/gpio/Build | 1 + tools/gpio/Makefile | 11 ++++- tools/gpio/gpio-watch.c | 99 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 tools/gpio/gpio-watch.c diff --git a/tools/gpio/.gitignore b/tools/gpio/.gitignore index a94c0e83b209..eab36c6d7751 100644 --- a/tools/gpio/.gitignore +++ b/tools/gpio/.gitignore @@ -1,4 +1,5 @@ gpio-event-mon gpio-hammer +gpio-watch lsgpio include/linux/gpio.h diff --git a/tools/gpio/Build b/tools/gpio/Build index 4141f35837db..67c7b7f6a717 100644 --- a/tools/gpio/Build +++ b/tools/gpio/Build @@ -2,3 +2,4 @@ gpio-utils-y += gpio-utils.o lsgpio-y += lsgpio.o gpio-utils.o gpio-hammer-y += gpio-hammer.o gpio-utils.o gpio-event-mon-y += gpio-event-mon.o gpio-utils.o +gpio-watch-y += gpio-watch.o diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile index 6080de58861f..842287e42c83 100644 --- a/tools/gpio/Makefile +++ b/tools/gpio/Makefile @@ -18,7 +18,7 @@ MAKEFLAGS += -r override CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include -ALL_TARGETS := lsgpio gpio-hammer gpio-event-mon +ALL_TARGETS := lsgpio gpio-hammer gpio-event-mon gpio-watch ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS)) all: $(ALL_PROGRAMS) @@ -66,6 +66,15 @@ $(GPIO_EVENT_MON_IN): prepare FORCE $(OUTPUT)gpio-utils-in.o $(OUTPUT)gpio-event-mon: $(GPIO_EVENT_MON_IN) $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ +# +# gpio-watch +# +GPIO_WATCH_IN := $(OUTPUT)gpio-watch-in.o +$(GPIO_WATCH_IN): prepare FORCE + $(Q)$(MAKE) $(build)=gpio-watch +$(OUTPUT)gpio-watch: $(GPIO_WATCH_IN) + $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ + clean: rm -f $(ALL_PROGRAMS) rm -f $(OUTPUT)include/linux/gpio.h diff --git a/tools/gpio/gpio-watch.c b/tools/gpio/gpio-watch.c new file mode 100644 index 000000000000..5cea24fddfa7 --- /dev/null +++ b/tools/gpio/gpio-watch.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * gpio-watch - monitor unrequested lines for property changes using the + * character device + * + * Copyright (C) 2019 BayLibre SAS + * Author: Bartosz Golaszewski + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + struct gpioline_info_changed chg; + struct gpioline_info req; + struct pollfd pfd; + int fd, i, j, ret; + char *event, *end; + ssize_t rd; + + if (argc < 3) + goto err_usage; + + fd = open(argv[1], O_RDWR | O_CLOEXEC); + if (fd < 0) { + perror("unable to open gpiochip"); + return EXIT_FAILURE; + } + + for (i = 0, j = 2; i < argc - 2; i++, j++) { + memset(&req, 0, sizeof(req)); + + req.line_offset = strtoul(argv[j], &end, 0); + if (*end != '\0') + goto err_usage; + + ret = ioctl(fd, GPIO_GET_LINEINFO_WATCH_IOCTL, &req); + if (ret) { + perror("unable to set up line watch"); + return EXIT_FAILURE; + } + } + + pfd.fd = fd; + pfd.events = POLLIN | POLLPRI; + + for (;;) { + ret = poll(&pfd, 1, 5000); + if (ret < 0) { + perror("error polling the linechanged fd"); + return EXIT_FAILURE; + } else if (ret > 0) { + memset(&chg, 0, sizeof(chg)); + rd = read(pfd.fd, &chg, sizeof(chg)); + if (rd < 0 || rd != sizeof(chg)) { + if (rd != sizeof(chg)) + errno = EIO; + + perror("error reading line change event"); + return EXIT_FAILURE; + } + + switch (chg.event_type) { + case GPIOLINE_CHANGED_REQUESTED: + event = "requested"; + break; + case GPIOLINE_CHANGED_RELEASED: + event = "released"; + break; + case GPIOLINE_CHANGED_CONFIG: + event = "config changed"; + break; + default: + fprintf(stderr, + "invalid event type received from the kernel\n"); + return EXIT_FAILURE; + } + + printf("line %u: %s at %llu\n", + chg.info.line_offset, event, chg.timestamp); + } + } + + return 0; + +err_usage: + printf("%s: ...\n", argv[0]); + return EXIT_FAILURE; +} From 38a49742de113746dfb954afe7b1b65a098a69a8 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 12 Feb 2020 09:48:36 +0100 Subject: [PATCH 0186/4444] rtc: sh: Restore devm_ioremap() alignment The alignment of the continuation of the devm_ioremap() call in sh_rtc_probe() was broken. Join the lines, as all parameters can fit on a single line. Fixes: 4bdc0d676a643140 ("remove ioremap_nocache and devm_ioremap_nocache") Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200212084836.9511-1-geert+renesas@glider.be Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-sh.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index feb1f8e52c00..9167b48014a1 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -504,8 +504,7 @@ static int __init sh_rtc_probe(struct platform_device *pdev) if (unlikely(!rtc->res)) return -EBUSY; - rtc->regbase = devm_ioremap(&pdev->dev, rtc->res->start, - rtc->regsize); + rtc->regbase = devm_ioremap(&pdev->dev, rtc->res->start, rtc->regsize); if (unlikely(!rtc->regbase)) return -EINVAL; From 4594d082dbe6385c2df6b838817ccd214c16b358 Mon Sep 17 00:00:00 2001 From: Srinivas Neeli Date: Wed, 12 Feb 2020 15:54:39 +0530 Subject: [PATCH 0187/4444] rtc: zynqmp: Clear alarm interrupt status before interrupt enable Fix multiple occurring interrupts for alarm interrupt. RTC module doesn't clear the alarm interrupt status bit immediately after the interrupt is triggered.This is due to the sticky nature of the alarm interrupt status register. The alarm interrupt status register can be cleared only after the second counter outruns the set alarm value. To fix multiple spurious interrupts, disable alarm interrupt in the handler and clear the status bit before enabling the alarm interrupt. Fixes: 11143c19eb57 ("rtc: add xilinx zynqmp rtc driver") Signed-off-by: Srinivas Neeli Acked-by: Michal Simek Link: https://lore.kernel.org/r/1581503079-387-1-git-send-email-srinivas.neeli@xilinx.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-zynqmp.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c index 5786866c09e9..4b1077e2f826 100644 --- a/drivers/rtc/rtc-zynqmp.c +++ b/drivers/rtc/rtc-zynqmp.c @@ -38,6 +38,8 @@ #define RTC_CALIB_DEF 0x198233 #define RTC_CALIB_MASK 0x1FFFFF +#define RTC_ALRM_MASK BIT(1) +#define RTC_MSEC 1000 struct xlnx_rtc_dev { struct rtc_device *rtc; @@ -123,11 +125,28 @@ static int xlnx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int xlnx_rtc_alarm_irq_enable(struct device *dev, u32 enabled) { struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev); + unsigned int status; + ulong timeout; + + timeout = jiffies + msecs_to_jiffies(RTC_MSEC); + + if (enabled) { + while (1) { + status = readl(xrtcdev->reg_base + RTC_INT_STS); + if (!((status & RTC_ALRM_MASK) == RTC_ALRM_MASK)) + break; + + if (time_after_eq(jiffies, timeout)) { + dev_err(dev, "Time out occur, while clearing alarm status bit\n"); + return -ETIMEDOUT; + } + writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_STS); + } - if (enabled) writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_EN); - else + } else { writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_DIS); + } return 0; } @@ -183,8 +202,8 @@ static irqreturn_t xlnx_rtc_interrupt(int irq, void *id) if (!(status & (RTC_INT_SEC | RTC_INT_ALRM))) return IRQ_NONE; - /* Clear RTC_INT_ALRM interrupt only */ - writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_STS); + /* Disable RTC_INT_ALRM interrupt only */ + writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_DIS); if (status & RTC_INT_ALRM) rtc_update_irq(xrtcdev->rtc, 1, RTC_IRQF | RTC_AF); From 91d14ab8d913e798b3f68663ffc2e1f7dc8c4a8b Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Tue, 11 Feb 2020 08:07:15 +0000 Subject: [PATCH 0188/4444] ARM: configs: at91: enable sama5d4 compatible watchdog Enable CONFIG_SAMA5D4_WATCHDOG. This driver is compatible with sam9x60 watchdog timer block. Signed-off-by: Eugen Hristev Link: https://lore.kernel.org/r/1581408369-14469-3-git-send-email-eugen.hristev@microchip.com Signed-off-by: Alexandre Belloni --- arch/arm/configs/at91_dt_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig index f66bb98a5cce..4a0ba2ae1a25 100644 --- a/arch/arm/configs/at91_dt_defconfig +++ b/arch/arm/configs/at91_dt_defconfig @@ -118,6 +118,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_HWMON is not set CONFIG_WATCHDOG=y CONFIG_AT91SAM9X_WATCHDOG=y +CONFIG_SAMA5D4_WATCHDOG=y CONFIG_MFD_ATMEL_FLEXCOM=y CONFIG_MFD_ATMEL_HLCDC=y CONFIG_REGULATOR=y From 8ba92585075cb7894cacf2728ec87bab0f6b37c2 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 14 Jan 2020 07:19:02 -0800 Subject: [PATCH 0189/4444] ARM: dts: vf610-zii-ssmb-spu3: Add voltage monitor DT node Add a DT node for various voltage supply rails connected to SoC's ADC for voltage monitoring purposes. Signed-off-by: Andrey Smirnov Cc: Chris Healy Cc: Fabio Estevam Cc: Shawn Guo Cc: linux-arm-kernel@lists.infradead.org Cc: devicetree@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf610-zii-ssmb-spu3.dts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/vf610-zii-ssmb-spu3.dts b/arch/arm/boot/dts/vf610-zii-ssmb-spu3.dts index 453fce80f858..3d05c894bdc0 100644 --- a/arch/arm/boot/dts/vf610-zii-ssmb-spu3.dts +++ b/arch/arm/boot/dts/vf610-zii-ssmb-spu3.dts @@ -46,6 +46,14 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; }; + + supply-voltage-monitor { + compatible = "iio-hwmon"; + io-channels = <&adc0 8>, /* 12V_MAIN */ + <&adc0 9>, /* +3.3V */ + <&adc1 8>, /* VCC_1V5 */ + <&adc1 9>; /* VCC_1V2 */ + }; }; &adc0 { From a049c965187ca42bfb6cf6cdc8a94c644f93e73c Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 14 Jan 2020 07:19:03 -0800 Subject: [PATCH 0190/4444] ARM: dts: vf610-zii-ssmb-dtu: Add voltage monitor DT node Add a DT node for various voltage supply rails connected to SoC's ADC for voltage monitoring purposes. Signed-off-by: Andrey Smirnov Cc: Chris Healy Cc: Fabio Estevam Cc: Shawn Guo Cc: linux-arm-kernel@lists.infradead.org Cc: devicetree@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf610-zii-ssmb-dtu.dts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/vf610-zii-ssmb-dtu.dts b/arch/arm/boot/dts/vf610-zii-ssmb-dtu.dts index 847c5858fea1..a6c22a79779e 100644 --- a/arch/arm/boot/dts/vf610-zii-ssmb-dtu.dts +++ b/arch/arm/boot/dts/vf610-zii-ssmb-dtu.dts @@ -46,6 +46,14 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; }; + + supply-voltage-monitor { + compatible = "iio-hwmon"; + io-channels = <&adc0 8>, /* 12V_MAIN */ + <&adc0 9>, /* +3.3V */ + <&adc1 8>, /* VCC_1V5 */ + <&adc1 9>; /* VCC_1V2 */ + }; }; &adc0 { From 68aaa6aa13756200d3eed46b66e71032d8295983 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 14 Jan 2020 07:19:04 -0800 Subject: [PATCH 0191/4444] ARM: dts: vf610-zii-spb4: Add voltage monitor DT node Add a DT node for various voltage supply rails connected to SoC's ADC for voltage monitoring purposes. Signed-off-by: Andrey Smirnov Cc: Chris Healy Cc: Fabio Estevam Cc: Shawn Guo Cc: linux-arm-kernel@lists.infradead.org Cc: devicetree@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf610-zii-spb4.dts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/vf610-zii-spb4.dts b/arch/arm/boot/dts/vf610-zii-spb4.dts index 77e1484211e4..55b4201e27f6 100644 --- a/arch/arm/boot/dts/vf610-zii-spb4.dts +++ b/arch/arm/boot/dts/vf610-zii-spb4.dts @@ -42,6 +42,14 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; }; + + supply-voltage-monitor { + compatible = "iio-hwmon"; + io-channels = <&adc0 8>, /* 28V_SW */ + <&adc0 9>, /* +3.3V */ + <&adc1 8>, /* VCC_1V5 */ + <&adc1 9>; /* VCC_1V2 */ + }; }; &adc0 { From 6c92d53d0da22467a6dab2e680607417cf50a2bd Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 14 Jan 2020 07:19:05 -0800 Subject: [PATCH 0192/4444] ARM: dts: vf610-zii-dev: Add voltage monitor DT node Add a DT node for various voltage supply rails connected to SoC's ADC for voltage monitoring purposes. Signed-off-by: Andrey Smirnov Cc: Chris Healy Cc: Fabio Estevam Cc: Shawn Guo Cc: linux-arm-kernel@lists.infradead.org Cc: devicetree@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf610-zii-dev.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/vf610-zii-dev.dtsi b/arch/arm/boot/dts/vf610-zii-dev.dtsi index a1b4ccee2a10..95d0060fb56c 100644 --- a/arch/arm/boot/dts/vf610-zii-dev.dtsi +++ b/arch/arm/boot/dts/vf610-zii-dev.dtsi @@ -84,6 +84,14 @@ regulator-boot-on; gpio = <&gpio0 6 0>; }; + + supply-voltage-monitor { + compatible = "iio-hwmon"; + io-channels = <&adc0 8>, /* VCC_1V5 */ + <&adc0 9>, /* VCC_1V8 */ + <&adc1 8>, /* VCC_1V0 */ + <&adc1 9>; /* VCC_1V2 */ + }; }; &adc0 { From 2439545b8c363953feaabf9b7124b8066154daaf Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 14 Jan 2020 07:19:06 -0800 Subject: [PATCH 0193/4444] ARM: dts: vf610-zii-cfu1: Add voltage monitor DT node Add a DT node for various voltage supply rails connected to SoC's ADC for voltage monitoring purposes. Signed-off-by: Andrey Smirnov Cc: Chris Healy Cc: Fabio Estevam Cc: Shawn Guo Cc: linux-arm-kernel@lists.infradead.org Cc: devicetree@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf610-zii-cfu1.dts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/vf610-zii-cfu1.dts b/arch/arm/boot/dts/vf610-zii-cfu1.dts index 28732249cfc0..ce1920c052fc 100644 --- a/arch/arm/boot/dts/vf610-zii-cfu1.dts +++ b/arch/arm/boot/dts/vf610-zii-cfu1.dts @@ -71,6 +71,14 @@ los-gpio = <&gpio4 4 GPIO_ACTIVE_HIGH>; tx-disable-gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>; }; + + supply-voltage-monitor { + compatible = "iio-hwmon"; + io-channels = <&adc0 8>, /* 28VDC_IN */ + <&adc0 9>, /* +3.3V */ + <&adc1 8>, /* VCC_1V5 */ + <&adc1 9>; /* VCC_1V2 */ + }; }; &adc0 { From 614215c8636aeb61961b3eb5030999a2254b3b52 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 12 Feb 2020 11:08:29 +0100 Subject: [PATCH 0194/4444] ARM: sunxi: Replace by The Allwinner platform code is not a clock provider, and just needs to call of_clk_init(). Hence it can include instead of . Signed-off-by: Geert Uytterhoeven Reviewed-by: Stephen Boyd Signed-off-by: Maxime Ripard --- arch/arm/mach-sunxi/sunxi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index 933b6930f024..06da2747a90b 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c @@ -10,9 +10,9 @@ * warranty of any kind, whether express or implied. */ -#include #include #include +#include #include #include From 2b48dcb7a821fc38e0be3e171bd02e058196ccf1 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Tue, 11 Feb 2020 19:59:30 +0100 Subject: [PATCH 0195/4444] clk: sunxi-ng: sun8i-de2: Split out H5 definitions H5 has less clocks and resets than A64. Currently that's not obvious because A64 is missing rotation core related clocks and reset. Split out H5 definition. A64 structures will be fixed in subsequent commit. Note that this patch depends on commit 19368d99746e ("clk: sunxi-ng: add support for Allwinner H3 DE2 CCU") for the H3 clock list. Fixes: 763c5bd045b1 ("clk: sunxi-ng: add support for DE2 CCU") Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c index d9668493c3f9..2478ae314d0f 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c @@ -192,6 +192,12 @@ static struct ccu_reset_map sun50i_a64_de2_resets[] = { [RST_WB] = { 0x08, BIT(2) }, }; +static struct ccu_reset_map sun50i_h5_de2_resets[] = { + [RST_MIXER0] = { 0x08, BIT(0) }, + [RST_MIXER1] = { 0x08, BIT(1) }, + [RST_WB] = { 0x08, BIT(2) }, +}; + static struct ccu_reset_map sun50i_h6_de3_resets[] = { [RST_MIXER0] = { 0x08, BIT(0) }, [RST_MIXER1] = { 0x08, BIT(1) }, @@ -229,6 +235,16 @@ static const struct sunxi_ccu_desc sun50i_a64_de2_clk_desc = { .num_resets = ARRAY_SIZE(sun50i_a64_de2_resets), }; +static const struct sunxi_ccu_desc sun50i_h5_de2_clk_desc = { + .ccu_clks = sun8i_h3_de2_clks, + .num_ccu_clks = ARRAY_SIZE(sun8i_h3_de2_clks), + + .hw_clks = &sun8i_h3_de2_hw_clks, + + .resets = sun50i_h5_de2_resets, + .num_resets = ARRAY_SIZE(sun50i_h5_de2_resets), +}; + static const struct sunxi_ccu_desc sun50i_h6_de3_clk_desc = { .ccu_clks = sun50i_h6_de3_clks, .num_ccu_clks = ARRAY_SIZE(sun50i_h6_de3_clks), @@ -347,7 +363,7 @@ static const struct of_device_id sunxi_de2_clk_ids[] = { }, { .compatible = "allwinner,sun50i-h5-de2-clk", - .data = &sun50i_a64_de2_clk_desc, + .data = &sun50i_h5_de2_clk_desc, }, { .compatible = "allwinner,sun50i-h6-de3-clk", From b4bbce660a3694811b5500c40b9cd69513b50d38 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Tue, 11 Feb 2020 19:59:31 +0100 Subject: [PATCH 0196/4444] clk: sunxi-ng: sun8i-de2: Add rotation core clocks and reset for A64 A64 has rotation core which needs clocks and reset. Because there is no appropriate structures available, make a separate, A64 specific structures. Fixes: cf4881c12935 ("clk: sunxi-ng: fix the A64/H5 clock description of DE2 CCU") Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 45 ++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c index 2478ae314d0f..c6220be8e205 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c @@ -108,6 +108,24 @@ static struct ccu_common *sun8i_v3s_de2_clks[] = { &wb_div_clk.common, }; +static struct ccu_common *sun50i_a64_de2_clks[] = { + &mixer0_clk.common, + &mixer1_clk.common, + &wb_clk.common, + + &bus_mixer0_clk.common, + &bus_mixer1_clk.common, + &bus_wb_clk.common, + + &mixer0_div_clk.common, + &mixer1_div_clk.common, + &wb_div_clk.common, + + &bus_rot_clk.common, + &rot_clk.common, + &rot_div_clk.common, +}; + static struct clk_hw_onecell_data sun8i_a83t_de2_hw_clks = { .hws = { [CLK_MIXER0] = &mixer0_clk.common.hw, @@ -156,6 +174,26 @@ static struct clk_hw_onecell_data sun8i_v3s_de2_hw_clks = { .num = CLK_NUMBER_WITHOUT_ROT, }; +static struct clk_hw_onecell_data sun50i_a64_de2_hw_clks = { + .hws = { + [CLK_MIXER0] = &mixer0_clk.common.hw, + [CLK_MIXER1] = &mixer1_clk.common.hw, + [CLK_WB] = &wb_clk.common.hw, + [CLK_ROT] = &rot_clk.common.hw, + + [CLK_BUS_MIXER0] = &bus_mixer0_clk.common.hw, + [CLK_BUS_MIXER1] = &bus_mixer1_clk.common.hw, + [CLK_BUS_WB] = &bus_wb_clk.common.hw, + [CLK_BUS_ROT] = &bus_rot_clk.common.hw, + + [CLK_MIXER0_DIV] = &mixer0_div_clk.common.hw, + [CLK_MIXER1_DIV] = &mixer1_div_clk.common.hw, + [CLK_WB_DIV] = &wb_div_clk.common.hw, + [CLK_ROT_DIV] = &rot_div_clk.common.hw, + }, + .num = CLK_NUMBER_WITH_ROT, +}; + static struct clk_hw_onecell_data sun50i_h6_de3_hw_clks = { .hws = { [CLK_MIXER0] = &mixer0_clk.common.hw, @@ -190,6 +228,7 @@ static struct ccu_reset_map sun50i_a64_de2_resets[] = { [RST_MIXER0] = { 0x08, BIT(0) }, [RST_MIXER1] = { 0x08, BIT(1) }, [RST_WB] = { 0x08, BIT(2) }, + [RST_ROT] = { 0x08, BIT(3) }, }; static struct ccu_reset_map sun50i_h5_de2_resets[] = { @@ -226,10 +265,10 @@ static const struct sunxi_ccu_desc sun8i_h3_de2_clk_desc = { }; static const struct sunxi_ccu_desc sun50i_a64_de2_clk_desc = { - .ccu_clks = sun8i_h3_de2_clks, - .num_ccu_clks = ARRAY_SIZE(sun8i_h3_de2_clks), + .ccu_clks = sun50i_a64_de2_clks, + .num_ccu_clks = ARRAY_SIZE(sun50i_a64_de2_clks), - .hw_clks = &sun8i_h3_de2_hw_clks, + .hw_clks = &sun50i_a64_de2_hw_clks, .resets = sun50i_a64_de2_resets, .num_resets = ARRAY_SIZE(sun50i_a64_de2_resets), From 75250eb75c828eebda77e23f44de0f037546ea9a Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Tue, 11 Feb 2020 19:59:32 +0100 Subject: [PATCH 0197/4444] clk: sunxi-ng: sun8i-de2: H6 doesn't have rotate core DE3 documentation regarding presence of rotate core in H6 is a bit confusing. Register descriptions mention bits for enabling rotate core clocks and reset, but general overview doesn't list it as feature of H6 display engine, BSP kernel doesn't support it and there is no interrupt listed for it. Manual poking registers also didn't reveal presence of rotate core. Let's assume there isn't any rotate core on H6 present and remove related clocks. With that done, structures are same as those for H5, so just reuse H5 structure. Fixes: 56808da9f97f ("clk: sunxi-ng: Add support for H6 DE3 clocks") Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 57 +--------------------------- 1 file changed, 1 insertion(+), 56 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c index c6220be8e205..87a30d072ae9 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c @@ -51,24 +51,6 @@ static SUNXI_CCU_M(mixer1_div_a83_clk, "mixer1-div", "pll-de", 0x0c, 4, 4, static SUNXI_CCU_M(wb_div_a83_clk, "wb-div", "pll-de", 0x0c, 8, 4, CLK_SET_RATE_PARENT); -static struct ccu_common *sun50i_h6_de3_clks[] = { - &mixer0_clk.common, - &mixer1_clk.common, - &wb_clk.common, - - &bus_mixer0_clk.common, - &bus_mixer1_clk.common, - &bus_wb_clk.common, - - &mixer0_div_clk.common, - &mixer1_div_clk.common, - &wb_div_clk.common, - - &bus_rot_clk.common, - &rot_clk.common, - &rot_div_clk.common, -}; - static struct ccu_common *sun8i_a83t_de2_clks[] = { &mixer0_clk.common, &mixer1_clk.common, @@ -194,26 +176,6 @@ static struct clk_hw_onecell_data sun50i_a64_de2_hw_clks = { .num = CLK_NUMBER_WITH_ROT, }; -static struct clk_hw_onecell_data sun50i_h6_de3_hw_clks = { - .hws = { - [CLK_MIXER0] = &mixer0_clk.common.hw, - [CLK_MIXER1] = &mixer1_clk.common.hw, - [CLK_WB] = &wb_clk.common.hw, - [CLK_ROT] = &rot_clk.common.hw, - - [CLK_BUS_MIXER0] = &bus_mixer0_clk.common.hw, - [CLK_BUS_MIXER1] = &bus_mixer1_clk.common.hw, - [CLK_BUS_WB] = &bus_wb_clk.common.hw, - [CLK_BUS_ROT] = &bus_rot_clk.common.hw, - - [CLK_MIXER0_DIV] = &mixer0_div_clk.common.hw, - [CLK_MIXER1_DIV] = &mixer1_div_clk.common.hw, - [CLK_WB_DIV] = &wb_div_clk.common.hw, - [CLK_ROT_DIV] = &rot_div_clk.common.hw, - }, - .num = CLK_NUMBER_WITH_ROT, -}; - static struct ccu_reset_map sun8i_a83t_de2_resets[] = { [RST_MIXER0] = { 0x08, BIT(0) }, /* @@ -237,13 +199,6 @@ static struct ccu_reset_map sun50i_h5_de2_resets[] = { [RST_WB] = { 0x08, BIT(2) }, }; -static struct ccu_reset_map sun50i_h6_de3_resets[] = { - [RST_MIXER0] = { 0x08, BIT(0) }, - [RST_MIXER1] = { 0x08, BIT(1) }, - [RST_WB] = { 0x08, BIT(2) }, - [RST_ROT] = { 0x08, BIT(3) }, -}; - static const struct sunxi_ccu_desc sun8i_a83t_de2_clk_desc = { .ccu_clks = sun8i_a83t_de2_clks, .num_ccu_clks = ARRAY_SIZE(sun8i_a83t_de2_clks), @@ -284,16 +239,6 @@ static const struct sunxi_ccu_desc sun50i_h5_de2_clk_desc = { .num_resets = ARRAY_SIZE(sun50i_h5_de2_resets), }; -static const struct sunxi_ccu_desc sun50i_h6_de3_clk_desc = { - .ccu_clks = sun50i_h6_de3_clks, - .num_ccu_clks = ARRAY_SIZE(sun50i_h6_de3_clks), - - .hw_clks = &sun50i_h6_de3_hw_clks, - - .resets = sun50i_h6_de3_resets, - .num_resets = ARRAY_SIZE(sun50i_h6_de3_resets), -}; - static const struct sunxi_ccu_desc sun8i_v3s_de2_clk_desc = { .ccu_clks = sun8i_v3s_de2_clks, .num_ccu_clks = ARRAY_SIZE(sun8i_v3s_de2_clks), @@ -406,7 +351,7 @@ static const struct of_device_id sunxi_de2_clk_ids[] = { }, { .compatible = "allwinner,sun50i-h6-de3-clk", - .data = &sun50i_h6_de3_clk_desc, + .data = &sun50i_h5_de2_clk_desc, }, { } }; From 8f9b11a33ad6976e17e7279a170864a1fc613803 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Tue, 11 Feb 2020 19:59:33 +0100 Subject: [PATCH 0198/4444] clk: sunxi-ng: sun8i-de2: Don't reuse A83T resets Currently, V3s and H3 reuse A83T reset structure. However, A83T contains additional core for rotation, which is not present in V3s and H3. Make new reset structure for H3 and let V3s reuse it. A83T reset structure will be amended in subsequent commit. Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c index 87a30d072ae9..bbbe1ed7aba1 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c @@ -179,9 +179,18 @@ static struct clk_hw_onecell_data sun50i_a64_de2_hw_clks = { static struct ccu_reset_map sun8i_a83t_de2_resets[] = { [RST_MIXER0] = { 0x08, BIT(0) }, /* - * For A83T, H3 and R40, mixer1 reset line is shared with wb, so - * only RST_WB is exported here. - * For V3s there's just no mixer1, so it also shares this struct. + * Mixer1 reset line is shared with wb, so only RST_WB is + * exported here. + */ + [RST_WB] = { 0x08, BIT(2) }, +}; + +static struct ccu_reset_map sun8i_h3_de2_resets[] = { + [RST_MIXER0] = { 0x08, BIT(0) }, + /* + * Mixer1 reset line is shared with wb, so only RST_WB is + * exported here. + * V3s doesn't have mixer1, so it also shares this struct. */ [RST_WB] = { 0x08, BIT(2) }, }; @@ -215,8 +224,8 @@ static const struct sunxi_ccu_desc sun8i_h3_de2_clk_desc = { .hw_clks = &sun8i_h3_de2_hw_clks, - .resets = sun8i_a83t_de2_resets, - .num_resets = ARRAY_SIZE(sun8i_a83t_de2_resets), + .resets = sun8i_h3_de2_resets, + .num_resets = ARRAY_SIZE(sun8i_h3_de2_resets), }; static const struct sunxi_ccu_desc sun50i_a64_de2_clk_desc = { @@ -245,8 +254,8 @@ static const struct sunxi_ccu_desc sun8i_v3s_de2_clk_desc = { .hw_clks = &sun8i_v3s_de2_hw_clks, - .resets = sun8i_a83t_de2_resets, - .num_resets = ARRAY_SIZE(sun8i_a83t_de2_resets), + .resets = sun8i_h3_de2_resets, + .num_resets = ARRAY_SIZE(sun8i_h3_de2_resets), }; static int sunxi_de2_clk_probe(struct platform_device *pdev) From b0bfba905cf81d540acaac7a4b23459f7df1bb24 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Tue, 11 Feb 2020 19:59:34 +0100 Subject: [PATCH 0199/4444] clk: sunxi-ng: sun8i-de2: Add rotation core clocks and reset for A83T A83T structures don't have clocks and reset for rotation core. Add them. Fixes: 763c5bd045b1 ("clk: sunxi-ng: add support for DE2 CCU") Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c index bbbe1ed7aba1..9656553c01f3 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c @@ -50,6 +50,8 @@ static SUNXI_CCU_M(mixer1_div_a83_clk, "mixer1-div", "pll-de", 0x0c, 4, 4, CLK_SET_RATE_PARENT); static SUNXI_CCU_M(wb_div_a83_clk, "wb-div", "pll-de", 0x0c, 8, 4, CLK_SET_RATE_PARENT); +static SUNXI_CCU_M(rot_div_a83_clk, "rot-div", "pll-de", 0x0c, 0x0c, 4, + CLK_SET_RATE_PARENT); static struct ccu_common *sun8i_a83t_de2_clks[] = { &mixer0_clk.common, @@ -63,6 +65,10 @@ static struct ccu_common *sun8i_a83t_de2_clks[] = { &mixer0_div_a83_clk.common, &mixer1_div_a83_clk.common, &wb_div_a83_clk.common, + + &bus_rot_clk.common, + &rot_clk.common, + &rot_div_a83_clk.common, }; static struct ccu_common *sun8i_h3_de2_clks[] = { @@ -113,16 +119,19 @@ static struct clk_hw_onecell_data sun8i_a83t_de2_hw_clks = { [CLK_MIXER0] = &mixer0_clk.common.hw, [CLK_MIXER1] = &mixer1_clk.common.hw, [CLK_WB] = &wb_clk.common.hw, + [CLK_ROT] = &rot_clk.common.hw, [CLK_BUS_MIXER0] = &bus_mixer0_clk.common.hw, [CLK_BUS_MIXER1] = &bus_mixer1_clk.common.hw, [CLK_BUS_WB] = &bus_wb_clk.common.hw, + [CLK_BUS_ROT] = &bus_rot_clk.common.hw, [CLK_MIXER0_DIV] = &mixer0_div_a83_clk.common.hw, [CLK_MIXER1_DIV] = &mixer1_div_a83_clk.common.hw, [CLK_WB_DIV] = &wb_div_a83_clk.common.hw, + [CLK_ROT_DIV] = &rot_div_a83_clk.common.hw, }, - .num = CLK_NUMBER_WITHOUT_ROT, + .num = CLK_NUMBER_WITH_ROT, }; static struct clk_hw_onecell_data sun8i_h3_de2_hw_clks = { @@ -183,6 +192,7 @@ static struct ccu_reset_map sun8i_a83t_de2_resets[] = { * exported here. */ [RST_WB] = { 0x08, BIT(2) }, + [RST_ROT] = { 0x08, BIT(3) }, }; static struct ccu_reset_map sun8i_h3_de2_resets[] = { From 11d0c436ffed1dba397e9adec9eaebfe7eef2d10 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Tue, 11 Feb 2020 19:59:35 +0100 Subject: [PATCH 0200/4444] clk: sunxi-ng: sun8i-de2: Add R40 specific quirks R40 is actually very similar to A64, but it doesn't have mixer1 reset. This means it's clocks and resets combination is unique and R40 specific quirks are needed. Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c index 9656553c01f3..5a278c391f1d 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c @@ -238,6 +238,16 @@ static const struct sunxi_ccu_desc sun8i_h3_de2_clk_desc = { .num_resets = ARRAY_SIZE(sun8i_h3_de2_resets), }; +static const struct sunxi_ccu_desc sun8i_r40_de2_clk_desc = { + .ccu_clks = sun50i_a64_de2_clks, + .num_ccu_clks = ARRAY_SIZE(sun50i_a64_de2_clks), + + .hw_clks = &sun50i_a64_de2_hw_clks, + + .resets = sun8i_a83t_de2_resets, + .num_resets = ARRAY_SIZE(sun8i_a83t_de2_resets), +}; + static const struct sunxi_ccu_desc sun50i_a64_de2_clk_desc = { .ccu_clks = sun50i_a64_de2_clks, .num_ccu_clks = ARRAY_SIZE(sun50i_a64_de2_clks), @@ -356,6 +366,10 @@ static const struct of_device_id sunxi_de2_clk_ids[] = { .compatible = "allwinner,sun8i-h3-de2-clk", .data = &sun8i_h3_de2_clk_desc, }, + { + .compatible = "allwinner,sun8i-r40-de2-clk", + .data = &sun8i_r40_de2_clk_desc, + }, { .compatible = "allwinner,sun8i-v3s-de2-clk", .data = &sun8i_v3s_de2_clk_desc, From b998b75f8603c37c8a43a3d849cd2c4929adf402 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Tue, 11 Feb 2020 19:59:36 +0100 Subject: [PATCH 0201/4444] clk: sunxi-ng: sun8i-de2: Sort structures V3s quirks are not in right place. Move it. Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c index 5a278c391f1d..524f33275bc7 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c @@ -248,6 +248,16 @@ static const struct sunxi_ccu_desc sun8i_r40_de2_clk_desc = { .num_resets = ARRAY_SIZE(sun8i_a83t_de2_resets), }; +static const struct sunxi_ccu_desc sun8i_v3s_de2_clk_desc = { + .ccu_clks = sun8i_v3s_de2_clks, + .num_ccu_clks = ARRAY_SIZE(sun8i_v3s_de2_clks), + + .hw_clks = &sun8i_v3s_de2_hw_clks, + + .resets = sun8i_a83t_de2_resets, + .num_resets = ARRAY_SIZE(sun8i_a83t_de2_resets), +}; + static const struct sunxi_ccu_desc sun50i_a64_de2_clk_desc = { .ccu_clks = sun50i_a64_de2_clks, .num_ccu_clks = ARRAY_SIZE(sun50i_a64_de2_clks), @@ -268,16 +278,6 @@ static const struct sunxi_ccu_desc sun50i_h5_de2_clk_desc = { .num_resets = ARRAY_SIZE(sun50i_h5_de2_resets), }; -static const struct sunxi_ccu_desc sun8i_v3s_de2_clk_desc = { - .ccu_clks = sun8i_v3s_de2_clks, - .num_ccu_clks = ARRAY_SIZE(sun8i_v3s_de2_clks), - - .hw_clks = &sun8i_v3s_de2_hw_clks, - - .resets = sun8i_h3_de2_resets, - .num_resets = ARRAY_SIZE(sun8i_h3_de2_resets), -}; - static int sunxi_de2_clk_probe(struct platform_device *pdev) { struct resource *res; From 82dabf599b221a712e951b9061c56669565552a9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 12 Feb 2020 09:50:08 +0100 Subject: [PATCH 0202/4444] ASoC: sh: fsi: Restore devm_ioremap() alignment The alignment of the continuation of the devm_ioremap() call in fsi_probe() was broken. Join the lines, as all parameters can fit on a single line. Fixes: 4bdc0d676a643140 ("remove ioremap_nocache and devm_ioremap_nocache") Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200212085008.9652-1-geert+renesas@glider.be Signed-off-by: Mark Brown --- sound/soc/sh/fsi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 4b35ef402604..5ef4221be6c3 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1938,8 +1938,7 @@ static int fsi_probe(struct platform_device *pdev) if (!master) return -ENOMEM; - master->base = devm_ioremap(&pdev->dev, - res->start, resource_size(res)); + master->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!master->base) { dev_err(&pdev->dev, "Unable to ioremap FSI registers.\n"); return -ENXIO; From 681c896ceb411ccd2ce0a88059d86ccf8d7a497e Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 11 Feb 2020 14:05:49 -0600 Subject: [PATCH 0203/4444] ASoC: wm0010: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertenly introduced[3] to the codebase from now on. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20200211200549.GA12072@embeddedor Signed-off-by: Mark Brown --- sound/soc/codecs/wm0010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 727d6703c905..fbcee21736e8 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -43,7 +43,7 @@ struct dfw_binrec { u8 command; u32 length:24; u32 address; - uint8_t data[0]; + uint8_t data[]; } __packed; struct dfw_inforec { From 128f825aeab79ebff9679a84f49105eda85ecf2c Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 12 Feb 2020 13:55:16 +0800 Subject: [PATCH 0204/4444] ASoC: max98357a: move control of SD_MODE to DAPM Some machine may share the same I2S lines for multiple codecs. For example, mediatek/mt8183/mt8183-da7219-max98357 shares the same lines between max98357a and da7219. When writing audio data through the I2S lines, all codecs on the lines would try to generate sound if they accepts DO line. As a result, multiple codecs generate sound at a time. Moves control of SD_MODE to DAPM so that machine drivers have chances to manipulate DAPM widget to turn on/off max98357a. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200212124608.1.I73b26b5e319de173d05823e79f5861bf1826261c@changeid Signed-off-by: Mark Brown --- sound/soc/codecs/max98357a.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c index 16313b973eaa..74f20114297c 100644 --- a/sound/soc/codecs/max98357a.c +++ b/sound/soc/codecs/max98357a.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -24,26 +25,24 @@ struct max98357a_priv { unsigned int sdmode_delay; }; -static int max98357a_daiops_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) +static int max98357a_sdmode_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) { - struct max98357a_priv *max98357a = snd_soc_dai_get_drvdata(dai); + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct max98357a_priv *max98357a = + snd_soc_component_get_drvdata(component); if (!max98357a->sdmode) return 0; - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - mdelay(max98357a->sdmode_delay); + if (event & SND_SOC_DAPM_POST_PMU) { + msleep(max98357a->sdmode_delay); gpiod_set_value(max98357a->sdmode, 1); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + dev_dbg(component->dev, "set sdmode to 1"); + } else if (event & SND_SOC_DAPM_PRE_PMD) { gpiod_set_value(max98357a->sdmode, 0); - break; + dev_dbg(component->dev, "set sdmode to 0"); } return 0; @@ -51,10 +50,14 @@ static int max98357a_daiops_trigger(struct snd_pcm_substream *substream, static const struct snd_soc_dapm_widget max98357a_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("Speaker"), + SND_SOC_DAPM_OUT_DRV_E("SD_MODE", SND_SOC_NOPM, 0, 0, NULL, 0, + max98357a_sdmode_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), }; static const struct snd_soc_dapm_route max98357a_dapm_routes[] = { - {"Speaker", NULL, "HiFi Playback"}, + {"SD_MODE", NULL, "HiFi Playback"}, + {"Speaker", NULL, "SD_MODE"}, }; static const struct snd_soc_component_driver max98357a_component_driver = { @@ -68,10 +71,6 @@ static const struct snd_soc_component_driver max98357a_component_driver = { .non_legacy_dai_naming = 1, }; -static const struct snd_soc_dai_ops max98357a_dai_ops = { - .trigger = max98357a_daiops_trigger, -}; - static struct snd_soc_dai_driver max98357a_dai_driver = { .name = "HiFi", .playback = { @@ -91,7 +90,6 @@ static struct snd_soc_dai_driver max98357a_dai_driver = { .channels_min = 1, .channels_max = 2, }, - .ops = &max98357a_dai_ops, }; static int max98357a_platform_probe(struct platform_device *pdev) From 514de1c935d1670e0f162210f3794cf0be67c8a7 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 12 Feb 2020 13:55:17 +0800 Subject: [PATCH 0205/4444] ASoC: mediatek: mt8183-da7219: add speaker switch Da7219 and max98357a share the same I2S lines. When writing audio data to the I2S, both codecs generate sound. Da7219 already has a separate control "Headphone Switch". Adds a new control "Speakers Switch" for turning on/off max98357a. Userspace program can decide to turn on/off which codecs by different use cases. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200212124608.2.I5fa3fdca69dbb5d3dd5031c939b9b24095065a94@changeid Signed-off-by: Mark Brown --- .../mediatek/mt8183/mt8183-da7219-max98357.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index c65493721e90..1626541cc0d6 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -372,9 +372,28 @@ static struct snd_soc_codec_conf mt6358_codec_conf[] = { }, }; +static const struct snd_kcontrol_new mt8183_da7219_max98357_snd_controls[] = { + SOC_DAPM_PIN_SWITCH("Speakers"), +}; + +static const +struct snd_soc_dapm_widget mt8183_da7219_max98357_dapm_widgets[] = { + SND_SOC_DAPM_SPK("Speakers", NULL), +}; + +static const struct snd_soc_dapm_route mt8183_da7219_max98357_dapm_routes[] = { + {"Speakers", NULL, "Speaker"}, +}; + static struct snd_soc_card mt8183_da7219_max98357_card = { .name = "mt8183_da7219_max98357", .owner = THIS_MODULE, + .controls = mt8183_da7219_max98357_snd_controls, + .num_controls = ARRAY_SIZE(mt8183_da7219_max98357_snd_controls), + .dapm_widgets = mt8183_da7219_max98357_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(mt8183_da7219_max98357_dapm_widgets), + .dapm_routes = mt8183_da7219_max98357_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(mt8183_da7219_max98357_dapm_routes), .dai_link = mt8183_da7219_max98357_dai_links, .num_links = ARRAY_SIZE(mt8183_da7219_max98357_dai_links), .aux_dev = &mt8183_da7219_max98357_headset_dev, From f43caa2adc96fc9c95fd77eef63cdff86ebf33cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Koutn=C3=BD?= Date: Fri, 24 Jan 2020 12:40:16 +0100 Subject: [PATCH 0206/4444] cgroup: Clean up css_set task traversal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit css_task_iter stores pointer to head of each iterable list, this dates back to commit 0f0a2b4fa621 ("cgroup: reorganize css_task_iter") when we did not store cur_cset. Let us utilize list heads directly in cur_cset and streamline css_task_iter_advance_css_set a bit. This is no intentional function change. Signed-off-by: Michal Koutný Signed-off-by: Tejun Heo --- include/linux/cgroup.h | 3 --- kernel/cgroup/cgroup.c | 61 +++++++++++++++++++----------------------- 2 files changed, 28 insertions(+), 36 deletions(-) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index e75d2191226b..f1219b927817 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -58,9 +58,6 @@ struct css_task_iter { struct list_head *tcset_head; struct list_head *task_pos; - struct list_head *tasks_head; - struct list_head *mg_tasks_head; - struct list_head *dying_tasks_head; struct list_head *cur_tasks_head; struct css_set *cur_cset; diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index c719a4154d6d..b4c4c4fbd6de 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -4391,29 +4391,24 @@ static void css_task_iter_advance_css_set(struct css_task_iter *it) lockdep_assert_held(&css_set_lock); - /* Advance to the next non-empty css_set */ - do { - cset = css_task_iter_next_css_set(it); - if (!cset) { - it->task_pos = NULL; - return; + /* Advance to the next non-empty css_set and find first non-empty tasks list*/ + while ((cset = css_task_iter_next_css_set(it))) { + if (!list_empty(&cset->tasks)) { + it->cur_tasks_head = &cset->tasks; + break; + } else if (!list_empty(&cset->mg_tasks)) { + it->cur_tasks_head = &cset->mg_tasks; + break; + } else if (!list_empty(&cset->dying_tasks)) { + it->cur_tasks_head = &cset->dying_tasks; + break; } - } while (!css_set_populated(cset) && list_empty(&cset->dying_tasks)); - - if (!list_empty(&cset->tasks)) { - it->task_pos = cset->tasks.next; - it->cur_tasks_head = &cset->tasks; - } else if (!list_empty(&cset->mg_tasks)) { - it->task_pos = cset->mg_tasks.next; - it->cur_tasks_head = &cset->mg_tasks; - } else { - it->task_pos = cset->dying_tasks.next; - it->cur_tasks_head = &cset->dying_tasks; } - - it->tasks_head = &cset->tasks; - it->mg_tasks_head = &cset->mg_tasks; - it->dying_tasks_head = &cset->dying_tasks; + if (!cset) { + it->task_pos = NULL; + return; + } + it->task_pos = it->cur_tasks_head->next; /* * We don't keep css_sets locked across iteration steps and thus @@ -4458,24 +4453,24 @@ static void css_task_iter_advance(struct css_task_iter *it) repeat: if (it->task_pos) { /* - * Advance iterator to find next entry. cset->tasks is - * consumed first and then ->mg_tasks. After ->mg_tasks, - * we move onto the next cset. + * Advance iterator to find next entry. We go through cset + * tasks, mg_tasks and dying_tasks, when consumed we move onto + * the next cset. */ if (it->flags & CSS_TASK_ITER_SKIPPED) it->flags &= ~CSS_TASK_ITER_SKIPPED; else it->task_pos = it->task_pos->next; - if (it->task_pos == it->tasks_head) { - it->task_pos = it->mg_tasks_head->next; - it->cur_tasks_head = it->mg_tasks_head; + if (it->task_pos == &it->cur_cset->tasks) { + it->cur_tasks_head = &it->cur_cset->mg_tasks; + it->task_pos = it->cur_tasks_head->next; } - if (it->task_pos == it->mg_tasks_head) { - it->task_pos = it->dying_tasks_head->next; - it->cur_tasks_head = it->dying_tasks_head; + if (it->task_pos == &it->cur_cset->mg_tasks) { + it->cur_tasks_head = &it->cur_cset->dying_tasks; + it->task_pos = it->cur_tasks_head->next; } - if (it->task_pos == it->dying_tasks_head) + if (it->task_pos == &it->cur_cset->dying_tasks) css_task_iter_advance_css_set(it); } else { /* called from start, proceed to the first cset */ @@ -4493,12 +4488,12 @@ repeat: goto repeat; /* and dying leaders w/o live member threads */ - if (it->cur_tasks_head == it->dying_tasks_head && + if (it->cur_tasks_head == &it->cur_cset->dying_tasks && !atomic_read(&task->signal->live)) goto repeat; } else { /* skip all dying ones */ - if (it->cur_tasks_head == it->dying_tasks_head) + if (it->cur_tasks_head == &it->cur_cset->dying_tasks) goto repeat; } } From 04189382c0be4e045d63a38b47f012a8f6c35edc Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Fri, 24 Jan 2020 12:40:17 +0100 Subject: [PATCH 0207/4444] kselftest/cgroup: add cgroup destruction test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new test to verify that a cgroup with dead processes can be destroyed. The test spawns a child process which allocates and touches 100MB of RAM to ensure prolonged exit. Subsequently it kills the child, waits until the cgroup containing the child is empty and destroys the cgroup. Signed-off-by: Suren Baghdasaryan [mkoutny@suse.com: Fix typo in test_cgcore_destroy comment] Acked-by: Michal Koutný Signed-off-by: Michal Koutný Signed-off-by: Tejun Heo --- tools/testing/selftests/cgroup/test_core.c | 113 +++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/tools/testing/selftests/cgroup/test_core.c b/tools/testing/selftests/cgroup/test_core.c index e19ce940cd6a..8289d3f03de4 100644 --- a/tools/testing/selftests/cgroup/test_core.c +++ b/tools/testing/selftests/cgroup/test_core.c @@ -2,7 +2,10 @@ #include #include +#include +#include #include +#include #include #include #include @@ -12,6 +15,115 @@ #include "../kselftest.h" #include "cgroup_util.h" +static int touch_anon(char *buf, size_t size) +{ + int fd; + char *pos = buf; + + fd = open("/dev/urandom", O_RDONLY); + if (fd < 0) + return -1; + + while (size > 0) { + ssize_t ret = read(fd, pos, size); + + if (ret < 0) { + if (errno != EINTR) { + close(fd); + return -1; + } + } else { + pos += ret; + size -= ret; + } + } + close(fd); + + return 0; +} + +static int alloc_and_touch_anon_noexit(const char *cgroup, void *arg) +{ + int ppid = getppid(); + size_t size = (size_t)arg; + void *buf; + + buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, + 0, 0); + if (buf == MAP_FAILED) + return -1; + + if (touch_anon((char *)buf, size)) { + munmap(buf, size); + return -1; + } + + while (getppid() == ppid) + sleep(1); + + munmap(buf, size); + return 0; +} + +/* + * Create a child process that allocates and touches 100MB, then waits to be + * killed. Wait until the child is attached to the cgroup, kill all processes + * in that cgroup and wait until "cgroup.procs" is empty. At this point try to + * destroy the empty cgroup. The test helps detect race conditions between + * dying processes leaving the cgroup and cgroup destruction path. + */ +static int test_cgcore_destroy(const char *root) +{ + int ret = KSFT_FAIL; + char *cg_test = NULL; + int child_pid; + char buf[PAGE_SIZE]; + + cg_test = cg_name(root, "cg_test"); + + if (!cg_test) + goto cleanup; + + for (int i = 0; i < 10; i++) { + if (cg_create(cg_test)) + goto cleanup; + + child_pid = cg_run_nowait(cg_test, alloc_and_touch_anon_noexit, + (void *) MB(100)); + + if (child_pid < 0) + goto cleanup; + + /* wait for the child to enter cgroup */ + if (cg_wait_for_proc_count(cg_test, 1)) + goto cleanup; + + if (cg_killall(cg_test)) + goto cleanup; + + /* wait for cgroup to be empty */ + while (1) { + if (cg_read(cg_test, "cgroup.procs", buf, sizeof(buf))) + goto cleanup; + if (buf[0] == '\0') + break; + usleep(1000); + } + + if (rmdir(cg_test)) + goto cleanup; + + if (waitpid(child_pid, NULL, 0) < 0) + goto cleanup; + } + ret = KSFT_PASS; +cleanup: + if (cg_test) + cg_destroy(cg_test); + free(cg_test); + return ret; +} + /* * A(0) - B(0) - C(1) * \ D(0) @@ -512,6 +624,7 @@ struct corecg_test { T(test_cgcore_populated), T(test_cgcore_proc_migration), T(test_cgcore_thread_migration), + T(test_cgcore_destroy), }; #undef T From 3010c5b9f5f476b35b24955f08a3a6c06ec8e878 Mon Sep 17 00:00:00 2001 From: Madhuparna Bhowmik Date: Sat, 18 Jan 2020 08:40:51 +0530 Subject: [PATCH 0208/4444] cgroup.c: Use built-in RCU list checking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit list_for_each_entry_rcu has built-in RCU and lock checking. Pass cond argument to list_for_each_entry_rcu() to silence false lockdep warning when CONFIG_PROVE_RCU_LIST is enabled by default. Even though the function css_next_child() already checks if cgroup_mutex or rcu_read_lock() is held using cgroup_assert_mutex_or_rcu_locked(), there is a need to pass cond to list_for_each_entry_rcu() to avoid false positive lockdep warning. Signed-off-by: Madhuparna Bhowmik Acked-by: Michal Koutný Signed-off-by: Tejun Heo --- kernel/cgroup/cgroup.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index b4c4c4fbd6de..7a310db6c807 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -4148,7 +4148,8 @@ struct cgroup_subsys_state *css_next_child(struct cgroup_subsys_state *pos, } else if (likely(!(pos->flags & CSS_RELEASED))) { next = list_entry_rcu(pos->sibling.next, struct cgroup_subsys_state, sibling); } else { - list_for_each_entry_rcu(next, &parent->children, sibling) + list_for_each_entry_rcu(next, &parent->children, sibling, + lockdep_is_held(&cgroup_mutex)) if (next->serial_nr > pos->serial_nr) break; } From a49e4629b5edf1db856de05fbf1aae05502ef1af Mon Sep 17 00:00:00 2001 From: Prateek Sood Date: Fri, 24 Jan 2020 20:37:29 +0530 Subject: [PATCH 0209/4444] cpuset: Make cpuset hotplug synchronous Convert cpuset_hotplug_workfn() into synchronous call for cpu hotplug path. For memory hotplug path it still gets queued as a work item. Since cpuset_hotplug_workfn() can be made synchronous for cpu hotplug path, it is not required to wait for cpuset hotplug while thawing processes. Signed-off-by: Prateek Sood Signed-off-by: Tejun Heo --- include/linux/cpuset.h | 3 --- kernel/cgroup/cpuset.c | 31 +++++++++++++++++++------------ kernel/power/process.c | 2 -- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h index 04c20de66afc..cede4cb98b78 100644 --- a/include/linux/cpuset.h +++ b/include/linux/cpuset.h @@ -54,7 +54,6 @@ extern int cpuset_init(void); extern void cpuset_init_smp(void); extern void cpuset_force_rebuild(void); extern void cpuset_update_active_cpus(void); -extern void cpuset_wait_for_hotplug(void); extern void cpuset_read_lock(void); extern void cpuset_read_unlock(void); extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask); @@ -176,8 +175,6 @@ static inline void cpuset_update_active_cpus(void) partition_sched_domains(1, NULL, NULL); } -static inline void cpuset_wait_for_hotplug(void) { } - static inline void cpuset_read_lock(void) { } static inline void cpuset_read_unlock(void) { } diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index 58f5073acff7..cafd4d2ff882 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -3101,7 +3101,7 @@ update_tasks: } /** - * cpuset_hotplug_workfn - handle CPU/memory hotunplug for a cpuset + * cpuset_hotplug - handle CPU/memory hotunplug for a cpuset * * This function is called after either CPU or memory configuration has * changed and updates cpuset accordingly. The top_cpuset is always @@ -3116,7 +3116,7 @@ update_tasks: * Note that CPU offlining during suspend is ignored. We don't modify * cpusets across suspend/resume cycles at all. */ -static void cpuset_hotplug_workfn(struct work_struct *work) +static void cpuset_hotplug(bool use_cpu_hp_lock) { static cpumask_t new_cpus; static nodemask_t new_mems; @@ -3201,25 +3201,32 @@ static void cpuset_hotplug_workfn(struct work_struct *work) /* rebuild sched domains if cpus_allowed has changed */ if (cpus_updated || force_rebuild) { force_rebuild = false; - rebuild_sched_domains(); + if (use_cpu_hp_lock) + rebuild_sched_domains(); + else { + /* Acquiring cpu_hotplug_lock is not required. + * When cpuset_hotplug() is called in hotplug path, + * cpu_hotplug_lock is held by the hotplug context + * which is waiting for cpuhp_thread_fun to indicate + * completion of callback. + */ + percpu_down_write(&cpuset_rwsem); + rebuild_sched_domains_locked(); + percpu_up_write(&cpuset_rwsem); + } } free_cpumasks(NULL, ptmp); } -void cpuset_update_active_cpus(void) +static void cpuset_hotplug_workfn(struct work_struct *work) { - /* - * We're inside cpu hotplug critical region which usually nests - * inside cgroup synchronization. Bounce actual hotplug processing - * to a work item to avoid reverse locking order. - */ - schedule_work(&cpuset_hotplug_work); + cpuset_hotplug(true); } -void cpuset_wait_for_hotplug(void) +void cpuset_update_active_cpus(void) { - flush_work(&cpuset_hotplug_work); + cpuset_hotplug(false); } /* diff --git a/kernel/power/process.c b/kernel/power/process.c index 4b6a54da7e65..08f7019357ee 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -204,8 +204,6 @@ void thaw_processes(void) __usermodehelper_set_disable_depth(UMH_FREEZING); thaw_workqueues(); - cpuset_wait_for_hotplug(); - read_lock(&tasklist_lock); for_each_process_thread(g, p) { /* No other threads should have PF_SUSPEND_TASK set */ From 239a5791ffd5559f51815df442c4dbbe7fc21ade Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 10 Feb 2020 13:11:42 -0800 Subject: [PATCH 0210/4444] dynamic_debug: allow to work if debugfs is disabled With the realization that having debugfs enabled on "production" systems is generally not a good idea, debugfs is being disabled from more and more platforms over time. However, the functionality of dynamic debugging still is needed at times, and since it relies on debugfs for its user api, having debugfs disabled also forces dynamic debug to be disabled. To get around this, also create the "control" file for dynamic_debug in procfs. This allows people turn on debugging as needed at runtime for individual driverfs and subsystems. Reported-by: many different companies Cc: Jason Baron Acked-by: Will Deacon Link: https://lore.kernel.org/r/20200210211142.GB1373304@kroah.com Signed-off-by: Greg Kroah-Hartman --- .../admin-guide/dynamic-debug-howto.rst | 3 ++ lib/Kconfig.debug | 7 +++-- lib/dynamic_debug.c | 28 +++++++++++++++---- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst index 252e5ef324e5..0dc2eb8e44e5 100644 --- a/Documentation/admin-guide/dynamic-debug-howto.rst +++ b/Documentation/admin-guide/dynamic-debug-howto.rst @@ -54,6 +54,9 @@ If you make a mistake with the syntax, the write will fail thus:: /dynamic_debug/control -bash: echo: write error: Invalid argument +Note, for systems without 'debugfs' enabled, the control file can be +found in ``/proc/dynamic_debug/control``. + Viewing Dynamic Debug Behaviour =============================== diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 69def4a9df00..7f4992fd8a2e 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -98,7 +98,7 @@ config DYNAMIC_DEBUG bool "Enable dynamic printk() support" default n depends on PRINTK - depends on DEBUG_FS + depends on (DEBUG_FS || PROC_FS) help Compiles debug level messages into the kernel, which would not @@ -116,8 +116,9 @@ config DYNAMIC_DEBUG Usage: Dynamic debugging is controlled via the 'dynamic_debug/control' file, - which is contained in the 'debugfs' filesystem. Thus, the debugfs - filesystem must first be mounted before making use of this feature. + which is contained in the 'debugfs' filesystem or procfs. + Thus, the debugfs or procfs filesystem must first be mounted before + making use of this feature. We refer the control file as: /dynamic_debug/control. This file contains a list of the debug statements that can be enabled. The format for each line of the file is: diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index c60409138e13..aae17d9522e5 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -876,6 +876,14 @@ static const struct file_operations ddebug_proc_fops = { .write = ddebug_proc_write }; +static const struct proc_ops proc_fops = { + .proc_open = ddebug_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = seq_release_private, + .proc_write = ddebug_proc_write +}; + /* * Allocate a new ddebug_table for the given module * and add it to the global list. @@ -991,15 +999,25 @@ static void ddebug_remove_all_tables(void) static __initdata int ddebug_init_success; -static int __init dynamic_debug_init_debugfs(void) +static int __init dynamic_debug_init_control(void) { - struct dentry *dir; + struct proc_dir_entry *procfs_dir; + struct dentry *debugfs_dir; if (!ddebug_init_success) return -ENODEV; - dir = debugfs_create_dir("dynamic_debug", NULL); - debugfs_create_file("control", 0644, dir, NULL, &ddebug_proc_fops); + /* Create the control file in debugfs if it is enabled */ + if (debugfs_initialized()) { + debugfs_dir = debugfs_create_dir("dynamic_debug", NULL); + debugfs_create_file("control", 0644, debugfs_dir, NULL, + &ddebug_proc_fops); + } + + /* Also create the control file in procfs */ + procfs_dir = proc_mkdir("dynamic_debug", NULL); + if (procfs_dir) + proc_create("control", 0644, procfs_dir, &proc_fops); return 0; } @@ -1077,4 +1095,4 @@ out_err: early_initcall(dynamic_debug_init); /* Debugfs setup must be done later */ -fs_initcall(dynamic_debug_init_debugfs); +fs_initcall(dynamic_debug_init_control); From 6f7e1c1929e0ae0d088cc1f7b5174a8faa7bd711 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Fri, 7 Feb 2020 15:13:24 +0100 Subject: [PATCH 0211/4444] arm64: dts: rk3399: Remove extcon unit address and extcon-cells from Gru The cros-ec-extcon has no reg property so remove the unit address from the DT node to make DT compiler happy. While here, remove the inexistent extcon-cells property from the extcon nodes. Signed-off-by: Enric Balletbo i Serra Link: https://lore.kernel.org/r/20200207141324.3188898-1-enric.balletbo@collabora.com Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi | 4 +--- arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi index 7cd6d470c1cb..1384dabbdf40 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi @@ -291,11 +291,9 @@ ap_i2c_tp: &i2c5 { #pwm-cells = <1>; }; - usbc_extcon1: extcon@1 { + usbc_extcon1: extcon1 { compatible = "google,extcon-usbc-cros-ec"; google,usb-port-id = <1>; - - #extcon-cells = <0>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi index dd5624975c9b..2f3997740068 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi @@ -570,11 +570,9 @@ ap_i2c_audio: &i2c8 { #size-cells = <0>; }; - usbc_extcon0: extcon@0 { + usbc_extcon0: extcon0 { compatible = "google,extcon-usbc-cros-ec"; google,usb-port-id = <0>; - - #extcon-cells = <0>; }; }; }; From e5ab00edc3d5c4cf90aa0bc918bfe87ee47a6990 Mon Sep 17 00:00:00 2001 From: Alexis Ballier Date: Thu, 6 Feb 2020 16:10:24 +0100 Subject: [PATCH 0212/4444] arm64: dts: rockchip: Add ethernet phy to rk3399-orangepi Enables INTB. The wiring is the same as the nanopi4, so this is heavily based on: - [1a4e6203f0c] arm64: dts: rockchip: Add nanopi4 ethernet phy - [bc43cee88aa] arm64: dts: rockchip: Update nanopi4 phy reset properties by Robin Murphy. Signed-off-by: Alexis Ballier Cc: devicetree@vger.kernel.org Cc: Heiko Stuebner Cc: Robin Murphy Cc: linux-arm-kernel@lists.infradead.org Cc: linux-rockchip@lists.infradead.org Cc: linux-kernel@vger.kernel.org Link: https://lore.kernel.org/r/20200206151025.3813-1-aballier@gentoo.org Signed-off-by: Heiko Stuebner --- .../boot/dts/rockchip/rk3399-orangepi.dts | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts b/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts index 9c659f3115c8..1767015e684c 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts @@ -202,14 +202,27 @@ clock_in_out = "input"; phy-supply = <&vcc3v3_s3>; phy-mode = "rgmii"; + phy-handle = <&rtl8211e>; pinctrl-names = "default"; - pinctrl-0 = <&rgmii_pins>; - snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; - snps,reset-active-low; - snps,reset-delays-us = <0 10000 50000>; + pinctrl-0 = <&rgmii_pins>, <&phy_intb>, <&phy_rstb>; tx_delay = <0x28>; rx_delay = <0x11>; status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + rtl8211e: phy@1 { + reg = <1>; + interrupt-parent = <&gpio3>; + interrupts = ; + reset-assert-us = <10000>; + reset-deassert-us = <30000>; + reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + }; + }; }; &gpu { @@ -537,6 +550,16 @@ }; }; + phy { + phy_intb: phy-intb { + rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + phy_rstb: phy-rstb { + rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + pmic { pmic_int_l: pmic-int-l { rockchip,pins = From dbb0a828e9ab5198bd0bb249f074d86910e123f6 Mon Sep 17 00:00:00 2001 From: Alexis Ballier Date: Thu, 6 Feb 2020 16:10:25 +0100 Subject: [PATCH 0213/4444] arm64: dts: rockchip: Explicitly pinmux the regulator configuration GPIOs on rk3399-orangepi Those GPIOs define which register is used by the GPU & CPUB regulators for sleep mode. The register is defined here, so better have the GPIOs explicitly set too. Signed-off-by: Alexis Ballier Cc: devicetree@vger.kernel.org Cc: Heiko Stuebner Cc: linux-arm-kernel@lists.infradead.org Cc: linux-rockchip@lists.infradead.org Cc: linux-kernel@vger.kernel.org Link: https://lore.kernel.org/r/20200206151025.3813-2-aballier@gentoo.org Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts b/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts index 1767015e684c..f9f7246d4d2f 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts @@ -432,6 +432,8 @@ compatible = "silergy,syr827"; reg = <0x40>; fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&cpu_b_sleep>; regulator-name = "vdd_cpu_b"; regulator-min-microvolt = <712500>; regulator-max-microvolt = <1500000>; @@ -449,6 +451,8 @@ compatible = "silergy,syr828"; reg = <0x41>; fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&gpu_sleep>; regulator-name = "vdd_gpu"; regulator-min-microvolt = <712500>; regulator-max-microvolt = <1500000>; @@ -561,6 +565,14 @@ }; pmic { + cpu_b_sleep: cpu-b-sleep { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + gpu_sleep: gpu-sleep { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + pmic_int_l: pmic-int-l { rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; From 6df970e4f5d2c273554550d40d8b92cea9bec1a0 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 5 Feb 2020 14:26:18 +0100 Subject: [PATCH 0214/4444] cgroup: unify attach permission checking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The core codepaths to check whether a process can be attached to a cgroup are the same for threads and thread-group leaders. Only a small piece of code verifying that source and destination cgroup are in the same domain differentiates the thread permission checking from thread-group leader permission checking. Since cgroup_migrate_vet_dst() only matters cgroup2 - it is a noop on cgroup1 - we can move it out of cgroup_attach_task(). All checks can now be consolidated into a new helper cgroup_attach_permissions() callable from both cgroup_procs_write() and cgroup_threads_write(). Cc: Tejun Heo Cc: Li Zefan Cc: Johannes Weiner Cc: cgroups@vger.kernel.org Acked-by: Michal Koutný Signed-off-by: Christian Brauner Signed-off-by: Tejun Heo --- kernel/cgroup/cgroup.c | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 7a310db6c807..9ca51bf3769a 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -2714,11 +2714,7 @@ int cgroup_attach_task(struct cgroup *dst_cgrp, struct task_struct *leader, { DEFINE_CGROUP_MGCTX(mgctx); struct task_struct *task; - int ret; - - ret = cgroup_migrate_vet_dst(dst_cgrp); - if (ret) - return ret; + int ret = 0; /* look up all src csets */ spin_lock_irq(&css_set_lock); @@ -4695,6 +4691,26 @@ static int cgroup_procs_write_permission(struct cgroup *src_cgrp, return 0; } +static int cgroup_attach_permissions(struct cgroup *src_cgrp, + struct cgroup *dst_cgrp, + struct super_block *sb, bool threadgroup) +{ + int ret = 0; + + ret = cgroup_procs_write_permission(src_cgrp, dst_cgrp, sb); + if (ret) + return ret; + + ret = cgroup_migrate_vet_dst(dst_cgrp); + if (ret) + return ret; + + if (!threadgroup && (src_cgrp->dom_cgrp != dst_cgrp->dom_cgrp)) + ret = -EOPNOTSUPP; + + return ret; +} + static ssize_t cgroup_procs_write(struct kernfs_open_file *of, char *buf, size_t nbytes, loff_t off) { @@ -4717,8 +4733,8 @@ static ssize_t cgroup_procs_write(struct kernfs_open_file *of, src_cgrp = task_cgroup_from_root(task, &cgrp_dfl_root); spin_unlock_irq(&css_set_lock); - ret = cgroup_procs_write_permission(src_cgrp, dst_cgrp, - of->file->f_path.dentry->d_sb); + ret = cgroup_attach_permissions(src_cgrp, dst_cgrp, + of->file->f_path.dentry->d_sb, true); if (ret) goto out_finish; @@ -4762,16 +4778,11 @@ static ssize_t cgroup_threads_write(struct kernfs_open_file *of, spin_unlock_irq(&css_set_lock); /* thread migrations follow the cgroup.procs delegation rule */ - ret = cgroup_procs_write_permission(src_cgrp, dst_cgrp, - of->file->f_path.dentry->d_sb); + ret = cgroup_attach_permissions(src_cgrp, dst_cgrp, + of->file->f_path.dentry->d_sb, false); if (ret) goto out_finish; - /* and must be contained in the same domain */ - ret = -EOPNOTSUPP; - if (src_cgrp->dom_cgrp != dst_cgrp->dom_cgrp) - goto out_finish; - ret = cgroup_attach_task(dst_cgrp, task, false); out_finish: From 17703097f3456498e6424614571648c6452f4d34 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 5 Feb 2020 14:26:19 +0100 Subject: [PATCH 0215/4444] cgroup: add cgroup_get_from_file() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a helper cgroup_get_from_file(). The helper will be used in subsequent patches to retrieve a cgroup while holding a reference to the struct file it was taken from. Cc: Tejun Heo Cc: Johannes Weiner Cc: Li Zefan Cc: cgroups@vger.kernel.org Acked-by: Michal Koutný Signed-off-by: Christian Brauner Signed-off-by: Tejun Heo --- kernel/cgroup/cgroup.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 9ca51bf3769a..16fe1c6cad35 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -5880,6 +5880,24 @@ void cgroup_fork(struct task_struct *child) INIT_LIST_HEAD(&child->cg_list); } +static struct cgroup *cgroup_get_from_file(struct file *f) +{ + struct cgroup_subsys_state *css; + struct cgroup *cgrp; + + css = css_tryget_online_from_dir(f->f_path.dentry, NULL); + if (IS_ERR(css)) + return ERR_CAST(css); + + cgrp = css->cgroup; + if (!cgroup_on_dfl(cgrp)) { + cgroup_put(cgrp); + return ERR_PTR(-EBADF); + } + + return cgrp; +} + /** * cgroup_can_fork - called on a new task before the process is exposed * @child: the task in question. @@ -6171,7 +6189,6 @@ EXPORT_SYMBOL_GPL(cgroup_get_from_path); */ struct cgroup *cgroup_get_from_fd(int fd) { - struct cgroup_subsys_state *css; struct cgroup *cgrp; struct file *f; @@ -6179,17 +6196,8 @@ struct cgroup *cgroup_get_from_fd(int fd) if (!f) return ERR_PTR(-EBADF); - css = css_tryget_online_from_dir(f->f_path.dentry, NULL); + cgrp = cgroup_get_from_file(f); fput(f); - if (IS_ERR(css)) - return ERR_CAST(css); - - cgrp = css->cgroup; - if (!cgroup_on_dfl(cgrp)) { - cgroup_put(cgrp); - return ERR_PTR(-EBADF); - } - return cgrp; } EXPORT_SYMBOL_GPL(cgroup_get_from_fd); From 5a5cf5cb30d7815c01035fde4b84edef85d11c68 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 5 Feb 2020 14:26:20 +0100 Subject: [PATCH 0216/4444] cgroup: refactor fork helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This refactors the fork helpers so they can be easily modified in the next patches. The patch just moves the cgroup threadgroup rwsem grab and release into the helpers. They don't need to be directly exposed in fork.c. Cc: Tejun Heo Cc: Johannes Weiner Cc: Li Zefan Cc: cgroups@vger.kernel.org Acked-by: Michal Koutný Signed-off-by: Christian Brauner Signed-off-by: Tejun Heo --- kernel/cgroup/cgroup.c | 42 +++++++++++++++++++++++++----------------- kernel/fork.c | 6 +----- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 16fe1c6cad35..502769b2683c 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -5900,17 +5900,20 @@ static struct cgroup *cgroup_get_from_file(struct file *f) /** * cgroup_can_fork - called on a new task before the process is exposed - * @child: the task in question. + * @child: the child process * - * This calls the subsystem can_fork() callbacks. If the can_fork() callback - * returns an error, the fork aborts with that error code. This allows for - * a cgroup subsystem to conditionally allow or deny new forks. + * This calls the subsystem can_fork() callbacks. If the cgroup_can_fork() + * callback returns an error, the fork aborts with that error code. This + * allows for a cgroup subsystem to conditionally allow or deny new forks. */ int cgroup_can_fork(struct task_struct *child) + __acquires(&cgroup_threadgroup_rwsem) __releases(&cgroup_threadgroup_rwsem) { struct cgroup_subsys *ss; int i, j, ret; + cgroup_threadgroup_change_begin(current); + do_each_subsys_mask(ss, i, have_canfork_callback) { ret = ss->can_fork(child); if (ret) @@ -5927,17 +5930,20 @@ out_revert: ss->cancel_fork(child); } + cgroup_threadgroup_change_end(current); + return ret; } /** - * cgroup_cancel_fork - called if a fork failed after cgroup_can_fork() - * @child: the task in question - * - * This calls the cancel_fork() callbacks if a fork failed *after* - * cgroup_can_fork() succeded. - */ + * cgroup_cancel_fork - called if a fork failed after cgroup_can_fork() + * @child: the child process + * + * This calls the cancel_fork() callbacks if a fork failed *after* + * cgroup_can_fork() succeded. + */ void cgroup_cancel_fork(struct task_struct *child) + __releases(&cgroup_threadgroup_rwsem) { struct cgroup_subsys *ss; int i; @@ -5945,19 +5951,19 @@ void cgroup_cancel_fork(struct task_struct *child) for_each_subsys(ss, i) if (ss->cancel_fork) ss->cancel_fork(child); + + cgroup_threadgroup_change_end(current); } /** - * cgroup_post_fork - called on a new task after adding it to the task list - * @child: the task in question + * cgroup_post_fork - finalize cgroup setup for the child process + * @child: the child process * - * Adds the task to the list running through its css_set if necessary and - * call the subsystem fork() callbacks. Has to be after the task is - * visible on the task list in case we race with the first call to - * cgroup_task_iter_start() - to guarantee that the new task ends up on its - * list. + * Attach the child process to its css_set calling the subsystem fork() + * callbacks. */ void cgroup_post_fork(struct task_struct *child) + __releases(&cgroup_threadgroup_rwsem) { struct cgroup_subsys *ss; struct css_set *cset; @@ -6003,6 +6009,8 @@ void cgroup_post_fork(struct task_struct *child) do_each_subsys_mask(ss, i, have_fork_callback) { ss->fork(child); } while_each_subsys_mask(); + + cgroup_threadgroup_change_end(current); } /** diff --git a/kernel/fork.c b/kernel/fork.c index 60a1295f4384..9245b6e53f55 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2174,7 +2174,6 @@ static __latent_entropy struct task_struct *copy_process( INIT_LIST_HEAD(&p->thread_group); p->task_works = NULL; - cgroup_threadgroup_change_begin(current); /* * Ensure that the cgroup subsystem policies allow the new process to be * forked. It should be noted the the new process's css_set can be changed @@ -2183,7 +2182,7 @@ static __latent_entropy struct task_struct *copy_process( */ retval = cgroup_can_fork(p); if (retval) - goto bad_fork_cgroup_threadgroup_change_end; + goto bad_fork_put_pidfd; /* * From this point on we must avoid any synchronous user-space @@ -2289,7 +2288,6 @@ static __latent_entropy struct task_struct *copy_process( proc_fork_connector(p); cgroup_post_fork(p); - cgroup_threadgroup_change_end(current); perf_event_fork(p); trace_task_newtask(p, clone_flags); @@ -2301,8 +2299,6 @@ bad_fork_cancel_cgroup: spin_unlock(¤t->sighand->siglock); write_unlock_irq(&tasklist_lock); cgroup_cancel_fork(p); -bad_fork_cgroup_threadgroup_change_end: - cgroup_threadgroup_change_end(current); bad_fork_put_pidfd: if (clone_flags & CLONE_PIDFD) { fput(pidfile); From f3553220d4cc458d69f7da6e71a3a6097778bd28 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 5 Feb 2020 14:26:21 +0100 Subject: [PATCH 0217/4444] cgroup: add cgroup_may_write() helper Add a cgroup_may_write() helper which we can use in the CLONE_INTO_CGROUP patch series to verify that we can write to the destination cgroup. Cc: Tejun Heo Cc: Johannes Weiner Cc: Li Zefan Cc: cgroups@vger.kernel.org Signed-off-by: Christian Brauner Signed-off-by: Tejun Heo --- kernel/cgroup/cgroup.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 502769b2683c..6d8bdddd8c28 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -4654,13 +4654,28 @@ static int cgroup_procs_show(struct seq_file *s, void *v) return 0; } +static int cgroup_may_write(const struct cgroup *cgrp, struct super_block *sb) +{ + int ret; + struct inode *inode; + + lockdep_assert_held(&cgroup_mutex); + + inode = kernfs_get_inode(sb, cgrp->procs_file.kn); + if (!inode) + return -ENOMEM; + + ret = inode_permission(inode, MAY_WRITE); + iput(inode); + return ret; +} + static int cgroup_procs_write_permission(struct cgroup *src_cgrp, struct cgroup *dst_cgrp, struct super_block *sb) { struct cgroup_namespace *ns = current->nsproxy->cgroup_ns; struct cgroup *com_cgrp = src_cgrp; - struct inode *inode; int ret; lockdep_assert_held(&cgroup_mutex); @@ -4670,12 +4685,7 @@ static int cgroup_procs_write_permission(struct cgroup *src_cgrp, com_cgrp = cgroup_parent(com_cgrp); /* %current should be authorized to migrate to the common ancestor */ - inode = kernfs_get_inode(sb, com_cgrp->procs_file.kn); - if (!inode) - return -ENOMEM; - - ret = inode_permission(inode, MAY_WRITE); - iput(inode); + ret = cgroup_may_write(com_cgrp, sb); if (ret) return ret; From ef2c41cf38a7559bbf91af42d5b6a4429db8fc68 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 5 Feb 2020 14:26:22 +0100 Subject: [PATCH 0218/4444] clone3: allow spawning processes into cgroups This adds support for creating a process in a different cgroup than its parent. Callers can limit and account processes and threads right from the moment they are spawned: - A service manager can directly spawn new services into dedicated cgroups. - A process can be directly created in a frozen cgroup and will be frozen as well. - The initial accounting jitter experienced by process supervisors and daemons is eliminated with this. - Threaded applications or even thread implementations can choose to create a specific cgroup layout where each thread is spawned directly into a dedicated cgroup. This feature is limited to the unified hierarchy. Callers need to pass a directory file descriptor for the target cgroup. The caller can choose to pass an O_PATH file descriptor. All usual migration restrictions apply, i.e. there can be no processes in inner nodes. In general, creating a process directly in a target cgroup adheres to all migration restrictions. One of the biggest advantages of this feature is that CLONE_INTO_GROUP does not need to grab the write side of the cgroup cgroup_threadgroup_rwsem. This global lock makes moving tasks/threads around super expensive. With clone3() this lock is avoided. Cc: Tejun Heo Cc: Ingo Molnar Cc: Oleg Nesterov Cc: Johannes Weiner Cc: Li Zefan Cc: Peter Zijlstra Cc: cgroups@vger.kernel.org Signed-off-by: Christian Brauner Signed-off-by: Tejun Heo --- include/linux/cgroup-defs.h | 5 +- include/linux/cgroup.h | 20 ++-- include/linux/sched/task.h | 4 + include/uapi/linux/sched.h | 5 + kernel/cgroup/cgroup.c | 191 +++++++++++++++++++++++++++++++----- kernel/cgroup/pids.c | 15 ++- kernel/fork.c | 13 ++- 7 files changed, 214 insertions(+), 39 deletions(-) diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h index 63097cb243cb..68c391f451d1 100644 --- a/include/linux/cgroup-defs.h +++ b/include/linux/cgroup-defs.h @@ -628,8 +628,9 @@ struct cgroup_subsys { void (*cancel_attach)(struct cgroup_taskset *tset); void (*attach)(struct cgroup_taskset *tset); void (*post_attach)(void); - int (*can_fork)(struct task_struct *task); - void (*cancel_fork)(struct task_struct *task); + int (*can_fork)(struct task_struct *task, + struct css_set *cset); + void (*cancel_fork)(struct task_struct *task, struct css_set *cset); void (*fork)(struct task_struct *task); void (*exit)(struct task_struct *task); void (*release)(struct task_struct *task); diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index f1219b927817..4598e4da6b1b 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -27,6 +27,8 @@ #include +struct kernel_clone_args; + #ifdef CONFIG_CGROUPS /* @@ -119,9 +121,12 @@ int proc_cgroup_show(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *tsk); void cgroup_fork(struct task_struct *p); -extern int cgroup_can_fork(struct task_struct *p); -extern void cgroup_cancel_fork(struct task_struct *p); -extern void cgroup_post_fork(struct task_struct *p); +extern int cgroup_can_fork(struct task_struct *p, + struct kernel_clone_args *kargs); +extern void cgroup_cancel_fork(struct task_struct *p, + struct kernel_clone_args *kargs); +extern void cgroup_post_fork(struct task_struct *p, + struct kernel_clone_args *kargs); void cgroup_exit(struct task_struct *p); void cgroup_release(struct task_struct *p); void cgroup_free(struct task_struct *p); @@ -705,9 +710,12 @@ static inline int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry) { return -EINVAL; } static inline void cgroup_fork(struct task_struct *p) {} -static inline int cgroup_can_fork(struct task_struct *p) { return 0; } -static inline void cgroup_cancel_fork(struct task_struct *p) {} -static inline void cgroup_post_fork(struct task_struct *p) {} +static inline int cgroup_can_fork(struct task_struct *p, + struct kernel_clone_args *kargs) { return 0; } +static inline void cgroup_cancel_fork(struct task_struct *p, + struct kernel_clone_args *kargs) {} +static inline void cgroup_post_fork(struct task_struct *p, + struct kernel_clone_args *kargs) {} static inline void cgroup_exit(struct task_struct *p) {} static inline void cgroup_release(struct task_struct *p) {} static inline void cgroup_free(struct task_struct *p) {} diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h index f1879884238e..38359071236a 100644 --- a/include/linux/sched/task.h +++ b/include/linux/sched/task.h @@ -13,6 +13,7 @@ struct task_struct; struct rusage; union thread_union; +struct css_set; /* All the bits taken by the old clone syscall. */ #define CLONE_LEGACY_FLAGS 0xffffffffULL @@ -29,6 +30,9 @@ struct kernel_clone_args { pid_t *set_tid; /* Number of elements in *set_tid */ size_t set_tid_size; + int cgroup; + struct cgroup *cgrp; + struct css_set *cset; }; /* diff --git a/include/uapi/linux/sched.h b/include/uapi/linux/sched.h index 2e3bc22c6f20..3bac0a8ceab2 100644 --- a/include/uapi/linux/sched.h +++ b/include/uapi/linux/sched.h @@ -35,6 +35,7 @@ /* Flags for the clone3() syscall. */ #define CLONE_CLEAR_SIGHAND 0x100000000ULL /* Clear any signal handler and reset to SIG_DFL. */ +#define CLONE_INTO_CGROUP 0x200000000ULL /* Clone into a specific cgroup given the right permissions. */ /* * cloning flags intersect with CSIGNAL so can be used with unshare and clone3 @@ -81,6 +82,8 @@ * @set_tid_size: This defines the size of the array referenced * in @set_tid. This cannot be larger than the * kernel's limit of nested PID namespaces. + * @cgroup: If CLONE_INTO_CGROUP is specified set this to + * a file descriptor for the cgroup. * * The structure is versioned by size and thus extensible. * New struct members must go at the end of the struct and @@ -97,11 +100,13 @@ struct clone_args { __aligned_u64 tls; __aligned_u64 set_tid; __aligned_u64 set_tid_size; + __aligned_u64 cgroup; }; #endif #define CLONE_ARGS_SIZE_VER0 64 /* sizeof first published struct */ #define CLONE_ARGS_SIZE_VER1 80 /* sizeof second published struct */ +#define CLONE_ARGS_SIZE_VER2 88 /* sizeof third published struct */ /* * Scheduling policies diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 6d8bdddd8c28..9a8a5ded3c48 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -5881,8 +5881,7 @@ out: * @child: pointer to task_struct of forking parent process. * * A task is associated with the init_css_set until cgroup_post_fork() - * attaches it to the parent's css_set. Empty cg_list indicates that - * @child isn't holding reference to its css_set. + * attaches it to the target css_set. */ void cgroup_fork(struct task_struct *child) { @@ -5908,24 +5907,154 @@ static struct cgroup *cgroup_get_from_file(struct file *f) return cgrp; } +/** + * cgroup_css_set_fork - find or create a css_set for a child process + * @kargs: the arguments passed to create the child process + * + * This functions finds or creates a new css_set which the child + * process will be attached to in cgroup_post_fork(). By default, + * the child process will be given the same css_set as its parent. + * + * If CLONE_INTO_CGROUP is specified this function will try to find an + * existing css_set which includes the requested cgroup and if not create + * a new css_set that the child will be attached to later. If this function + * succeeds it will hold cgroup_threadgroup_rwsem on return. If + * CLONE_INTO_CGROUP is requested this function will grab cgroup mutex + * before grabbing cgroup_threadgroup_rwsem and will hold a reference + * to the target cgroup. + */ +static int cgroup_css_set_fork(struct kernel_clone_args *kargs) + __acquires(&cgroup_mutex) __acquires(&cgroup_threadgroup_rwsem) +{ + int ret; + struct cgroup *dst_cgrp = NULL; + struct css_set *cset; + struct super_block *sb; + struct file *f; + + if (kargs->flags & CLONE_INTO_CGROUP) + mutex_lock(&cgroup_mutex); + + cgroup_threadgroup_change_begin(current); + + spin_lock_irq(&css_set_lock); + cset = task_css_set(current); + get_css_set(cset); + spin_unlock_irq(&css_set_lock); + + if (!(kargs->flags & CLONE_INTO_CGROUP)) { + kargs->cset = cset; + return 0; + } + + f = fget_raw(kargs->cgroup); + if (!f) { + ret = -EBADF; + goto err; + } + sb = f->f_path.dentry->d_sb; + + dst_cgrp = cgroup_get_from_file(f); + if (IS_ERR(dst_cgrp)) { + ret = PTR_ERR(dst_cgrp); + dst_cgrp = NULL; + goto err; + } + + if (cgroup_is_dead(dst_cgrp)) { + ret = -ENODEV; + goto err; + } + + /* + * Verify that we the target cgroup is writable for us. This is + * usually done by the vfs layer but since we're not going through + * the vfs layer here we need to do it "manually". + */ + ret = cgroup_may_write(dst_cgrp, sb); + if (ret) + goto err; + + ret = cgroup_attach_permissions(cset->dfl_cgrp, dst_cgrp, sb, + !(kargs->flags & CLONE_THREAD)); + if (ret) + goto err; + + kargs->cset = find_css_set(cset, dst_cgrp); + if (!kargs->cset) { + ret = -ENOMEM; + goto err; + } + + put_css_set(cset); + fput(f); + kargs->cgrp = dst_cgrp; + return ret; + +err: + cgroup_threadgroup_change_end(current); + mutex_unlock(&cgroup_mutex); + if (f) + fput(f); + if (dst_cgrp) + cgroup_put(dst_cgrp); + put_css_set(cset); + if (kargs->cset) + put_css_set(kargs->cset); + return ret; +} + +/** + * cgroup_css_set_put_fork - drop references we took during fork + * @kargs: the arguments passed to create the child process + * + * Drop references to the prepared css_set and target cgroup if + * CLONE_INTO_CGROUP was requested. + */ +static void cgroup_css_set_put_fork(struct kernel_clone_args *kargs) + __releases(&cgroup_threadgroup_rwsem) __releases(&cgroup_mutex) +{ + cgroup_threadgroup_change_end(current); + + if (kargs->flags & CLONE_INTO_CGROUP) { + struct cgroup *cgrp = kargs->cgrp; + struct css_set *cset = kargs->cset; + + mutex_unlock(&cgroup_mutex); + + if (cset) { + put_css_set(cset); + kargs->cset = NULL; + } + + if (cgrp) { + cgroup_put(cgrp); + kargs->cgrp = NULL; + } + } +} + /** * cgroup_can_fork - called on a new task before the process is exposed * @child: the child process * + * This prepares a new css_set for the child process which the child will + * be attached to in cgroup_post_fork(). * This calls the subsystem can_fork() callbacks. If the cgroup_can_fork() * callback returns an error, the fork aborts with that error code. This * allows for a cgroup subsystem to conditionally allow or deny new forks. */ -int cgroup_can_fork(struct task_struct *child) - __acquires(&cgroup_threadgroup_rwsem) __releases(&cgroup_threadgroup_rwsem) +int cgroup_can_fork(struct task_struct *child, struct kernel_clone_args *kargs) { struct cgroup_subsys *ss; int i, j, ret; - cgroup_threadgroup_change_begin(current); + ret = cgroup_css_set_fork(kargs); + if (ret) + return ret; do_each_subsys_mask(ss, i, have_canfork_callback) { - ret = ss->can_fork(child); + ret = ss->can_fork(child, kargs->cset); if (ret) goto out_revert; } while_each_subsys_mask(); @@ -5937,32 +6066,34 @@ out_revert: if (j >= i) break; if (ss->cancel_fork) - ss->cancel_fork(child); + ss->cancel_fork(child, kargs->cset); } - cgroup_threadgroup_change_end(current); + cgroup_css_set_put_fork(kargs); return ret; } /** - * cgroup_cancel_fork - called if a fork failed after cgroup_can_fork() - * @child: the child process - * - * This calls the cancel_fork() callbacks if a fork failed *after* - * cgroup_can_fork() succeded. - */ -void cgroup_cancel_fork(struct task_struct *child) - __releases(&cgroup_threadgroup_rwsem) + * cgroup_cancel_fork - called if a fork failed after cgroup_can_fork() + * @child: the child process + * @kargs: the arguments passed to create the child process + * + * This calls the cancel_fork() callbacks if a fork failed *after* + * cgroup_can_fork() succeded and cleans up references we took to + * prepare a new css_set for the child process in cgroup_can_fork(). + */ +void cgroup_cancel_fork(struct task_struct *child, + struct kernel_clone_args *kargs) { struct cgroup_subsys *ss; int i; for_each_subsys(ss, i) if (ss->cancel_fork) - ss->cancel_fork(child); + ss->cancel_fork(child, kargs->cset); - cgroup_threadgroup_change_end(current); + cgroup_css_set_put_fork(kargs); } /** @@ -5972,22 +6103,27 @@ void cgroup_cancel_fork(struct task_struct *child) * Attach the child process to its css_set calling the subsystem fork() * callbacks. */ -void cgroup_post_fork(struct task_struct *child) - __releases(&cgroup_threadgroup_rwsem) +void cgroup_post_fork(struct task_struct *child, + struct kernel_clone_args *kargs) + __releases(&cgroup_threadgroup_rwsem) __releases(&cgroup_mutex) { struct cgroup_subsys *ss; struct css_set *cset; int i; + cset = kargs->cset; + kargs->cset = NULL; + spin_lock_irq(&css_set_lock); /* init tasks are special, only link regular threads */ if (likely(child->pid)) { WARN_ON_ONCE(!list_empty(&child->cg_list)); - cset = task_css_set(current); /* current is @child's parent */ - get_css_set(cset); cset->nr_tasks++; css_set_move_task(child, NULL, cset, false); + } else { + put_css_set(cset); + cset = NULL; } /* @@ -6020,7 +6156,16 @@ void cgroup_post_fork(struct task_struct *child) ss->fork(child); } while_each_subsys_mask(); - cgroup_threadgroup_change_end(current); + /* Make the new cset the root_cset of the new cgroup namespace. */ + if (kargs->flags & CLONE_NEWCGROUP) { + struct css_set *rcset = child->nsproxy->cgroup_ns->root_cset; + + get_css_set(cset); + child->nsproxy->cgroup_ns->root_cset = cset; + put_css_set(rcset); + } + + cgroup_css_set_put_fork(kargs); } /** diff --git a/kernel/cgroup/pids.c b/kernel/cgroup/pids.c index 138059eb730d..511af87f685e 100644 --- a/kernel/cgroup/pids.c +++ b/kernel/cgroup/pids.c @@ -33,6 +33,7 @@ #include #include #include +#include #define PIDS_MAX (PID_MAX_LIMIT + 1ULL) #define PIDS_MAX_STR "max" @@ -214,13 +215,16 @@ static void pids_cancel_attach(struct cgroup_taskset *tset) * task_css_check(true) in pids_can_fork() and pids_cancel_fork() relies * on cgroup_threadgroup_change_begin() held by the copy_process(). */ -static int pids_can_fork(struct task_struct *task) +static int pids_can_fork(struct task_struct *task, struct css_set *cset) { struct cgroup_subsys_state *css; struct pids_cgroup *pids; int err; - css = task_css_check(current, pids_cgrp_id, true); + if (cset) + css = cset->subsys[pids_cgrp_id]; + else + css = task_css_check(current, pids_cgrp_id, true); pids = css_pids(css); err = pids_try_charge(pids, 1); if (err) { @@ -235,12 +239,15 @@ static int pids_can_fork(struct task_struct *task) return err; } -static void pids_cancel_fork(struct task_struct *task) +static void pids_cancel_fork(struct task_struct *task, struct css_set *cset) { struct cgroup_subsys_state *css; struct pids_cgroup *pids; - css = task_css_check(current, pids_cgrp_id, true); + if (cset) + css = cset->subsys[pids_cgrp_id]; + else + css = task_css_check(current, pids_cgrp_id, true); pids = css_pids(css); pids_uncharge(pids, 1); } diff --git a/kernel/fork.c b/kernel/fork.c index 9245b6e53f55..635d6369dfb9 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2180,7 +2180,7 @@ static __latent_entropy struct task_struct *copy_process( * between here and cgroup_post_fork() if an organisation operation is in * progress. */ - retval = cgroup_can_fork(p); + retval = cgroup_can_fork(p, args); if (retval) goto bad_fork_put_pidfd; @@ -2287,7 +2287,7 @@ static __latent_entropy struct task_struct *copy_process( write_unlock_irq(&tasklist_lock); proc_fork_connector(p); - cgroup_post_fork(p); + cgroup_post_fork(p, args); perf_event_fork(p); trace_task_newtask(p, clone_flags); @@ -2298,7 +2298,7 @@ static __latent_entropy struct task_struct *copy_process( bad_fork_cancel_cgroup: spin_unlock(¤t->sighand->siglock); write_unlock_irq(&tasklist_lock); - cgroup_cancel_fork(p); + cgroup_cancel_fork(p, args); bad_fork_put_pidfd: if (clone_flags & CLONE_PIDFD) { fput(pidfile); @@ -2627,6 +2627,9 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs, !valid_signal(args.exit_signal))) return -EINVAL; + if ((args.flags & CLONE_INTO_CGROUP) && args.cgroup < 0) + return -EINVAL; + *kargs = (struct kernel_clone_args){ .flags = args.flags, .pidfd = u64_to_user_ptr(args.pidfd), @@ -2637,6 +2640,7 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs, .stack_size = args.stack_size, .tls = args.tls, .set_tid_size = args.set_tid_size, + .cgroup = args.cgroup, }; if (args.set_tid && @@ -2680,7 +2684,8 @@ static inline bool clone3_stack_valid(struct kernel_clone_args *kargs) static bool clone3_args_valid(struct kernel_clone_args *kargs) { /* Verify that no unknown flags are passed along. */ - if (kargs->flags & ~(CLONE_LEGACY_FLAGS | CLONE_CLEAR_SIGHAND)) + if (kargs->flags & + ~(CLONE_LEGACY_FLAGS | CLONE_CLEAR_SIGHAND | CLONE_INTO_CGROUP)) return false; /* From 9bd5910d7f3db2f65be139d2679dd9daa4a3419a Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 5 Feb 2020 14:26:23 +0100 Subject: [PATCH 0219/4444] selftests/cgroup: add tests for cloning into cgroups Expand the cgroup test-suite to include tests for CLONE_INTO_CGROUP. This adds the following tests: - CLONE_INTO_CGROUP manages to clone a process directly into a correctly delegated cgroup - CLONE_INTO_CGROUP fails to clone a process into a cgroup that has been removed after we've opened an fd to it - CLONE_INTO_CGROUP fails to clone a process into an invalid domain cgroup - CLONE_INTO_CGROUP adheres to the no internal process constraint - CLONE_INTO_CGROUP works with the freezer feature Cc: Tejun Heo Cc: Shuah Khan Cc: cgroups@vger.kernel.org Cc: linux-kselftest@vger.kernel.org Acked-by: Roman Gushchin Signed-off-by: Christian Brauner Signed-off-by: Tejun Heo --- tools/testing/selftests/cgroup/Makefile | 6 +- tools/testing/selftests/cgroup/cgroup_util.c | 126 ++++++++++++++++++ tools/testing/selftests/cgroup/cgroup_util.h | 4 + tools/testing/selftests/cgroup/test_core.c | 64 +++++++++ .../selftests/clone3/clone3_selftests.h | 19 ++- 5 files changed, 214 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/cgroup/Makefile b/tools/testing/selftests/cgroup/Makefile index 66aafe1f5746..967f268fde74 100644 --- a/tools/testing/selftests/cgroup/Makefile +++ b/tools/testing/selftests/cgroup/Makefile @@ -11,6 +11,6 @@ TEST_GEN_PROGS += test_freezer include ../lib.mk -$(OUTPUT)/test_memcontrol: cgroup_util.c -$(OUTPUT)/test_core: cgroup_util.c -$(OUTPUT)/test_freezer: cgroup_util.c +$(OUTPUT)/test_memcontrol: cgroup_util.c ../clone3/clone3_selftests.h +$(OUTPUT)/test_core: cgroup_util.c ../clone3/clone3_selftests.h +$(OUTPUT)/test_freezer: cgroup_util.c ../clone3/clone3_selftests.h diff --git a/tools/testing/selftests/cgroup/cgroup_util.c b/tools/testing/selftests/cgroup/cgroup_util.c index 8f7131dcf1ff..8a637ca7d73a 100644 --- a/tools/testing/selftests/cgroup/cgroup_util.c +++ b/tools/testing/selftests/cgroup/cgroup_util.c @@ -15,6 +15,7 @@ #include #include "cgroup_util.h" +#include "../clone3/clone3_selftests.h" static ssize_t read_text(const char *path, char *buf, size_t max_len) { @@ -331,12 +332,112 @@ int cg_run(const char *cgroup, } } +pid_t clone_into_cgroup(int cgroup_fd) +{ +#ifdef CLONE_ARGS_SIZE_VER2 + pid_t pid; + + struct clone_args args = { + .flags = CLONE_INTO_CGROUP, + .exit_signal = SIGCHLD, + .cgroup = cgroup_fd, + }; + + pid = sys_clone3(&args, sizeof(struct clone_args)); + /* + * Verify that this is a genuine test failure: + * ENOSYS -> clone3() not available + * E2BIG -> CLONE_INTO_CGROUP not available + */ + if (pid < 0 && (errno == ENOSYS || errno == E2BIG)) + goto pretend_enosys; + + return pid; + +pretend_enosys: +#endif + errno = ENOSYS; + return -ENOSYS; +} + +int clone_reap(pid_t pid, int options) +{ + int ret; + siginfo_t info = { + .si_signo = 0, + }; + +again: + ret = waitid(P_PID, pid, &info, options | __WALL | __WNOTHREAD); + if (ret < 0) { + if (errno == EINTR) + goto again; + return -1; + } + + if (options & WEXITED) { + if (WIFEXITED(info.si_status)) + return WEXITSTATUS(info.si_status); + } + + if (options & WSTOPPED) { + if (WIFSTOPPED(info.si_status)) + return WSTOPSIG(info.si_status); + } + + if (options & WCONTINUED) { + if (WIFCONTINUED(info.si_status)) + return 0; + } + + return -1; +} + +int dirfd_open_opath(const char *dir) +{ + return open(dir, O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW | O_PATH); +} + +#define close_prot_errno(fd) \ + if (fd >= 0) { \ + int _e_ = errno; \ + close(fd); \ + errno = _e_; \ + } + +static int clone_into_cgroup_run_nowait(const char *cgroup, + int (*fn)(const char *cgroup, void *arg), + void *arg) +{ + int cgroup_fd; + pid_t pid; + + cgroup_fd = dirfd_open_opath(cgroup); + if (cgroup_fd < 0) + return -1; + + pid = clone_into_cgroup(cgroup_fd); + close_prot_errno(cgroup_fd); + if (pid == 0) + exit(fn(cgroup, arg)); + + return pid; +} + int cg_run_nowait(const char *cgroup, int (*fn)(const char *cgroup, void *arg), void *arg) { int pid; + pid = clone_into_cgroup_run_nowait(cgroup, fn, arg); + if (pid > 0) + return pid; + + /* Genuine test failure. */ + if (pid < 0 && errno != ENOSYS) + return -1; + pid = fork(); if (pid == 0) { char buf[64]; @@ -450,3 +551,28 @@ int proc_read_strstr(int pid, bool thread, const char *item, const char *needle) return strstr(buf, needle) ? 0 : -1; } + +int clone_into_cgroup_run_wait(const char *cgroup) +{ + int cgroup_fd; + pid_t pid; + + cgroup_fd = dirfd_open_opath(cgroup); + if (cgroup_fd < 0) + return -1; + + pid = clone_into_cgroup(cgroup_fd); + close_prot_errno(cgroup_fd); + if (pid < 0) + return -1; + + if (pid == 0) + exit(EXIT_SUCCESS); + + /* + * We don't care whether this fails. We only care whether the initial + * clone succeeded. + */ + (void)clone_reap(pid, WEXITED); + return 0; +} diff --git a/tools/testing/selftests/cgroup/cgroup_util.h b/tools/testing/selftests/cgroup/cgroup_util.h index 49c54fbdb229..5a1305dd1f0b 100644 --- a/tools/testing/selftests/cgroup/cgroup_util.h +++ b/tools/testing/selftests/cgroup/cgroup_util.h @@ -50,3 +50,7 @@ extern int cg_wait_for_proc_count(const char *cgroup, int count); extern int cg_killall(const char *cgroup); extern ssize_t proc_read_text(int pid, bool thread, const char *item, char *buf, size_t size); extern int proc_read_strstr(int pid, bool thread, const char *item, const char *needle); +extern pid_t clone_into_cgroup(int cgroup_fd); +extern int clone_reap(pid_t pid, int options); +extern int clone_into_cgroup_run_wait(const char *cgroup); +extern int dirfd_open_opath(const char *dir); diff --git a/tools/testing/selftests/cgroup/test_core.c b/tools/testing/selftests/cgroup/test_core.c index 8289d3f03de4..3df648c37876 100644 --- a/tools/testing/selftests/cgroup/test_core.c +++ b/tools/testing/selftests/cgroup/test_core.c @@ -137,8 +137,11 @@ cleanup: static int test_cgcore_populated(const char *root) { int ret = KSFT_FAIL; + int err; char *cg_test_a = NULL, *cg_test_b = NULL; char *cg_test_c = NULL, *cg_test_d = NULL; + int cgroup_fd = -EBADF; + pid_t pid; cg_test_a = cg_name(root, "cg_test_a"); cg_test_b = cg_name(root, "cg_test_a/cg_test_b"); @@ -190,6 +193,52 @@ static int test_cgcore_populated(const char *root) if (cg_read_strcmp(cg_test_d, "cgroup.events", "populated 0\n")) goto cleanup; + /* Test that we can directly clone into a new cgroup. */ + cgroup_fd = dirfd_open_opath(cg_test_d); + if (cgroup_fd < 0) + goto cleanup; + + pid = clone_into_cgroup(cgroup_fd); + if (pid < 0) { + if (errno == ENOSYS) + goto cleanup_pass; + goto cleanup; + } + + if (pid == 0) { + if (raise(SIGSTOP)) + exit(EXIT_FAILURE); + exit(EXIT_SUCCESS); + } + + err = cg_read_strcmp(cg_test_d, "cgroup.events", "populated 1\n"); + + (void)clone_reap(pid, WSTOPPED); + (void)kill(pid, SIGCONT); + (void)clone_reap(pid, WEXITED); + + if (err) + goto cleanup; + + if (cg_read_strcmp(cg_test_d, "cgroup.events", "populated 0\n")) + goto cleanup; + + /* Remove cgroup. */ + if (cg_test_d) { + cg_destroy(cg_test_d); + free(cg_test_d); + cg_test_d = NULL; + } + + pid = clone_into_cgroup(cgroup_fd); + if (pid < 0) + goto cleanup_pass; + if (pid == 0) + exit(EXIT_SUCCESS); + (void)clone_reap(pid, WEXITED); + goto cleanup; + +cleanup_pass: ret = KSFT_PASS; cleanup: @@ -205,6 +254,8 @@ cleanup: free(cg_test_c); free(cg_test_b); free(cg_test_a); + if (cgroup_fd >= 0) + close(cgroup_fd); return ret; } @@ -248,6 +299,16 @@ static int test_cgcore_invalid_domain(const char *root) if (errno != EOPNOTSUPP) goto cleanup; + if (!clone_into_cgroup_run_wait(child)) + goto cleanup; + + if (errno == ENOSYS) + goto cleanup_pass; + + if (errno != EOPNOTSUPP) + goto cleanup; + +cleanup_pass: ret = KSFT_PASS; cleanup: @@ -457,6 +518,9 @@ static int test_cgcore_internal_process_constraint(const char *root) if (!cg_enter_current(parent)) goto cleanup; + if (!clone_into_cgroup_run_wait(parent)) + goto cleanup; + ret = KSFT_PASS; cleanup: diff --git a/tools/testing/selftests/clone3/clone3_selftests.h b/tools/testing/selftests/clone3/clone3_selftests.h index a3f2c8ad8bcc..91c1a78ddb39 100644 --- a/tools/testing/selftests/clone3/clone3_selftests.h +++ b/tools/testing/selftests/clone3/clone3_selftests.h @@ -5,12 +5,24 @@ #define _GNU_SOURCE #include +#include +#include #include #include -#include +#include + +#include "../kselftest.h" #define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr))) +#ifndef CLONE_INTO_CGROUP +#define CLONE_INTO_CGROUP 0x200000000ULL /* Clone into a specific cgroup given the right permissions. */ +#endif + +#ifndef CLONE_ARGS_SIZE_VER0 +#define CLONE_ARGS_SIZE_VER0 64 +#endif + #ifndef __NR_clone3 #define __NR_clone3 -1 struct clone_args { @@ -22,10 +34,13 @@ struct clone_args { __aligned_u64 stack; __aligned_u64 stack_size; __aligned_u64 tls; +#define CLONE_ARGS_SIZE_VER1 80 __aligned_u64 set_tid; __aligned_u64 set_tid_size; +#define CLONE_ARGS_SIZE_VER2 88 + __aligned_u64 cgroup; }; -#endif +#endif /* __NR_clone3 */ static pid_t sys_clone3(struct clone_args *args, size_t size) { From 04ac0ad7e8edc7f1a7b3e219db245060fcaf59a4 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 10 Feb 2020 09:31:05 +0530 Subject: [PATCH 0220/4444] dt-bindings: clk: qcom: Add support for GPU GX GDSCR In the cases where the GPU SW requires to use the GX GDSCR add support for the same. Signed-off-by: Taniya Das Link: https://lkml.kernel.org/r/1581307266-26989-1-git-send-email-tdas@codeaurora.org Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/qcom,gpucc-sc7180.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/dt-bindings/clock/qcom,gpucc-sc7180.h b/include/dt-bindings/clock/qcom,gpucc-sc7180.h index 0e4643b08b49..65e706d7d9c6 100644 --- a/include/dt-bindings/clock/qcom,gpucc-sc7180.h +++ b/include/dt-bindings/clock/qcom,gpucc-sc7180.h @@ -15,7 +15,8 @@ #define GPU_CC_CXO_CLK 6 #define GPU_CC_GMU_CLK_SRC 7 -/* CAM_CC GDSCRs */ +/* GPU_CC GDSCRs */ #define CX_GDSC 0 +#define GX_GDSC 1 #endif From 1a6151128c847c473da1c7e7022ef78d3e2d6689 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 10 Feb 2020 09:31:06 +0530 Subject: [PATCH 0221/4444] clk: qcom: gpucc: Add support for GX GDSC for SC7180 Most of the time the CPU should not be touching the GX domain on the GPU except for a very special use case when the CPU needs to force the GX headswitch off. Add the GX domain for that use case. As part of this add a dummy enable function for the GX gdsc to simulate success so that the pm_runtime reference counting is correct. This matches what was done in sdm845 in commit 85a3d920d30a ("clk: qcom: Add a dummy enable function for GX gdsc"). Signed-off-by: Taniya Das Reviewed-by: Douglas Anderson Link: https://lkml.kernel.org/r/1581307266-26989-2-git-send-email-tdas@codeaurora.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gpucc-sc7180.c | 37 +++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/clk/qcom/gpucc-sc7180.c b/drivers/clk/qcom/gpucc-sc7180.c index a96c0b945de2..7b656b6aeced 100644 --- a/drivers/clk/qcom/gpucc-sc7180.c +++ b/drivers/clk/qcom/gpucc-sc7180.c @@ -170,8 +170,45 @@ static struct gdsc cx_gdsc = { .flags = VOTABLE, }; +/* + * On SC7180 the GPU GX domain is *almost* entirely controlled by the GMU + * running in the CX domain so the CPU doesn't need to know anything about the + * GX domain EXCEPT.... + * + * Hardware constraints dictate that the GX be powered down before the CX. If + * the GMU crashes it could leave the GX on. In order to successfully bring back + * the device the CPU needs to disable the GX headswitch. There being no sane + * way to reach in and touch that register from deep inside the GPU driver we + * need to set up the infrastructure to be able to ensure that the GPU can + * ensure that the GX is off during this super special case. We do this by + * defining a GX gdsc with a dummy enable function and a "default" disable + * function. + * + * This allows us to attach with genpd_dev_pm_attach_by_name() in the GPU + * driver. During power up, nothing will happen from the CPU (and the GMU will + * power up normally but during power down this will ensure that the GX domain + * is *really* off - this gives us a semi standard way of doing what we need. + */ +static int gx_gdsc_enable(struct generic_pm_domain *domain) +{ + /* Do nothing but give genpd the impression that we were successful */ + return 0; +} + +static struct gdsc gx_gdsc = { + .gdscr = 0x100c, + .clamp_io_ctrl = 0x1508, + .pd = { + .name = "gx_gdsc", + .power_on = gx_gdsc_enable, + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = CLAMP_IO, +}; + static struct gdsc *gpu_cc_sc7180_gdscs[] = { [CX_GDSC] = &cx_gdsc, + [GX_GDSC] = &gx_gdsc, }; static struct clk_regmap *gpu_cc_sc7180_clocks[] = { From f78f29079327a2f0052096f65a06f66838e82b70 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 4 Feb 2020 22:54:21 -0800 Subject: [PATCH 0222/4444] clk: qcom: alpha-pll: Make error prints more informative I recently ran across this printk error message spewing in my logs Call set rate on the PLL with rounded rates! and I had no idea what clk that was or what rate was failing to round properly. Make the printk more informative by telling us what went wrong and also add the name of the clk that's failing to change rate. Furthermore, update the other printks in this file with the clk name each time so we know what clk we're talking about. Cc: Taniya Das Cc: Venkata Narendra Kumar Gutta Signed-off-by: Stephen Boyd Link: https://lkml.kernel.org/r/20200205065421.9426-1-swboyd@chromium.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-alpha-pll.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 7c2936da9b14..6d946770a80f 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -544,7 +544,8 @@ static int __clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate, rate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); vco = alpha_pll_find_vco(pll, rate); if (pll->vco_table && !vco) { - pr_err("alpha pll not in a valid vco range\n"); + pr_err("%s: alpha pll not in a valid vco range\n", + clk_hw_get_name(hw)); return -EINVAL; } @@ -722,7 +723,7 @@ static int alpha_pll_huayra_set_rate(struct clk_hw *hw, unsigned long rate, */ if (clk_alpha_pll_is_enabled(hw)) { if (cur_alpha != a) { - pr_err("clock needs to be gated %s\n", + pr_err("%s: clock needs to be gated\n", clk_hw_get_name(hw)); return -EBUSY; } @@ -1170,7 +1171,7 @@ static int alpha_pll_fabia_set_rate(struct clk_hw *hw, unsigned long rate, struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); u32 l, alpha_width = pll_alpha_width(pll); u64 a; - unsigned long rrate; + unsigned long rrate, max = rate + FABIA_PLL_RATE_MARGIN; rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); @@ -1178,8 +1179,9 @@ static int alpha_pll_fabia_set_rate(struct clk_hw *hw, unsigned long rate, * Due to limited number of bits for fractional rate programming, the * rounded up rate could be marginally higher than the requested rate. */ - if (rrate > (rate + FABIA_PLL_RATE_MARGIN) || rrate < rate) { - pr_err("Call set rate on the PLL with rounded rates!\n"); + if (rrate > max || rrate < rate) { + pr_err("%s: Rounded rate %lu not within range [%lu, %lu)\n", + clk_hw_get_name(hw), rrate, rate, max); return -EINVAL; } @@ -1196,6 +1198,7 @@ static int alpha_pll_fabia_prepare(struct clk_hw *hw) struct clk_hw *parent_hw; unsigned long cal_freq, rrate; u32 cal_l, val, alpha_width = pll_alpha_width(pll); + const char *name = clk_hw_get_name(hw); u64 a; int ret; @@ -1210,7 +1213,7 @@ static int alpha_pll_fabia_prepare(struct clk_hw *hw) vco = alpha_pll_find_vco(pll, clk_hw_get_rate(hw)); if (!vco) { - pr_err("alpha pll: not in a valid vco range\n"); + pr_err("%s: alpha pll not in a valid vco range\n", name); return -EINVAL; } @@ -1236,7 +1239,7 @@ static int alpha_pll_fabia_prepare(struct clk_hw *hw) /* Bringup the PLL at calibration frequency */ ret = clk_alpha_pll_enable(hw); if (ret) { - pr_err("alpha pll calibration failed\n"); + pr_err("%s: alpha pll calibration failed\n", name); return ret; } From fdd373a4e0c859c64149aaacd082b6f4e58a6489 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 24 Jan 2020 14:32:21 -0800 Subject: [PATCH 0223/4444] dt-bindings: clock: Add RPMHCC bindings for SM8250 Add bindings and update documentation for clock rpmh driver on SM8250. Acked-by: Rob Herring Reviewed-by: Vinod Koul Reviewed-by: Bjorn Andersson Signed-off-by: Taniya Das Signed-off-by: Venkata Narendra Kumar Gutta Link: https://lkml.kernel.org/r/1579905147-12142-2-git-send-email-vnkgutta@codeaurora.org Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml | 1 + include/dt-bindings/clock/qcom,rpmh.h | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml index 2cd158f13bab..2b633a4b0bc2 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml @@ -20,6 +20,7 @@ properties: - qcom,sc7180-rpmh-clk - qcom,sdm845-rpmh-clk - qcom,sm8150-rpmh-clk + - qcom,sm8250-rpmh-clk clocks: maxItems: 1 diff --git a/include/dt-bindings/clock/qcom,rpmh.h b/include/dt-bindings/clock/qcom,rpmh.h index edcab3f7b7d3..2e6c54e65455 100644 --- a/include/dt-bindings/clock/qcom,rpmh.h +++ b/include/dt-bindings/clock/qcom,rpmh.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2018, 2020, The Linux Foundation. All rights reserved. */ #ifndef _DT_BINDINGS_CLK_MSM_RPMH_H @@ -19,5 +19,7 @@ #define RPMH_RF_CLK3 10 #define RPMH_RF_CLK3_A 11 #define RPMH_IPA_CLK 12 +#define RPMH_LN_BB_CLK1 13 +#define RPMH_LN_BB_CLK1_A 14 #endif From 29093b1a5833c24c692abb1370de547d2a60e6be Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 24 Jan 2020 14:32:22 -0800 Subject: [PATCH 0224/4444] clk: qcom: rpmh: Add support for RPMH clocks on SM8250 Add support for RPMH clocks on SM8250. Reviewed-by: Vinod Koul Reviewed-by: Bjorn Andersson Signed-off-by: Taniya Das Signed-off-by: Venkata Narendra Kumar Gutta Link: https://lkml.kernel.org/r/1579905147-12142-3-git-send-email-vnkgutta@codeaurora.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-rpmh.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c index 98a118c1e244..12bd8715dece 100644 --- a/drivers/clk/qcom/clk-rpmh.c +++ b/drivers/clk/qcom/clk-rpmh.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include @@ -404,6 +404,28 @@ static const struct clk_rpmh_desc clk_rpmh_sc7180 = { .num_clks = ARRAY_SIZE(sc7180_rpmh_clocks), }; +DEFINE_CLK_RPMH_VRM(sm8250, ln_bb_clk1, ln_bb_clk1_ao, "lnbclka1", 2); + +static struct clk_hw *sm8250_rpmh_clocks[] = { + [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw, + [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw, + [RPMH_LN_BB_CLK1] = &sm8250_ln_bb_clk1.hw, + [RPMH_LN_BB_CLK1_A] = &sm8250_ln_bb_clk1_ao.hw, + [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw, + [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw, + [RPMH_LN_BB_CLK3] = &sdm845_ln_bb_clk3.hw, + [RPMH_LN_BB_CLK3_A] = &sdm845_ln_bb_clk3_ao.hw, + [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw, + [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw, + [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw, + [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw, +}; + +static const struct clk_rpmh_desc clk_rpmh_sm8250 = { + .clks = sm8250_rpmh_clocks, + .num_clks = ARRAY_SIZE(sm8250_rpmh_clocks), +}; + static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec, void *data) { @@ -490,6 +512,7 @@ static const struct of_device_id clk_rpmh_match_table[] = { { .compatible = "qcom,sc7180-rpmh-clk", .data = &clk_rpmh_sc7180}, { .compatible = "qcom,sdm845-rpmh-clk", .data = &clk_rpmh_sdm845}, { .compatible = "qcom,sm8150-rpmh-clk", .data = &clk_rpmh_sm8150}, + { .compatible = "qcom,sm8250-rpmh-clk", .data = &clk_rpmh_sm8250}, { } }; MODULE_DEVICE_TABLE(of, clk_rpmh_match_table); From f21cf9c77ee82ef8adfeb2143adfacf21ec1d5cc Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 5 Feb 2020 15:27:59 -0800 Subject: [PATCH 0225/4444] clk: Don't cache errors from clk_ops::get_phase() We don't check for errors from clk_ops::get_phase() before storing away the result into the clk_core::phase member. This can lead to some fairly confusing debugfs information if these ops do return an error. Let's skip the store when this op fails to fix this. While we're here, move the locking outside of clk_core_get_phase() to simplify callers from the debugfs side. Cc: Douglas Anderson Cc: Heiko Stuebner Cc: Jerome Brunet Signed-off-by: Stephen Boyd Link: https://lkml.kernel.org/r/20200205232802.29184-2-sboyd@kernel.org Acked-by: Jerome Brunet --- drivers/clk/clk.c | 48 +++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f0f2b599fd7e..82d96d4071b1 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2660,12 +2660,14 @@ static int clk_core_get_phase(struct clk_core *core) { int ret; - clk_prepare_lock(); + lockdep_assert_held(&prepare_lock); + if (!core->ops->get_phase) + return 0; + /* Always try to update cached phase if possible */ - if (core->ops->get_phase) - core->phase = core->ops->get_phase(core->hw); - ret = core->phase; - clk_prepare_unlock(); + ret = core->ops->get_phase(core->hw); + if (ret >= 0) + core->phase = ret; return ret; } @@ -2679,10 +2681,16 @@ static int clk_core_get_phase(struct clk_core *core) */ int clk_get_phase(struct clk *clk) { + int ret; + if (!clk) return 0; - return clk_core_get_phase(clk->core); + clk_prepare_lock(); + ret = clk_core_get_phase(clk->core); + clk_prepare_unlock(); + + return ret; } EXPORT_SYMBOL_GPL(clk_get_phase); @@ -2896,13 +2904,21 @@ static struct hlist_head *orphan_list[] = { static void clk_summary_show_one(struct seq_file *s, struct clk_core *c, int level) { - seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu %5d %6d\n", + int phase; + + seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu ", level * 3 + 1, "", 30 - level * 3, c->name, c->enable_count, c->prepare_count, c->protect_count, - clk_core_get_rate(c), clk_core_get_accuracy(c), - clk_core_get_phase(c), - clk_core_get_scaled_duty_cycle(c, 100000)); + clk_core_get_rate(c), clk_core_get_accuracy(c)); + + phase = clk_core_get_phase(c); + if (phase >= 0) + seq_printf(s, "%5d", phase); + else + seq_puts(s, "-----"); + + seq_printf(s, " %6d\n", clk_core_get_scaled_duty_cycle(c, 100000)); } static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c, @@ -2939,6 +2955,7 @@ DEFINE_SHOW_ATTRIBUTE(clk_summary); static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level) { + int phase; unsigned long min_rate, max_rate; clk_core_get_boundaries(c, &min_rate, &max_rate); @@ -2952,7 +2969,9 @@ static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level) seq_printf(s, "\"min_rate\": %lu,", min_rate); seq_printf(s, "\"max_rate\": %lu,", max_rate); seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c)); - seq_printf(s, "\"phase\": %d,", clk_core_get_phase(c)); + phase = clk_core_get_phase(c); + if (phase >= 0) + seq_printf(s, "\"phase\": %d,", phase); seq_printf(s, "\"duty_cycle\": %u", clk_core_get_scaled_duty_cycle(c, 100000)); } @@ -3434,14 +3453,11 @@ static int __clk_core_init(struct clk_core *core) core->accuracy = 0; /* - * Set clk's phase. + * Set clk's phase by clk_core_get_phase() caching the phase. * Since a phase is by definition relative to its parent, just * query the current clock phase, or just assume it's in phase. */ - if (core->ops->get_phase) - core->phase = core->ops->get_phase(core->hw); - else - core->phase = 0; + clk_core_get_phase(core); /* * Set clk's duty cycle. From 768a5d4f63c29d3bed5abb3c187312fcf623fa05 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 5 Feb 2020 15:28:00 -0800 Subject: [PATCH 0226/4444] clk: Use 'parent' to shorten lines in __clk_core_init() Some lines are getting long in this function. Let's move 'parent' up to the top of the function and use it in many places whenever there is a parent for a clk. This shortens some lines by avoiding core->parent-> indirections. Cc: Douglas Anderson Cc: Heiko Stuebner Cc: Jerome Brunet Signed-off-by: Stephen Boyd Link: https://lkml.kernel.org/r/20200205232802.29184-3-sboyd@kernel.org Acked-by: Jerome Brunet --- drivers/clk/clk.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 82d96d4071b1..3ddca6084e8e 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3342,6 +3342,7 @@ static void clk_core_reparent_orphans_nolock(void) static int __clk_core_init(struct clk_core *core) { int ret; + struct clk_core *parent; unsigned long rate; if (!core) @@ -3413,7 +3414,7 @@ static int __clk_core_init(struct clk_core *core) goto out; } - core->parent = __clk_init_parent(core); + parent = core->parent = __clk_init_parent(core); /* * Populate core->parent if parent has already been clk_core_init'd. If @@ -3425,10 +3426,9 @@ static int __clk_core_init(struct clk_core *core) * clocks and re-parent any that are children of the clock currently * being clk_init'd. */ - if (core->parent) { - hlist_add_head(&core->child_node, - &core->parent->children); - core->orphan = core->parent->orphan; + if (parent) { + hlist_add_head(&core->child_node, &parent->children); + core->orphan = parent->orphan; } else if (!core->num_parents) { hlist_add_head(&core->child_node, &clk_root_list); core->orphan = false; @@ -3446,9 +3446,9 @@ static int __clk_core_init(struct clk_core *core) */ if (core->ops->recalc_accuracy) core->accuracy = core->ops->recalc_accuracy(core->hw, - __clk_get_accuracy(core->parent)); - else if (core->parent) - core->accuracy = core->parent->accuracy; + __clk_get_accuracy(parent)); + else if (parent) + core->accuracy = parent->accuracy; else core->accuracy = 0; @@ -3472,9 +3472,9 @@ static int __clk_core_init(struct clk_core *core) */ if (core->ops->recalc_rate) rate = core->ops->recalc_rate(core->hw, - clk_core_get_rate_nolock(core->parent)); - else if (core->parent) - rate = core->parent->rate; + clk_core_get_rate_nolock(parent)); + else if (parent) + rate = parent->rate; else rate = 0; core->rate = core->req_rate = rate; From 0daa376d832f4ce585f153efee4233b52fa3fe58 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 5 Feb 2020 15:28:01 -0800 Subject: [PATCH 0227/4444] clk: Move rate and accuracy recalc to mostly consumer APIs There's some confusion about when recalc is done for the rate and accuracy clk consumer APIs in relation to the prepare lock being taken. Oddly enough, we take the lock again in debugfs APIs so that we can call the internal "clk_core" APIs to get these fields with any necessary recalculations. Instead of having this confusion, let's introduce a recalc variant of these two consumer APIs as internal helpers and call them from the consumer APIs and the debugfs code so that we don't take the lock more than once. Cc: Douglas Anderson Cc: Heiko Stuebner Cc: Jerome Brunet Signed-off-by: Stephen Boyd Link: https://lkml.kernel.org/r/20200205232802.29184-4-sboyd@kernel.org Acked-by: Jerome Brunet --- drivers/clk/clk.c | 48 +++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 3ddca6084e8e..dc8bdfbd6a0c 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -488,7 +488,7 @@ unsigned long clk_hw_get_rate(const struct clk_hw *hw) } EXPORT_SYMBOL_GPL(clk_hw_get_rate); -static unsigned long __clk_get_accuracy(struct clk_core *core) +static unsigned long clk_core_get_accuracy_no_lock(struct clk_core *core) { if (!core) return 0; @@ -1517,18 +1517,12 @@ static void __clk_recalc_accuracies(struct clk_core *core) __clk_recalc_accuracies(child); } -static long clk_core_get_accuracy(struct clk_core *core) +static long clk_core_get_accuracy_recalc(struct clk_core *core) { - unsigned long accuracy; - - clk_prepare_lock(); if (core && (core->flags & CLK_GET_ACCURACY_NOCACHE)) __clk_recalc_accuracies(core); - accuracy = __clk_get_accuracy(core); - clk_prepare_unlock(); - - return accuracy; + return clk_core_get_accuracy_no_lock(core); } /** @@ -1542,10 +1536,16 @@ static long clk_core_get_accuracy(struct clk_core *core) */ long clk_get_accuracy(struct clk *clk) { + long accuracy; + if (!clk) return 0; - return clk_core_get_accuracy(clk->core); + clk_prepare_lock(); + accuracy = clk_core_get_accuracy_recalc(clk->core); + clk_prepare_unlock(); + + return accuracy; } EXPORT_SYMBOL_GPL(clk_get_accuracy); @@ -1599,19 +1599,12 @@ static void __clk_recalc_rates(struct clk_core *core, unsigned long msg) __clk_recalc_rates(child, msg); } -static unsigned long clk_core_get_rate(struct clk_core *core) +static unsigned long clk_core_get_rate_recalc(struct clk_core *core) { - unsigned long rate; - - clk_prepare_lock(); - if (core && (core->flags & CLK_GET_RATE_NOCACHE)) __clk_recalc_rates(core, 0); - rate = clk_core_get_rate_nolock(core); - clk_prepare_unlock(); - - return rate; + return clk_core_get_rate_nolock(core); } /** @@ -1624,10 +1617,16 @@ static unsigned long clk_core_get_rate(struct clk_core *core) */ unsigned long clk_get_rate(struct clk *clk) { + unsigned long rate; + if (!clk) return 0; - return clk_core_get_rate(clk->core); + clk_prepare_lock(); + rate = clk_core_get_rate_recalc(clk->core); + clk_prepare_unlock(); + + return rate; } EXPORT_SYMBOL_GPL(clk_get_rate); @@ -2910,7 +2909,8 @@ static void clk_summary_show_one(struct seq_file *s, struct clk_core *c, level * 3 + 1, "", 30 - level * 3, c->name, c->enable_count, c->prepare_count, c->protect_count, - clk_core_get_rate(c), clk_core_get_accuracy(c)); + clk_core_get_rate_recalc(c), + clk_core_get_accuracy_recalc(c)); phase = clk_core_get_phase(c); if (phase >= 0) @@ -2965,10 +2965,10 @@ static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level) seq_printf(s, "\"enable_count\": %d,", c->enable_count); seq_printf(s, "\"prepare_count\": %d,", c->prepare_count); seq_printf(s, "\"protect_count\": %d,", c->protect_count); - seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c)); + seq_printf(s, "\"rate\": %lu,", clk_core_get_rate_recalc(c)); seq_printf(s, "\"min_rate\": %lu,", min_rate); seq_printf(s, "\"max_rate\": %lu,", max_rate); - seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c)); + seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy_recalc(c)); phase = clk_core_get_phase(c); if (phase >= 0) seq_printf(s, "\"phase\": %d,", phase); @@ -3446,7 +3446,7 @@ static int __clk_core_init(struct clk_core *core) */ if (core->ops->recalc_accuracy) core->accuracy = core->ops->recalc_accuracy(core->hw, - __clk_get_accuracy(parent)); + clk_core_get_accuracy_no_lock(parent)); else if (parent) core->accuracy = parent->accuracy; else From 2760878662a290ac57cff8a5a8d8bda8f4dddc37 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 5 Feb 2020 15:28:02 -0800 Subject: [PATCH 0228/4444] clk: Bail out when calculating phase fails during clk registration Bail out of clk registration if we fail to get the phase for a clk that has a clk_ops::get_phase() callback. Print a warning too so that driver authors can easily figure out that some clk is unable to read back phase information at boot. Cc: Douglas Anderson Cc: Heiko Stuebner Suggested-by: Jerome Brunet Signed-off-by: Stephen Boyd Link: https://lkml.kernel.org/r/20200205232802.29184-5-sboyd@kernel.org Acked-by: Jerome Brunet --- drivers/clk/clk.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index dc8bdfbd6a0c..ed1797857bae 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3457,7 +3457,12 @@ static int __clk_core_init(struct clk_core *core) * Since a phase is by definition relative to its parent, just * query the current clock phase, or just assume it's in phase. */ - clk_core_get_phase(core); + ret = clk_core_get_phase(core); + if (ret < 0) { + pr_warn("%s: Failed to get phase for clk '%s'\n", __func__, + core->name); + goto out; + } /* * Set clk's duty cycle. From 5bf7f4a249387a6062b9a14c8a77e7ba2fd6a53b Mon Sep 17 00:00:00 2001 From: Codrin Ciubotariu Date: Fri, 31 Jan 2020 13:58:16 +0200 Subject: [PATCH 0229/4444] clk: at91: sam9x60: Don't use audio PLL On sam9x60, there is not audio PLL and so I2S and classD have to use one of the best matching parents for their generated clock. Fixes: 01e2113de9a5 ("clk: at91: add sam9x60 pmc driver") Signed-off-by: Codrin Ciubotariu Link: https://lkml.kernel.org/r/20200131115816.12483-1-codrin.ciubotariu@microchip.com Signed-off-by: Stephen Boyd --- drivers/clk/at91/sam9x60.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/clk/at91/sam9x60.c b/drivers/clk/at91/sam9x60.c index 77398aefeb6d..bacb32c15b26 100644 --- a/drivers/clk/at91/sam9x60.c +++ b/drivers/clk/at91/sam9x60.c @@ -124,7 +124,6 @@ static const struct { char *n; u8 id; struct clk_range r; - bool pll; } sam9x60_gck[] = { { .n = "flex0_gclk", .id = 5, }, { .n = "flex1_gclk", .id = 6, }, @@ -144,11 +143,9 @@ static const struct { { .n = "sdmmc1_gclk", .id = 26, .r = { .min = 0, .max = 105000000 }, }, { .n = "flex11_gclk", .id = 32, }, { .n = "flex12_gclk", .id = 33, }, - { .n = "i2s_gclk", .id = 34, .r = { .min = 0, .max = 105000000 }, - .pll = true, }, + { .n = "i2s_gclk", .id = 34, .r = { .min = 0, .max = 105000000 }, }, { .n = "pit64b_gclk", .id = 37, }, - { .n = "classd_gclk", .id = 42, .r = { .min = 0, .max = 100000000 }, - .pll = true, }, + { .n = "classd_gclk", .id = 42, .r = { .min = 0, .max = 100000000 }, }, { .n = "tcb1_gclk", .id = 45, }, { .n = "dbgu_gclk", .id = 47, }, }; @@ -290,7 +287,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) sam9x60_gck[i].n, parent_names, 6, sam9x60_gck[i].id, - sam9x60_gck[i].pll, + false, &sam9x60_gck[i].r); if (IS_ERR(hw)) goto err_free; From b0ecf1c6c6e82da4847900fad0272abfd014666d Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 17 Jan 2020 13:36:46 +0200 Subject: [PATCH 0230/4444] clk: at91: usb: continue if clk_hw_round_rate() return zero clk_hw_round_rate() may call round rate function of its parents. In case of SAM9X60 two of USB parrents are PLLA and UPLL. These clocks are controlled by clk-sam9x60-pll.c driver. The round rate function for this driver is sam9x60_pll_round_rate() which call in turn sam9x60_pll_get_best_div_mul(). In case the requested rate is not in the proper range (rate < characteristics->output[0].min && rate > characteristics->output[0].max) the sam9x60_pll_round_rate() will return a negative number to its caller (called by clk_core_round_rate_nolock()). clk_hw_round_rate() will return zero in case a negative number is returned by clk_core_round_rate_nolock(). With this, the USB clock will continue its rate computation even caller of clk_hw_round_rate() returned an error. With this, the USB clock on SAM9X60 may not chose the best parent. I detected this after a suspend/resume cycle on SAM9X60. Signed-off-by: Claudiu Beznea Link: https://lkml.kernel.org/r/1579261009-4573-2-git-send-email-claudiu.beznea@microchip.com Signed-off-by: Stephen Boyd --- drivers/clk/at91/clk-usb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c index 22aede42a336..3c0bd7e51b09 100644 --- a/drivers/clk/at91/clk-usb.c +++ b/drivers/clk/at91/clk-usb.c @@ -75,6 +75,9 @@ static int at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw, tmp_parent_rate = req->rate * div; tmp_parent_rate = clk_hw_round_rate(parent, tmp_parent_rate); + if (!tmp_parent_rate) + continue; + tmp_rate = DIV_ROUND_CLOSEST(tmp_parent_rate, div); if (tmp_rate < req->rate) tmp_diff = req->rate - tmp_rate; From 43b203d32b77d1b1b2209e22837f49767020553e Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 17 Jan 2020 13:36:47 +0200 Subject: [PATCH 0231/4444] clk: at91: sam9x60: fix usb clock parents SAM9X60's USB clock has 3 parents: plla, upll and main_osc. Fixes: 01e2113de9a5 ("clk: at91: add sam9x60 pmc driver") Signed-off-by: Claudiu Beznea Link: https://lkml.kernel.org/r/1579261009-4573-3-git-send-email-claudiu.beznea@microchip.com Acked-by: Alexandre Belloni Signed-off-by: Stephen Boyd --- drivers/clk/at91/sam9x60.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/clk/at91/sam9x60.c b/drivers/clk/at91/sam9x60.c index bacb32c15b26..cc19e8fb83be 100644 --- a/drivers/clk/at91/sam9x60.c +++ b/drivers/clk/at91/sam9x60.c @@ -234,9 +234,8 @@ static void __init sam9x60_pmc_setup(struct device_node *np) parent_names[0] = "pllack"; parent_names[1] = "upllck"; - parent_names[2] = "mainck"; - parent_names[3] = "mainck"; - hw = sam9x60_clk_register_usb(regmap, "usbck", parent_names, 4); + parent_names[2] = "main_osc"; + hw = sam9x60_clk_register_usb(regmap, "usbck", parent_names, 3); if (IS_ERR(hw)) goto err_free; From d7a83d67a1694c42cc95fc0755d823f7ca3bfcfb Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 17 Jan 2020 13:36:48 +0200 Subject: [PATCH 0232/4444] clk: at91: usb: use proper usbs_mask Use usbs_mask passed as argument. The usbs_mask is different for SAM9X60. Fixes: 2423eeaead6f8 ("clk: at91: usb: Add sam9x60 support") Signed-off-by: Claudiu Beznea Link: https://lkml.kernel.org/r/1579261009-4573-4-git-send-email-claudiu.beznea@microchip.com Acked-by: Alexandre Belloni Signed-off-by: Stephen Boyd --- drivers/clk/at91/clk-usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c index 3c0bd7e51b09..c0895c993cce 100644 --- a/drivers/clk/at91/clk-usb.c +++ b/drivers/clk/at91/clk-usb.c @@ -214,7 +214,7 @@ _at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name, usb->hw.init = &init; usb->regmap = regmap; - usb->usbs_mask = SAM9X5_USBS_MASK; + usb->usbs_mask = usbs_mask; hw = &usb->hw; ret = clk_hw_register(NULL, &usb->hw); From 9962fb0d19958215b5bc6b9279f824b55aabdec2 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 17 Jan 2020 13:36:49 +0200 Subject: [PATCH 0233/4444] clk: at91: usb: introduce num_parents in driver's structure SAM9X60 USB clock may have up to 3 parents. Save the number of parents in driver's data structure and validate against it when setting parent. Signed-off-by: Claudiu Beznea Link: https://lkml.kernel.org/r/1579261009-4573-5-git-send-email-claudiu.beznea@microchip.com Acked-by: Alexandre Belloni Signed-off-by: Stephen Boyd --- drivers/clk/at91/clk-usb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c index c0895c993cce..31d5c45e30d7 100644 --- a/drivers/clk/at91/clk-usb.c +++ b/drivers/clk/at91/clk-usb.c @@ -25,6 +25,7 @@ struct at91sam9x5_clk_usb { struct clk_hw hw; struct regmap *regmap; u32 usbs_mask; + u8 num_parents; }; #define to_at91sam9x5_clk_usb(hw) \ @@ -110,7 +111,7 @@ static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index) { struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); - if (index > 1) + if (index >= usb->num_parents) return -EINVAL; regmap_update_bits(usb->regmap, AT91_PMC_USB, usb->usbs_mask, index); @@ -215,6 +216,7 @@ _at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name, usb->hw.init = &init; usb->regmap = regmap; usb->usbs_mask = usbs_mask; + usb->num_parents = num_parents; hw = &usb->hw; ret = clk_hw_register(NULL, &usb->hw); From 12dc8d3be9d86cccc35dcf32828d3a8e9d48e0d1 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 17 Jan 2020 22:05:29 +0100 Subject: [PATCH 0234/4444] clk: at91: add at91sam9g45 pmc driver Add a driver for the PMC clocks of the at91sam9g45 family. Signed-off-by: Alexandre Belloni Link: https://lkml.kernel.org/r/20200117210529.17490-1-alexandre.belloni@bootlin.com Signed-off-by: Stephen Boyd --- drivers/clk/at91/Makefile | 1 + drivers/clk/at91/at91sam9g45.c | 220 +++++++++++++++++++++++++++++++++ 2 files changed, 221 insertions(+) create mode 100644 drivers/clk/at91/at91sam9g45.c diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 3732241352ce..c02c53a0e02e 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_HAVE_AT91_GENERATED_CLK) += clk-generated.o obj-$(CONFIG_HAVE_AT91_I2S_MUX_CLK) += clk-i2s-mux.o obj-$(CONFIG_HAVE_AT91_SAM9X60_PLL) += clk-sam9x60-pll.o obj-$(CONFIG_SOC_AT91SAM9) += at91sam9260.o at91sam9rl.o at91sam9x5.o +obj-$(CONFIG_SOC_AT91SAM9) += at91sam9g45.o obj-$(CONFIG_SOC_SAM9X60) += sam9x60.o obj-$(CONFIG_SOC_SAMA5D4) += sama5d4.o obj-$(CONFIG_SOC_SAMA5D2) += sama5d2.o diff --git a/drivers/clk/at91/at91sam9g45.c b/drivers/clk/at91/at91sam9g45.c new file mode 100644 index 000000000000..38a7d2d2df0c --- /dev/null +++ b/drivers/clk/at91/at91sam9g45.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include + +#include + +#include "pmc.h" + +static const struct clk_master_characteristics mck_characteristics = { + .output = { .min = 0, .max = 133333333 }, + .divisors = { 1, 2, 4, 3 }, +}; + +static u8 plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 }; + +static u16 plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 }; + +static const struct clk_range plla_outputs[] = { + { .min = 745000000, .max = 800000000 }, + { .min = 695000000, .max = 750000000 }, + { .min = 645000000, .max = 700000000 }, + { .min = 595000000, .max = 650000000 }, + { .min = 545000000, .max = 600000000 }, + { .min = 495000000, .max = 555000000 }, + { .min = 445000000, .max = 500000000 }, + { .min = 400000000, .max = 450000000 }, +}; + +static const struct clk_pll_characteristics plla_characteristics = { + .input = { .min = 2000000, .max = 32000000 }, + .num_output = ARRAY_SIZE(plla_outputs), + .output = plla_outputs, + .icpll = plla_icpll, + .out = plla_out, +}; + +static const struct { + char *n; + char *p; + u8 id; +} at91sam9g45_systemck[] = { + { .n = "ddrck", .p = "masterck", .id = 2 }, + { .n = "uhpck", .p = "usbck", .id = 6 }, + { .n = "pck0", .p = "prog0", .id = 8 }, + { .n = "pck1", .p = "prog1", .id = 9 }, +}; + +static const struct clk_pcr_layout at91sam9g45_pcr_layout = { + .offset = 0x10c, + .cmd = BIT(12), + .pid_mask = GENMASK(5, 0), + .div_mask = GENMASK(17, 16), +}; + +struct pck { + char *n; + u8 id; +}; + +static const struct pck at91sam9g45_periphck[] = { + { .n = "pioA_clk", .id = 2, }, + { .n = "pioB_clk", .id = 3, }, + { .n = "pioC_clk", .id = 4, }, + { .n = "pioDE_clk", .id = 5, }, + { .n = "trng_clk", .id = 6, }, + { .n = "usart0_clk", .id = 7, }, + { .n = "usart1_clk", .id = 8, }, + { .n = "usart2_clk", .id = 9, }, + { .n = "usart3_clk", .id = 10, }, + { .n = "mci0_clk", .id = 11, }, + { .n = "twi0_clk", .id = 12, }, + { .n = "twi1_clk", .id = 13, }, + { .n = "spi0_clk", .id = 14, }, + { .n = "spi1_clk", .id = 15, }, + { .n = "ssc0_clk", .id = 16, }, + { .n = "ssc1_clk", .id = 17, }, + { .n = "tcb0_clk", .id = 18, }, + { .n = "pwm_clk", .id = 19, }, + { .n = "adc_clk", .id = 20, }, + { .n = "dma0_clk", .id = 21, }, + { .n = "uhphs_clk", .id = 22, }, + { .n = "lcd_clk", .id = 23, }, + { .n = "ac97_clk", .id = 24, }, + { .n = "macb0_clk", .id = 25, }, + { .n = "isi_clk", .id = 26, }, + { .n = "udphs_clk", .id = 27, }, + { .n = "aestdessha_clk", .id = 28, }, + { .n = "mci1_clk", .id = 29, }, + { .n = "vdec_clk", .id = 30, }, +}; + +static void __init at91sam9g45_pmc_setup(struct device_node *np) +{ + const char *slck_name, *mainxtal_name; + struct pmc_data *at91sam9g45_pmc; + const char *parent_names[6]; + struct regmap *regmap; + struct clk_hw *hw; + int i; + bool bypass; + + i = of_property_match_string(np, "clock-names", "slow_clk"); + if (i < 0) + return; + + slck_name = of_clk_get_parent_name(np, i); + + i = of_property_match_string(np, "clock-names", "main_xtal"); + if (i < 0) + return; + mainxtal_name = of_clk_get_parent_name(np, i); + + regmap = syscon_node_to_regmap(np); + if (IS_ERR(regmap)) + return; + + at91sam9g45_pmc = pmc_data_allocate(PMC_MAIN + 1, + nck(at91sam9g45_systemck), + nck(at91sam9g45_periphck), 0); + if (!at91sam9g45_pmc) + return; + + bypass = of_property_read_bool(np, "atmel,osc-bypass"); + + hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, + bypass); + if (IS_ERR(hw)) + goto err_free; + + hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc"); + if (IS_ERR(hw)) + goto err_free; + + at91sam9g45_pmc->chws[PMC_MAIN] = hw; + + hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0, + &at91rm9200_pll_layout, &plla_characteristics); + if (IS_ERR(hw)) + goto err_free; + + hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack"); + if (IS_ERR(hw)) + goto err_free; + + hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck"); + if (IS_ERR(hw)) + goto err_free; + + at91sam9g45_pmc->chws[PMC_UTMI] = hw; + + parent_names[0] = slck_name; + parent_names[1] = "mainck"; + parent_names[2] = "plladivck"; + parent_names[3] = "utmick"; + hw = at91_clk_register_master(regmap, "masterck", 4, parent_names, + &at91rm9200_master_layout, + &mck_characteristics); + if (IS_ERR(hw)) + goto err_free; + + at91sam9g45_pmc->chws[PMC_MCK] = hw; + + parent_names[0] = "plladivck"; + parent_names[1] = "utmick"; + hw = at91sam9x5_clk_register_usb(regmap, "usbck", parent_names, 2); + if (IS_ERR(hw)) + goto err_free; + + parent_names[0] = slck_name; + parent_names[1] = "mainck"; + parent_names[2] = "plladivck"; + parent_names[3] = "utmick"; + parent_names[4] = "masterck"; + for (i = 0; i < 2; i++) { + char name[6]; + + snprintf(name, sizeof(name), "prog%d", i); + + hw = at91_clk_register_programmable(regmap, name, + parent_names, 5, i, + &at91sam9g45_programmable_layout); + if (IS_ERR(hw)) + goto err_free; + } + + for (i = 0; i < ARRAY_SIZE(at91sam9g45_systemck); i++) { + hw = at91_clk_register_system(regmap, at91sam9g45_systemck[i].n, + at91sam9g45_systemck[i].p, + at91sam9g45_systemck[i].id); + if (IS_ERR(hw)) + goto err_free; + + at91sam9g45_pmc->shws[at91sam9g45_systemck[i].id] = hw; + } + + for (i = 0; i < ARRAY_SIZE(at91sam9g45_periphck); i++) { + hw = at91_clk_register_peripheral(regmap, + at91sam9g45_periphck[i].n, + "masterck", + at91sam9g45_periphck[i].id); + if (IS_ERR(hw)) + goto err_free; + + at91sam9g45_pmc->phws[at91sam9g45_periphck[i].id] = hw; + } + + of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9g45_pmc); + + return; + +err_free: + pmc_data_free(at91sam9g45_pmc); +} +/* + * The TCB is used as the clocksource so its clock is needed early. This means + * this can't be a platform driver. + */ +CLK_OF_DECLARE_DRIVER(at91sam9g45_pmc, "atmel,at91sam9g45-pmc", + at91sam9g45_pmc_setup); From 0969b242f7b8e5de0a1c28f81d8558fd678c066d Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 10 Jan 2020 23:30:33 +0100 Subject: [PATCH 0235/4444] clk: at91: add sama5d3 pmc driver Add a driver for the PMC clocks of the sama5d3. Signed-off-by: Alexandre Belloni Link: https://lkml.kernel.org/r/20200110223033.1261791-1-alexandre.belloni@bootlin.com Signed-off-by: Stephen Boyd --- drivers/clk/at91/Makefile | 1 + drivers/clk/at91/sama5d3.c | 240 +++++++++++++++++++++++++++++++++++++ 2 files changed, 241 insertions(+) create mode 100644 drivers/clk/at91/sama5d3.c diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index c02c53a0e02e..54a94c32d972 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -18,5 +18,6 @@ obj-$(CONFIG_HAVE_AT91_SAM9X60_PLL) += clk-sam9x60-pll.o obj-$(CONFIG_SOC_AT91SAM9) += at91sam9260.o at91sam9rl.o at91sam9x5.o obj-$(CONFIG_SOC_AT91SAM9) += at91sam9g45.o obj-$(CONFIG_SOC_SAM9X60) += sam9x60.o +obj-$(CONFIG_SOC_SAMA5D3) += sama5d3.o obj-$(CONFIG_SOC_SAMA5D4) += sama5d4.o obj-$(CONFIG_SOC_SAMA5D2) += sama5d2.o diff --git a/drivers/clk/at91/sama5d3.c b/drivers/clk/at91/sama5d3.c new file mode 100644 index 000000000000..88506f909c08 --- /dev/null +++ b/drivers/clk/at91/sama5d3.c @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include + +#include + +#include "pmc.h" + +static const struct clk_master_characteristics mck_characteristics = { + .output = { .min = 0, .max = 166000000 }, + .divisors = { 1, 2, 4, 3 }, +}; + +static u8 plla_out[] = { 0 }; + +static u16 plla_icpll[] = { 0 }; + +static const struct clk_range plla_outputs[] = { + { .min = 400000000, .max = 1000000000 }, +}; + +static const struct clk_pll_characteristics plla_characteristics = { + .input = { .min = 8000000, .max = 50000000 }, + .num_output = ARRAY_SIZE(plla_outputs), + .output = plla_outputs, + .icpll = plla_icpll, + .out = plla_out, +}; + +static const struct clk_pcr_layout sama5d3_pcr_layout = { + .offset = 0x10c, + .cmd = BIT(12), + .pid_mask = GENMASK(6, 0), + .div_mask = GENMASK(17, 16), +}; + +static const struct { + char *n; + char *p; + u8 id; +} sama5d3_systemck[] = { + { .n = "ddrck", .p = "masterck", .id = 2 }, + { .n = "lcdck", .p = "masterck", .id = 3 }, + { .n = "smdck", .p = "smdclk", .id = 4 }, + { .n = "uhpck", .p = "usbck", .id = 6 }, + { .n = "udpck", .p = "usbck", .id = 7 }, + { .n = "pck0", .p = "prog0", .id = 8 }, + { .n = "pck1", .p = "prog1", .id = 9 }, + { .n = "pck2", .p = "prog2", .id = 10 }, +}; + +static const struct { + char *n; + u8 id; + struct clk_range r; +} sama5d3_periphck[] = { + { .n = "dbgu_clk", .id = 2, }, + { .n = "hsmc_clk", .id = 5, }, + { .n = "pioA_clk", .id = 6, }, + { .n = "pioB_clk", .id = 7, }, + { .n = "pioC_clk", .id = 8, }, + { .n = "pioD_clk", .id = 9, }, + { .n = "pioE_clk", .id = 10, }, + { .n = "usart0_clk", .id = 12, .r = { .min = 0, .max = 83000000 }, }, + { .n = "usart1_clk", .id = 13, .r = { .min = 0, .max = 83000000 }, }, + { .n = "usart2_clk", .id = 14, .r = { .min = 0, .max = 83000000 }, }, + { .n = "usart3_clk", .id = 15, .r = { .min = 0, .max = 83000000 }, }, + { .n = "uart0_clk", .id = 16, .r = { .min = 0, .max = 83000000 }, }, + { .n = "uart1_clk", .id = 17, .r = { .min = 0, .max = 83000000 }, }, + { .n = "twi0_clk", .id = 18, .r = { .min = 0, .max = 41500000 }, }, + { .n = "twi1_clk", .id = 19, .r = { .min = 0, .max = 41500000 }, }, + { .n = "twi2_clk", .id = 20, .r = { .min = 0, .max = 41500000 }, }, + { .n = "mci0_clk", .id = 21, }, + { .n = "mci1_clk", .id = 22, }, + { .n = "mci2_clk", .id = 23, }, + { .n = "spi0_clk", .id = 24, .r = { .min = 0, .max = 166000000 }, }, + { .n = "spi1_clk", .id = 25, .r = { .min = 0, .max = 166000000 }, }, + { .n = "tcb0_clk", .id = 26, .r = { .min = 0, .max = 166000000 }, }, + { .n = "tcb1_clk", .id = 27, .r = { .min = 0, .max = 166000000 }, }, + { .n = "pwm_clk", .id = 28, }, + { .n = "adc_clk", .id = 29, .r = { .min = 0, .max = 83000000 }, }, + { .n = "dma0_clk", .id = 30, }, + { .n = "dma1_clk", .id = 31, }, + { .n = "uhphs_clk", .id = 32, }, + { .n = "udphs_clk", .id = 33, }, + { .n = "macb0_clk", .id = 34, }, + { .n = "macb1_clk", .id = 35, }, + { .n = "lcdc_clk", .id = 36, }, + { .n = "isi_clk", .id = 37, }, + { .n = "ssc0_clk", .id = 38, .r = { .min = 0, .max = 83000000 }, }, + { .n = "ssc1_clk", .id = 39, .r = { .min = 0, .max = 83000000 }, }, + { .n = "can0_clk", .id = 40, .r = { .min = 0, .max = 83000000 }, }, + { .n = "can1_clk", .id = 41, .r = { .min = 0, .max = 83000000 }, }, + { .n = "sha_clk", .id = 42, }, + { .n = "aes_clk", .id = 43, }, + { .n = "tdes_clk", .id = 44, }, + { .n = "trng_clk", .id = 45, }, + { .n = "fuse_clk", .id = 48, }, + { .n = "mpddr_clk", .id = 49, }, +}; + +static void __init sama5d3_pmc_setup(struct device_node *np) +{ + const char *slck_name, *mainxtal_name; + struct pmc_data *sama5d3_pmc; + const char *parent_names[5]; + struct regmap *regmap; + struct clk_hw *hw; + int i; + bool bypass; + + i = of_property_match_string(np, "clock-names", "slow_clk"); + if (i < 0) + return; + + slck_name = of_clk_get_parent_name(np, i); + + i = of_property_match_string(np, "clock-names", "main_xtal"); + if (i < 0) + return; + mainxtal_name = of_clk_get_parent_name(np, i); + + regmap = syscon_node_to_regmap(np); + if (IS_ERR(regmap)) + return; + + sama5d3_pmc = pmc_data_allocate(PMC_MAIN + 1, + nck(sama5d3_systemck), + nck(sama5d3_periphck), 0); + if (!sama5d3_pmc) + return; + + hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000, + 50000000); + if (IS_ERR(hw)) + goto err_free; + + bypass = of_property_read_bool(np, "atmel,osc-bypass"); + + hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, + bypass); + if (IS_ERR(hw)) + goto err_free; + + parent_names[0] = "main_rc_osc"; + parent_names[1] = "main_osc"; + hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2); + if (IS_ERR(hw)) + goto err_free; + + hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0, + &sama5d3_pll_layout, &plla_characteristics); + if (IS_ERR(hw)) + goto err_free; + + hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack"); + if (IS_ERR(hw)) + goto err_free; + + hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck"); + if (IS_ERR(hw)) + goto err_free; + + sama5d3_pmc->chws[PMC_UTMI] = hw; + + parent_names[0] = slck_name; + parent_names[1] = "mainck"; + parent_names[2] = "plladivck"; + parent_names[3] = "utmick"; + hw = at91_clk_register_master(regmap, "masterck", 4, parent_names, + &at91sam9x5_master_layout, + &mck_characteristics); + if (IS_ERR(hw)) + goto err_free; + + sama5d3_pmc->chws[PMC_MCK] = hw; + + parent_names[0] = "plladivck"; + parent_names[1] = "utmick"; + hw = at91sam9x5_clk_register_usb(regmap, "usbck", parent_names, 2); + if (IS_ERR(hw)) + goto err_free; + + hw = at91sam9x5_clk_register_smd(regmap, "smdclk", parent_names, 2); + if (IS_ERR(hw)) + goto err_free; + + parent_names[0] = slck_name; + parent_names[1] = "mainck"; + parent_names[2] = "plladivck"; + parent_names[3] = "utmick"; + parent_names[4] = "masterck"; + for (i = 0; i < 3; i++) { + char name[6]; + + snprintf(name, sizeof(name), "prog%d", i); + + hw = at91_clk_register_programmable(regmap, name, + parent_names, 5, i, + &at91sam9x5_programmable_layout); + if (IS_ERR(hw)) + goto err_free; + } + + for (i = 0; i < ARRAY_SIZE(sama5d3_systemck); i++) { + hw = at91_clk_register_system(regmap, sama5d3_systemck[i].n, + sama5d3_systemck[i].p, + sama5d3_systemck[i].id); + if (IS_ERR(hw)) + goto err_free; + + sama5d3_pmc->shws[sama5d3_systemck[i].id] = hw; + } + + for (i = 0; i < ARRAY_SIZE(sama5d3_periphck); i++) { + hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, + &sama5d3_pcr_layout, + sama5d3_periphck[i].n, + "masterck", + sama5d3_periphck[i].id, + &sama5d3_periphck[i].r); + if (IS_ERR(hw)) + goto err_free; + + sama5d3_pmc->phws[sama5d3_periphck[i].id] = hw; + } + + of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sama5d3_pmc); + + return; + +err_free: + pmc_data_free(sama5d3_pmc); +} +/* + * The TCB is used as the clocksource so its clock is needed early. This means + * this can't be a platform driver. + */ +CLK_OF_DECLARE_DRIVER(sama5d3_pmc, "atmel,sama5d3-pmc", sama5d3_pmc_setup); From 143e04dab6b4c73c66b1708f6bc3212b9cb71dbb Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 16 Jan 2020 18:23:16 +0100 Subject: [PATCH 0236/4444] clk: at91: add at91sam9n12 pmc driver Add a driver for the PMC clocks of the at91sam9n12 family. Signed-off-by: Alexandre Belloni Link: https://lkml.kernel.org/r/20200116172316.426703-1-alexandre.belloni@bootlin.com Signed-off-by: Stephen Boyd --- drivers/clk/at91/Makefile | 1 + drivers/clk/at91/at91sam9n12.c | 238 +++++++++++++++++++++++++++++++++ 2 files changed, 239 insertions(+) create mode 100644 drivers/clk/at91/at91sam9n12.c diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 54a94c32d972..7ab244f346c4 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_HAVE_AT91_I2S_MUX_CLK) += clk-i2s-mux.o obj-$(CONFIG_HAVE_AT91_SAM9X60_PLL) += clk-sam9x60-pll.o obj-$(CONFIG_SOC_AT91SAM9) += at91sam9260.o at91sam9rl.o at91sam9x5.o obj-$(CONFIG_SOC_AT91SAM9) += at91sam9g45.o +obj-$(CONFIG_SOC_AT91SAM9) += at91sam9n12.o at91sam9x5.o obj-$(CONFIG_SOC_SAM9X60) += sam9x60.o obj-$(CONFIG_SOC_SAMA5D3) += sama5d3.o obj-$(CONFIG_SOC_SAMA5D4) += sama5d4.o diff --git a/drivers/clk/at91/at91sam9n12.c b/drivers/clk/at91/at91sam9n12.c new file mode 100644 index 000000000000..8bb39d2ba84b --- /dev/null +++ b/drivers/clk/at91/at91sam9n12.c @@ -0,0 +1,238 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include + +#include + +#include "pmc.h" + +static const struct clk_master_characteristics mck_characteristics = { + .output = { .min = 0, .max = 133333333 }, + .divisors = { 1, 2, 4, 3 }, + .have_div3_pres = 1, +}; + +static u8 plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 }; + +static u16 plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 }; + +static const struct clk_range plla_outputs[] = { + { .min = 745000000, .max = 800000000 }, + { .min = 695000000, .max = 750000000 }, + { .min = 645000000, .max = 700000000 }, + { .min = 595000000, .max = 650000000 }, + { .min = 545000000, .max = 600000000 }, + { .min = 495000000, .max = 555000000 }, + { .min = 445000000, .max = 500000000 }, + { .min = 400000000, .max = 450000000 }, +}; + +static const struct clk_pll_characteristics plla_characteristics = { + .input = { .min = 2000000, .max = 32000000 }, + .num_output = ARRAY_SIZE(plla_outputs), + .output = plla_outputs, + .icpll = plla_icpll, + .out = plla_out, +}; + +static u8 pllb_out[] = { 0 }; + +static const struct clk_range pllb_outputs[] = { + { .min = 30000000, .max = 100000000 }, +}; + +static const struct clk_pll_characteristics pllb_characteristics = { + .input = { .min = 2000000, .max = 32000000 }, + .num_output = ARRAY_SIZE(pllb_outputs), + .output = pllb_outputs, + .out = pllb_out, +}; + +static const struct { + char *n; + char *p; + u8 id; +} at91sam9n12_systemck[] = { + { .n = "ddrck", .p = "masterck", .id = 2 }, + { .n = "lcdck", .p = "masterck", .id = 3 }, + { .n = "uhpck", .p = "usbck", .id = 6 }, + { .n = "udpck", .p = "usbck", .id = 7 }, + { .n = "pck0", .p = "prog0", .id = 8 }, + { .n = "pck1", .p = "prog1", .id = 9 }, +}; + +static const struct clk_pcr_layout at91sam9n12_pcr_layout = { + .offset = 0x10c, + .cmd = BIT(12), + .pid_mask = GENMASK(5, 0), + .div_mask = GENMASK(17, 16), +}; + +struct pck { + char *n; + u8 id; +}; + +static const struct pck at91sam9n12_periphck[] = { + { .n = "pioAB_clk", .id = 2, }, + { .n = "pioCD_clk", .id = 3, }, + { .n = "fuse_clk", .id = 4, }, + { .n = "usart0_clk", .id = 5, }, + { .n = "usart1_clk", .id = 6, }, + { .n = "usart2_clk", .id = 7, }, + { .n = "usart3_clk", .id = 8, }, + { .n = "twi0_clk", .id = 9, }, + { .n = "twi1_clk", .id = 10, }, + { .n = "mci0_clk", .id = 12, }, + { .n = "spi0_clk", .id = 13, }, + { .n = "spi1_clk", .id = 14, }, + { .n = "uart0_clk", .id = 15, }, + { .n = "uart1_clk", .id = 16, }, + { .n = "tcb_clk", .id = 17, }, + { .n = "pwm_clk", .id = 18, }, + { .n = "adc_clk", .id = 19, }, + { .n = "dma0_clk", .id = 20, }, + { .n = "uhphs_clk", .id = 22, }, + { .n = "udphs_clk", .id = 23, }, + { .n = "lcdc_clk", .id = 25, }, + { .n = "sha_clk", .id = 27, }, + { .n = "ssc0_clk", .id = 28, }, + { .n = "aes_clk", .id = 29, }, + { .n = "trng_clk", .id = 30, }, +}; + +static void __init at91sam9n12_pmc_setup(struct device_node *np) +{ + struct clk_range range = CLK_RANGE(0, 0); + const char *slck_name, *mainxtal_name; + struct pmc_data *at91sam9n12_pmc; + const char *parent_names[6]; + struct regmap *regmap; + struct clk_hw *hw; + int i; + bool bypass; + + i = of_property_match_string(np, "clock-names", "slow_clk"); + if (i < 0) + return; + + slck_name = of_clk_get_parent_name(np, i); + + i = of_property_match_string(np, "clock-names", "main_xtal"); + if (i < 0) + return; + mainxtal_name = of_clk_get_parent_name(np, i); + + regmap = syscon_node_to_regmap(np); + if (IS_ERR(regmap)) + return; + + at91sam9n12_pmc = pmc_data_allocate(PMC_MAIN + 1, + nck(at91sam9n12_systemck), 31, 0); + if (!at91sam9n12_pmc) + return; + + hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000, + 50000000); + if (IS_ERR(hw)) + goto err_free; + + bypass = of_property_read_bool(np, "atmel,osc-bypass"); + + hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, + bypass); + if (IS_ERR(hw)) + goto err_free; + + parent_names[0] = "main_rc_osc"; + parent_names[1] = "main_osc"; + hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2); + if (IS_ERR(hw)) + goto err_free; + + at91sam9n12_pmc->chws[PMC_MAIN] = hw; + + hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0, + &at91rm9200_pll_layout, &plla_characteristics); + if (IS_ERR(hw)) + goto err_free; + + hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack"); + if (IS_ERR(hw)) + goto err_free; + + hw = at91_clk_register_pll(regmap, "pllbck", "mainck", 1, + &at91rm9200_pll_layout, &pllb_characteristics); + if (IS_ERR(hw)) + goto err_free; + + parent_names[0] = slck_name; + parent_names[1] = "mainck"; + parent_names[2] = "plladivck"; + parent_names[3] = "pllbck"; + hw = at91_clk_register_master(regmap, "masterck", 4, parent_names, + &at91sam9x5_master_layout, + &mck_characteristics); + if (IS_ERR(hw)) + goto err_free; + + at91sam9n12_pmc->chws[PMC_MCK] = hw; + + hw = at91sam9n12_clk_register_usb(regmap, "usbck", "pllbck"); + if (IS_ERR(hw)) + goto err_free; + + parent_names[0] = slck_name; + parent_names[1] = "mainck"; + parent_names[2] = "plladivck"; + parent_names[3] = "pllbck"; + parent_names[4] = "masterck"; + for (i = 0; i < 2; i++) { + char name[6]; + + snprintf(name, sizeof(name), "prog%d", i); + + hw = at91_clk_register_programmable(regmap, name, + parent_names, 5, i, + &at91sam9x5_programmable_layout); + if (IS_ERR(hw)) + goto err_free; + } + + for (i = 0; i < ARRAY_SIZE(at91sam9n12_systemck); i++) { + hw = at91_clk_register_system(regmap, at91sam9n12_systemck[i].n, + at91sam9n12_systemck[i].p, + at91sam9n12_systemck[i].id); + if (IS_ERR(hw)) + goto err_free; + + at91sam9n12_pmc->shws[at91sam9n12_systemck[i].id] = hw; + } + + for (i = 0; i < ARRAY_SIZE(at91sam9n12_periphck); i++) { + hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, + &at91sam9n12_pcr_layout, + at91sam9n12_periphck[i].n, + "masterck", + at91sam9n12_periphck[i].id, + &range); + if (IS_ERR(hw)) + goto err_free; + + at91sam9n12_pmc->phws[at91sam9n12_periphck[i].id] = hw; + } + + of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9n12_pmc); + + return; + +err_free: + pmc_data_free(at91sam9n12_pmc); +} +/* + * The TCB is used as the clocksource so its clock is needed early. This means + * this can't be a platform driver. + */ +CLK_OF_DECLARE_DRIVER(at91sam9n12_pmc, "atmel,at91sam9n12-pmc", + at91sam9n12_pmc_setup); From 8d7a577d04e8ce24b1b81ee44ec8cd1dda2a9cd9 Mon Sep 17 00:00:00 2001 From: Aditya Pakki Date: Tue, 21 Jan 2020 17:33:49 -0600 Subject: [PATCH 0237/4444] clk: samsung: Remove redundant check in samsung_cmu_register_one Consistent with other instances of samsung_clk_init, the check if ctx is NULL is redundant. The function currently does not return NULL. Signed-off-by: Aditya Pakki Link: https://lkml.kernel.org/r/20200121233349.28627-1-pakki001@umn.edu Acked-by: Chanwoo Choi Signed-off-by: Stephen Boyd --- drivers/clk/samsung/clk.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index dad31308c071..1949ae7851b2 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -356,10 +356,6 @@ struct samsung_clk_provider * __init samsung_cmu_register_one( } ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids); - if (!ctx) { - panic("%s: unable to allocate ctx\n", __func__); - return ctx; - } if (cmu->pll_clks) samsung_clk_register_pll(ctx, cmu->pll_clks, cmu->nr_pll_clks, From be545c79b28917caa0cee231f376be2a2e5c9d0e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 6 Dec 2019 14:34:14 +0100 Subject: [PATCH 0238/4444] clk: Fix continuation of of_clk_detect_critical() The second line of the of_clk_detect_critical() function signature is not indented according to coding style. Signed-off-by: Geert Uytterhoeven Link: https://lkml.kernel.org/r/20191206133414.23925-1-geert+renesas@glider.be Acked-by: Lee Jones Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f0f2b599fd7e..e42145cd996a 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4865,8 +4865,8 @@ static int parent_ready(struct device_node *np) * * Return: error code or zero on success */ -int of_clk_detect_critical(struct device_node *np, - int index, unsigned long *flags) +int of_clk_detect_critical(struct device_node *np, int index, + unsigned long *flags) { struct property *prop; const __be32 *cur; From cc26ed7be46c5f5fa45f3df8161ed7ca3c4d318c Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 14 Jan 2020 10:07:25 -0600 Subject: [PATCH 0239/4444] clk: stratix10: use do_div() for 64-bit calculation do_div() macro to perform u64 division and guards against overflow if the result is too large for the unsigned long return type. Signed-off-by: Dinh Nguyen Link: https://lkml.kernel.org/r/20200114160726.19771-1-dinguyen@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/socfpga/clk-pll-s10.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c index 4705eb544f01..8d7b1d0c4664 100644 --- a/drivers/clk/socfpga/clk-pll-s10.c +++ b/drivers/clk/socfpga/clk-pll-s10.c @@ -39,7 +39,9 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk, /* read VCO1 reg for numerator and denominator */ reg = readl(socfpgaclk->hw.reg); refdiv = (reg & SOCFPGA_PLL_REFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT; - vco_freq = (unsigned long long)parent_rate / refdiv; + + vco_freq = parent_rate; + do_div(vco_freq, refdiv); /* Read mdiv and fdiv from the fdbck register */ reg = readl(socfpgaclk->hw.reg + 0x4); From 8c0e783d2c7be2bb75bf233574a3f1ad1e818cb1 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 14 Jan 2020 10:07:26 -0600 Subject: [PATCH 0240/4444] clk: socfpga: stratix10: simplify parameter passing Just pass the clock pointer structure to the various register functions. Signed-off-by: Dinh Nguyen Link: https://lkml.kernel.org/r/20200114160726.19771-2-dinguyen@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/socfpga/clk-gate-s10.c | 40 +++++++++++--------------- drivers/clk/socfpga/clk-periph-s10.c | 42 ++++++++++++++-------------- drivers/clk/socfpga/clk-pll-s10.c | 13 +++++---- drivers/clk/socfpga/clk-s10.c | 29 +++---------------- drivers/clk/socfpga/stratix10-clk.h | 25 ++++++----------- 5 files changed, 57 insertions(+), 92 deletions(-) diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c index 54a464fa63e0..8be4722f6064 100644 --- a/drivers/clk/socfpga/clk-gate-s10.c +++ b/drivers/clk/socfpga/clk-gate-s10.c @@ -65,54 +65,49 @@ static const struct clk_ops dbgclk_ops = { .get_parent = socfpga_gate_get_parent, }; -struct clk *s10_register_gate(const char *name, const char *parent_name, - const char * const *parent_names, - u8 num_parents, unsigned long flags, - void __iomem *regbase, unsigned long gate_reg, - unsigned long gate_idx, unsigned long div_reg, - unsigned long div_offset, u8 div_width, - unsigned long bypass_reg, u8 bypass_shift, - u8 fixed_div) +struct clk *s10_register_gate(const struct stratix10_gate_clock *clks, void __iomem *regbase) { struct clk *clk; struct socfpga_gate_clk *socfpga_clk; struct clk_init_data init; + const char * const *parent_names = clks->parent_names; + const char *parent_name = clks->parent_name; socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL); if (!socfpga_clk) return NULL; - socfpga_clk->hw.reg = regbase + gate_reg; - socfpga_clk->hw.bit_idx = gate_idx; + socfpga_clk->hw.reg = regbase + clks->gate_reg; + socfpga_clk->hw.bit_idx = clks->gate_idx; gateclk_ops.enable = clk_gate_ops.enable; gateclk_ops.disable = clk_gate_ops.disable; - socfpga_clk->fixed_div = fixed_div; + socfpga_clk->fixed_div = clks->fixed_div; - if (div_reg) - socfpga_clk->div_reg = regbase + div_reg; + if (clks->div_reg) + socfpga_clk->div_reg = regbase + clks->div_reg; else socfpga_clk->div_reg = NULL; - socfpga_clk->width = div_width; - socfpga_clk->shift = div_offset; + socfpga_clk->width = clks->div_width; + socfpga_clk->shift = clks->div_offset; - if (bypass_reg) - socfpga_clk->bypass_reg = regbase + bypass_reg; + if (clks->bypass_reg) + socfpga_clk->bypass_reg = regbase + clks->bypass_reg; else socfpga_clk->bypass_reg = NULL; - socfpga_clk->bypass_shift = bypass_shift; + socfpga_clk->bypass_shift = clks->bypass_shift; - if (streq(name, "cs_pdbg_clk")) + if (streq(clks->name, "cs_pdbg_clk")) init.ops = &dbgclk_ops; else init.ops = &gateclk_ops; - init.name = name; - init.flags = flags; + init.name = clks->name; + init.flags = clks->flags; - init.num_parents = num_parents; + init.num_parents = clks->num_parents; init.parent_names = parent_names ? parent_names : &parent_name; socfpga_clk->hw.hw.init = &init; @@ -121,6 +116,5 @@ struct clk *s10_register_gate(const char *name, const char *parent_name, kfree(socfpga_clk); return NULL; } - return clk; } diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c index 1a191eeeebba..dd6d4056e9de 100644 --- a/drivers/clk/socfpga/clk-periph-s10.c +++ b/drivers/clk/socfpga/clk-periph-s10.c @@ -73,26 +73,27 @@ static const struct clk_ops peri_cnt_clk_ops = { .get_parent = clk_periclk_get_parent, }; -struct clk *s10_register_periph(const char *name, const char *parent_name, - const char * const *parent_names, - u8 num_parents, unsigned long flags, - void __iomem *reg, unsigned long offset) +struct clk *s10_register_periph(const struct stratix10_perip_c_clock *clks, + void __iomem *reg) { struct clk *clk; struct socfpga_periph_clk *periph_clk; struct clk_init_data init; + const char *name = clks->name; + const char *parent_name = clks->parent_name; + const char * const *parent_names = clks->parent_names; periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL); if (WARN_ON(!periph_clk)) return NULL; - periph_clk->hw.reg = reg + offset; + periph_clk->hw.reg = reg + clks->offset; init.name = name; init.ops = &peri_c_clk_ops; - init.flags = flags; + init.flags = clks->flags; - init.num_parents = num_parents; + init.num_parents = clks->num_parents; init.parent_names = parent_names ? parent_names : &parent_name; periph_clk->hw.hw.init = &init; @@ -105,38 +106,37 @@ struct clk *s10_register_periph(const char *name, const char *parent_name, return clk; } -struct clk *s10_register_cnt_periph(const char *name, const char *parent_name, - const char * const *parent_names, - u8 num_parents, unsigned long flags, - void __iomem *regbase, unsigned long offset, - u8 fixed_divider, unsigned long bypass_reg, - unsigned long bypass_shift) +struct clk *s10_register_cnt_periph(const struct stratix10_perip_cnt_clock *clks, + void __iomem *regbase) { struct clk *clk; struct socfpga_periph_clk *periph_clk; struct clk_init_data init; + const char *name = clks->name; + const char *parent_name = clks->parent_name; + const char * const *parent_names = clks->parent_names; periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL); if (WARN_ON(!periph_clk)) return NULL; - if (offset) - periph_clk->hw.reg = regbase + offset; + if (clks->offset) + periph_clk->hw.reg = regbase + clks->offset; else periph_clk->hw.reg = NULL; - if (bypass_reg) - periph_clk->bypass_reg = regbase + bypass_reg; + if (clks->bypass_reg) + periph_clk->bypass_reg = regbase + clks->bypass_reg; else periph_clk->bypass_reg = NULL; - periph_clk->bypass_shift = bypass_shift; - periph_clk->fixed_div = fixed_divider; + periph_clk->bypass_shift = clks->bypass_shift; + periph_clk->fixed_div = clks->fixed_divider; init.name = name; init.ops = &peri_cnt_clk_ops; - init.flags = flags; + init.flags = clks->flags; - init.num_parents = num_parents; + init.num_parents = clks->num_parents; init.parent_names = parent_names ? parent_names : &parent_name; periph_clk->hw.hw.init = &init; diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c index 8d7b1d0c4664..a301bb22f36c 100644 --- a/drivers/clk/socfpga/clk-pll-s10.c +++ b/drivers/clk/socfpga/clk-pll-s10.c @@ -110,19 +110,20 @@ static struct clk_ops clk_boot_ops = { .prepare = clk_pll_prepare, }; -struct clk *s10_register_pll(const char *name, const char * const *parent_names, - u8 num_parents, unsigned long flags, - void __iomem *reg, unsigned long offset) +struct clk *s10_register_pll(const struct stratix10_pll_clock *clks, + void __iomem *reg) { struct clk *clk; struct socfpga_pll *pll_clk; struct clk_init_data init; + const char *name = clks->name; + const char * const *parent_names = clks->parent_names; pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); if (WARN_ON(!pll_clk)) return NULL; - pll_clk->hw.reg = reg + offset; + pll_clk->hw.reg = reg + clks->offset; if (streq(name, SOCFPGA_BOOT_CLK)) init.ops = &clk_boot_ops; @@ -130,9 +131,9 @@ struct clk *s10_register_pll(const char *name, const char * const *parent_names, init.ops = &clk_pll_ops; init.name = name; - init.flags = flags; + init.flags = clks->flags; - init.num_parents = num_parents; + init.num_parents = clks->num_parents; init.parent_names = parent_names; pll_clk->hw.hw.init = &init; diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c index 993f3a73c71e..dea7c6c7d269 100644 --- a/drivers/clk/socfpga/clk-s10.c +++ b/drivers/clk/socfpga/clk-s10.c @@ -177,9 +177,7 @@ static int s10_clk_register_c_perip(const struct stratix10_perip_c_clock *clks, int i; for (i = 0; i < nums; i++) { - clk = s10_register_periph(clks[i].name, clks[i].parent_name, - clks[i].parent_names, clks[i].num_parents, - clks[i].flags, base, clks[i].offset); + clk = s10_register_periph(&clks[i], base); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); @@ -198,14 +196,7 @@ static int s10_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *cl int i; for (i = 0; i < nums; i++) { - clk = s10_register_cnt_periph(clks[i].name, clks[i].parent_name, - clks[i].parent_names, - clks[i].num_parents, - clks[i].flags, base, - clks[i].offset, - clks[i].fixed_divider, - clks[i].bypass_reg, - clks[i].bypass_shift); + clk = s10_register_cnt_periph(&clks[i], base); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); @@ -225,16 +216,7 @@ static int s10_clk_register_gate(const struct stratix10_gate_clock *clks, int i; for (i = 0; i < nums; i++) { - clk = s10_register_gate(clks[i].name, clks[i].parent_name, - clks[i].parent_names, - clks[i].num_parents, - clks[i].flags, base, - clks[i].gate_reg, - clks[i].gate_idx, clks[i].div_reg, - clks[i].div_offset, clks[i].div_width, - clks[i].bypass_reg, - clks[i].bypass_shift, - clks[i].fixed_div); + clk = s10_register_gate(&clks[i], base); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); @@ -254,10 +236,7 @@ static int s10_clk_register_pll(const struct stratix10_pll_clock *clks, int i; for (i = 0; i < nums; i++) { - clk = s10_register_pll(clks[i].name, clks[i].parent_names, - clks[i].num_parents, - clks[i].flags, base, - clks[i].offset); + clk = s10_register_pll(&clks[i], base); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h index e8e121907952..fcabef42249c 100644 --- a/drivers/clk/socfpga/stratix10-clk.h +++ b/drivers/clk/socfpga/stratix10-clk.h @@ -60,21 +60,12 @@ struct stratix10_gate_clock { u8 fixed_div; }; -struct clk *s10_register_pll(const char *, const char *const *, u8, - unsigned long, void __iomem *, unsigned long); - -struct clk *s10_register_periph(const char *, const char *, - const char * const *, u8, unsigned long, - void __iomem *, unsigned long); -struct clk *s10_register_cnt_periph(const char *, const char *, - const char * const *, u8, - unsigned long, void __iomem *, - unsigned long, u8, unsigned long, - unsigned long); -struct clk *s10_register_gate(const char *, const char *, - const char * const *, u8, - unsigned long, void __iomem *, - unsigned long, unsigned long, - unsigned long, unsigned long, u8, - unsigned long, u8, u8); +struct clk *s10_register_pll(const struct stratix10_pll_clock *, + void __iomem *); +struct clk *s10_register_periph(const struct stratix10_perip_c_clock *, + void __iomem *); +struct clk *s10_register_cnt_periph(const struct stratix10_perip_cnt_clock *, + void __iomem *); +struct clk *s10_register_gate(const struct stratix10_gate_clock *, + void __iomem *); #endif /* __STRATIX10_CLK_H */ From dd03907bf129b42e9e3203fdf405ea9873b28dd3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Feb 2020 12:14:37 +0900 Subject: [PATCH 0241/4444] ASoC: soc-pcm: call snd_soc_component_open/close() once Current soc_pcm_open() calls snd_soc_component_open() under loop. Thus, it needs to care about opened/not-yet-opened Component. But, if soc-component.c is handling it, soc-pcm.c don't need to care about it. This patch adds opened flag to soc-component.h, and simplify soc-pcm.c. This is one of prepare for cleanup soc-pcm-open() Signed-off-by: Kuninori Morimoto Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/874kvzcey1.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 7 +++++-- sound/soc/soc-component.c | 35 ++++++++++++++++++++++++++++------- sound/soc/soc-pcm.c | 19 ++++++------------- 3 files changed, 39 insertions(+), 22 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 154d02fbbfed..1866ecc8e94b 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -147,8 +147,6 @@ struct snd_soc_component { unsigned int active; - unsigned int suspended:1; /* is in suspend PM state */ - struct list_head list; struct list_head card_aux_list; /* for auxiliary bound components */ struct list_head card_list; @@ -182,6 +180,11 @@ struct snd_soc_component { struct dentry *debugfs_root; const char *debugfs_prefix; #endif + + /* bit field */ + unsigned int suspended:1; /* is in suspend PM state */ + unsigned int opened:1; + unsigned int module:1; }; #define for_each_component_dais(component, dai)\ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index 14e175cdeeb8..ee00c09df5e7 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -297,34 +297,55 @@ EXPORT_SYMBOL_GPL(snd_soc_component_set_jack); int snd_soc_component_module_get(struct snd_soc_component *component, int upon_open) { + if (component->module) + return 0; + if (component->driver->module_get_upon_open == !!upon_open && !try_module_get(component->dev->driver->owner)) return -ENODEV; + component->module = 1; + return 0; } void snd_soc_component_module_put(struct snd_soc_component *component, int upon_open) { - if (component->driver->module_get_upon_open == !!upon_open) + if (component->module && + component->driver->module_get_upon_open == !!upon_open) module_put(component->dev->driver->owner); + + component->module = 0; } int snd_soc_component_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - if (component->driver->open) - return component->driver->open(component, substream); - return 0; + int ret = 0; + + if (!component->opened && + component->driver->open) + ret = component->driver->open(component, substream); + + if (ret == 0) + component->opened = 1; + + return ret; } int snd_soc_component_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - if (component->driver->close) - return component->driver->close(component, substream); - return 0; + int ret = 0; + + if (component->opened && + component->driver->close) + ret = component->driver->close(component, substream); + + component->opened = 0; + + return ret; } int snd_soc_component_prepare(struct snd_soc_component *component, diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index d53afb96b05b..ae94d8a86992 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -463,16 +463,13 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) hw->rate_max = min_not_zero(hw->rate_max, rate_max); } -static int soc_pcm_components_open(struct snd_pcm_substream *substream, - struct snd_soc_component **last) +static int soc_pcm_components_open(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_component *component; int i, ret = 0; for_each_rtd_components(rtd, i, component) { - *last = component; - ret = snd_soc_component_module_get_when_open(component); if (ret < 0) { dev_err(component->dev, @@ -489,21 +486,17 @@ static int soc_pcm_components_open(struct snd_pcm_substream *substream, return ret; } } - *last = NULL; + return 0; } -static int soc_pcm_components_close(struct snd_pcm_substream *substream, - struct snd_soc_component *last) +static int soc_pcm_components_close(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_component *component; int i, r, ret = 0; for_each_rtd_components(rtd, i, component) { - if (component == last) - break; - r = snd_soc_component_close(component, substream); if (r < 0) ret = r; /* use last ret */ @@ -545,7 +538,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) goto out; } - ret = soc_pcm_components_open(substream, &component); + ret = soc_pcm_components_open(substream); if (ret < 0) goto component_err; @@ -642,7 +635,7 @@ codec_dai_err: snd_soc_dai_shutdown(codec_dai, substream); component_err: - soc_pcm_components_close(substream, component); + soc_pcm_components_close(substream); snd_soc_dai_shutdown(cpu_dai, substream); out: @@ -696,7 +689,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) soc_rtd_shutdown(rtd, substream); - soc_pcm_components_close(substream, NULL); + soc_pcm_components_close(substream); snd_soc_dapm_stream_stop(rtd, substream->stream); From 62c86d1d5fd942c741791be94f670b99ffedfb5c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Feb 2020 12:14:41 +0900 Subject: [PATCH 0242/4444] ASoC: soc-pcm: move soc_pcm_close() next to soc_pcm_open() This patch moves soc_pcm_close() next to soc_pcm_open(). This is prepare for soc_pcm_open() cleanup. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/8736bjcexx.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 88 ++++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index ae94d8a86992..8aa775e0eb0d 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -507,6 +507,50 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream) return ret; } +/* + * Called by ALSA when a PCM substream is closed. Private data can be + * freed here. The cpu DAI, codec DAI, machine and components are also + * shutdown. + */ +static int soc_pcm_close(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_component *component; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai; + int i; + + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + + snd_soc_runtime_deactivate(rtd, substream->stream); + + snd_soc_dai_digital_mute(cpu_dai, 1, substream->stream); + + snd_soc_dai_shutdown(cpu_dai, substream); + + for_each_rtd_codec_dai(rtd, i, codec_dai) + snd_soc_dai_shutdown(codec_dai, substream); + + soc_rtd_shutdown(rtd, substream); + + soc_pcm_components_close(substream); + + snd_soc_dapm_stream_stop(rtd, substream->stream); + + mutex_unlock(&rtd->card->pcm_mutex); + + for_each_rtd_components(rtd, i, component) { + pm_runtime_mark_last_busy(component->dev); + pm_runtime_put_autosuspend(component->dev); + } + + for_each_rtd_components(rtd, i, component) + if (!component->active) + pinctrl_pm_select_sleep_state(component->dev); + + return 0; +} + /* * Called by ALSA when a PCM substream is opened, the runtime->hw record is * then initialized and any private data can be allocated. This also calls @@ -663,50 +707,6 @@ static void codec2codec_close_delayed_work(struct snd_soc_pcm_runtime *rtd) */ } -/* - * Called by ALSA when a PCM substream is closed. Private data can be - * freed here. The cpu DAI, codec DAI, machine and components are also - * shutdown. - */ -static int soc_pcm_close(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct snd_soc_dai *codec_dai; - int i; - - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); - - snd_soc_runtime_deactivate(rtd, substream->stream); - - snd_soc_dai_digital_mute(cpu_dai, 1, substream->stream); - - snd_soc_dai_shutdown(cpu_dai, substream); - - for_each_rtd_codec_dai(rtd, i, codec_dai) - snd_soc_dai_shutdown(codec_dai, substream); - - soc_rtd_shutdown(rtd, substream); - - soc_pcm_components_close(substream); - - snd_soc_dapm_stream_stop(rtd, substream->stream); - - mutex_unlock(&rtd->card->pcm_mutex); - - for_each_rtd_components(rtd, i, component) { - pm_runtime_mark_last_busy(component->dev); - pm_runtime_put_autosuspend(component->dev); - } - - for_each_rtd_components(rtd, i, component) - if (!component->active) - pinctrl_pm_select_sleep_state(component->dev); - - return 0; -} - /* * Called by ALSA when the PCM substream is prepared, can set format, sample * rate, etc. This function is non atomic and can be called multiple times, From 5d9fa03e6c3514266fa94851ab1b6dd6e0595a13 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Feb 2020 12:14:45 +0900 Subject: [PATCH 0243/4444] ASoC: soc-pcm: tidyup soc_pcm_open() order soc_pcm_open() operation order is not good. At first, soc_pcm_open() operation order is 1) CPU DAI startup 2) Component open 3) Codec DAI startup 4) rtd startup But here, 2) will call try_module_get() if component has module_get_upon_open flags. This means 1) CPU DAI startup will be operated *before* its module was loaded. DAI should be called *after* Component. Second, soc_pcm_close() operation order is 1) CPU DAI shutdown 2) Codec DAI shutdown 3) rtd shutdown 4) Component close soc_pcm_open() and soc_pcm_close() are paired function, but, its operation order is unbalance. This patch tidyup soc_pcm_open() order to Component -> rtd -> DAI. This is one of prepare for cleanup soc-pcm-open() Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/871rr3cext.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 8aa775e0eb0d..6630fadd6e09 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -574,25 +574,32 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + ret = soc_pcm_components_open(substream); + if (ret < 0) + goto component_err; + + ret = soc_rtd_startup(rtd, substream); + if (ret < 0) { + pr_err("ASoC: %s startup failed: %d\n", + rtd->dai_link->name, ret); + goto component_err; + } + /* startup the audio subsystem */ ret = snd_soc_dai_startup(cpu_dai, substream); if (ret < 0) { dev_err(cpu_dai->dev, "ASoC: can't open interface %s: %d\n", cpu_dai->name, ret); - goto out; + goto cpu_dai_err; } - ret = soc_pcm_components_open(substream); - if (ret < 0) - goto component_err; - for_each_rtd_codec_dai(rtd, i, codec_dai) { ret = snd_soc_dai_startup(codec_dai, substream); if (ret < 0) { dev_err(codec_dai->dev, "ASoC: can't open codec %s: %d\n", codec_dai->name, ret); - goto codec_dai_err; + goto config_err; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -601,13 +608,6 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) codec_dai->rx_mask = 0; } - ret = soc_rtd_startup(rtd, substream); - if (ret < 0) { - pr_err("ASoC: %s startup failed: %d\n", - rtd->dai_link->name, ret); - goto codec_dai_err; - } - /* Dynamic PCM DAI links compat checks use dynamic capabilities */ if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) goto dynamic; @@ -672,17 +672,15 @@ dynamic: return 0; config_err: - soc_rtd_shutdown(rtd, substream); - -codec_dai_err: for_each_rtd_codec_dai(rtd, i, codec_dai) snd_soc_dai_shutdown(codec_dai, substream); +cpu_dai_err: + snd_soc_dai_shutdown(cpu_dai, substream); + soc_rtd_shutdown(rtd, substream); component_err: soc_pcm_components_close(substream); - snd_soc_dai_shutdown(cpu_dai, substream); -out: mutex_unlock(&rtd->card->pcm_mutex); for_each_rtd_components(rtd, i, component) { From eadd54c75f1ef1566a6fe004787c028eb095f8b4 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Mon, 27 Jan 2020 10:18:06 +0100 Subject: [PATCH 0244/4444] dt-bindings: Convert the binding file google, cros-ec-codec.txt to yaml format. This was tested and verified with: make dt_binding_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml Signed-off-by: Dafna Hirschfeld Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20200127091806.11403-1-dafna.hirschfeld@collabora.com Signed-off-by: Mark Brown --- .../bindings/sound/google,cros-ec-codec.txt | 44 ------------- .../bindings/sound/google,cros-ec-codec.yaml | 62 +++++++++++++++++++ 2 files changed, 62 insertions(+), 44 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt create mode 100644 Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml diff --git a/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt b/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt deleted file mode 100644 index 8ca52dcc5572..000000000000 --- a/Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt +++ /dev/null @@ -1,44 +0,0 @@ -Audio codec controlled by ChromeOS EC - -Google's ChromeOS EC codec is a digital mic codec provided by the -Embedded Controller (EC) and is controlled via a host-command interface. - -An EC codec node should only be found as a sub-node of the EC node (see -Documentation/devicetree/bindings/mfd/cros-ec.txt). - -Required properties: -- compatible: Must contain "google,cros-ec-codec" -- #sound-dai-cells: Should be 1. The cell specifies number of DAIs. - -Optional properties: -- reg: Pysical base address and length of shared memory region from EC. - It contains 3 unsigned 32-bit integer. The first 2 integers - combine to become an unsigned 64-bit physical address. The last - one integer is length of the shared memory. -- memory-region: Shared memory region to EC. A "shared-dma-pool". See - ../reserved-memory/reserved-memory.txt for details. - -Example: - -{ - ... - - reserved_mem: reserved_mem { - compatible = "shared-dma-pool"; - reg = <0 0x52800000 0 0x100000>; - no-map; - }; -} - -cros-ec@0 { - compatible = "google,cros-ec-spi"; - - ... - - cros_ec_codec: ec-codec { - compatible = "google,cros-ec-codec"; - #sound-dai-cells = <1>; - reg = <0x0 0x10500000 0x80000>; - memory-region = <&reserved_mem>; - }; -}; diff --git a/Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml b/Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml new file mode 100644 index 000000000000..94a85d0cbf43 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: GPL-2.0-only +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/google,cros-ec-codec.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Audio codec controlled by ChromeOS EC + +maintainers: + - Cheng-Yi Chiang + +description: | + Google's ChromeOS EC codec is a digital mic codec provided by the + Embedded Controller (EC) and is controlled via a host-command interface. + An EC codec node should only be found as a sub-node of the EC node (see + Documentation/devicetree/bindings/mfd/cros-ec.txt). + +properties: + compatible: + const: google,cros-ec-codec + + "#sound-dai-cells": + const: 1 + + reg: + items: + - description: | + Physical base address and length of shared memory region from EC. + It contains 3 unsigned 32-bit integer. The first 2 integers + combine to become an unsigned 64-bit physical address. + The last one integer is the length of the shared memory. + + memory-region: + $ref: '/schemas/types.yaml#/definitions/phandle' + description: | + Shared memory region to EC. A "shared-dma-pool". + See ../reserved-memory/reserved-memory.txt for details. + +required: + - compatible + - '#sound-dai-cells' + +additionalProperties: false + +examples: + - | + reserved_mem: reserved_mem { + compatible = "shared-dma-pool"; + reg = <0 0x52800000 0 0x100000>; + no-map; + }; + cros-ec@0 { + compatible = "google,cros-ec-spi"; + #address-cells = <2>; + #size-cells = <1>; + cros_ec_codec: ec-codec { + compatible = "google,cros-ec-codec"; + #sound-dai-cells = <1>; + reg = <0x0 0x10500000 0x80000>; + memory-region = <&reserved_mem>; + }; + }; From ce0c97f8a2936d05951da7093b881c8eaaee72e0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 12 Feb 2020 15:56:48 +0100 Subject: [PATCH 0245/4444] ASoC: Fix SND_SOC_ALL_CODECS imply SPI fallout Fixes for CONFIG_SPI=n: WARNING: unmet direct dependencies detected for REGMAP_SPI Depends on [n]: SPI [=n] Selected by [m]: - SND_SOC_ADAU1781_SPI [=m] && SOUND [=m] && !UML && SND [=m] && SND_SOC [=m] - SND_SOC_ADAU1977_SPI [=m] && SOUND [=m] && !UML && SND [=m] && SND_SOC [=m] ERROR: "spi_async" [...] undefined! ERROR: "spi_get_device_id" [...] undefined! ERROR: "__spi_register_driver" [...] undefined! ERROR: "spi_setup" [...] undefined! ERROR: "spi_sync" [...] undefined! ERROR: "spi_write_then_read" [...] undefined! Reported-by: Randy Dunlap Fixes: ea00d95200d02ece ("ASoC: Use imply for SND_SOC_ALL_CODECS") Signed-off-by: Geert Uytterhoeven Acked-by: Randy Dunlap # build-tested Link: https://lore.kernel.org/r/20200212145650.4602-2-geert@linux-m68k.org Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 68 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 7a14b1c416b5..c2fb985de8c4 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -327,12 +327,14 @@ config SND_SOC_AC97_CODEC config SND_SOC_AD1836 tristate + depends on SPI_MASTER config SND_SOC_AD193X tristate config SND_SOC_AD193X_SPI tristate + depends on SPI_MASTER select SND_SOC_AD193X config SND_SOC_AD193X_I2C @@ -390,6 +392,7 @@ config SND_SOC_ADAU1781_I2C config SND_SOC_ADAU1781_SPI tristate + depends on SPI_MASTER select SND_SOC_ADAU1781 select REGMAP_SPI @@ -398,6 +401,7 @@ config SND_SOC_ADAU1977 config SND_SOC_ADAU1977_SPI tristate + depends on SPI_MASTER select SND_SOC_ADAU1977 select REGMAP_SPI @@ -441,6 +445,7 @@ config SND_SOC_ADAV80X config SND_SOC_ADAV801 tristate + depends on SPI_MASTER select SND_SOC_ADAV80X config SND_SOC_ADAV803 @@ -498,6 +503,7 @@ config SND_SOC_ALC5623 config SND_SOC_ALC5632 tristate + depends on I2C config SND_SOC_BD28623 tristate "ROHM BD28623 CODEC" @@ -698,6 +704,7 @@ config SND_SOC_L3 config SND_SOC_DA7210 tristate + depends on I2C config SND_SOC_DA7213 tristate "Dialog DA7213 CODEC" @@ -705,15 +712,19 @@ config SND_SOC_DA7213 config SND_SOC_DA7218 tristate + depends on I2C config SND_SOC_DA7219 tristate + depends on I2C config SND_SOC_DA732X tristate + depends on I2C config SND_SOC_DA9055 tristate + depends on I2C config SND_SOC_DMIC tristate "Generic Digital Microphone CODEC" @@ -773,9 +784,11 @@ config SND_SOC_INNO_RK3036 config SND_SOC_ISABELLE tristate + depends on I2C config SND_SOC_LM49453 tristate + depends on I2C config SND_SOC_LOCHNAGAR_SC tristate "Lochnagar Sound Card" @@ -802,17 +815,20 @@ config SND_SOC_MAX98088 depends on I2C config SND_SOC_MAX98090 - tristate + tristate + depends on I2C config SND_SOC_MAX98095 - tristate + tristate + depends on I2C config SND_SOC_MAX98357A tristate "Maxim MAX98357A CODEC" depends on GPIOLIB config SND_SOC_MAX98371 - tristate + tristate + depends on I2C config SND_SOC_MAX98504 tristate "Maxim MAX98504 speaker amplifier" @@ -823,10 +839,12 @@ config SND_SOC_MAX9867 depends on I2C config SND_SOC_MAX98925 - tristate + tristate + depends on I2C config SND_SOC_MAX98926 tristate + depends on I2C config SND_SOC_MAX98927 tristate "Maxim Integrated MAX98927 Speaker Amplifier" @@ -838,6 +856,7 @@ config SND_SOC_MAX98373 config SND_SOC_MAX9850 tristate + depends on I2C config SND_SOC_MAX9860 tristate "Maxim MAX9860 Mono Audio Voice Codec" @@ -1016,26 +1035,32 @@ config SND_SOC_RT298 config SND_SOC_RT1011 tristate + depends on I2C config SND_SOC_RT1015 tristate + depends on I2C config SND_SOC_RT1305 tristate + depends on I2C config SND_SOC_RT1308 tristate + depends on I2C config SND_SOC_RT1308_SDW tristate "Realtek RT1308 Codec - SDW" - depends on SOUNDWIRE + depends on I2C && SOUNDWIRE select REGMAP_SOUNDWIRE config SND_SOC_RT5514 tristate + depends on I2C config SND_SOC_RT5514_SPI tristate + depends on SPI_MASTER config SND_SOC_RT5514_SPI_BUILTIN bool # force RT5514_SPI to be built-in to avoid link errors @@ -1051,30 +1076,39 @@ config SND_SOC_RT5631 config SND_SOC_RT5640 tristate + depends on I2C config SND_SOC_RT5645 tristate + depends on I2C config SND_SOC_RT5651 tristate + depends on I2C config SND_SOC_RT5659 tristate + depends on I2C config SND_SOC_RT5660 tristate + depends on I2C config SND_SOC_RT5663 tristate + depends on I2C config SND_SOC_RT5665 tristate + depends on I2C config SND_SOC_RT5668 tristate + depends on I2C config SND_SOC_RT5670 tristate + depends on I2C config SND_SOC_RT5677 tristate @@ -1087,6 +1121,7 @@ config SND_SOC_RT5677_SPI config SND_SOC_RT5682 tristate + depends on I2C config SND_SOC_RT700 tristate @@ -1154,6 +1189,7 @@ config SND_SOC_SSM2305 config SND_SOC_SSM2518 tristate + depends on I2C config SND_SOC_SSM2602 tristate @@ -1185,6 +1221,7 @@ config SND_SOC_STA350 config SND_SOC_STA529 tristate + depends on I2C config SND_SOC_STAC9766 tristate @@ -1282,6 +1319,7 @@ config SND_SOC_TLV320AIC3X config SND_SOC_TLV320DAC33 tristate + depends on I2C config SND_SOC_TS3A227E tristate "TI Headset/Mic detect and keypress chip" @@ -1348,18 +1386,23 @@ config SND_SOC_WL1273 config SND_SOC_WM0010 tristate + depends on SPI_MASTER config SND_SOC_WM1250_EV1 tristate + depends on I2C config SND_SOC_WM2000 tristate + depends on I2C config SND_SOC_WM2200 tristate + depends on I2C config SND_SOC_WM5100 tristate + depends on I2C config SND_SOC_WM5102 tristate @@ -1462,9 +1505,11 @@ config SND_SOC_WM8904 config SND_SOC_WM8940 tristate + depends on I2C config SND_SOC_WM8955 tristate + depends on I2C config SND_SOC_WM8960 tristate "Wolfson Microelectronics WM8960 CODEC" @@ -1472,6 +1517,7 @@ config SND_SOC_WM8960 config SND_SOC_WM8961 tristate + depends on I2C config SND_SOC_WM8962 tristate "Wolfson Microelectronics WM8962 CODEC" @@ -1479,6 +1525,7 @@ config SND_SOC_WM8962 config SND_SOC_WM8971 tristate + depends on I2C config SND_SOC_WM8974 tristate "Wolfson Microelectronics WM8974 codec" @@ -1490,6 +1537,7 @@ config SND_SOC_WM8978 config SND_SOC_WM8983 tristate + depends on I2C config SND_SOC_WM8985 tristate "Wolfson Microelectronics WM8985 and WM8758 codec driver" @@ -1500,12 +1548,15 @@ config SND_SOC_WM8988 config SND_SOC_WM8990 tristate + depends on I2C config SND_SOC_WM8991 tristate + depends on I2C config SND_SOC_WM8993 tristate + depends on I2C config SND_SOC_WM8994 tristate @@ -1515,6 +1566,7 @@ config SND_SOC_WM8995 config SND_SOC_WM8996 tristate + depends on I2C config SND_SOC_WM8997 tristate @@ -1528,6 +1580,7 @@ config SND_SOC_WM9081 config SND_SOC_WM9090 tristate + depends on I2C config SND_SOC_WM9705 tristate @@ -1561,6 +1614,7 @@ config SND_SOC_ZX_AUD96P22 # Amp config SND_SOC_LM4857 tristate + depends on I2C config SND_SOC_MAX9759 tristate "Maxim MAX9759 speaker Amplifier" @@ -1568,15 +1622,18 @@ config SND_SOC_MAX9759 config SND_SOC_MAX9768 tristate + depends on I2C config SND_SOC_MAX9877 tristate + depends on I2C config SND_SOC_MC13783 tristate config SND_SOC_ML26124 tristate + depends on I2C config SND_SOC_MT6351 tristate "MediaTek MT6351 Codec" @@ -1614,6 +1671,7 @@ config SND_SOC_NAU8824 config SND_SOC_NAU8825 tristate + depends on I2C config SND_SOC_TPA6130A2 tristate "Texas Instruments TPA6130A2 headphone amplifier" From 1d0158f547e0dbefa9e18930e93f270ab0309707 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 12 Feb 2020 15:56:49 +0100 Subject: [PATCH 0246/4444] ASoC: Fix SND_SOC_ALL_CODECS imply I2C fallout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes for CONFIG_I2C=n: WARNING: unmet direct dependencies detected for REGMAP_I2C Depends on [n]: I2C [=n] Selected by [m]: - SND_SOC_ADAU1781_I2C [=m] && SOUND [=m] && !UML && SND [=m] && SND_SOC [=m] - SND_SOC_ADAU1977_I2C [=m] && SOUND [=m] && !UML && SND [=m] && SND_SOC [=m] - SND_SOC_RT5677 [=m] && SOUND [=m] && !UML && SND [=m] && SND_SOC [=m] sound/soc/codecs/...: error: type defaults to ‘int’ in declaration of ‘module_i2c_driver’ [-Werror=implicit-int] drivers/base/regmap/regmap-i2c.c: In function ‘regmap_smbus_byte_reg_read’: drivers/base/regmap/regmap-i2c.c:25:8: error: implicit declaration of function ‘i2c_smbus_read_byte_data’; did you mean ‘i2c_set_adapdata’? [-Werror=implicit-function-declaration] Fixes: ea00d95200d02ece ("ASoC: Use imply for SND_SOC_ALL_CODECS") Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200212145650.4602-3-geert@linux-m68k.org Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index c2fb985de8c4..3ef804d07dee 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -339,6 +339,7 @@ config SND_SOC_AD193X_SPI config SND_SOC_AD193X_I2C tristate + depends on I2C select SND_SOC_AD193X config SND_SOC_AD1980 @@ -353,6 +354,7 @@ config SND_SOC_ADAU_UTILS config SND_SOC_ADAU1373 tristate + depends on I2C select SND_SOC_ADAU_UTILS config SND_SOC_ADAU1701 @@ -387,6 +389,7 @@ config SND_SOC_ADAU1781 config SND_SOC_ADAU1781_I2C tristate + depends on I2C select SND_SOC_ADAU1781 select REGMAP_I2C @@ -407,6 +410,7 @@ config SND_SOC_ADAU1977_SPI config SND_SOC_ADAU1977_I2C tristate + depends on I2C select SND_SOC_ADAU1977 select REGMAP_I2C @@ -450,6 +454,7 @@ config SND_SOC_ADAV801 config SND_SOC_ADAV803 tristate + depends on I2C select SND_SOC_ADAV80X config SND_SOC_ADS117X @@ -471,6 +476,7 @@ config SND_SOC_AK4458 config SND_SOC_AK4535 tristate + depends on I2C config SND_SOC_AK4554 tristate "AKM AK4554 CODEC" @@ -481,6 +487,7 @@ config SND_SOC_AK4613 config SND_SOC_AK4641 tristate + depends on I2C config SND_SOC_AK4642 tristate "AKM AK4642 CODEC" @@ -488,6 +495,7 @@ config SND_SOC_AK4642 config SND_SOC_AK4671 tristate + depends on I2C config SND_SOC_AK5386 tristate "AKM AK5638 CODEC" @@ -1112,6 +1120,7 @@ config SND_SOC_RT5670 config SND_SOC_RT5677 tristate + depends on I2C select REGMAP_I2C select REGMAP_IRQ From d8dd3f92a6ba11f9046df48765e6f12ad70a3946 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 12 Feb 2020 15:56:50 +0100 Subject: [PATCH 0247/4444] ASoC: Fix SND_SOC_ALL_CODECS imply misc fallout Fixes for missing miscellaneous support: ERROR: "abx500_get_register_interruptible" [...] undefined! ERROR: "abx500_set_register_interruptible" [...] undefined! ERROR: "arizona_free_irq" [...] undefined! ERROR: "arizona_request_irq" [...] undefined! ERROR: "arizona_set_irq_wake" [...] undefined! ERROR: "mc13xxx_reg_rmw" [...] undefined! ERROR: "mc13xxx_reg_write" [...] undefined! ERROR: "snd_soc_free_ac97_component" [...] undefined! ERROR: "snd_soc_new_ac97_component" [...] undefined! Reported-by: Randy Dunlap Fixes: ea00d95200d02ece ("ASoC: Use imply for SND_SOC_ALL_CODECS") Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200212145650.4602-4-geert@linux-m68k.org Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 3ef804d07dee..d957fd6980b1 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -319,6 +319,7 @@ config SND_SOC_WM_ADSP config SND_SOC_AB8500_CODEC tristate + depends on ABX500_CORE config SND_SOC_AC97_CODEC tristate "Build generic ASoC AC97 CODEC driver" @@ -343,8 +344,9 @@ config SND_SOC_AD193X_I2C select SND_SOC_AD193X config SND_SOC_AD1980 - select REGMAP_AC97 tristate + depends on SND_SOC_AC97_BUS + select REGMAP_AC97 config SND_SOC_AD73311 tristate @@ -646,6 +648,7 @@ config SND_SOC_CS47L15 config SND_SOC_CS47L24 tristate + depends on MFD_CS47L24 config SND_SOC_CS47L35 tristate @@ -1234,6 +1237,7 @@ config SND_SOC_STA529 config SND_SOC_STAC9766 tristate + depends on SND_SOC_AC97_BUS config SND_SOC_STI_SAS tristate "codec Audio support for STI SAS codec" @@ -1415,9 +1419,11 @@ config SND_SOC_WM5100 config SND_SOC_WM5102 tristate + depends on MFD_WM5102 config SND_SOC_WM5110 tristate + depends on MFD_WM5110 config SND_SOC_WM8350 tristate @@ -1579,9 +1585,11 @@ config SND_SOC_WM8996 config SND_SOC_WM8997 tristate + depends on MFD_WM8997 config SND_SOC_WM8998 tristate + depends on MFD_WM8998 config SND_SOC_WM9081 tristate @@ -1639,6 +1647,7 @@ config SND_SOC_MAX9877 config SND_SOC_MC13783 tristate + depends on MFD_MC13XXX config SND_SOC_ML26124 tristate From 618b4d07a4420ca9f01837f183ce7b1ac0b31307 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Fri, 7 Feb 2020 15:03:56 +0800 Subject: [PATCH 0248/4444] scsi: ufs: ufs-mediatek: fix TX LCC disabling timing MediaTek UFS host requires TX LCC to be disabled on both host and device sides. This can be done by disabling host's local TX LCC before link startup. Correct TX LCC disabling timing in MediaTek UFS driver. Link: https://lore.kernel.org/r/20200207070357.17169-2-stanley.chu@mediatek.com Reviewed-by: Avri Altman Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-mediatek.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 0ce08872d671..8f73c860f423 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -313,6 +313,15 @@ static int ufs_mtk_pre_link(struct ufs_hba *hba) ufs_mtk_unipro_powerdown(hba, 0); + /* + * Setting PA_Local_TX_LCC_Enable to 0 before link startup + * to make sure that both host and device TX LCC are disabled + * once link startup is completed. + */ + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0); + if (ret) + return ret; + /* disable deep stall */ ret = ufshcd_dme_get(hba, UIC_ARG_MIB(VS_SAVEPOWERCONTROL), &tmp); if (ret) @@ -344,9 +353,6 @@ static void ufs_mtk_setup_clk_gating(struct ufs_hba *hba) static int ufs_mtk_post_link(struct ufs_hba *hba) { - /* disable device LCC */ - ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0); - /* enable unipro clock gating feature */ ufs_mtk_cfg_unipro_cg(hba, true); From 984eaac133e3d6d993ffd4de9e4bdc2c94de742b Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Fri, 7 Feb 2020 15:03:57 +0800 Subject: [PATCH 0249/4444] scsi: ufs: introduce common function to disable host TX LCC Many vendors would like to disable host TX LCC during initialization flow. Introduce a common function for all users to make drivers easier to read and maintained. This patch does not change any functionality. Link: https://lore.kernel.org/r/20200207070357.17169-3-stanley.chu@mediatek.com Reviewed-by: Can Guo Reviewed-by: Avri Altman Reviewed-by: Asutosh Das Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/cdns-pltfrm.c | 2 +- drivers/scsi/ufs/ufs-hisi.c | 2 +- drivers/scsi/ufs/ufs-mediatek.c | 2 +- drivers/scsi/ufs/ufs-qcom.c | 4 +--- drivers/scsi/ufs/ufshcd-pci.c | 2 +- drivers/scsi/ufs/ufshcd.h | 5 +++++ 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c index 56a6a1ed5ec2..da065a259f6e 100644 --- a/drivers/scsi/ufs/cdns-pltfrm.c +++ b/drivers/scsi/ufs/cdns-pltfrm.c @@ -192,7 +192,7 @@ static int cdns_ufs_link_startup_notify(struct ufs_hba *hba, * and device TX LCC are disabled once link startup is * completed. */ - ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0); + ufshcd_disable_host_tx_lcc(hba); /* * Disabling Autohibern8 feature in cadence UFS diff --git a/drivers/scsi/ufs/ufs-hisi.c b/drivers/scsi/ufs/ufs-hisi.c index 5d6487350a6c..074a6a055a4c 100644 --- a/drivers/scsi/ufs/ufs-hisi.c +++ b/drivers/scsi/ufs/ufs-hisi.c @@ -235,7 +235,7 @@ static int ufs_hisi_link_startup_pre_change(struct ufs_hba *hba) ufshcd_writel(hba, reg, REG_AUTO_HIBERNATE_IDLE_TIMER); /* Unipro PA_Local_TX_LCC_Enable */ - ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x155E, 0x0), 0x0); + ufshcd_disable_host_tx_lcc(hba); /* close Unipro VS_Mk2ExtnSupport */ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD0AB, 0x0), 0x0); ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(0xD0AB, 0x0), &value); diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 8f73c860f423..9d05962feb15 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -318,7 +318,7 @@ static int ufs_mtk_pre_link(struct ufs_hba *hba) * to make sure that both host and device TX LCC are disabled * once link startup is completed. */ - ret = ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0); + ret = ufshcd_disable_host_tx_lcc(hba); if (ret) return ret; diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index c69c29a1ceb9..c2e703d58f63 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -554,9 +554,7 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba *hba, * completed. */ if (ufshcd_get_local_unipro_ver(hba) != UFS_UNIPRO_VER_1_41) - err = ufshcd_dme_set(hba, - UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), - 0); + err = ufshcd_disable_host_tx_lcc(hba); break; case POST_CHANGE: diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c index 3b19de3ae9a3..8f78a8151499 100644 --- a/drivers/scsi/ufs/ufshcd-pci.c +++ b/drivers/scsi/ufs/ufshcd-pci.c @@ -44,7 +44,7 @@ static int ufs_intel_disable_lcc(struct ufs_hba *hba) ufshcd_dme_get(hba, attr, &lcc_enable); if (lcc_enable) - ufshcd_dme_set(hba, attr, 0); + ufshcd_disable_host_tx_lcc(hba); return 0; } diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 81c71a3e3474..8f516b205c32 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -914,6 +914,11 @@ static inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info) pwr_info->pwr_tx == FASTAUTO_MODE); } +static inline int ufshcd_disable_host_tx_lcc(struct ufs_hba *hba) +{ + return ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0); +} + /* Expose Query-Request API */ int ufshcd_query_descriptor_retry(struct ufs_hba *hba, enum query_opcode opcode, From 518b32f1ddf5830698f270272d2ca465e788a273 Mon Sep 17 00:00:00 2001 From: Can Guo Date: Tue, 11 Feb 2020 21:38:29 -0800 Subject: [PATCH 0250/4444] scsi: ufs: Select INITIAL ADAPT type for HS Gear4 ADAPT is added specifically for HS Gear4 mode only. Select INITIAL ADAPT before power mode change to G4 and select NO ADAPT before switch to non-G4 modes. [mkp: fixed typo in header file] Link: https://lore.kernel.org/r/1581485910-8307-3-git-send-email-cang@codeaurora.org Signed-off-by: Can Guo Reviewed-by: Avri Altman Reviewed-by: Asutosh Das Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-qcom.c | 14 ++++++++++++++ drivers/scsi/ufs/unipro.h | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index c2e703d58f63..78849fd097d4 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -896,6 +896,20 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba, if (!ufshcd_is_hs_mode(&hba->pwr_info) && ufshcd_is_hs_mode(dev_req_params)) ufs_qcom_dev_ref_clk_ctrl(host, true); + + if (host->hw_ver.major >= 0x4) { + if (dev_req_params->gear_tx == UFS_HS_G4) { + /* INITIAL ADAPT */ + ufshcd_dme_set(hba, + UIC_ARG_MIB(PA_TXHSADAPTTYPE), + PA_INITIAL_ADAPT); + } else { + /* NO ADAPT */ + ufshcd_dme_set(hba, + UIC_ARG_MIB(PA_TXHSADAPTTYPE), + PA_NO_ADAPT); + } + } break; case POST_CHANGE: if (ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx, diff --git a/drivers/scsi/ufs/unipro.h b/drivers/scsi/ufs/unipro.h index 3dc4d8b76509..766d551df3fc 100644 --- a/drivers/scsi/ufs/unipro.h +++ b/drivers/scsi/ufs/unipro.h @@ -146,6 +146,12 @@ #define PA_SLEEPNOCONFIGTIME 0x15A2 #define PA_STALLNOCONFIGTIME 0x15A3 #define PA_SAVECONFIGTIME 0x15A4 +#define PA_TXHSADAPTTYPE 0x15D4 + +/* Adpat type for PA_TXHSADAPTTYPE attribute */ +#define PA_REFRESH_ADAPT 0x00 +#define PA_INITIAL_ADAPT 0x01 +#define PA_NO_ADAPT 0x03 #define PA_TACTIVATE_TIME_UNIT_US 10 #define PA_HIBERN8_TIME_UNIT_US 100 @@ -203,6 +209,7 @@ enum ufs_hs_gear_tag { UFS_HS_G1, /* HS Gear 1 (default for reset) */ UFS_HS_G2, /* HS Gear 2 */ UFS_HS_G3, /* HS Gear 3 */ + UFS_HS_G4, /* HS Gear 4 */ }; enum ufs_unipro_ver { From 2824ec9f9e8116670e383a9db8df301d10507ca9 Mon Sep 17 00:00:00 2001 From: Sayali Lokhande Date: Mon, 10 Feb 2020 19:40:44 -0800 Subject: [PATCH 0251/4444] scsi: ufs: Flush exception event before suspend Exception event can be raised by the device when system suspend is in progress. This will result in unclocked register access in exception event handler as clocks will be turned off during suspend. This change makes sure to flush exception event handler work in suspend before disabling clocks to avoid unclocked register access issue. Link: https://lore.kernel.org/r/1581392451-28743-2-git-send-email-cang@codeaurora.org Reviewed-by: Bean Huo Signed-off-by: Sayali Lokhande Signed-off-by: Asutosh Das Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 214a3f373dd8..bae0a406ab7c 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -4730,8 +4730,15 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) * UFS device needs urgent BKOPs. */ if (!hba->pm_op_in_progress && - ufshcd_is_exception_event(lrbp->ucd_rsp_ptr)) - schedule_work(&hba->eeh_work); + ufshcd_is_exception_event(lrbp->ucd_rsp_ptr) && + schedule_work(&hba->eeh_work)) { + /* + * Prevent suspend once eeh_work is scheduled + * to avoid deadlock between ufshcd_suspend + * and exception event handler. + */ + pm_runtime_get_noresume(hba->dev); + } break; case UPIU_TRANSACTION_REJECT_UPIU: /* TODO: handle Reject UPIU Response */ @@ -5184,7 +5191,14 @@ static void ufshcd_exception_event_handler(struct work_struct *work) out: ufshcd_scsi_unblock_requests(hba); - pm_runtime_put_sync(hba->dev); + /* + * pm_runtime_get_noresume is called while scheduling + * eeh_work to avoid suspend racing with exception work. + * Hence decrement usage counter using pm_runtime_put_noidle + * to allow suspend on completion of exception event handler. + */ + pm_runtime_put_noidle(hba->dev); + pm_runtime_put(hba->dev); return; } @@ -7925,6 +7939,7 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) goto enable_gating; } + flush_work(&hba->eeh_work); ret = ufshcd_link_state_transition(hba, req_link_state, 1); if (ret) goto set_dev_active; From 90d88f47e8d03b263f26345639da97de00c3b783 Mon Sep 17 00:00:00 2001 From: Asutosh Das Date: Mon, 10 Feb 2020 19:40:45 -0800 Subject: [PATCH 0252/4444] scsi: ufs: set load before setting voltage in regulators This sequence change is required to avoid dips in voltage during boot-up. Apparently, this dip is caused because in the original sequence, the regulators are initialized in lpm mode. And then when the load is set to high, and more current is drawn, than is allowed in lpm, the dip is seen. Link: https://lore.kernel.org/r/1581392451-28743-3-git-send-email-cang@codeaurora.org Reviewed-by: Hongwu Su Reviewed-by: Bean Huo Reviewed-by: Stanley Chu Signed-off-by: Asutosh Das Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index bae0a406ab7c..9c39fae99b61 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -7249,6 +7249,11 @@ static int ufshcd_config_vreg(struct device *dev, name = vreg->name; if (regulator_count_voltages(reg) > 0) { + uA_load = on ? vreg->max_uA : 0; + ret = ufshcd_config_vreg_load(dev, vreg, uA_load); + if (ret) + goto out; + if (vreg->min_uV && vreg->max_uV) { min_uV = on ? vreg->min_uV : 0; ret = regulator_set_voltage(reg, min_uV, vreg->max_uV); @@ -7259,11 +7264,6 @@ static int ufshcd_config_vreg(struct device *dev, goto out; } } - - uA_load = on ? vreg->max_uA : 0; - ret = ufshcd_config_vreg_load(dev, vreg, uA_load); - if (ret) - goto out; } out: return ret; From 8240dd97cef42485b0f28553d31bc5c6a23dd0cc Mon Sep 17 00:00:00 2001 From: Can Guo Date: Mon, 10 Feb 2020 19:40:46 -0800 Subject: [PATCH 0253/4444] scsi: ufs-qcom: Adjust bus bandwidth voting and unvoting The bus bandwidth voting is required to be done before the bus clocks are enabled, and the unvoting is required to be done only after the bus clocks are disabled. Link: https://lore.kernel.org/r/1581392451-28743-4-git-send-email-cang@codeaurora.org Reviewed-by: Asutosh Das Reviewed-by: Hongwu Su Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-qcom.c | 78 +++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 78849fd097d4..2800a47d9e6d 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -38,7 +38,6 @@ enum { static struct ufs_qcom_host *ufs_qcom_hosts[MAX_UFS_QCOM_HOSTS]; -static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote); static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host); static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba, u32 clk_cycles); @@ -672,7 +671,7 @@ static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result) } } -static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote) +static int __ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote) { int err = 0; @@ -703,7 +702,7 @@ static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host) vote = ufs_qcom_get_bus_vote(host, mode); if (vote >= 0) - err = ufs_qcom_set_bus_vote(host, vote); + err = __ufs_qcom_set_bus_vote(host, vote); else err = vote; @@ -714,6 +713,35 @@ static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host) return err; } +static int ufs_qcom_set_bus_vote(struct ufs_hba *hba, bool on) +{ + struct ufs_qcom_host *host = ufshcd_get_variant(hba); + int vote, err; + + /* + * In case ufs_qcom_init() is not yet done, simply ignore. + * This ufs_qcom_set_bus_vote() shall be called from + * ufs_qcom_init() after init is done. + */ + if (!host) + return 0; + + if (on) { + vote = host->bus_vote.saved_vote; + if (vote == host->bus_vote.min_bw_vote) + ufs_qcom_update_bus_bw_vote(host); + } else { + vote = host->bus_vote.min_bw_vote; + } + + err = __ufs_qcom_set_bus_vote(host, vote); + if (err) + dev_err(hba->dev, "%s: set bus vote failed %d\n", + __func__, err); + + return err; +} + static ssize_t show_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr, char *buf) @@ -790,7 +818,7 @@ static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host) return 0; } -static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote) +static int ufs_qcom_set_bus_vote(struct ufs_hba *host, bool on) { return 0; } @@ -1042,8 +1070,7 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, enum ufs_notify_change_status status) { struct ufs_qcom_host *host = ufshcd_get_variant(hba); - int err; - int vote = 0; + int err = 0; /* * In case ufs_qcom_init() is not yet done, simply ignore. @@ -1053,28 +1080,28 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, if (!host) return 0; - if (on && (status == POST_CHANGE)) { - /* enable the device ref clock for HS mode*/ - if (ufshcd_is_hs_mode(&hba->pwr_info)) - ufs_qcom_dev_ref_clk_ctrl(host, true); - vote = host->bus_vote.saved_vote; - if (vote == host->bus_vote.min_bw_vote) - ufs_qcom_update_bus_bw_vote(host); - - } else if (!on && (status == PRE_CHANGE)) { - if (!ufs_qcom_is_link_active(hba)) { - /* disable device ref_clk */ - ufs_qcom_dev_ref_clk_ctrl(host, false); + switch (status) { + case PRE_CHANGE: + if (on) { + err = ufs_qcom_set_bus_vote(hba, true); + } else { + if (!ufs_qcom_is_link_active(hba)) { + /* disable device ref_clk */ + ufs_qcom_dev_ref_clk_ctrl(host, false); + } } - - vote = host->bus_vote.min_bw_vote; + break; + case POST_CHANGE: + if (on) { + /* enable the device ref clock for HS mode*/ + if (ufshcd_is_hs_mode(&hba->pwr_info)) + ufs_qcom_dev_ref_clk_ctrl(host, true); + } else { + err = ufs_qcom_set_bus_vote(hba, false); + } + break; } - err = ufs_qcom_set_bus_vote(host, vote); - if (err) - dev_err(hba->dev, "%s: set bus vote failed %d\n", - __func__, err); - return err; } @@ -1250,6 +1277,7 @@ static int ufs_qcom_init(struct ufs_hba *hba) ufs_qcom_set_caps(hba); ufs_qcom_advertise_quirks(hba); + ufs_qcom_set_bus_vote(hba, true); ufs_qcom_setup_clocks(hba, true, POST_CHANGE); if (hba->dev->id < MAX_UFS_QCOM_HOSTS) From 38f3242e9e2022a7613dd4c108f2b7d55a9bb00a Mon Sep 17 00:00:00 2001 From: Can Guo Date: Mon, 10 Feb 2020 19:40:47 -0800 Subject: [PATCH 0254/4444] scsi: ufs: Remove the check before call setup clock notify vops The functionality of vendor specific ops should be handled properly in platform specific driver, but should not count on the UFS driver. Link: https://lore.kernel.org/r/1581392451-28743-5-git-send-email-cang@codeaurora.org Reviewed-by: Bean Huo Reviewed-by: Stanley Chu Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 9c39fae99b61..661ba376b4da 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -7403,16 +7403,9 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, if (list_empty(head)) goto out; - /* - * vendor specific setup_clocks ops may depend on clocks managed by - * this standard driver hence call the vendor specific setup_clocks - * before disabling the clocks managed here. - */ - if (!on) { - ret = ufshcd_vops_setup_clocks(hba, on, PRE_CHANGE); - if (ret) - return ret; - } + ret = ufshcd_vops_setup_clocks(hba, on, PRE_CHANGE); + if (ret) + return ret; list_for_each_entry(clki, head, list) { if (!IS_ERR_OR_NULL(clki->clk)) { @@ -7436,16 +7429,9 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, } } - /* - * vendor specific setup_clocks ops may depend on clocks managed by - * this standard driver hence call the vendor specific setup_clocks - * after enabling the clocks managed here. - */ - if (on) { - ret = ufshcd_vops_setup_clocks(hba, on, POST_CHANGE); - if (ret) - return ret; - } + ret = ufshcd_vops_setup_clocks(hba, on, POST_CHANGE); + if (ret) + return ret; out: if (ret) { From c63d6099a7959ecc919b2549dc6b71f53521f819 Mon Sep 17 00:00:00 2001 From: Can Guo Date: Mon, 10 Feb 2020 19:40:48 -0800 Subject: [PATCH 0255/4444] scsi: ufs: Fix ufshcd_hold() caused scheduling while atomic The async version of ufshcd_hold(async == true), which is only called in queuecommand path as for now, is expected to work in atomic context, thus it should not sleep or schedule out. When it runs into the condition that clocks are ON but link is still in hibern8 state, it should bail out without flushing the clock ungate work. Fixes: f2a785ac2312 ("scsi: ufshcd: Fix race between clk scaling and ungate work") Link: https://lore.kernel.org/r/1581392451-28743-6-git-send-email-cang@codeaurora.org Reviewed-by: Hongwu Su Reviewed-by: Asutosh Das Reviewed-by: Bean Huo Reviewed-by: Stanley Chu Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 661ba376b4da..19270748ecd4 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1518,6 +1518,11 @@ start: */ if (ufshcd_can_hibern8_during_gating(hba) && ufshcd_is_link_hibern8(hba)) { + if (async) { + rc = -EAGAIN; + hba->clk_gating.active_reqs--; + break; + } spin_unlock_irqrestore(hba->host->host_lock, flags); flush_work(&hba->clk_gating.ungate_work); spin_lock_irqsave(hba->host->host_lock, flags); From 09f17791e640dcb8b29cc0b3279e73f48985c2be Mon Sep 17 00:00:00 2001 From: Can Guo Date: Mon, 10 Feb 2020 19:40:49 -0800 Subject: [PATCH 0256/4444] scsi: ufs: Add dev ref clock gating wait time support In UFS version 3.0, a newly added attribute bRefClkGatingWaitTime defines the minimum time for which the reference clock is required by device during transition to LS-MODE or HIBERN8 state. Make this change to reflect the new requirement by adding delays before turning off the clock. Link: https://lore.kernel.org/r/1581392451-28743-7-git-send-email-cang@codeaurora.org Reviewed-by: Asutosh Das Reviewed-by: Bean Huo Reviewed-by: Stanley Chu Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs.h | 3 +++ drivers/scsi/ufs/ufshcd.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index cfe380348bf0..990cb48e2403 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -167,6 +167,7 @@ enum attr_idn { QUERY_ATTR_IDN_FFU_STATUS = 0x14, QUERY_ATTR_IDN_PSA_STATE = 0x15, QUERY_ATTR_IDN_PSA_DATA_SIZE = 0x16, + QUERY_ATTR_IDN_REF_CLK_GATING_WAIT_TIME = 0x17, }; /* Descriptor idn for Query requests */ @@ -534,6 +535,8 @@ struct ufs_dev_info { u16 wmanufacturerid; /*UFS device Product Name */ u8 *model; + u16 wspecversion; + u32 clk_gating_wait_us; }; /** diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 19270748ecd4..f4aa10fdbb0c 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -91,6 +91,9 @@ /* default delay of autosuspend: 2000 ms */ #define RPM_AUTOSUSPEND_DELAY_MS 2000 +/* Default value of wait time before gating device ref clock */ +#define UFSHCD_REF_CLK_GATING_WAIT_US 0xFF /* microsecs */ + #define ufshcd_toggle_vreg(_dev, _vreg, _on) \ ({ \ int _ret; \ @@ -3281,6 +3284,31 @@ static inline int ufshcd_read_unit_desc_param(struct ufs_hba *hba, param_offset, param_read_buf, param_size); } +static int ufshcd_get_ref_clk_gating_wait(struct ufs_hba *hba) +{ + int err = 0; + u32 gating_wait = UFSHCD_REF_CLK_GATING_WAIT_US; + + if (hba->dev_info.wspecversion >= 0x300) { + err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, + QUERY_ATTR_IDN_REF_CLK_GATING_WAIT_TIME, 0, 0, + &gating_wait); + if (err) + dev_err(hba->dev, "Failed reading bRefClkGatingWait. err = %d, use default %uus\n", + err, gating_wait); + + if (gating_wait == 0) { + gating_wait = UFSHCD_REF_CLK_GATING_WAIT_US; + dev_err(hba->dev, "Undefined ref clk gating wait time, use default %uus\n", + gating_wait); + } + + hba->dev_info.clk_gating_wait_us = gating_wait; + } + + return err; +} + /** * ufshcd_memory_alloc - allocate memory for host memory space data structures * @hba: per adapter instance @@ -6627,6 +6655,10 @@ static int ufs_get_device_desc(struct ufs_hba *hba) dev_info->wmanufacturerid = desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8 | desc_buf[DEVICE_DESC_PARAM_MANF_ID + 1]; + /* getting Specification Version in big endian format */ + dev_info->wspecversion = desc_buf[DEVICE_DESC_PARAM_SPEC_VER] << 8 | + desc_buf[DEVICE_DESC_PARAM_SPEC_VER + 1]; + model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME]; err = ufshcd_read_string_desc(hba, model_index, &dev_info->model, SD_ASCII_STD); @@ -7004,6 +7036,8 @@ static int ufshcd_device_params_init(struct ufs_hba *hba) goto out; } + ufshcd_get_ref_clk_gating_wait(hba); + ufs_fixup_device_setup(hba); if (!ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG, From 1cbadd0c331fb151fafc698bf2ecc35122953715 Mon Sep 17 00:00:00 2001 From: Can Guo Date: Mon, 10 Feb 2020 19:40:50 -0800 Subject: [PATCH 0257/4444] scsi: ufs-qcom: Delay specific time before gate ref clk After enter hibern8, as UFS JEDEC ver 3.0 requires, a specific gating wait time is required before disable the device reference clock. If it is not specified, use the old delay. Link: https://lore.kernel.org/r/1581392451-28743-8-git-send-email-cang@codeaurora.org Reviewed-by: Asutosh Das Reviewed-by: Hongwu Su Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-qcom.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 2800a47d9e6d..8339050f0af2 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -843,11 +843,27 @@ static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable) /* * If we are here to disable this clock it might be immediately * after entering into hibern8 in which case we need to make - * sure that device ref_clk is active at least 1us after the + * sure that device ref_clk is active for specific time after * hibern8 enter. */ - if (!enable) - udelay(1); + if (!enable) { + unsigned long gating_wait; + + gating_wait = host->hba->dev_info.clk_gating_wait_us; + if (!gating_wait) { + udelay(1); + } else { + /* + * bRefClkGatingWaitTime defines the minimum + * time for which the reference clock is + * required by device during transition from + * HS-MODE to LS-MODE or HIBERN8 state. Give it + * more delay to be on the safe side. + */ + gating_wait += 10; + usleep_range(gating_wait, gating_wait + 10); + } + } writel_relaxed(temp, host->dev_ref_clk_ctrl_mmio); From 21437391a5f923bf3d3e09bc9cbde49b47bc4eaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Vok=C3=A1=C4=8D?= Date: Wed, 15 Jan 2020 16:17:28 +0100 Subject: [PATCH 0258/4444] ARM: dts: imx6dl-yapp4: Specify USB overcurrent protection polarity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After reset the oc protection polarity is set to active high on imx6. If the polarity is not specified in device tree it is not changed. The imx6dl-yapp4 platform uses an active-low oc signal so explicitly configure that in the device tree. Signed-off-by: Michal Vokáč Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6dl-yapp4-common.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi b/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi index 80ed5f16a76e..2b9423d55c37 100644 --- a/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi +++ b/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi @@ -562,6 +562,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usbh1>; vbus-supply = <®_usb_h1_vbus>; + over-current-active-low; status = "disabled"; }; @@ -569,6 +570,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usbotg>; vbus-supply = <®_usb_otg_vbus>; + over-current-active-low; srp-disable; hnp-disable; adp-disable; From b8fa484376901b812a21549962ffed075b77befd Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 14 Jan 2020 09:26:05 +0800 Subject: [PATCH 0259/4444] dt-bindings: clock: Convert i.MX8MQ to json-schema Convert the i.MX8MQ clock binding to DT schema format using json-schema Signed-off-by: Anson Huang Reviewed-by: Rob Herring Signed-off-by: Shawn Guo --- .../bindings/clock/imx8mq-clock.txt | 20 ------ .../bindings/clock/imx8mq-clock.yaml | 72 +++++++++++++++++++ 2 files changed, 72 insertions(+), 20 deletions(-) delete mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.txt create mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.yaml diff --git a/Documentation/devicetree/bindings/clock/imx8mq-clock.txt b/Documentation/devicetree/bindings/clock/imx8mq-clock.txt deleted file mode 100644 index 52de8263e012..000000000000 --- a/Documentation/devicetree/bindings/clock/imx8mq-clock.txt +++ /dev/null @@ -1,20 +0,0 @@ -* Clock bindings for NXP i.MX8M Quad - -Required properties: -- compatible: Should be "fsl,imx8mq-ccm" -- reg: Address and length of the register set -- #clock-cells: Should be <1> -- clocks: list of clock specifiers, must contain an entry for each required - entry in clock-names -- clock-names: should include the following entries: - - "ckil" - - "osc_25m" - - "osc_27m" - - "clk_ext1" - - "clk_ext2" - - "clk_ext3" - - "clk_ext4" - -The clock consumer should specify the desired clock by having the clock -ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx8mq-clock.h -for the full list of i.MX8M Quad clock IDs. diff --git a/Documentation/devicetree/bindings/clock/imx8mq-clock.yaml b/Documentation/devicetree/bindings/clock/imx8mq-clock.yaml new file mode 100644 index 000000000000..77790f0fdcd3 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/imx8mq-clock.yaml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bindings/clock/imx8mq-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP i.MX8M Quad Clock Control Module Binding + +maintainers: + - Anson Huang + +description: | + NXP i.MX8M Quad clock control module is an integrated clock controller, which + generates and supplies to all modules. + +properties: + compatible: + const: fsl,imx8mq-ccm + + reg: + maxItems: 1 + + clocks: + items: + - description: 32k osc + - description: 25m osc + - description: 27m osc + - description: ext1 clock input + - description: ext2 clock input + - description: ext3 clock input + - description: ext4 clock input + + clock-names: + items: + - const: ckil + - const: osc_25m + - const: osc_27m + - const: clk_ext1 + - const: clk_ext2 + - const: clk_ext3 + - const: clk_ext4 + + '#clock-cells': + const: 1 + description: + The clock consumer should specify the desired clock by having the clock + ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx8mq-clock.h + for the full list of i.MX8M Quad clock IDs. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + +examples: + # Clock Control Module node: + - | + clk: clock-controller@30380000 { + compatible = "fsl,imx8mq-ccm"; + reg = <0x30380000 0x10000>; + #clock-cells = <1>; + clocks = <&ckil>, <&osc_25m>, <&osc_27m>, + <&clk_ext1>, <&clk_ext2>, + <&clk_ext3>, <&clk_ext4>; + clock-names = "ckil", "osc_25m", "osc_27m", + "clk_ext1", "clk_ext2", + "clk_ext3", "clk_ext4"; + }; + +... From 16d848e11836a17702534b65007176d12246d0b3 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 14 Jan 2020 09:26:06 +0800 Subject: [PATCH 0260/4444] dt-bindings: clock: Convert i.MX8MM to json-schema Convert the i.MX8MM clock binding to DT schema format using json-schema Signed-off-by: Anson Huang Reviewed-by: Rob Herring Signed-off-by: Shawn Guo --- .../bindings/clock/imx8mm-clock.txt | 29 -------- .../bindings/clock/imx8mm-clock.yaml | 68 +++++++++++++++++++ 2 files changed, 68 insertions(+), 29 deletions(-) delete mode 100644 Documentation/devicetree/bindings/clock/imx8mm-clock.txt create mode 100644 Documentation/devicetree/bindings/clock/imx8mm-clock.yaml diff --git a/Documentation/devicetree/bindings/clock/imx8mm-clock.txt b/Documentation/devicetree/bindings/clock/imx8mm-clock.txt deleted file mode 100644 index 8e4ab9e619a1..000000000000 --- a/Documentation/devicetree/bindings/clock/imx8mm-clock.txt +++ /dev/null @@ -1,29 +0,0 @@ -* Clock bindings for NXP i.MX8M Mini - -Required properties: -- compatible: Should be "fsl,imx8mm-ccm" -- reg: Address and length of the register set -- #clock-cells: Should be <1> -- clocks: list of clock specifiers, must contain an entry for each required - entry in clock-names -- clock-names: should include the following entries: - - "osc_32k" - - "osc_24m" - - "clk_ext1" - - "clk_ext2" - - "clk_ext3" - - "clk_ext4" - -clk: clock-controller@30380000 { - compatible = "fsl,imx8mm-ccm"; - reg = <0x0 0x30380000 0x0 0x10000>; - #clock-cells = <1>; - clocks = <&osc_32k>, <&osc_24m>, <&clk_ext1>, <&clk_ext2>, - <&clk_ext3>, <&clk_ext4>; - clock-names = "osc_32k", "osc_24m", "clk_ext1", "clk_ext2", - "clk_ext3", "clk_ext4"; -}; - -The clock consumer should specify the desired clock by having the clock -ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx8mm-clock.h -for the full list of i.MX8M Mini clock IDs. diff --git a/Documentation/devicetree/bindings/clock/imx8mm-clock.yaml b/Documentation/devicetree/bindings/clock/imx8mm-clock.yaml new file mode 100644 index 000000000000..f5be181bd21d --- /dev/null +++ b/Documentation/devicetree/bindings/clock/imx8mm-clock.yaml @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bindings/clock/imx8mm-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP i.MX8M Mini Clock Control Module Binding + +maintainers: + - Anson Huang + +description: | + NXP i.MX8M Mini clock control module is an integrated clock controller, which + generates and supplies to all modules. + +properties: + compatible: + const: fsl,imx8mm-ccm + + reg: + maxItems: 1 + + clocks: + items: + - description: 32k osc + - description: 24m osc + - description: ext1 clock input + - description: ext2 clock input + - description: ext3 clock input + - description: ext4 clock input + + clock-names: + items: + - const: osc_32k + - const: osc_24m + - const: clk_ext1 + - const: clk_ext2 + - const: clk_ext3 + - const: clk_ext4 + + '#clock-cells': + const: 1 + description: + The clock consumer should specify the desired clock by having the clock + ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx8mm-clock.h + for the full list of i.MX8M Mini clock IDs. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + +examples: + # Clock Control Module node: + - | + clk: clock-controller@30380000 { + compatible = "fsl,imx8mm-ccm"; + reg = <0x30380000 0x10000>; + #clock-cells = <1>; + clocks = <&osc_32k>, <&osc_24m>, <&clk_ext1>, <&clk_ext2>, + <&clk_ext3>, <&clk_ext4>; + clock-names = "osc_32k", "osc_24m", "clk_ext1", "clk_ext2", + "clk_ext3", "clk_ext4"; + }; + +... From d2d46dfaa72b41b4d6adf6ef1068ee00a51ba0fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Thu, 16 Jan 2020 09:37:16 +0200 Subject: [PATCH 0261/4444] dt-bindings: clock: imx8mn: add SNVS clock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add macro for the SNVS clock of the i.MX8MN. Signed-off-by: Horia Geantă Acked-by: Rob Herring Signed-off-by: Shawn Guo --- include/dt-bindings/clock/imx8mn-clock.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/dt-bindings/clock/imx8mn-clock.h b/include/dt-bindings/clock/imx8mn-clock.h index 0f2b8423ce1d..43883fe65db5 100644 --- a/include/dt-bindings/clock/imx8mn-clock.h +++ b/include/dt-bindings/clock/imx8mn-clock.h @@ -228,6 +228,8 @@ #define IMX8MN_SYS_PLL2_333M_CG 209 #define IMX8MN_SYS_PLL2_500M_CG 210 -#define IMX8MN_CLK_END 211 +#define IMX8MN_CLK_SNVS_ROOT 211 + +#define IMX8MN_CLK_END 212 #endif From b86a8ad2870e100e2f3ee1ae6c7741e3d771b89d Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 14 Jan 2020 09:26:07 +0800 Subject: [PATCH 0262/4444] dt-bindings: clock: Refine i.MX8MN clock binding Refine i.MX8MN clock binding by removing useless content and updating the example, it makes all i.MX8M SoCs' clock binding aligned. Signed-off-by: Anson Huang Reviewed-by: Rob Herring Signed-off-by: Shawn Guo --- .../bindings/clock/imx8mn-clock.yaml | 48 +------------------ 1 file changed, 2 insertions(+), 46 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/imx8mn-clock.yaml b/Documentation/devicetree/bindings/clock/imx8mn-clock.yaml index cd0b8a341321..49730474c1a7 100644 --- a/Documentation/devicetree/bindings/clock/imx8mn-clock.yaml +++ b/Documentation/devicetree/bindings/clock/imx8mn-clock.yaml @@ -40,7 +40,7 @@ properties: '#clock-cells': const: 1 - description: | + description: The clock consumer should specify the desired clock by having the clock ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx8mn-clock.h for the full list of i.MX8M Nano clock IDs. @@ -57,7 +57,7 @@ examples: - | clk: clock-controller@30380000 { compatible = "fsl,imx8mn-ccm"; - reg = <0x0 0x30380000 0x0 0x10000>; + reg = <0x30380000 0x10000>; #clock-cells = <1>; clocks = <&osc_32k>, <&osc_24m>, <&clk_ext1>, <&clk_ext2>, <&clk_ext3>, <&clk_ext4>; @@ -65,48 +65,4 @@ examples: "clk_ext2", "clk_ext3", "clk_ext4"; }; - # Required external clocks for Clock Control Module node: - - | - osc_32k: clock-osc-32k { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <32768>; - clock-output-names = "osc_32k"; - }; - - osc_24m: clock-osc-24m { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <24000000>; - clock-output-names = "osc_24m"; - }; - - clk_ext1: clock-ext1 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <133000000>; - clock-output-names = "clk_ext1"; - }; - - clk_ext2: clock-ext2 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <133000000>; - clock-output-names = "clk_ext2"; - }; - - clk_ext3: clock-ext3 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <133000000>; - clock-output-names = "clk_ext3"; - }; - - clk_ext4: clock-ext4 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency= <133000000>; - clock-output-names = "clk_ext4"; - }; - ... From 16e71d4da7999ddef87f5ba2274d77da0cab2772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Thu, 16 Jan 2020 09:37:17 +0200 Subject: [PATCH 0263/4444] clk: imx8mn: add SNVS clock to clock tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i.mx8mn has support for clock gating the snvs module. Add it into clock tree so that rtc-snvs driver could use it. Note this will also be required in the snvs_pwrkey driver, once support for clock management will be added. Signed-off-by: Horia Geantă Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mn.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c index c5e7316b4c66..a181eb2df876 100644 --- a/drivers/clk/imx/clk-imx8mn.c +++ b/drivers/clk/imx/clk-imx8mn.c @@ -523,6 +523,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) hws[IMX8MN_CLK_SAI5_IPG] = imx_clk_hw_gate2_shared2("sai5_ipg_clk", "ipg_audio_root", base + 0x4370, 0, &share_count_sai5); hws[IMX8MN_CLK_SAI6_ROOT] = imx_clk_hw_gate2_shared2("sai6_root_clk", "sai6", base + 0x4380, 0, &share_count_sai6); hws[IMX8MN_CLK_SAI6_IPG] = imx_clk_hw_gate2_shared2("sai6_ipg_clk", "ipg_audio_root", base + 0x4380, 0, &share_count_sai6); + hws[IMX8MN_CLK_SNVS_ROOT] = imx_clk_hw_gate4("snvs_root_clk", "ipg_root", base + 0x4470, 0); hws[IMX8MN_CLK_UART1_ROOT] = imx_clk_hw_gate4("uart1_root_clk", "uart1", base + 0x4490, 0); hws[IMX8MN_CLK_UART2_ROOT] = imx_clk_hw_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0); hws[IMX8MN_CLK_UART3_ROOT] = imx_clk_hw_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0); From 57795654fb553a78f07a9f92d87fb2582379cd93 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Thu, 16 Jan 2020 14:50:49 +0800 Subject: [PATCH 0264/4444] clk: imx: pll14xx: Add new frequency entries for pll1443x table Add new frequency entries to pll1443x table to meet different display settings requirement. Signed-off-by: Anson Huang Reviewed-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-pll14xx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c index 5b0519a81a7a..37e311e1d058 100644 --- a/drivers/clk/imx/clk-pll14xx.c +++ b/drivers/clk/imx/clk-pll14xx.c @@ -55,8 +55,10 @@ static const struct imx_pll14xx_rate_table imx_pll1416x_tbl[] = { }; static const struct imx_pll14xx_rate_table imx_pll1443x_tbl[] = { + PLL_1443X_RATE(1039500000U, 173, 2, 1, 16384), PLL_1443X_RATE(650000000U, 325, 3, 2, 0), PLL_1443X_RATE(594000000U, 198, 2, 2, 0), + PLL_1443X_RATE(519750000U, 173, 2, 2, 16384), PLL_1443X_RATE(393216000U, 262, 2, 3, 9437), PLL_1443X_RATE(361267200U, 361, 3, 3, 17511), }; From 42ef961b247f340f365b096e25983b4ee256f3ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Thu, 16 Jan 2020 09:37:18 +0200 Subject: [PATCH 0265/4444] arm64: dts: imx8mn: add clock for snvs rtc node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initial commit adding imx8mn support: 6c3debcbae47 ("arm64: dts: freescale: Add i.MX8MN dtsi support") added the "clock-names" property for the snvs rtc node, however it missed adding the clock. Signed-off-by: Horia Geantă Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mn.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi index a44b5438e842..d23347aaedda 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi @@ -358,6 +358,7 @@ offset = <0x34>; interrupts = , ; + clocks = <&clk IMX8MN_CLK_SNVS_ROOT>; clock-names = "snvs-rtc"; }; From 815364d0424e72cde1d16f2ef3a75cd8e48411bf Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Tue, 10 Dec 2019 00:43:50 +0100 Subject: [PATCH 0266/4444] arm64: dts: freescale: add Kontron sl28 support Add device tree files for the Kontron SMARC-sAL28 board and its carriers. Signed-off-by: Michael Walle Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/Makefile | 4 + .../fsl-ls1028a-kontron-kbox-a-230-ls.dts | 27 +++ .../fsl-ls1028a-kontron-sl28-var3-ads2.dts | 106 +++++++++++ .../fsl-ls1028a-kontron-sl28-var4.dts | 50 +++++ .../freescale/fsl-ls1028a-kontron-sl28.dts | 174 ++++++++++++++++++ 5 files changed, 361 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-kbox-a-230-ls.dts create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var3-ads2.dts create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var4.dts create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28.dts diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index bac293e6ee33..6088e3629151 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -4,6 +4,10 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-frwy.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-oxalis.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-qds.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-rdb.dtb +dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-kontron-kbox-a-230-ls.dtb +dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-kontron-sl28.dtb +dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-kontron-sl28-var3-ads2.dtb +dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-kontron-sl28-var4.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-qds.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-rdb.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-qds.dtb diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-kbox-a-230-ls.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-kbox-a-230-ls.dts new file mode 100644 index 000000000000..aaf3c04771c3 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-kbox-a-230-ls.dts @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Device Tree File for the Kontron KBox A-230-LS. + * + * This consists of a Kontron SMARC-sAL28 (Dual PHY) and a special + * carrier (s1914). + * + * Copyright (C) 2019 Michael Walle + * + */ + +/dts-v1/; +#include "fsl-ls1028a-kontron-sl28-var4.dts" + +/ { + model = "Kontron KBox A-230-LS"; + compatible = "kontron,kbox-a-230-ls", "kontron,sl28-var4", + "kontron,sl28", "fsl,ls1028a"; +}; + +&i2c4 { + eeprom@50 { + compatible = "atmel,24c32"; + reg = <0x50>; + pagesize = <32>; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var3-ads2.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var3-ads2.dts new file mode 100644 index 000000000000..7de55f2aa7dc --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var3-ads2.dts @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Device Tree file for the Kontron SMARC-sAL28 board on a SMARC Eval 2.0 + * carrier (ADS2). + * + * Copyright (C) 2019 Michael Walle + * + */ + +/dts-v1/; +#include "fsl-ls1028a-kontron-sl28.dts" + +/ { + model = "Kontron SMARC-sAL28 (Single PHY) on SMARC Eval 2.0 carrier"; + compatible = "kontron,sl28-var3-ads2", "kontron,sl28-var3", + "kontron,sl28", "fsl,ls1028a"; + + sound { + #address-cells = <1>; + #size-cells = <0>; + compatible = "simple-audio-card"; + simple-audio-card,widgets = + "Headphone", "Headphone Jack", + "Line", "Line Out Jack", + "Microphone", "Microphone Jack", + "Line", "Line In Jack"; + simple-audio-card,routing = + "Line Out Jack", "LINEOUTR", + "Line Out Jack", "LINEOUTL", + "Headphone Jack", "HPOUTR", + "Headphone Jack", "HPOUTL", + "IN1L", "Line In Jack", + "IN1R", "Line In Jack", + "Microphone Jack", "MICBIAS", + "IN2L", "Microphone Jack", + "IN2R", "Microphone Jack"; + simple-audio-card,mclk-fs = <256>; + + simple-audio-card,dai-link@0 { + reg = <0>; + bitclock-master = <&dailink0_master>; + frame-master = <&dailink0_master>; + format = "i2s"; + + cpu { + sound-dai = <&sai6>; + }; + + dailink0_master: codec { + sound-dai = <&wm8904>; + }; + }; + + simple-audio-card,dai-link@1 { + reg = <1>; + bitclock-master = <&dailink1_master>; + frame-master = <&dailink1_master>; + format = "i2s"; + + cpu { + sound-dai = <&sai5>; + }; + + dailink1_master: codec { + sound-dai = <&wm8904>; + }; + }; + }; +}; + +&i2c4 { + status = "okay"; + + wm8904: audio-codec@1a { + #sound-dai-cells = <0>; + compatible = "wlf,wm8904"; + reg = <0x1a>; + clocks = <&mclk>; + clock-names = "mclk"; + assigned-clocks = <&mclk>; + assigned-clock-rates = <1250000>; + }; + + eeprom@50 { + compatible = "atmel,24c32"; + reg = <0x50>; + pagesize = <32>; + }; +}; + +&sai5 { + status = "okay"; +}; + +&sai6 { + status = "okay"; +}; + +&soc { + mclk: clock-mclk@f130080 { + compatible = "fsl,vf610-sai-clock"; + reg = <0x0 0xf130080 0x0 0x80>; + clocks = <&clockgen 4 1>; + #clock-cells = <0>; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var4.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var4.dts new file mode 100644 index 000000000000..f659e89face8 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var4.dts @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Device Tree file for the Kontron SMARC-sAL28 board. + * + * This is for the network variant 4 which has two ethernet ports. It + * extends the base and provides one more port connected via RGMII. + * + * Copyright (C) 2019 Michael Walle + * + */ + +/dts-v1/; +#include "fsl-ls1028a-kontron-sl28.dts" +#include + +/ { + model = "Kontron SMARC-sAL28 (Dual PHY)"; + compatible = "kontron,sl28-var4", "kontron,sl28", "fsl,ls1028a"; +}; + +&enetc_port1 { + phy-handle = <&phy1>; + phy-connection-type = "rgmii-id"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + phy1: ethernet-phy@4 { + reg = <0x4>; + eee-broken-1000t; + eee-broken-100tx; + + qca,clk-out-frequency = <125000000>; + qca,clk-out-strength = ; + + vddio-supply = <&vddh>; + + vddio: vddio-regulator { + regulator-name = "VDDIO"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vddh: vddh-regulator { + regulator-name = "VDDH"; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28.dts new file mode 100644 index 000000000000..d221ed471cde --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28.dts @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Device Tree file for the Kontron SMARC-sAL28 board. + * + * Copyright (C) 2019 Michael Walle + * + */ + +/dts-v1/; +#include "fsl-ls1028a.dtsi" + +/ { + model = "Kontron SMARC-sAL28"; + compatible = "kontron,sl28", "fsl,ls1028a"; + + aliases { + crypto = &crypto; + serial0 = &duart0; + serial1 = &duart1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&duart0 { + status = "okay"; +}; + +&duart1 { + status = "okay"; +}; + +&enetc_port0 { + phy-handle = <&phy0>; + phy-connection-type = "sgmii"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + phy0: ethernet-phy@5 { + reg = <0x5>; + eee-broken-1000t; + eee-broken-100tx; + }; + }; +}; + +&esdhc { + sd-uhs-sdr104; + sd-uhs-sdr50; + sd-uhs-sdr25; + sd-uhs-sdr12; + status = "okay"; +}; + +&esdhc1 { + mmc-hs200-1_8v; + mmc-hs400-1_8v; + bus-width = <8>; + status = "okay"; +}; + +&fspi { + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + m25p,fast-read; + spi-max-frequency = <133000000>; + reg = <0>; + /* The following setting enables 1-1-2 (CMD-ADDR-DATA) mode */ + spi-rx-bus-width = <2>; /* 2 SPI Rx lines */ + spi-tx-bus-width = <1>; /* 1 SPI Tx line */ + + partition@0 { + reg = <0x000000 0x010000>; + label = "rcw"; + read-only; + }; + + partition@10000 { + reg = <0x010000 0x0f0000>; + label = "failsafe bootloader"; + read-only; + }; + + partition@100000 { + reg = <0x100000 0x040000>; + label = "failsafe DP firmware"; + read-only; + }; + + partition@140000 { + reg = <0x140000 0x0a0000>; + label = "failsafe trusted firmware"; + read-only; + }; + + partition@1e0000 { + reg = <0x1e0000 0x020000>; + label = "reserved"; + read-only; + }; + + partition@200000 { + reg = <0x200000 0x010000>; + label = "configuration store"; + }; + + partition@210000 { + reg = <0x210000 0x0f0000>; + label = "bootloader"; + }; + + partition@300000 { + reg = <0x300000 0x040000>; + label = "DP firmware"; + }; + + partition@340000 { + reg = <0x340000 0x0a0000>; + label = "trusted firmware"; + }; + + partition@3e0000 { + reg = <0x3e0000 0x020000>; + label = "bootloader environment"; + }; + }; +}; + +&gpio1 { + gpio-line-names = + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "TDO", "TCK", + "", "", "", "", "", "", "", ""; +}; + +&gpio2 { + gpio-line-names = + "", "", "", "", "", "", "TMS", "TDI", + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", ""; +}; + +&i2c0 { + status = "okay"; + + rtc@32 { + compatible = "microcrystal,rv8803"; + reg = <0x32>; + }; + + eeprom@50 { + compatible = "atmel,24c32"; + reg = <0x50>; + pagesize = <32>; + }; +}; + +&i2c3 { + status = "okay"; +}; + +&i2c4 { + status = "okay"; +}; From 53458f86683bee0551c87db4022e6ccc3ab8c868 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 10 Jan 2020 07:20:31 +0000 Subject: [PATCH 0267/4444] arm64: dts: imx8mn: Init rates and parents configs for clocks Add the initial configuration for clocks that need default parent and rate setting. NoC sources from SYS PLL3, running at 600MHz. Audio AHB/IPG clks needs to run at 400MHz for better performance. Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mn.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi index d23347aaedda..c98a37666347 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi @@ -380,6 +380,16 @@ <&clk_ext3>, <&clk_ext4>; clock-names = "osc_32k", "osc_24m", "clk_ext1", "clk_ext2", "clk_ext3", "clk_ext4"; + assigned-clocks = <&clk IMX8MN_CLK_NOC>, + <&clk IMX8MN_CLK_AUDIO_AHB>, + <&clk IMX8MN_CLK_IPG_AUDIO_ROOT>, + <&clk IMX8MN_SYS_PLL3>; + assigned-clock-parents = <&clk IMX8MN_SYS_PLL3_OUT>, + <&clk IMX8MN_SYS_PLL1_800M>; + assigned-clock-rates = <0>, + <400000000>, + <400000000>, + <600000000>; }; src: reset-controller@30390000 { From 70ea360330419af587d1d6740a58a968ea7f9781 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 16 Jan 2020 06:38:03 +0000 Subject: [PATCH 0268/4444] arm64: dts: freescale: s32v234: use generic name bus Per devicetree specification, generic names are recommended to be used, such as bus. AIPS is a AHB - IP bridge bus, so we could use bus as node name. Script: sed -i "s/\ Cc: Stefan-Gabriel Mirea Cc: Mihaela Martinas Cc: Dan Nica Cc: Stoica Cosmin-Stefan Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/s32v234.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/s32v234.dtsi b/arch/arm64/boot/dts/freescale/s32v234.dtsi index e746b9c48f7a..ba0b5305d481 100644 --- a/arch/arm64/boot/dts/freescale/s32v234.dtsi +++ b/arch/arm64/boot/dts/freescale/s32v234.dtsi @@ -104,7 +104,7 @@ interrupt-parent = <&gic>; ranges; - aips0: aips-bus@40000000 { + aips0: bus@40000000 { compatible = "simple-bus"; #address-cells = <2>; #size-cells = <2>; @@ -120,7 +120,7 @@ }; }; - aips1: aips-bus@40080000 { + aips1: bus@40080000 { compatible = "simple-bus"; #address-cells = <2>; #size-cells = <2>; From 0d9630084cf83537a63ed9be727acffd8c0253d2 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 12 Feb 2020 09:51:38 +0100 Subject: [PATCH 0269/4444] scsi: zorro_esp: Restore devm_ioremap() alignment Restore alignment of the continuations of the ioremap() calls in zorro_esp_probe(). Join lines where all parameters can fit on a single line. Link: https://lore.kernel.org/r/20200212085138.10009-1-geert+renesas@glider.be Fixes: 4bdc0d676a643140 ("remove ioremap_nocache and devm_ioremap_nocache") Signed-off-by: Geert Uytterhoeven Signed-off-by: Martin K. Petersen --- drivers/scsi/zorro_esp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/zorro_esp.c b/drivers/scsi/zorro_esp.c index bdd82e497d5f..c6727bcbc2e3 100644 --- a/drivers/scsi/zorro_esp.c +++ b/drivers/scsi/zorro_esp.c @@ -801,8 +801,7 @@ static int zorro_esp_probe(struct zorro_dev *z, /* additional setup required for Fastlane */ if (zep->zorro3 && ent->driver_data == ZORRO_BLZ1230II) { /* map full address space up to ESP base for DMA */ - zep->board_base = ioremap(board, - FASTLANE_ESP_ADDR-1); + zep->board_base = ioremap(board, FASTLANE_ESP_ADDR - 1); if (!zep->board_base) { pr_err("Cannot allocate board address space\n"); err = -ENOMEM; @@ -843,7 +842,7 @@ static int zorro_esp_probe(struct zorro_dev *z, * dma_registers size if adding any more */ esp->dma_regs = ioremap(dmaaddr, - sizeof(struct fastlane_dma_registers)); + sizeof(struct fastlane_dma_registers)); } else /* ZorroII address space remapped nocache by early startup */ esp->dma_regs = ZTWO_VADDR(dmaaddr); From 5693340143702ecf791521dc5d2afa81f3bf3ed8 Mon Sep 17 00:00:00 2001 From: John Garry Date: Tue, 11 Feb 2020 01:33:12 +0800 Subject: [PATCH 0270/4444] scsi: core: Delete scsi_use_blk_mq Module param scsi_use_blk_mq has not been referenced for some time, so zap it. Link: https://lore.kernel.org/r/1581355992-139274-1-git-send-email-john.garry@huawei.com Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi.c | 4 ---- drivers/scsi/scsi_priv.h | 1 - 2 files changed, 5 deletions(-) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 930e4803d888..4b9fdfab77d9 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -764,10 +764,6 @@ MODULE_LICENSE("GPL"); module_param(scsi_logging_level, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(scsi_logging_level, "a bit mask of logging levels"); -/* This should go away in the future, it doesn't do anything anymore */ -bool scsi_use_blk_mq = true; -module_param_named(use_blk_mq, scsi_use_blk_mq, bool, S_IWUSR | S_IRUGO); - static int __init init_scsi(void) { int error; diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 3bff9f7aa684..25b0aaaf5ae8 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -29,7 +29,6 @@ extern int scsi_init_hosts(void); extern void scsi_exit_hosts(void); /* scsi.c */ -extern bool scsi_use_blk_mq; int scsi_init_sense_cache(struct Scsi_Host *shost); void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd); #ifdef CONFIG_SCSI_LOGGING From 1a1a9fafc6a2536835b38886ca4afe50d19dd2b9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 12 Feb 2020 11:08:30 +0100 Subject: [PATCH 0271/4444] ARM: zynq: Replace by The Zynq platform code is not a clock provider, and just needs to call of_clk_init(). Hence it can include instead of . Signed-off-by: Geert Uytterhoeven Reviewed-by: Stephen Boyd Signed-off-by: Michal Simek --- arch/arm/mach-zynq/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 3a4248fd7962..a9dd2f71cd19 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -12,10 +12,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include From 59528807715f81f123631f57446b08219efa7526 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 14 Jan 2020 17:52:23 -0600 Subject: [PATCH 0272/4444] soundwire: stream: update state machine and add state checks The state machine and notes don't accurately explain or allow transitions from STREAM_DEPREPARED and STREAM_DISABLED. Add more explanations and allow for more transitions as a result of a trigger_stop(), trigger_suspend() and prepare(), depending on the ALSA/ASoC layer behavior defined by the INFO_RESUME and INFO_PAUSE flags. Also add basic checks to help debug inconsistent states and illegal state machine transitions. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200114235227.14502-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- Documentation/driver-api/soundwire/stream.rst | 61 +++++++++++++------ drivers/soundwire/stream.c | 37 +++++++++++ 2 files changed, 81 insertions(+), 17 deletions(-) diff --git a/Documentation/driver-api/soundwire/stream.rst b/Documentation/driver-api/soundwire/stream.rst index 5351bd2f34a8..8bceece51554 100644 --- a/Documentation/driver-api/soundwire/stream.rst +++ b/Documentation/driver-api/soundwire/stream.rst @@ -156,22 +156,27 @@ Below shows the SoundWire stream states and state transition diagram. :: +-----------+ +------------+ +----------+ +----------+ | ALLOCATED +---->| CONFIGURED +---->| PREPARED +---->| ENABLED | | STATE | | STATE | | STATE | | STATE | - +-----------+ +------------+ +----------+ +----+-----+ - ^ - | - | - v - +----------+ +------------+ +----+-----+ + +-----------+ +------------+ +---+--+---+ +----+-----+ + ^ ^ ^ + | | | + __| |___________ | + | | | + v | v + +----------+ +-----+------+ +-+--+-----+ | RELEASED |<----------+ DEPREPARED |<-------+ DISABLED | | STATE | | STATE | | STATE | +----------+ +------------+ +----------+ -NOTE: State transition between prepare and deprepare is supported in Spec -but not in the software (subsystem) +NOTE: State transitions between ``SDW_STREAM_ENABLED`` and +``SDW_STREAM_DISABLED`` are only relevant when then INFO_PAUSE flag is +supported at the ALSA/ASoC level. Likewise the transition between +``SDW_DISABLED_STATE`` and ``SDW_PREPARED_STATE`` depends on the +INFO_RESUME flag. -NOTE2: Stream state transition checks need to be handled by caller -framework, for example ALSA/ASoC. No checks for stream transition exist in -SoundWire subsystem. +NOTE2: The framework implements basic state transition checks, but +does not e.g. check if a transition from DISABLED to ENABLED is valid +on a specific platform. Such tests need to be added at the ALSA/ASoC +level. Stream State Operations ----------------------- @@ -246,6 +251,9 @@ SDW_STREAM_PREPARED Prepare state of stream. Operations performed before entering in this state: + (0) Steps 1 and 2 are omitted in the case of a resume operation, + where the bus bandwidth is known. + (1) Bus parameters such as bandwidth, frame shape, clock frequency, are computed based on current stream as well as already active stream(s) on Bus. Re-computation is required to accommodate current @@ -270,9 +278,11 @@ Prepare state of stream. Operations performed before entering in this state: After all above operations are successful, stream state is set to ``SDW_STREAM_PREPARED``. -Bus implements below API for PREPARE state which needs to be called once per -stream. From ASoC DPCM framework, this stream state is linked to -.prepare() operation. +Bus implements below API for PREPARE state which needs to be called +once per stream. From ASoC DPCM framework, this stream state is linked +to .prepare() operation. Since the .trigger() operations may not +follow the .prepare(), a direct transition from +``SDW_STREAM_PREPARED`` to ``SDW_STREAM_DEPREPARED`` is allowed. .. code-block:: c @@ -332,6 +342,14 @@ Bus implements below API for DISABLED state which needs to be called once per stream. From ASoC DPCM framework, this stream state is linked to .trigger() stop operation. +When the INFO_PAUSE flag is supported, a direct transition to +``SDW_STREAM_ENABLED`` is allowed. + +For resume operations where ASoC will use the .prepare() callback, the +stream can transition from ``SDW_STREAM_DISABLED`` to +``SDW_STREAM_PREPARED``, with all required settings restored but +without updating the bandwidth and bit allocation. + .. code-block:: c int sdw_disable_stream(struct sdw_stream_runtime * stream); @@ -353,9 +371,18 @@ state: After all above operations are successful, stream state is set to ``SDW_STREAM_DEPREPARED``. -Bus implements below API for DEPREPARED state which needs to be called once -per stream. From ASoC DPCM framework, this stream state is linked to -.trigger() stop operation. +Bus implements below API for DEPREPARED state which needs to be called +once per stream. ALSA/ASoC do not have a concept of 'deprepare', and +the mapping from this stream state to ALSA/ASoC operation may be +implementation specific. + +When the INFO_PAUSE flag is supported, the stream state is linked to +the .hw_free() operation - the stream is not deprepared on a +TRIGGER_STOP. + +Other implementations may transition to the ``SDW_STREAM_DEPREPARED`` +state on TRIGGER_STOP, should they require a transition through the +``SDW_STREAM_PREPARED`` state. .. code-block:: c diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index 178ae92b8cc1..6aa0b5d370c0 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -1553,8 +1553,18 @@ int sdw_prepare_stream(struct sdw_stream_runtime *stream) sdw_acquire_bus_lock(stream); + if (stream->state != SDW_STREAM_CONFIGURED && + stream->state != SDW_STREAM_DEPREPARED && + stream->state != SDW_STREAM_DISABLED) { + pr_err("%s: %s: inconsistent state state %d\n", + __func__, stream->name, stream->state); + ret = -EINVAL; + goto state_err; + } + ret = _sdw_prepare_stream(stream); +state_err: sdw_release_bus_lock(stream); return ret; } @@ -1619,8 +1629,17 @@ int sdw_enable_stream(struct sdw_stream_runtime *stream) sdw_acquire_bus_lock(stream); + if (stream->state != SDW_STREAM_PREPARED && + stream->state != SDW_STREAM_DISABLED) { + pr_err("%s: %s: inconsistent state state %d\n", + __func__, stream->name, stream->state); + ret = -EINVAL; + goto state_err; + } + ret = _sdw_enable_stream(stream); +state_err: sdw_release_bus_lock(stream); return ret; } @@ -1693,8 +1712,16 @@ int sdw_disable_stream(struct sdw_stream_runtime *stream) sdw_acquire_bus_lock(stream); + if (stream->state != SDW_STREAM_ENABLED) { + pr_err("%s: %s: inconsistent state state %d\n", + __func__, stream->name, stream->state); + ret = -EINVAL; + goto state_err; + } + ret = _sdw_disable_stream(stream); +state_err: sdw_release_bus_lock(stream); return ret; } @@ -1749,8 +1776,18 @@ int sdw_deprepare_stream(struct sdw_stream_runtime *stream) } sdw_acquire_bus_lock(stream); + + if (stream->state != SDW_STREAM_PREPARED && + stream->state != SDW_STREAM_DISABLED) { + pr_err("%s: %s: inconsistent state state %d\n", + __func__, stream->name, stream->state); + ret = -EINVAL; + goto state_err; + } + ret = _sdw_deprepare_stream(stream); +state_err: sdw_release_bus_lock(stream); return ret; } From c32464c9393d0a426b5abbf01980ff5ecfb34a98 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 14 Jan 2020 17:52:24 -0600 Subject: [PATCH 0273/4444] soundwire: stream: only prepare stream when it is configured. We don't need to prepare the stream again if the stream is already prepared. sdw_prepare_stream() could be called multiple times without calling sdw_deprepare_stream(). We call sdw_prepare_stream() in the prepare dai ops and sdw_deprepare_stream() in the hw_free dai ops. If an xrun happens, sdw_prepare_stream() will be called but sdw_deprepare_stream() will not, which results in an imbalance and an invalid total bandwidth. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20200114235227.14502-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/stream.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index 6aa0b5d370c0..bd0bddf73830 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -1544,7 +1544,7 @@ restore_params: */ int sdw_prepare_stream(struct sdw_stream_runtime *stream) { - int ret = 0; + int ret; if (!stream) { pr_err("SoundWire: Handle not found for stream\n"); @@ -1553,6 +1553,11 @@ int sdw_prepare_stream(struct sdw_stream_runtime *stream) sdw_acquire_bus_lock(stream); + if (stream->state == SDW_STREAM_PREPARED) { + ret = 0; + goto state_err; + } + if (stream->state != SDW_STREAM_CONFIGURED && stream->state != SDW_STREAM_DEPREPARED && stream->state != SDW_STREAM_DISABLED) { From c7a8f049b828dc8e01acd56911a1816b7725d9c3 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 14 Jan 2020 17:52:25 -0600 Subject: [PATCH 0274/4444] soundwire: stream: do not update parameters during DISABLED-PREPARED transition After a system suspend, the ALSA/ASoC core will invoke the .prepare() callback and a TRIGGER_START when INFO_RESUME is not supported. Likewise, when an underflow occurs, the .prepare callback will be invoked. In both cases, the stream can be in DISABLED mode, and will transition into the PREPARED mode. We however don't want the bus bandwidth to be recomputed. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200114235227.14502-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/stream.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index bd0bddf73830..c28ce7f0d742 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -1460,7 +1460,8 @@ static void sdw_release_bus_lock(struct sdw_stream_runtime *stream) } } -static int _sdw_prepare_stream(struct sdw_stream_runtime *stream) +static int _sdw_prepare_stream(struct sdw_stream_runtime *stream, + bool update_params) { struct sdw_master_runtime *m_rt; struct sdw_bus *bus = NULL; @@ -1480,6 +1481,9 @@ static int _sdw_prepare_stream(struct sdw_stream_runtime *stream) return -EINVAL; } + if (!update_params) + goto program_params; + /* Increment cumulative bus bandwidth */ /* TODO: Update this during Device-Device support */ bus->params.bandwidth += m_rt->stream->params.rate * @@ -1495,6 +1499,7 @@ static int _sdw_prepare_stream(struct sdw_stream_runtime *stream) } } +program_params: /* Program params */ ret = sdw_program_params(bus); if (ret < 0) { @@ -1544,6 +1549,7 @@ restore_params: */ int sdw_prepare_stream(struct sdw_stream_runtime *stream) { + bool update_params = true; int ret; if (!stream) { @@ -1567,7 +1573,16 @@ int sdw_prepare_stream(struct sdw_stream_runtime *stream) goto state_err; } - ret = _sdw_prepare_stream(stream); + /* + * when the stream is DISABLED, this means sdw_prepare_stream() + * is called as a result of an underflow or a resume operation. + * In this case, the bus parameters shall not be recomputed, but + * still need to be re-applied + */ + if (stream->state == SDW_STREAM_DISABLED) + update_params = false; + + ret = _sdw_prepare_stream(stream, update_params); state_err: sdw_release_bus_lock(stream); From 60835022e196de1a4d73c249e99f34b7204ca267 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Tue, 14 Jan 2020 17:52:26 -0600 Subject: [PATCH 0275/4444] soundwire: stream: fix support for multiple Slaves on the same link The existing code will unconditionally return after dealing with the first Slave on a link. This return should only happen when there is an error case. Tested on Comet Lake platform. Signed-off-by: Rander Wang Link: https://lore.kernel.org/r/20200114235227.14502-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/stream.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index c28ce7f0d742..da10f38298c0 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -587,10 +587,11 @@ static int sdw_notify_config(struct sdw_master_runtime *m_rt) if (slave->ops->bus_config) { ret = slave->ops->bus_config(slave, &bus->params); - if (ret < 0) + if (ret < 0) { dev_err(bus->dev, "Notify Slave: %d failed\n", slave->dev_num); - return ret; + return ret; + } } } From bfaa3549541cf8bf16246dfd9b4d2f3af679be86 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Tue, 14 Jan 2020 17:52:27 -0600 Subject: [PATCH 0276/4444] soundwire: stream: don't program ports when a stream that has not been prepared In the Intel QA multi-pipelines test case, there are two pipelines for playback and capture on the same bus. The test fails with an error when setting port params: [ 599.224812] rt711 sdw:0:25d:711:0: invalid dpn_prop direction 1 port_num 0 [ 599.224815] sdw_program_slave_port_params failed -22 [ 599.224819] intel-sdw sdw-master-0: Program transport params failed: -22 [ 599.224822] intel-sdw sdw-master-0: Program params failed: -22 [ 599.224828] sdw_enable_stream: SDW0 Pin2-Playback: done This problem is root-caused to the programming of the capture stream ports while it is not yet prepared, the calling sequence is: (1) hw_params for playback. The playback stream provide the port information to Bus. (2) stream_prepare for playback, Transport and port parameters are computed for playback. (3) hw_params for capture. The capture stream provide the port information to Bus, but it has not been prepared so is not accounted for in the bandwidth allocation. (4) stream_enable for playback. Program transport and port parameters for all masters and slaves. Since the transport and port parameters are not computed for capture stream, sdw_program_slave_port_params will generate a error when setting port params for capture. in step (4), we should only program the ports for the stream that have been prepared. A stream that is only in CONFIGURED state should be ignored, its ports will be programmed when it becomes PREPARED. Tested on Comet Lake. GitHub issue: https://github.com/thesofproject/linux/issues/1637 Signed-off-by: Pierre-Louis Bossart Signed-off-by: Rander Wang Link: https://lore.kernel.org/r/20200114235227.14502-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/stream.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index da10f38298c0..00348d1fc606 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -603,13 +603,25 @@ static int sdw_notify_config(struct sdw_master_runtime *m_rt) * and Slave(s) * * @bus: SDW bus instance + * @prepare: true if sdw_program_params() is called by _prepare. */ -static int sdw_program_params(struct sdw_bus *bus) +static int sdw_program_params(struct sdw_bus *bus, bool prepare) { struct sdw_master_runtime *m_rt; int ret = 0; list_for_each_entry(m_rt, &bus->m_rt_list, bus_node) { + + /* + * this loop walks through all master runtimes for a + * bus, but the ports can only be configured while + * explicitly preparing a stream or handling an + * already-prepared stream otherwise. + */ + if (!prepare && + m_rt->stream->state == SDW_STREAM_CONFIGURED) + continue; + ret = sdw_program_port_params(m_rt); if (ret < 0) { dev_err(bus->dev, @@ -1502,7 +1514,7 @@ static int _sdw_prepare_stream(struct sdw_stream_runtime *stream, program_params: /* Program params */ - ret = sdw_program_params(bus); + ret = sdw_program_params(bus, true); if (ret < 0) { dev_err(bus->dev, "Program params failed: %d\n", ret); goto restore_params; @@ -1602,7 +1614,7 @@ static int _sdw_enable_stream(struct sdw_stream_runtime *stream) bus = m_rt->bus; /* Program params */ - ret = sdw_program_params(bus); + ret = sdw_program_params(bus, false); if (ret < 0) { dev_err(bus->dev, "Program params failed: %d\n", ret); return ret; @@ -1687,7 +1699,7 @@ static int _sdw_disable_stream(struct sdw_stream_runtime *stream) struct sdw_bus *bus = m_rt->bus; /* Program params */ - ret = sdw_program_params(bus); + ret = sdw_program_params(bus, false); if (ret < 0) { dev_err(bus->dev, "Program params failed: %d\n", ret); return ret; @@ -1769,7 +1781,7 @@ static int _sdw_deprepare_stream(struct sdw_stream_runtime *stream) m_rt->ch_count * m_rt->stream->params.bps; /* Program params */ - ret = sdw_program_params(bus); + ret = sdw_program_params(bus, false); if (ret < 0) { dev_err(bus->dev, "Program params failed: %d\n", ret); return ret; From ec7ba9e1500b0af5bf30b4e56bfaaf3a88850bbf Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 13 Feb 2020 11:27:25 +0800 Subject: [PATCH 0277/4444] ASoC: mediatek: mt8183-da7219: change supported formats of DL2 and UL1 DL2 and UL1 are for BTSCO. Provides only 16-bit, mono, 8kHz and 16kHz to userspace. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200213112003.1.Ie5aedb9d34ebfc7f05ceb382bfe346c45331cd63@changeid Signed-off-by: Mark Brown --- .../mediatek/mt8183/mt8183-da7219-max98357.c | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index 1626541cc0d6..b52ffed882a7 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -116,6 +116,46 @@ static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } +static int +mt8183_da7219_max98357_bt_sco_startup( + struct snd_pcm_substream *substream) +{ + static const unsigned int rates[] = { + 8000, 16000 + }; + static const struct snd_pcm_hw_constraint_list constraints_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, + }; + static const unsigned int channels[] = { + 1, + }; + static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, + }; + + struct snd_pcm_runtime *runtime = substream->runtime; + + snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); + runtime->hw.channels_max = 1; + snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + + runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; + snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); + + return 0; +} + +static const struct snd_soc_ops mt8183_da7219_max98357_bt_sco_ops = { + .startup = mt8183_da7219_max98357_bt_sco_startup, +}; + /* FE */ SND_SOC_DAILINK_DEFS(playback1, DAILINK_COMP_ARRAY(COMP_CPU("DL1")), @@ -222,6 +262,7 @@ static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, + .ops = &mt8183_da7219_max98357_bt_sco_ops, SND_SOC_DAILINK_REG(playback2), }, { @@ -240,6 +281,7 @@ static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, + .ops = &mt8183_da7219_max98357_bt_sco_ops, SND_SOC_DAILINK_REG(capture1), }, { From 8726ee6148fe24e2b29d4a961ad95c4ff8025d1d Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 13 Feb 2020 11:27:26 +0800 Subject: [PATCH 0278/4444] ASoC: mediatek: mt8183-da7219: pull TDM GPIO pins down when probed 1. Switch TDM GPIO pins according to playback on or off. 2. Pull TDM GPIO pins down when probed to avoid current leakage. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200213112003.2.I1d568b0c99742c6e755d051aadfd52e4be3cc0a5@changeid Signed-off-by: Mark Brown --- .../mediatek/mt8183/mt8183-da7219-max98357.c | 104 +++++++++++++++++- 1 file changed, 98 insertions(+), 6 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index b52ffed882a7..d7685916a5cb 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -18,6 +18,22 @@ static struct snd_soc_jack headset_jack; +enum PINCTRL_PIN_STATE { + PIN_STATE_DEFAULT = 0, + PIN_TDM_OUT_ON, + PIN_TDM_OUT_OFF, + PIN_STATE_MAX +}; + +static const char * const mt8183_pin_str[PIN_STATE_MAX] = { + "default", "aud_tdm_out_on", "aud_tdm_out_off", +}; + +struct mt8183_da7219_max98357_priv { + struct pinctrl *pinctrl; + struct pinctrl_state *pin_states[PIN_STATE_MAX]; +}; + static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -244,6 +260,47 @@ SND_SOC_DAILINK_DEFS(tdm, DAILINK_COMP_ARRAY(COMP_DUMMY()), DAILINK_COMP_ARRAY(COMP_EMPTY())); +static int mt8183_da7219_tdm_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct mt8183_da7219_max98357_priv *priv = + snd_soc_card_get_drvdata(rtd->card); + int ret; + + if (IS_ERR(priv->pin_states[PIN_TDM_OUT_ON])) + return PTR_ERR(priv->pin_states[PIN_TDM_OUT_ON]); + + ret = pinctrl_select_state(priv->pinctrl, + priv->pin_states[PIN_TDM_OUT_ON]); + if (ret) + dev_err(rtd->card->dev, "%s failed to select state %d\n", + __func__, ret); + + return ret; +} + +static void mt8183_da7219_tdm_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct mt8183_da7219_max98357_priv *priv = + snd_soc_card_get_drvdata(rtd->card); + int ret; + + if (IS_ERR(priv->pin_states[PIN_TDM_OUT_OFF])) + return; + + ret = pinctrl_select_state(priv->pinctrl, + priv->pin_states[PIN_TDM_OUT_OFF]); + if (ret) + dev_err(rtd->card->dev, "%s failed to select state %d\n", + __func__, ret); +} + +static struct snd_soc_ops mt8183_da7219_tdm_ops = { + .startup = mt8183_da7219_tdm_startup, + .shutdown = mt8183_da7219_tdm_shutdown, +}; + static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { /* FE */ { @@ -395,6 +452,8 @@ static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { .no_pcm = 1, .dpcm_playback = 1, .ignore_suspend = 1, + .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, + .ops = &mt8183_da7219_tdm_ops, SND_SOC_DAILINK_REG(tdm), }, }; @@ -470,7 +529,7 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) struct snd_soc_card *card = &mt8183_da7219_max98357_card; struct device_node *platform_node; struct snd_soc_dai_link *dai_link; - struct pinctrl *default_pins; + struct mt8183_da7219_max98357_priv *priv; int ret, i; card->dev = &pdev->dev; @@ -504,12 +563,45 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) return ret; } - default_pins = - devm_pinctrl_get_select(&pdev->dev, PINCTRL_STATE_DEFAULT); - if (IS_ERR(default_pins)) { - dev_err(&pdev->dev, "%s set pins failed\n", + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + snd_soc_card_set_drvdata(card, priv); + + priv->pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(priv->pinctrl)) { + dev_err(&pdev->dev, "%s devm_pinctrl_get failed\n", __func__); - return PTR_ERR(default_pins); + return PTR_ERR(priv->pinctrl); + } + + for (i = 0; i < PIN_STATE_MAX; i++) { + priv->pin_states[i] = pinctrl_lookup_state(priv->pinctrl, + mt8183_pin_str[i]); + if (IS_ERR(priv->pin_states[i])) { + ret = PTR_ERR(priv->pin_states[i]); + dev_info(&pdev->dev, "%s Can't find pin state %s %d\n", + __func__, mt8183_pin_str[i], ret); + } + } + + if (!IS_ERR(priv->pin_states[PIN_TDM_OUT_OFF])) { + ret = pinctrl_select_state(priv->pinctrl, + priv->pin_states[PIN_TDM_OUT_OFF]); + if (ret) + dev_info(&pdev->dev, + "%s failed to select state %d\n", + __func__, ret); + } + + if (!IS_ERR(priv->pin_states[PIN_STATE_DEFAULT])) { + ret = pinctrl_select_state(priv->pinctrl, + priv->pin_states[PIN_STATE_DEFAULT]); + if (ret) + dev_info(&pdev->dev, + "%s failed to select state %d\n", + __func__, ret); } return ret; From 195a6431710543ace009ff8e32dcf1e087506199 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 13 Feb 2020 11:27:27 +0800 Subject: [PATCH 0279/4444] ASoC: mediatek: mt8183-da7219: support TDM out and 8ch I2S out Supports TDM out and 8ch I2S out. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200213112003.3.I30f0b8c87d5ec2a0e5f1b0fabf0a8ccef374f5ea@changeid Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index d7685916a5cb..c7f766f24e44 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -450,6 +450,9 @@ static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { { .name = "TDM", .no_pcm = 1, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_IB_IF | + SND_SOC_DAIFMT_CBM_CFM, .dpcm_playback = 1, .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, From ff0035e4c22371a29e4e0d4a07cdce5726fe50aa Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 13 Feb 2020 11:27:28 +0800 Subject: [PATCH 0280/4444] ASoC: mediatek: mt8183-da7219: apply some refactors 1. Moves headset jack to card-specific storage. 2. Removes trailing blank line. 3. Moves card registration to the end of probe. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200213112003.4.Ia542007f51d3de753a9e0a83135ee074581dbf71@changeid Signed-off-by: Mark Brown --- .../mediatek/mt8183/mt8183-da7219-max98357.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index c7f766f24e44..c0c85972cfb7 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -16,8 +16,6 @@ #include "../../codecs/da7219-aad.h" #include "../../codecs/da7219.h" -static struct snd_soc_jack headset_jack; - enum PINCTRL_PIN_STATE { PIN_STATE_DEFAULT = 0, PIN_TDM_OUT_ON, @@ -32,6 +30,7 @@ static const char * const mt8183_pin_str[PIN_STATE_MAX] = { struct mt8183_da7219_max98357_priv { struct pinctrl *pinctrl; struct pinctrl_state *pin_states[PIN_STATE_MAX]; + struct snd_soc_jack headset_jack; }; static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream, @@ -510,6 +509,8 @@ static int mt8183_da7219_max98357_headset_init(struct snd_soc_component *component) { int ret; + struct mt8183_da7219_max98357_priv *priv = + snd_soc_card_get_drvdata(component->card); /* Enable Headset and 4 Buttons Jack detection */ ret = snd_soc_card_jack_new(&mt8183_da7219_max98357_card, @@ -517,12 +518,12 @@ mt8183_da7219_max98357_headset_init(struct snd_soc_component *component) SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3, - &headset_jack, + &priv->headset_jack, NULL, 0); if (ret) return ret; - da7219_aad_jack_det(component, &headset_jack); + da7219_aad_jack_det(component, &priv->headset_jack); return ret; } @@ -559,13 +560,6 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) return -EINVAL; } - ret = devm_snd_soc_register_card(&pdev->dev, card); - if (ret) { - dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", - __func__, ret); - return ret; - } - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -607,7 +601,7 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) __func__, ret); } - return ret; + return devm_snd_soc_register_card(&pdev->dev, card); } #ifdef CONFIG_OF @@ -634,4 +628,3 @@ MODULE_DESCRIPTION("MT8183-DA7219-MAX98357 ALSA SoC machine driver"); MODULE_AUTHOR("Shunli Wang "); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("mt8183_da7219_max98357 soc card"); - From 0c48a65394ab6d2b4afde3fbe840dbb05a52d929 Mon Sep 17 00:00:00 2001 From: "derek.fang" Date: Thu, 13 Feb 2020 15:05:10 +0800 Subject: [PATCH 0281/4444] ASoC: rt5682: Enable PLL2 function Enable RT5682 PLL2 function to implement the more complex frequency conversion. Signed-off-by: derek.fang Link: https://lore.kernel.org/r/1581577510-1807-1-git-send-email-derek.fang@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 217 +++++++++++++++++++++++++++++--------- sound/soc/codecs/rt5682.h | 39 ++++++- 2 files changed, 206 insertions(+), 50 deletions(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 82a636620131..9fbb3862f8d7 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -64,9 +64,9 @@ struct rt5682_priv { int bclk[RT5682_AIFS]; int master[RT5682_AIFS]; - int pll_src; - int pll_in; - int pll_out; + int pll_src[RT5682_PLLS]; + int pll_in[RT5682_PLLS]; + int pll_out[RT5682_PLLS]; int jack_type; }; @@ -75,6 +75,7 @@ static const struct reg_sequence patch_list[] = { {RT5682_HP_IMP_SENS_CTRL_19, 0x1000}, {RT5682_DAC_ADC_DIG_VOL1, 0xa020}, {RT5682_I2C_CTRL, 0x000f}, + {RT5682_PLL2_INTERNAL, 0x8266}, }; static const struct reg_default rt5682_reg[] = { @@ -222,7 +223,7 @@ static const struct reg_default rt5682_reg[] = { {0x0148, 0x0000}, {0x0149, 0x0000}, {0x0150, 0x79a1}, - {0x0151, 0x0000}, + {0x0156, 0xaaaa}, {0x0160, 0x4ec0}, {0x0161, 0x0080}, {0x0162, 0x0200}, @@ -928,10 +929,10 @@ static int rt5682_headset_detect(struct snd_soc_component *component, RT5682_PWR_VREF2 | RT5682_PWR_MB, RT5682_PWR_VREF2 | RT5682_PWR_MB); snd_soc_component_update_bits(component, - RT5682_PWR_ANLG_1, RT5682_PWR_FV2, 0); + RT5682_PWR_ANLG_1, RT5682_PWR_FV2, 0); usleep_range(15000, 20000); snd_soc_component_update_bits(component, - RT5682_PWR_ANLG_1, RT5682_PWR_FV2, RT5682_PWR_FV2); + RT5682_PWR_ANLG_1, RT5682_PWR_FV2, RT5682_PWR_FV2); snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3, RT5682_PWR_CBJ, RT5682_PWR_CBJ); @@ -1298,6 +1299,21 @@ static int is_sys_clk_from_pll1(struct snd_soc_dapm_widget *w, return 0; } +static int is_sys_clk_from_pll2(struct snd_soc_dapm_widget *w, + struct snd_soc_dapm_widget *sink) +{ + unsigned int val; + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + + val = snd_soc_component_read32(component, RT5682_GLB_CLK); + val &= RT5682_SCLK_SRC_MASK; + if (val == RT5682_SCLK_SRC_PLL2) + return 1; + else + return 0; +} + static int is_using_asrc(struct snd_soc_dapm_widget *w, struct snd_soc_dapm_widget *sink) { @@ -1612,9 +1628,11 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("PLL2B", RT5682_PWR_ANLG_3, RT5682_PWR_PLL2B_BIT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("PLL2F", RT5682_PWR_ANLG_3, RT5682_PWR_PLL2F_BIT, - 0, NULL, 0), + 0, set_filter_clk, SND_SOC_DAPM_PRE_PMU), SND_SOC_DAPM_SUPPLY("Vref1", RT5682_PWR_ANLG_1, RT5682_PWR_VREF1_BIT, 0, rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_SUPPLY("Vref2", RT5682_PWR_ANLG_1, RT5682_PWR_VREF2_BIT, 0, + NULL, 0), /* ASRC */ SND_SOC_DAPM_SUPPLY_S("DAC STO1 ASRC", 1, RT5682_PLL_TRACK_1, @@ -1796,7 +1814,11 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = { static const struct snd_soc_dapm_route rt5682_dapm_routes[] = { /*PLL*/ {"ADC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll1}, + {"ADC Stereo1 Filter", NULL, "PLL2B", is_sys_clk_from_pll2}, + {"ADC Stereo1 Filter", NULL, "PLL2F", is_sys_clk_from_pll2}, {"DAC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll1}, + {"DAC Stereo1 Filter", NULL, "PLL2B", is_sys_clk_from_pll2}, + {"DAC Stereo1 Filter", NULL, "PLL2F", is_sys_clk_from_pll2}, /*ASRC*/ {"ADC Stereo1 Filter", NULL, "ADC STO1 ASRC", is_using_asrc}, @@ -2053,8 +2075,10 @@ static int rt5682_hw_params(struct snd_pcm_substream *substream, RT5682_I2S1_DL_MASK, len_1); if (rt5682->master[RT5682_AIF1]) { snd_soc_component_update_bits(component, - RT5682_ADDA_CLK_1, RT5682_I2S_M_DIV_MASK, - pre_div << RT5682_I2S_M_DIV_SFT); + RT5682_ADDA_CLK_1, RT5682_I2S_M_DIV_MASK | + RT5682_I2S_CLK_SRC_MASK, + pre_div << RT5682_I2S_M_DIV_SFT | + (rt5682->sysclk_src) << RT5682_I2S_CLK_SRC_SFT); } if (params_channels(params) == 1) /* mono mode */ snd_soc_component_update_bits(component, @@ -2227,61 +2251,157 @@ static int rt5682_set_component_pll(struct snd_soc_component *component, unsigned int freq_out) { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); - struct rl6231_pll_code pll_code; + struct rl6231_pll_code pll_code, pll2f_code, pll2b_code; + unsigned int pll2_fout1; int ret; - if (source == rt5682->pll_src && freq_in == rt5682->pll_in && - freq_out == rt5682->pll_out) + if (source == rt5682->pll_src[pll_id] && + freq_in == rt5682->pll_in[pll_id] && + freq_out == rt5682->pll_out[pll_id]) return 0; if (!freq_in || !freq_out) { dev_dbg(component->dev, "PLL disabled\n"); - rt5682->pll_in = 0; - rt5682->pll_out = 0; + rt5682->pll_in[pll_id] = 0; + rt5682->pll_out[pll_id] = 0; snd_soc_component_update_bits(component, RT5682_GLB_CLK, RT5682_SCLK_SRC_MASK, RT5682_SCLK_SRC_MCLK); return 0; } - switch (source) { - case RT5682_PLL1_S_MCLK: - snd_soc_component_update_bits(component, RT5682_GLB_CLK, - RT5682_PLL1_SRC_MASK, RT5682_PLL1_SRC_MCLK); - break; - case RT5682_PLL1_S_BCLK1: - snd_soc_component_update_bits(component, RT5682_GLB_CLK, - RT5682_PLL1_SRC_MASK, RT5682_PLL1_SRC_BCLK1); - break; - default: - dev_err(component->dev, "Unknown PLL Source %d\n", source); - return -EINVAL; + if (pll_id == RT5682_PLL2) { + switch (source) { + case RT5682_PLL2_S_MCLK: + snd_soc_component_update_bits(component, + RT5682_GLB_CLK, RT5682_PLL2_SRC_MASK, + RT5682_PLL2_SRC_MCLK); + break; + default: + dev_err(component->dev, "Unknown PLL2 Source %d\n", + source); + return -EINVAL; + } + + /** + * PLL2 concatenates 2 PLL units. + * We suggest the Fout of the front PLL is 3.84MHz. + */ + pll2_fout1 = 3840000; + ret = rl6231_pll_calc(freq_in, pll2_fout1, &pll2f_code); + if (ret < 0) { + dev_err(component->dev, "Unsupport input clock %d\n", + freq_in); + return ret; + } + dev_dbg(component->dev, "PLL2F: fin=%d fout=%d bypass=%d m=%d n=%d k=%d\n", + freq_in, pll2_fout1, + pll2f_code.m_bp, + (pll2f_code.m_bp ? 0 : pll2f_code.m_code), + pll2f_code.n_code, pll2f_code.k_code); + + ret = rl6231_pll_calc(pll2_fout1, freq_out, &pll2b_code); + if (ret < 0) { + dev_err(component->dev, "Unsupport input clock %d\n", + pll2_fout1); + return ret; + } + dev_dbg(component->dev, "PLL2B: fin=%d fout=%d bypass=%d m=%d n=%d k=%d\n", + pll2_fout1, freq_out, + pll2b_code.m_bp, + (pll2b_code.m_bp ? 0 : pll2b_code.m_code), + pll2b_code.n_code, pll2b_code.k_code); + + snd_soc_component_write(component, RT5682_PLL2_CTRL_1, + pll2f_code.k_code << RT5682_PLL2F_K_SFT | + pll2b_code.k_code << RT5682_PLL2B_K_SFT | + pll2b_code.m_code); + snd_soc_component_write(component, RT5682_PLL2_CTRL_2, + pll2f_code.m_code << RT5682_PLL2F_M_SFT | + pll2b_code.n_code); + snd_soc_component_write(component, RT5682_PLL2_CTRL_3, + pll2f_code.n_code << RT5682_PLL2F_N_SFT); + snd_soc_component_update_bits(component, RT5682_PLL2_CTRL_4, + RT5682_PLL2B_M_BP_MASK | RT5682_PLL2F_M_BP_MASK | 0xf, + (pll2b_code.m_bp ? 1 : 0) << RT5682_PLL2B_M_BP_SFT | + (pll2f_code.m_bp ? 1 : 0) << RT5682_PLL2F_M_BP_SFT | + 0xf); + } else { + switch (source) { + case RT5682_PLL1_S_MCLK: + snd_soc_component_update_bits(component, + RT5682_GLB_CLK, RT5682_PLL1_SRC_MASK, + RT5682_PLL1_SRC_MCLK); + break; + case RT5682_PLL1_S_BCLK1: + snd_soc_component_update_bits(component, + RT5682_GLB_CLK, RT5682_PLL1_SRC_MASK, + RT5682_PLL1_SRC_BCLK1); + break; + default: + dev_err(component->dev, "Unknown PLL1 Source %d\n", + source); + return -EINVAL; + } + + ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); + if (ret < 0) { + dev_err(component->dev, "Unsupport input clock %d\n", + freq_in); + return ret; + } + + dev_dbg(component->dev, "bypass=%d m=%d n=%d k=%d\n", + pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), + pll_code.n_code, pll_code.k_code); + + snd_soc_component_write(component, RT5682_PLL_CTRL_1, + pll_code.n_code << RT5682_PLL_N_SFT | pll_code.k_code); + snd_soc_component_write(component, RT5682_PLL_CTRL_2, + (pll_code.m_bp ? 0 : pll_code.m_code) << RT5682_PLL_M_SFT | + pll_code.m_bp << RT5682_PLL_M_BP_SFT | RT5682_PLL_RST); } - ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); - if (ret < 0) { - dev_err(component->dev, "Unsupport input clock %d\n", freq_in); - return ret; - } - - dev_dbg(component->dev, "bypass=%d m=%d n=%d k=%d\n", - pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), - pll_code.n_code, pll_code.k_code); - - snd_soc_component_write(component, RT5682_PLL_CTRL_1, - pll_code.n_code << RT5682_PLL_N_SFT | pll_code.k_code); - snd_soc_component_write(component, RT5682_PLL_CTRL_2, - (pll_code.m_bp ? 0 : pll_code.m_code) << RT5682_PLL_M_SFT | - pll_code.m_bp << RT5682_PLL_M_BP_SFT | RT5682_PLL_RST); - - rt5682->pll_in = freq_in; - rt5682->pll_out = freq_out; - rt5682->pll_src = source; + rt5682->pll_in[pll_id] = freq_in; + rt5682->pll_out[pll_id] = freq_out; + rt5682->pll_src[pll_id] = source; return 0; } -static int rt5682_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) +static int rt5682_set_bclk1_ratio(struct snd_soc_dai *dai, unsigned int ratio) +{ + struct snd_soc_component *component = dai->component; + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + + rt5682->bclk[dai->id] = ratio; + + switch (ratio) { + case 256: + snd_soc_component_update_bits(component, RT5682_TDM_TCON_CTRL, + RT5682_TDM_BCLK_MS1_MASK, RT5682_TDM_BCLK_MS1_256); + break; + case 128: + snd_soc_component_update_bits(component, RT5682_TDM_TCON_CTRL, + RT5682_TDM_BCLK_MS1_MASK, RT5682_TDM_BCLK_MS1_128); + break; + case 64: + snd_soc_component_update_bits(component, RT5682_TDM_TCON_CTRL, + RT5682_TDM_BCLK_MS1_MASK, RT5682_TDM_BCLK_MS1_64); + break; + case 32: + snd_soc_component_update_bits(component, RT5682_TDM_TCON_CTRL, + RT5682_TDM_BCLK_MS1_MASK, RT5682_TDM_BCLK_MS1_32); + break; + default: + dev_err(dai->dev, "Invalid bclk1 ratio %d\n", ratio); + return -EINVAL; + } + + return 0; +} + +static int rt5682_set_bclk2_ratio(struct snd_soc_dai *dai, unsigned int ratio) { struct snd_soc_component *component = dai->component; struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); @@ -2300,7 +2420,7 @@ static int rt5682_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) RT5682_I2S2_BCLK_MS2_32); break; default: - dev_err(dai->dev, "Invalid bclk ratio %d\n", ratio); + dev_err(dai->dev, "Invalid bclk2 ratio %d\n", ratio); return -EINVAL; } @@ -2389,12 +2509,13 @@ static const struct snd_soc_dai_ops rt5682_aif1_dai_ops = { .hw_params = rt5682_hw_params, .set_fmt = rt5682_set_dai_fmt, .set_tdm_slot = rt5682_set_tdm_slot, + .set_bclk_ratio = rt5682_set_bclk1_ratio, }; static const struct snd_soc_dai_ops rt5682_aif2_dai_ops = { .hw_params = rt5682_hw_params, .set_fmt = rt5682_set_dai_fmt, - .set_bclk_ratio = rt5682_set_bclk_ratio, + .set_bclk_ratio = rt5682_set_bclk2_ratio, }; static struct snd_soc_dai_driver rt5682_dai[] = { diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h index 4d3a8c41546e..465c99b7f906 100644 --- a/sound/soc/codecs/rt5682.h +++ b/sound/soc/codecs/rt5682.h @@ -177,7 +177,7 @@ #define RT5682_TEST_MODE_CTRL_4 0x0148 #define RT5682_TEST_MODE_CTRL_5 0x0149 #define RT5682_PLL1_INTERNAL 0x0150 -#define RT5682_PLL2_INTERNAL 0x0151 +#define RT5682_PLL2_INTERNAL 0x0156 #define RT5682_STO_NG2_CTRL_1 0x0160 #define RT5682_STO_NG2_CTRL_2 0x0161 #define RT5682_STO_NG2_CTRL_3 0x0162 @@ -738,7 +738,7 @@ #define RT5682_ADC_OSR_D_24 (0x7 << 12) #define RT5682_ADC_OSR_D_32 (0x8 << 12) #define RT5682_ADC_OSR_D_48 (0x9 << 12) -#define RT5682_I2S_M_DIV_MASK (0xf << 12) +#define RT5682_I2S_M_DIV_MASK (0xf << 8) #define RT5682_I2S_M_DIV_SFT 8 #define RT5682_I2S_M_D_1 (0x0 << 8) #define RT5682_I2S_M_D_2 (0x1 << 8) @@ -820,6 +820,12 @@ #define RT5682_TDM_DF_PCM_B (0x3 << 11) #define RT5682_TDM_DF_PCM_A_N (0x6 << 11) #define RT5682_TDM_DF_PCM_B_N (0x7 << 11) +#define RT5682_TDM_BCLK_MS1_MASK (0x3 << 9) +#define RT5682_TDM_BCLK_MS1_SFT 9 +#define RT5682_TDM_BCLK_MS1_32 (0x0 << 9) +#define RT5682_TDM_BCLK_MS1_64 (0x1 << 9) +#define RT5682_TDM_BCLK_MS1_128 (0x2 << 9) +#define RT5682_TDM_BCLK_MS1_256 (0x3 << 9) #define RT5682_TDM_CL_MASK (0x3 << 4) #define RT5682_TDM_CL_16 (0x0 << 4) #define RT5682_TDM_CL_20 (0x1 << 4) @@ -1049,6 +1055,28 @@ #define RT5682_PWR_CLK1M_PD (0x0 << 8) #define RT5682_PWR_CLK1M_PU (0x1 << 8) +/* PLL2 M/N/K Code Control 1 (0x009b) */ +#define RT5682_PLL2F_K_MASK (0x1f << 8) +#define RT5682_PLL2F_K_SFT 8 +#define RT5682_PLL2B_K_MASK (0xf << 4) +#define RT5682_PLL2B_K_SFT 4 +#define RT5682_PLL2B_M_MASK (0xf << 0) + +/* PLL2 M/N/K Code Control 2 (0x009c) */ +#define RT5682_PLL2F_M_MASK (0x3f << 8) +#define RT5682_PLL2F_M_SFT 8 +#define RT5682_PLL2B_N_MASK (0x3f << 0) + +/* PLL2 M/N/K Code Control 2 (0x009d) */ +#define RT5682_PLL2F_N_MASK (0x7f << 8) +#define RT5682_PLL2F_N_SFT 8 + +/* PLL2 M/N/K Code Control 2 (0x009e) */ +#define RT5682_PLL2B_M_BP_MASK (0x1 << 11) +#define RT5682_PLL2B_M_BP_SFT 11 +#define RT5682_PLL2F_M_BP_MASK (0x1 << 7) +#define RT5682_PLL2F_M_BP_SFT 7 + /* RC Clock Control (0x009f) */ #define RT5682_POW_IRQ (0x1 << 15) #define RT5682_POW_JDH (0x1 << 14) @@ -1315,6 +1343,13 @@ enum { RT5682_PLL1_S_MCLK, RT5682_PLL1_S_BCLK1, RT5682_PLL1_S_RCCLK, + RT5682_PLL2_S_MCLK, +}; + +enum { + RT5682_PLL1, + RT5682_PLL2, + RT5682_PLLS, }; enum { From f7b280c6388137185fab4408da18d989ba36c721 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 11 Feb 2020 21:53:35 +0800 Subject: [PATCH 0282/4444] dmaengine: idxd: remove set but not used variable 'group' drivers/dma/idxd/sysfs.c: In function engine_group_id_store: drivers/dma/idxd/sysfs.c:419:29: warning: variable group set but not used [-Wunused-but-set-variable] It is not used, so remove it. Reported-by: Hulk Robot Signed-off-by: YueHaibing Acked-by: Dave Jiang Link: https://lore.kernel.org/r/20200211135335.55924-1-yuehaibing@huawei.com Signed-Off-By: Vinod Koul --- drivers/dma/idxd/sysfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c index 6d907fe150aa..e4f35bdf252e 100644 --- a/drivers/dma/idxd/sysfs.c +++ b/drivers/dma/idxd/sysfs.c @@ -416,7 +416,7 @@ static ssize_t engine_group_id_store(struct device *dev, struct idxd_device *idxd = engine->idxd; long id; int rc; - struct idxd_group *prevg, *group; + struct idxd_group *prevg; rc = kstrtol(buf, 10, &id); if (rc < 0) @@ -436,7 +436,6 @@ static ssize_t engine_group_id_store(struct device *dev, return count; } - group = &idxd->groups[id]; prevg = engine->group; if (prevg) From bfc8f1a87c37e9762b8e37474267db36401e8161 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Mon, 10 Feb 2020 23:18:55 +0800 Subject: [PATCH 0283/4444] dmaengine: idxd: remove set but not used variable 'idxd_cdev' drivers/dma/idxd/cdev.c: In function idxd_cdev_open: drivers/dma/idxd/cdev.c:77:20: warning: variable idxd_cdev set but not used [-Wunused-but-set-variable] commit 42d279f9137a ("dmaengine: idxd: add char driver to expose submission portal to userland") involed this. Reported-by: Hulk Robot Signed-off-by: YueHaibing Acked-by: Dave Jiang Link: https://lore.kernel.org/r/20200210151855.55044-1-yuehaibing@huawei.com Signed-off-by: Vinod Koul --- drivers/dma/idxd/cdev.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c index 1d7347825b95..8dfdbe37e381 100644 --- a/drivers/dma/idxd/cdev.c +++ b/drivers/dma/idxd/cdev.c @@ -74,12 +74,10 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp) struct idxd_device *idxd; struct idxd_wq *wq; struct device *dev; - struct idxd_cdev *idxd_cdev; wq = inode_wq(inode); idxd = wq->idxd; dev = &idxd->pdev->dev; - idxd_cdev = &wq->idxd_cdev; dev_dbg(dev, "%s called\n", __func__); From ff095986e6b449bc095b018388519f1e413a7fa8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 12 Feb 2020 11:48:40 +0100 Subject: [PATCH 0284/4444] dt-bindings: dma: ti-edma: fix example compatible property Make sure that the compatible string in the edma1_tptc1 example node matches the binding by removing the space between the manufacturer and model. Signed-off-by: Johan Hovold Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20200212104840.20393-1-johan@kernel.org Signed-off-by: Vinod Koul --- Documentation/devicetree/bindings/dma/ti-edma.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/dma/ti-edma.txt b/Documentation/devicetree/bindings/dma/ti-edma.txt index 0e1398f93aa2..29fcd37082e8 100644 --- a/Documentation/devicetree/bindings/dma/ti-edma.txt +++ b/Documentation/devicetree/bindings/dma/ti-edma.txt @@ -180,7 +180,7 @@ edma1_tptc0: tptc@27b0000 { }; edma1_tptc1: tptc@27b8000 { - compatible = "ti, k2g-edma3-tptc", "ti,edma3-tptc"; + compatible = "ti,k2g-edma3-tptc", "ti,edma3-tptc"; reg = <0x027b8000 0x400>; power-domains = <&k2g_pds 0x4f>; }; From 57a8cc725622185576dcd3df718e91fcda1ef5dd Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 12 Feb 2020 18:37:03 -0600 Subject: [PATCH 0285/4444] dmaengine: bcm-sba-raid: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200213003703.GA4177@embeddedor.com Signed-off-by: Vinod Koul --- drivers/dma/bcm-sba-raid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/bcm-sba-raid.c b/drivers/dma/bcm-sba-raid.c index 275e90fa829d..64239da02e74 100644 --- a/drivers/dma/bcm-sba-raid.c +++ b/drivers/dma/bcm-sba-raid.c @@ -120,7 +120,7 @@ struct sba_request { struct brcm_message msg; struct dma_async_tx_descriptor tx; /* SBA commands */ - struct brcm_sba_command cmds[0]; + struct brcm_sba_command cmds[]; }; enum sba_version { From 6a8785082c83f0a223bc970d99edcd742435dab2 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 12 Feb 2020 18:35:35 -0600 Subject: [PATCH 0286/4444] dmaengine: uniphier-mdmac: replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200213003535.GA3269@embeddedor.com Signed-off-by: Vinod Koul --- drivers/dma/uniphier-mdmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/uniphier-mdmac.c b/drivers/dma/uniphier-mdmac.c index 21b8f1131d55..618839df0748 100644 --- a/drivers/dma/uniphier-mdmac.c +++ b/drivers/dma/uniphier-mdmac.c @@ -68,7 +68,7 @@ struct uniphier_mdmac_device { struct dma_device ddev; struct clk *clk; void __iomem *reg_base; - struct uniphier_mdmac_chan channels[0]; + struct uniphier_mdmac_chan channels[]; }; static struct uniphier_mdmac_chan * From 5ca3364a83b2d78590c3acd40a9edc716465f7af Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 12 Feb 2020 18:39:25 -0600 Subject: [PATCH 0287/4444] dmaengine: ti: omap-dma: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20200213003925.GA6906@embeddedor.com Signed-off-by: Vinod Koul --- drivers/dma/ti/omap-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/ti/omap-dma.c b/drivers/dma/ti/omap-dma.c index a014ab96e673..918301e17552 100644 --- a/drivers/dma/ti/omap-dma.c +++ b/drivers/dma/ti/omap-dma.c @@ -124,7 +124,7 @@ struct omap_desc { uint32_t csdp; /* CSDP value */ unsigned sglen; - struct omap_sg sg[0]; + struct omap_sg sg[]; }; enum { From 6ebb827f7aad504ea438d0d2903293bd6f904463 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 7 Feb 2020 10:44:45 +0800 Subject: [PATCH 0288/4444] dmaengine: sun4i: use 'linear_mode' in sun4i_dma_prep_dma_cyclic drivers/dma/sun4i-dma.c: In function sun4i_dma_prep_dma_cyclic: drivers/dma/sun4i-dma.c:672:24: warning: variable linear_mode set but not used [-Wunused-but-set-variable] commit ffc079a4accc ("dmaengine: sun4i: Add support for cyclic requests with dedicated DMA") involved this, explicitly using the value makes the code more readable. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20200207024445.44600-1-yuehaibing@huawei.com Signed-off-by: Vinod Koul --- drivers/dma/sun4i-dma.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c index bbc2bda3b902..e87fc7c460dd 100644 --- a/drivers/dma/sun4i-dma.c +++ b/drivers/dma/sun4i-dma.c @@ -698,10 +698,12 @@ sun4i_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf, size_t len, endpoints = SUN4I_DMA_CFG_DST_DRQ_TYPE(vchan->endpoint) | SUN4I_DMA_CFG_DST_ADDR_MODE(io_mode) | SUN4I_DMA_CFG_SRC_DRQ_TYPE(ram_type); + SUN4I_DMA_CFG_SRC_ADDR_MODE(linear_mode); } else { src = sconfig->src_addr; dest = buf; endpoints = SUN4I_DMA_CFG_DST_DRQ_TYPE(ram_type) | + SUN4I_DMA_CFG_DST_ADDR_MODE(linear_mode) | SUN4I_DMA_CFG_SRC_DRQ_TYPE(vchan->endpoint) | SUN4I_DMA_CFG_SRC_ADDR_MODE(io_mode); } From acd624185d204b0ae2360b4648cc50802df5da01 Mon Sep 17 00:00:00 2001 From: chenqiwu Date: Tue, 28 Jan 2020 13:35:46 +0800 Subject: [PATCH 0289/4444] dmaengine: ti: dma-crossbar: convert to devm_platform_ioremap_resource() Use a new API devm_platform_ioremap_resource() to simplify code. Signed-off-by: chenqiwu Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/1580189746-2864-1-git-send-email-qiwuchen55@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/ti/dma-crossbar.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/dma/ti/dma-crossbar.c b/drivers/dma/ti/dma-crossbar.c index f255056696ee..4ba8fa5d9c36 100644 --- a/drivers/dma/ti/dma-crossbar.c +++ b/drivers/dma/ti/dma-crossbar.c @@ -133,7 +133,6 @@ static int ti_am335x_xbar_probe(struct platform_device *pdev) const struct of_device_id *match; struct device_node *dma_node; struct ti_am335x_xbar_data *xbar; - struct resource *res; void __iomem *iomem; int i, ret; @@ -173,8 +172,7 @@ static int ti_am335x_xbar_probe(struct platform_device *pdev) xbar->xbar_events = TI_AM335X_XBAR_LINES; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - iomem = devm_ioremap_resource(&pdev->dev, res); + iomem = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(iomem)) return PTR_ERR(iomem); @@ -323,7 +321,6 @@ static int ti_dra7_xbar_probe(struct platform_device *pdev) struct device_node *dma_node; struct ti_dra7_xbar_data *xbar; struct property *prop; - struct resource *res; u32 safe_val; int sz; void __iomem *iomem; @@ -403,8 +400,7 @@ static int ti_dra7_xbar_probe(struct platform_device *pdev) kfree(rsv_events); } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - iomem = devm_ioremap_resource(&pdev->dev, res); + iomem = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(iomem)) return PTR_ERR(iomem); From 306e59cc32a3cdcf5332e5ea5d6ad899629f3604 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 22 Jan 2020 11:04:49 +0100 Subject: [PATCH 0290/4444] dt-bindings: clk: meson: add the gxl internal dac gate Add the gxl ACODEC clock id to the gxbb clock controller bindings Acked-by: Neil Armstrong Signed-off-by: Jerome Brunet --- include/dt-bindings/clock/gxbb-clkc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h index db0763e96173..4073eb7a9da1 100644 --- a/include/dt-bindings/clock/gxbb-clkc.h +++ b/include/dt-bindings/clock/gxbb-clkc.h @@ -146,5 +146,6 @@ #define CLKID_CTS_VDAC 201 #define CLKID_HDMI_TX 202 #define CLKID_HDMI 205 +#define CLKID_ACODEC 206 #endif /* __GXBB_CLKC_H */ From 73c7ddd8ee15dc5e06ffb2e22bde89c3deff3c45 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 22 Jan 2020 11:04:50 +0100 Subject: [PATCH 0291/4444] clk: meson: gxbb: add the gxl internal dac gate Add the ACODEC clock gate to the gxl clk controller driver Acked-by: Neil Armstrong Signed-off-by: Jerome Brunet --- drivers/clk/meson/gxbb.c | 3 +++ drivers/clk/meson/gxbb.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 1f9c056e684c..47916c4f1700 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -2613,6 +2613,7 @@ static MESON_GATE(gxbb_assist_misc, HHI_GCLK_MPEG0, 23); static MESON_GATE(gxbb_emmc_a, HHI_GCLK_MPEG0, 24); static MESON_GATE(gxbb_emmc_b, HHI_GCLK_MPEG0, 25); static MESON_GATE(gxbb_emmc_c, HHI_GCLK_MPEG0, 26); +static MESON_GATE(gxl_acodec, HHI_GCLK_MPEG0, 28); static MESON_GATE(gxbb_spi, HHI_GCLK_MPEG0, 30); static MESON_GATE(gxbb_i2s_spdif, HHI_GCLK_MPEG1, 2); @@ -3100,6 +3101,7 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = { [CLKID_HDMI_SEL] = &gxbb_hdmi_sel.hw, [CLKID_HDMI_DIV] = &gxbb_hdmi_div.hw, [CLKID_HDMI] = &gxbb_hdmi.hw, + [CLKID_ACODEC] = &gxl_acodec.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -3491,6 +3493,7 @@ static struct clk_regmap *const gxl_clk_regmaps[] = { &gxl_hdmi_pll_od, &gxl_hdmi_pll_od2, &gxl_hdmi_pll_dco, + &gxl_acodec, }; static const struct meson_eeclkc_data gxbb_clkc_data = { diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h index b53584fe66cf..1ee8cb7e2f5a 100644 --- a/drivers/clk/meson/gxbb.h +++ b/drivers/clk/meson/gxbb.h @@ -188,7 +188,7 @@ #define CLKID_HDMI_SEL 203 #define CLKID_HDMI_DIV 204 -#define NR_CLKS 206 +#define NR_CLKS 207 /* include the CLKIDs that have been made part of the DT binding */ #include From 83b89a75de9bf71203fddca00dc1cd8c9f5e6fd2 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 22 Jan 2020 11:04:51 +0100 Subject: [PATCH 0292/4444] clk: meson: gxbb: set audio output clock hierarchy The aiu devices peripheral clocks needs the aiu and aiu_glue clocks to operate. Reflect this hierarchy in the gxbb clock tree. Fixes: 738f66d3211d ("clk: gxbb: add AmLogic GXBB clk controller driver") Acked-by: Neil Armstrong Signed-off-by: Jerome Brunet --- drivers/clk/meson/gxbb.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 47916c4f1700..5fd6a574f8c3 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -2619,14 +2619,6 @@ static MESON_GATE(gxbb_spi, HHI_GCLK_MPEG0, 30); static MESON_GATE(gxbb_i2s_spdif, HHI_GCLK_MPEG1, 2); static MESON_GATE(gxbb_eth, HHI_GCLK_MPEG1, 3); static MESON_GATE(gxbb_demux, HHI_GCLK_MPEG1, 4); -static MESON_GATE(gxbb_aiu_glue, HHI_GCLK_MPEG1, 6); -static MESON_GATE(gxbb_iec958, HHI_GCLK_MPEG1, 7); -static MESON_GATE(gxbb_i2s_out, HHI_GCLK_MPEG1, 8); -static MESON_GATE(gxbb_amclk, HHI_GCLK_MPEG1, 9); -static MESON_GATE(gxbb_aififo2, HHI_GCLK_MPEG1, 10); -static MESON_GATE(gxbb_mixer, HHI_GCLK_MPEG1, 11); -static MESON_GATE(gxbb_mixer_iface, HHI_GCLK_MPEG1, 12); -static MESON_GATE(gxbb_adc, HHI_GCLK_MPEG1, 13); static MESON_GATE(gxbb_blkmv, HHI_GCLK_MPEG1, 14); static MESON_GATE(gxbb_aiu, HHI_GCLK_MPEG1, 15); static MESON_GATE(gxbb_uart1, HHI_GCLK_MPEG1, 16); @@ -2681,6 +2673,16 @@ static MESON_GATE(gxbb_ao_ahb_bus, HHI_GCLK_AO, 2); static MESON_GATE(gxbb_ao_iface, HHI_GCLK_AO, 3); static MESON_GATE(gxbb_ao_i2c, HHI_GCLK_AO, 4); +/* AIU gates */ +static MESON_PCLK(gxbb_aiu_glue, HHI_GCLK_MPEG1, 6, &gxbb_aiu.hw); +static MESON_PCLK(gxbb_iec958, HHI_GCLK_MPEG1, 7, &gxbb_aiu_glue.hw); +static MESON_PCLK(gxbb_i2s_out, HHI_GCLK_MPEG1, 8, &gxbb_aiu_glue.hw); +static MESON_PCLK(gxbb_amclk, HHI_GCLK_MPEG1, 9, &gxbb_aiu_glue.hw); +static MESON_PCLK(gxbb_aififo2, HHI_GCLK_MPEG1, 10, &gxbb_aiu_glue.hw); +static MESON_PCLK(gxbb_mixer, HHI_GCLK_MPEG1, 11, &gxbb_aiu_glue.hw); +static MESON_PCLK(gxbb_mixer_iface, HHI_GCLK_MPEG1, 12, &gxbb_aiu_glue.hw); +static MESON_PCLK(gxbb_adc, HHI_GCLK_MPEG1, 13, &gxbb_aiu_glue.hw); + /* Array of all clocks provided by this provider */ static struct clk_hw_onecell_data gxbb_hw_onecell_data = { From 1dfa5a5ab34560fd9647083f623d19705be2e706 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 13 Feb 2020 16:51:51 +0100 Subject: [PATCH 0293/4444] ASoC: core: allow a dt node to provide several components At the moment, querying the dai_name will stop of the first component matching the dt node. This does not allow a device (single dt node) to provide several ASoC components which could then be used through DT. This change let the search go on if the xlate function of the component returns an error, giving the possibility to another component to match and return the dai_name. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200213155159.3235792-2-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 068d809c349a..03b87427faa7 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3102,6 +3102,14 @@ int snd_soc_get_dai_name(struct of_phandle_args *args, *dai_name = dai->driver->name; if (!*dai_name) *dai_name = pos->name; + } else if (ret) { + /* + * if another error than ENOTSUPP is returned go on and + * check if another component is provided with the same + * node. This may happen if a device provides several + * components + */ + continue; } break; From 9c29fd9bdf92900dc0cc5c2d8f58951a7bdc0f41 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 13 Feb 2020 16:51:52 +0100 Subject: [PATCH 0294/4444] ASoC: meson: g12a: extract codec-to-codec utils The hdmi routing mechanism used on g12a hdmi is also used: * other Amlogic SoC types * for the internal DAC path Each of these codec glues are slightly different but the idea behind it remains the same. This change extract some helper functions from the g12a-tohdmitx driver to make them available for other Amlogic codecs. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200213155159.3235792-3-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/Kconfig | 4 + sound/soc/meson/Makefile | 2 + sound/soc/meson/g12a-tohdmitx.c | 219 ++++++----------------------- sound/soc/meson/meson-codec-glue.c | 149 ++++++++++++++++++++ sound/soc/meson/meson-codec-glue.h | 32 +++++ 5 files changed, 230 insertions(+), 176 deletions(-) create mode 100644 sound/soc/meson/meson-codec-glue.c create mode 100644 sound/soc/meson/meson-codec-glue.h diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index 2e3676147cea..ee6d53949d45 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -85,9 +85,13 @@ config SND_MESON_AXG_PDM Select Y or M to add support for PDM input embedded in the Amlogic AXG SoC family +config SND_MESON_CODEC_GLUE + tristate + config SND_MESON_G12A_TOHDMITX tristate "Amlogic G12A To HDMI TX Control Support" select REGMAP_MMIO + select SND_MESON_CODEC_GLUE imply SND_SOC_HDMI_CODEC help Select Y or M to add support for HDMI audio on the g12a SoC diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index 1a8b1470ed84..529a807b3f37 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -11,6 +11,7 @@ snd-soc-meson-axg-sound-card-objs := axg-card.o snd-soc-meson-axg-spdifin-objs := axg-spdifin.o snd-soc-meson-axg-spdifout-objs := axg-spdifout.o snd-soc-meson-axg-pdm-objs := axg-pdm.o +snd-soc-meson-codec-glue-objs := meson-codec-glue.o snd-soc-meson-g12a-tohdmitx-objs := g12a-tohdmitx.o obj-$(CONFIG_SND_MESON_AXG_FIFO) += snd-soc-meson-axg-fifo.o @@ -24,4 +25,5 @@ obj-$(CONFIG_SND_MESON_AXG_SOUND_CARD) += snd-soc-meson-axg-sound-card.o obj-$(CONFIG_SND_MESON_AXG_SPDIFIN) += snd-soc-meson-axg-spdifin.o obj-$(CONFIG_SND_MESON_AXG_SPDIFOUT) += snd-soc-meson-axg-spdifout.o obj-$(CONFIG_SND_MESON_AXG_PDM) += snd-soc-meson-axg-pdm.o +obj-$(CONFIG_SND_MESON_CODEC_GLUE) += snd-soc-meson-codec-glue.o obj-$(CONFIG_SND_MESON_G12A_TOHDMITX) += snd-soc-meson-g12a-tohdmitx.o diff --git a/sound/soc/meson/g12a-tohdmitx.c b/sound/soc/meson/g12a-tohdmitx.c index 9cfbd343a00c..f8853f2fba08 100644 --- a/sound/soc/meson/g12a-tohdmitx.c +++ b/sound/soc/meson/g12a-tohdmitx.c @@ -12,112 +12,51 @@ #include #include +#include "meson-codec-glue.h" #define G12A_TOHDMITX_DRV_NAME "g12a-tohdmitx" #define TOHDMITX_CTRL0 0x0 #define CTRL0_ENABLE_SHIFT 31 -#define CTRL0_I2S_DAT_SEL GENMASK(13, 12) +#define CTRL0_I2S_DAT_SEL_SHIFT 12 +#define CTRL0_I2S_DAT_SEL (0x3 << CTRL0_I2S_DAT_SEL_SHIFT) #define CTRL0_I2S_LRCLK_SEL GENMASK(9, 8) #define CTRL0_I2S_BLK_CAP_INV BIT(7) #define CTRL0_I2S_BCLK_O_INV BIT(6) #define CTRL0_I2S_BCLK_SEL GENMASK(5, 4) #define CTRL0_SPDIF_CLK_CAP_INV BIT(3) #define CTRL0_SPDIF_CLK_O_INV BIT(2) -#define CTRL0_SPDIF_SEL BIT(1) +#define CTRL0_SPDIF_SEL_SHIFT 1 +#define CTRL0_SPDIF_SEL (0x1 << CTRL0_SPDIF_SEL_SHIFT) #define CTRL0_SPDIF_CLK_SEL BIT(0) -struct g12a_tohdmitx_input { - struct snd_soc_pcm_stream params; - unsigned int fmt; -}; - -static struct snd_soc_dapm_widget * -g12a_tohdmitx_get_input(struct snd_soc_dapm_widget *w) -{ - struct snd_soc_dapm_path *p = NULL; - struct snd_soc_dapm_widget *in; - - snd_soc_dapm_widget_for_each_source_path(w, p) { - if (!p->connect) - continue; - - /* Check that we still are in the same component */ - if (snd_soc_dapm_to_component(w->dapm) != - snd_soc_dapm_to_component(p->source->dapm)) - continue; - - if (p->source->id == snd_soc_dapm_dai_in) - return p->source; - - in = g12a_tohdmitx_get_input(p->source); - if (in) - return in; - } - - return NULL; -} - -static struct g12a_tohdmitx_input * -g12a_tohdmitx_get_input_data(struct snd_soc_dapm_widget *w) -{ - struct snd_soc_dapm_widget *in = - g12a_tohdmitx_get_input(w); - struct snd_soc_dai *dai; - - if (WARN_ON(!in)) - return NULL; - - dai = in->priv; - - return dai->playback_dma_data; -} - static const char * const g12a_tohdmitx_i2s_mux_texts[] = { "I2S A", "I2S B", "I2S C", }; -static SOC_ENUM_SINGLE_EXT_DECL(g12a_tohdmitx_i2s_mux_enum, - g12a_tohdmitx_i2s_mux_texts); - -static int g12a_tohdmitx_get_input_val(struct snd_soc_component *component, - unsigned int mask) -{ - unsigned int val; - - snd_soc_component_read(component, TOHDMITX_CTRL0, &val); - return (val & mask) >> __ffs(mask); -} - -static int g12a_tohdmitx_i2s_mux_get_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = - snd_soc_dapm_kcontrol_component(kcontrol); - - ucontrol->value.enumerated.item[0] = - g12a_tohdmitx_get_input_val(component, CTRL0_I2S_DAT_SEL); - - return 0; -} - static int g12a_tohdmitx_i2s_mux_put_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int mux = ucontrol->value.enumerated.item[0]; - unsigned int val = g12a_tohdmitx_get_input_val(component, - CTRL0_I2S_DAT_SEL); + unsigned int mux, changed; + + mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]); + changed = snd_soc_component_test_bits(component, e->reg, + CTRL0_I2S_DAT_SEL, + FIELD_PREP(CTRL0_I2S_DAT_SEL, + mux)); + + if (!changed) + return 0; /* Force disconnect of the mux while updating */ - if (val != mux) - snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL); + snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL); - snd_soc_component_update_bits(component, TOHDMITX_CTRL0, + snd_soc_component_update_bits(component, e->reg, CTRL0_I2S_DAT_SEL | CTRL0_I2S_LRCLK_SEL | CTRL0_I2S_BCLK_SEL, @@ -130,30 +69,19 @@ static int g12a_tohdmitx_i2s_mux_put_enum(struct snd_kcontrol *kcontrol, return 0; } +static SOC_ENUM_SINGLE_DECL(g12a_tohdmitx_i2s_mux_enum, TOHDMITX_CTRL0, + CTRL0_I2S_DAT_SEL_SHIFT, + g12a_tohdmitx_i2s_mux_texts); + static const struct snd_kcontrol_new g12a_tohdmitx_i2s_mux = SOC_DAPM_ENUM_EXT("I2S Source", g12a_tohdmitx_i2s_mux_enum, - g12a_tohdmitx_i2s_mux_get_enum, + snd_soc_dapm_get_enum_double, g12a_tohdmitx_i2s_mux_put_enum); static const char * const g12a_tohdmitx_spdif_mux_texts[] = { "SPDIF A", "SPDIF B", }; -static SOC_ENUM_SINGLE_EXT_DECL(g12a_tohdmitx_spdif_mux_enum, - g12a_tohdmitx_spdif_mux_texts); - -static int g12a_tohdmitx_spdif_mux_get_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = - snd_soc_dapm_kcontrol_component(kcontrol); - - ucontrol->value.enumerated.item[0] = - g12a_tohdmitx_get_input_val(component, CTRL0_SPDIF_SEL); - - return 0; -} - static int g12a_tohdmitx_spdif_mux_put_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -162,13 +90,18 @@ static int g12a_tohdmitx_spdif_mux_put_enum(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int mux = ucontrol->value.enumerated.item[0]; - unsigned int val = g12a_tohdmitx_get_input_val(component, - CTRL0_SPDIF_SEL); + unsigned int mux, changed; + + mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]); + changed = snd_soc_component_test_bits(component, TOHDMITX_CTRL0, + CTRL0_SPDIF_SEL, + FIELD_PREP(CTRL0_SPDIF_SEL, mux)); + + if (!changed) + return 0; /* Force disconnect of the mux while updating */ - if (val != mux) - snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL); + snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL); snd_soc_component_update_bits(component, TOHDMITX_CTRL0, CTRL0_SPDIF_SEL | @@ -181,9 +114,13 @@ static int g12a_tohdmitx_spdif_mux_put_enum(struct snd_kcontrol *kcontrol, return 0; } +static SOC_ENUM_SINGLE_DECL(g12a_tohdmitx_spdif_mux_enum, TOHDMITX_CTRL0, + CTRL0_SPDIF_SEL_SHIFT, + g12a_tohdmitx_spdif_mux_texts); + static const struct snd_kcontrol_new g12a_tohdmitx_spdif_mux = SOC_DAPM_ENUM_EXT("SPDIF Source", g12a_tohdmitx_spdif_mux_enum, - g12a_tohdmitx_spdif_mux_get_enum, + snd_soc_dapm_get_enum_double, g12a_tohdmitx_spdif_mux_put_enum); static const struct snd_kcontrol_new g12a_tohdmitx_out_enable = @@ -201,83 +138,13 @@ static const struct snd_soc_dapm_widget g12a_tohdmitx_widgets[] = { &g12a_tohdmitx_out_enable), }; -static int g12a_tohdmitx_input_probe(struct snd_soc_dai *dai) -{ - struct g12a_tohdmitx_input *data; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - dai->playback_dma_data = data; - return 0; -} - -static int g12a_tohdmitx_input_remove(struct snd_soc_dai *dai) -{ - kfree(dai->playback_dma_data); - return 0; -} - -static int g12a_tohdmitx_input_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct g12a_tohdmitx_input *data = dai->playback_dma_data; - - data->params.rates = snd_pcm_rate_to_rate_bit(params_rate(params)); - data->params.rate_min = params_rate(params); - data->params.rate_max = params_rate(params); - data->params.formats = 1 << params_format(params); - data->params.channels_min = params_channels(params); - data->params.channels_max = params_channels(params); - data->params.sig_bits = dai->driver->playback.sig_bits; - - return 0; -} - - -static int g12a_tohdmitx_input_set_fmt(struct snd_soc_dai *dai, - unsigned int fmt) -{ - struct g12a_tohdmitx_input *data = dai->playback_dma_data; - - /* Save the source stream format for the downstream link */ - data->fmt = fmt; - return 0; -} - -static int g12a_tohdmitx_output_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct g12a_tohdmitx_input *in_data = - g12a_tohdmitx_get_input_data(dai->capture_widget); - - if (!in_data) - return -ENODEV; - - if (WARN_ON(!rtd->dai_link->params)) { - dev_warn(dai->dev, "codec2codec link expected\n"); - return -EINVAL; - } - - /* Replace link params with the input params */ - rtd->dai_link->params = &in_data->params; - - if (!in_data->fmt) - return 0; - - return snd_soc_runtime_set_dai_fmt(rtd, in_data->fmt); -} - static const struct snd_soc_dai_ops g12a_tohdmitx_input_ops = { - .hw_params = g12a_tohdmitx_input_hw_params, - .set_fmt = g12a_tohdmitx_input_set_fmt, + .hw_params = meson_codec_glue_input_hw_params, + .set_fmt = meson_codec_glue_input_set_fmt, }; static const struct snd_soc_dai_ops g12a_tohdmitx_output_ops = { - .startup = g12a_tohdmitx_output_startup, + .startup = meson_codec_glue_output_startup, }; #define TOHDMITX_SPDIF_FORMATS \ @@ -304,8 +171,8 @@ static const struct snd_soc_dai_ops g12a_tohdmitx_output_ops = { .id = (xid), \ .playback = TOHDMITX_STREAM(xname, "Playback", xfmt, xchmax), \ .ops = &g12a_tohdmitx_input_ops, \ - .probe = g12a_tohdmitx_input_probe, \ - .remove = g12a_tohdmitx_input_remove, \ + .probe = meson_codec_glue_input_dai_probe, \ + .remove = meson_codec_glue_input_dai_remove, \ } #define TOHDMITX_OUT(xname, xid, xfmt, xchmax) { \ diff --git a/sound/soc/meson/meson-codec-glue.c b/sound/soc/meson/meson-codec-glue.c new file mode 100644 index 000000000000..97bbc967e176 --- /dev/null +++ b/sound/soc/meson/meson-codec-glue.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2019 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include + +#include "meson-codec-glue.h" + +static struct snd_soc_dapm_widget * +meson_codec_glue_get_input(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_dapm_path *p = NULL; + struct snd_soc_dapm_widget *in; + + snd_soc_dapm_widget_for_each_source_path(w, p) { + if (!p->connect) + continue; + + /* Check that we still are in the same component */ + if (snd_soc_dapm_to_component(w->dapm) != + snd_soc_dapm_to_component(p->source->dapm)) + continue; + + if (p->source->id == snd_soc_dapm_dai_in) + return p->source; + + in = meson_codec_glue_get_input(p->source); + if (in) + return in; + } + + return NULL; +} + +static void meson_codec_glue_input_set_data(struct snd_soc_dai *dai, + struct meson_codec_glue_input *data) +{ + dai->playback_dma_data = data; +} + +struct meson_codec_glue_input * +meson_codec_glue_input_get_data(struct snd_soc_dai *dai) +{ + return dai->playback_dma_data; +} +EXPORT_SYMBOL_GPL(meson_codec_glue_input_get_data); + +static struct meson_codec_glue_input * +meson_codec_glue_output_get_input_data(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_dapm_widget *in = + meson_codec_glue_get_input(w); + struct snd_soc_dai *dai; + + if (WARN_ON(!in)) + return NULL; + + dai = in->priv; + + return meson_codec_glue_input_get_data(dai); +} + +int meson_codec_glue_input_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct meson_codec_glue_input *data = + meson_codec_glue_input_get_data(dai); + + data->params.rates = snd_pcm_rate_to_rate_bit(params_rate(params)); + data->params.rate_min = params_rate(params); + data->params.rate_max = params_rate(params); + data->params.formats = 1 << params_format(params); + data->params.channels_min = params_channels(params); + data->params.channels_max = params_channels(params); + data->params.sig_bits = dai->driver->playback.sig_bits; + + return 0; +} +EXPORT_SYMBOL_GPL(meson_codec_glue_input_hw_params); + +int meson_codec_glue_input_set_fmt(struct snd_soc_dai *dai, + unsigned int fmt) +{ + struct meson_codec_glue_input *data = + meson_codec_glue_input_get_data(dai); + + /* Save the source stream format for the downstream link */ + data->fmt = fmt; + return 0; +} +EXPORT_SYMBOL_GPL(meson_codec_glue_input_set_fmt); + +int meson_codec_glue_output_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct meson_codec_glue_input *in_data = + meson_codec_glue_output_get_input_data(dai->capture_widget); + + if (!in_data) + return -ENODEV; + + if (WARN_ON(!rtd->dai_link->params)) { + dev_warn(dai->dev, "codec2codec link expected\n"); + return -EINVAL; + } + + /* Replace link params with the input params */ + rtd->dai_link->params = &in_data->params; + + if (!in_data->fmt) + return 0; + + return snd_soc_runtime_set_dai_fmt(rtd, in_data->fmt); +} +EXPORT_SYMBOL_GPL(meson_codec_glue_output_startup); + +int meson_codec_glue_input_dai_probe(struct snd_soc_dai *dai) +{ + struct meson_codec_glue_input *data; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + meson_codec_glue_input_set_data(dai, data); + return 0; +} +EXPORT_SYMBOL_GPL(meson_codec_glue_input_dai_probe); + +int meson_codec_glue_input_dai_remove(struct snd_soc_dai *dai) +{ + struct meson_codec_glue_input *data = + meson_codec_glue_input_get_data(dai); + + kfree(data); + return 0; +} +EXPORT_SYMBOL_GPL(meson_codec_glue_input_dai_remove); + +MODULE_AUTHOR("Jerome Brunet "); +MODULE_DESCRIPTION("Amlogic Codec Glue Helpers"); +MODULE_LICENSE("GPL v2"); + diff --git a/sound/soc/meson/meson-codec-glue.h b/sound/soc/meson/meson-codec-glue.h new file mode 100644 index 000000000000..07f99446c0c6 --- /dev/null +++ b/sound/soc/meson/meson-codec-glue.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (c) 2018 Baylibre SAS. + * Author: Jerome Brunet + */ + +#ifndef _MESON_CODEC_GLUE_H +#define _MESON_CODEC_GLUE_H + +#include + +struct meson_codec_glue_input { + struct snd_soc_pcm_stream params; + unsigned int fmt; +}; + +/* Input helpers */ +struct meson_codec_glue_input * +meson_codec_glue_input_get_data(struct snd_soc_dai *dai); +int meson_codec_glue_input_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai); +int meson_codec_glue_input_set_fmt(struct snd_soc_dai *dai, + unsigned int fmt); +int meson_codec_glue_input_dai_probe(struct snd_soc_dai *dai); +int meson_codec_glue_input_dai_remove(struct snd_soc_dai *dai); + +/* Output helpers */ +int meson_codec_glue_output_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai); + +#endif /* _MESON_CODEC_GLUE_H */ From 06b72824386795bf6f0a6ac0f0cfef6b7f0165c1 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 13 Feb 2020 16:51:53 +0100 Subject: [PATCH 0295/4444] ASoC: meson: aiu: add audio output dt-bindings Add the dt-bindings and documentation of the AIU audio controller. This component provides most of the audio outputs found on the Amlogic Gx SoC family. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200213155159.3235792-4-jbrunet@baylibre.com Signed-off-by: Mark Brown --- .../bindings/sound/amlogic,aiu.yaml | 111 ++++++++++++++++++ include/dt-bindings/sound/meson-aiu.h | 18 +++ 2 files changed, 129 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/amlogic,aiu.yaml create mode 100644 include/dt-bindings/sound/meson-aiu.h diff --git a/Documentation/devicetree/bindings/sound/amlogic,aiu.yaml b/Documentation/devicetree/bindings/sound/amlogic,aiu.yaml new file mode 100644 index 000000000000..3ef7632dcb59 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/amlogic,aiu.yaml @@ -0,0 +1,111 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/amlogic,aiu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic AIU audio output controller + +maintainers: + - Jerome Brunet + +properties: + $nodename: + pattern: "^audio-controller@.*" + + "#sound-dai-cells": + const: 2 + + compatible: + items: + - enum: + - amlogic,aiu-gxbb + - amlogic,aiu-gxl + - const: + amlogic,aiu + + clocks: + items: + - description: AIU peripheral clock + - description: I2S peripheral clock + - description: I2S output clock + - description: I2S master clock + - description: I2S mixer clock + - description: SPDIF peripheral clock + - description: SPDIF output clock + - description: SPDIF master clock + - description: SPDIF master clock multiplexer + + clock-names: + items: + - const: pclk + - const: i2s_pclk + - const: i2s_aoclk + - const: i2s_mclk + - const: i2s_mixer + - const: spdif_pclk + - const: spdif_aoclk + - const: spdif_mclk + - const: spdif_mclk_sel + + interrupts: + items: + - description: I2S interrupt line + - description: SPDIF interrupt line + + interrupt-names: + items: + - const: i2s + - const: spdif + + reg: + maxItems: 1 + + resets: + maxItems: 1 + +required: + - "#sound-dai-cells" + - compatible + - clocks + - clock-names + - interrupts + - interrupt-names + - reg + - resets + +examples: + - | + #include + #include + #include + #include + + aiu: audio-controller@5400 { + compatible = "amlogic,aiu-gxl", "amlogic,aiu"; + #sound-dai-cells = <2>; + reg = <0x0 0x5400 0x0 0x2ac>; + interrupts = , + ; + interrupt-names = "i2s", "spdif"; + clocks = <&clkc CLKID_AIU_GLUE>, + <&clkc CLKID_I2S_OUT>, + <&clkc CLKID_AOCLK_GATE>, + <&clkc CLKID_CTS_AMCLK>, + <&clkc CLKID_MIXER_IFACE>, + <&clkc CLKID_IEC958>, + <&clkc CLKID_IEC958_GATE>, + <&clkc CLKID_CTS_MCLK_I958>, + <&clkc CLKID_CTS_I958>; + clock-names = "pclk", + "i2s_pclk", + "i2s_aoclk", + "i2s_mclk", + "i2s_mixer", + "spdif_pclk", + "spdif_aoclk", + "spdif_mclk", + "spdif_mclk_sel"; + resets = <&reset RESET_AIU>; + }; + diff --git a/include/dt-bindings/sound/meson-aiu.h b/include/dt-bindings/sound/meson-aiu.h new file mode 100644 index 000000000000..1051b8af298b --- /dev/null +++ b/include/dt-bindings/sound/meson-aiu.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __DT_MESON_AIU_H +#define __DT_MESON_AIU_H + +#define AIU_CPU 0 +#define AIU_HDMI 1 +#define AIU_ACODEC 2 + +#define CPU_I2S_FIFO 0 +#define CPU_SPDIF_FIFO 1 +#define CPU_I2S_ENCODER 2 +#define CPU_SPDIF_ENCODER 3 + +#define CTRL_I2S 0 +#define CTRL_PCM 1 +#define CTRL_OUT 2 + +#endif /* __DT_MESON_AIU_H */ From 6ae9ca9ce986bffe71fd0fbf9595de8500891b52 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 13 Feb 2020 16:51:54 +0100 Subject: [PATCH 0296/4444] ASoC: meson: aiu: add i2s and spdif support Add support for the i2s and spdif audio outputs (AIU) found in the amlogic Gx SoC family Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200213155159.3235792-5-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/Kconfig | 7 + sound/soc/meson/Makefile | 7 + sound/soc/meson/aiu-encoder-i2s.c | 324 ++++++++++++++++++++++++++ sound/soc/meson/aiu-encoder-spdif.c | 209 +++++++++++++++++ sound/soc/meson/aiu-fifo-i2s.c | 153 ++++++++++++ sound/soc/meson/aiu-fifo-spdif.c | 186 +++++++++++++++ sound/soc/meson/aiu-fifo.c | 223 ++++++++++++++++++ sound/soc/meson/aiu-fifo.h | 50 ++++ sound/soc/meson/aiu.c | 348 ++++++++++++++++++++++++++++ sound/soc/meson/aiu.h | 82 +++++++ 10 files changed, 1589 insertions(+) create mode 100644 sound/soc/meson/aiu-encoder-i2s.c create mode 100644 sound/soc/meson/aiu-encoder-spdif.c create mode 100644 sound/soc/meson/aiu-fifo-i2s.c create mode 100644 sound/soc/meson/aiu-fifo-spdif.c create mode 100644 sound/soc/meson/aiu-fifo.c create mode 100644 sound/soc/meson/aiu-fifo.h create mode 100644 sound/soc/meson/aiu.c create mode 100644 sound/soc/meson/aiu.h diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index ee6d53949d45..ca269dedfc7f 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -2,6 +2,13 @@ menu "ASoC support for Amlogic platforms" depends on ARCH_MESON || COMPILE_TEST +config SND_MESON_AIU + tristate "Amlogic AIU" + select SND_PCM_IEC958 + help + Select Y or M to add support for the Audio output subsystem found + in the Amlogic GX SoC family + config SND_MESON_AXG_FIFO tristate select REGMAP_MMIO diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index 529a807b3f37..a7b79d717288 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -1,5 +1,11 @@ # SPDX-License-Identifier: (GPL-2.0 OR MIT) +snd-soc-meson-aiu-objs := aiu.o +snd-soc-meson-aiu-objs += aiu-encoder-i2s.o +snd-soc-meson-aiu-objs += aiu-encoder-spdif.o +snd-soc-meson-aiu-objs += aiu-fifo.o +snd-soc-meson-aiu-objs += aiu-fifo-i2s.o +snd-soc-meson-aiu-objs += aiu-fifo-spdif.o snd-soc-meson-axg-fifo-objs := axg-fifo.o snd-soc-meson-axg-frddr-objs := axg-frddr.o snd-soc-meson-axg-toddr-objs := axg-toddr.o @@ -14,6 +20,7 @@ snd-soc-meson-axg-pdm-objs := axg-pdm.o snd-soc-meson-codec-glue-objs := meson-codec-glue.o snd-soc-meson-g12a-tohdmitx-objs := g12a-tohdmitx.o +obj-$(CONFIG_SND_MESON_AIU) += snd-soc-meson-aiu.o obj-$(CONFIG_SND_MESON_AXG_FIFO) += snd-soc-meson-axg-fifo.o obj-$(CONFIG_SND_MESON_AXG_FRDDR) += snd-soc-meson-axg-frddr.o obj-$(CONFIG_SND_MESON_AXG_TODDR) += snd-soc-meson-axg-toddr.o diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encoder-i2s.c new file mode 100644 index 000000000000..13bf029086a9 --- /dev/null +++ b/sound/soc/meson/aiu-encoder-i2s.c @@ -0,0 +1,324 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2020 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include +#include + +#include "aiu.h" + +#define AIU_I2S_SOURCE_DESC_MODE_8CH BIT(0) +#define AIU_I2S_SOURCE_DESC_MODE_24BIT BIT(5) +#define AIU_I2S_SOURCE_DESC_MODE_32BIT BIT(9) +#define AIU_I2S_SOURCE_DESC_MODE_SPLIT BIT(11) +#define AIU_RST_SOFT_I2S_FAST BIT(0) + +#define AIU_I2S_DAC_CFG_MSB_FIRST BIT(2) +#define AIU_I2S_MISC_HOLD_EN BIT(2) +#define AIU_CLK_CTRL_I2S_DIV_EN BIT(0) +#define AIU_CLK_CTRL_I2S_DIV GENMASK(3, 2) +#define AIU_CLK_CTRL_AOCLK_INVERT BIT(6) +#define AIU_CLK_CTRL_LRCLK_INVERT BIT(7) +#define AIU_CLK_CTRL_LRCLK_SKEW GENMASK(9, 8) +#define AIU_CLK_CTRL_MORE_HDMI_AMCLK BIT(6) +#define AIU_CLK_CTRL_MORE_I2S_DIV GENMASK(5, 0) +#define AIU_CODEC_DAC_LRCLK_CTRL_DIV GENMASK(11, 0) + +struct aiu_encoder_i2s { + struct clk *aoclk; + struct clk *mclk; + struct clk *mixer; + struct clk *pclk; +}; + +static void aiu_encoder_i2s_divider_enable(struct snd_soc_component *component, + bool enable) +{ + snd_soc_component_update_bits(component, AIU_CLK_CTRL, + AIU_CLK_CTRL_I2S_DIV_EN, + enable ? AIU_CLK_CTRL_I2S_DIV_EN : 0); +} + +static void aiu_encoder_i2s_hold(struct snd_soc_component *component, + bool enable) +{ + snd_soc_component_update_bits(component, AIU_I2S_MISC, + AIU_I2S_MISC_HOLD_EN, + enable ? AIU_I2S_MISC_HOLD_EN : 0); +} + +static int aiu_encoder_i2s_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + aiu_encoder_i2s_hold(component, false); + return 0; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + aiu_encoder_i2s_hold(component, true); + return 0; + + default: + return -EINVAL; + } +} + +static int aiu_encoder_i2s_setup_desc(struct snd_soc_component *component, + struct snd_pcm_hw_params *params) +{ + /* Always operate in split (classic interleaved) mode */ + unsigned int desc = AIU_I2S_SOURCE_DESC_MODE_SPLIT; + unsigned int val; + + /* Reset required to update the pipeline */ + snd_soc_component_write(component, AIU_RST_SOFT, AIU_RST_SOFT_I2S_FAST); + snd_soc_component_read(component, AIU_I2S_SYNC, &val); + + switch (params_physical_width(params)) { + case 16: /* Nothing to do */ + break; + + case 32: + desc |= (AIU_I2S_SOURCE_DESC_MODE_24BIT | + AIU_I2S_SOURCE_DESC_MODE_32BIT); + break; + + default: + return -EINVAL; + } + + switch (params_channels(params)) { + case 2: /* Nothing to do */ + break; + case 8: + desc |= AIU_I2S_SOURCE_DESC_MODE_8CH; + break; + default: + return -EINVAL; + } + + snd_soc_component_update_bits(component, AIU_I2S_SOURCE_DESC, + AIU_I2S_SOURCE_DESC_MODE_8CH | + AIU_I2S_SOURCE_DESC_MODE_24BIT | + AIU_I2S_SOURCE_DESC_MODE_32BIT | + AIU_I2S_SOURCE_DESC_MODE_SPLIT, + desc); + + return 0; +} + +static int aiu_encoder_i2s_set_clocks(struct snd_soc_component *component, + struct snd_pcm_hw_params *params) +{ + struct aiu *aiu = snd_soc_component_get_drvdata(component); + unsigned int srate = params_rate(params); + unsigned int fs, bs; + + /* Get the oversampling factor */ + fs = DIV_ROUND_CLOSEST(clk_get_rate(aiu->i2s.clks[MCLK].clk), srate); + + if (fs % 64) + return -EINVAL; + + /* Send data MSB first */ + snd_soc_component_update_bits(component, AIU_I2S_DAC_CFG, + AIU_I2S_DAC_CFG_MSB_FIRST, + AIU_I2S_DAC_CFG_MSB_FIRST); + + /* Set bclk to lrlck ratio */ + snd_soc_component_update_bits(component, AIU_CODEC_DAC_LRCLK_CTRL, + AIU_CODEC_DAC_LRCLK_CTRL_DIV, + FIELD_PREP(AIU_CODEC_DAC_LRCLK_CTRL_DIV, + 64 - 1)); + + /* Use CLK_MORE for mclk to bclk divider */ + snd_soc_component_update_bits(component, AIU_CLK_CTRL, + AIU_CLK_CTRL_I2S_DIV, 0); + + /* + * NOTE: this HW is odd. + * In most configuration, the i2s divider is 'mclk / blck'. + * However, in 16 bits - 8ch mode, this factor needs to be + * increased by 50% to get the correct output rate. + * No idea why ! + */ + bs = fs / 64; + if (params_width(params) == 16 && params_channels(params) == 8) { + if (bs % 2) { + dev_err(component->dev, + "Cannot increase i2s divider by 50%%\n"); + return -EINVAL; + } + bs += bs / 2; + } + + snd_soc_component_update_bits(component, AIU_CLK_CTRL_MORE, + AIU_CLK_CTRL_MORE_I2S_DIV, + FIELD_PREP(AIU_CLK_CTRL_MORE_I2S_DIV, + bs - 1)); + + /* Make sure amclk is used for HDMI i2s as well */ + snd_soc_component_update_bits(component, AIU_CLK_CTRL_MORE, + AIU_CLK_CTRL_MORE_HDMI_AMCLK, + AIU_CLK_CTRL_MORE_HDMI_AMCLK); + + return 0; +} + +static int aiu_encoder_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + int ret; + + /* Disable the clock while changing the settings */ + aiu_encoder_i2s_divider_enable(component, false); + + ret = aiu_encoder_i2s_setup_desc(component, params); + if (ret) { + dev_err(dai->dev, "setting i2s desc failed\n"); + return ret; + } + + ret = aiu_encoder_i2s_set_clocks(component, params); + if (ret) { + dev_err(dai->dev, "setting i2s clocks failed\n"); + return ret; + } + + aiu_encoder_i2s_divider_enable(component, true); + + return 0; +} + +static int aiu_encoder_i2s_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + + aiu_encoder_i2s_divider_enable(component, false); + + return 0; +} + +static int aiu_encoder_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_component *component = dai->component; + unsigned int inv = fmt & SND_SOC_DAIFMT_INV_MASK; + unsigned int val = 0; + unsigned int skew; + + /* Only CPU Master / Codec Slave supported ATM */ + if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) + return -EINVAL; + + if (inv == SND_SOC_DAIFMT_NB_IF || + inv == SND_SOC_DAIFMT_IB_IF) + val |= AIU_CLK_CTRL_LRCLK_INVERT; + + if (inv == SND_SOC_DAIFMT_IB_NF || + inv == SND_SOC_DAIFMT_IB_IF) + val |= AIU_CLK_CTRL_AOCLK_INVERT; + + /* Signal skew */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + /* Invert sample clock for i2s */ + val ^= AIU_CLK_CTRL_LRCLK_INVERT; + skew = 1; + break; + case SND_SOC_DAIFMT_LEFT_J: + skew = 0; + break; + default: + return -EINVAL; + } + + val |= FIELD_PREP(AIU_CLK_CTRL_LRCLK_SKEW, skew); + snd_soc_component_update_bits(component, AIU_CLK_CTRL, + AIU_CLK_CTRL_LRCLK_INVERT | + AIU_CLK_CTRL_AOCLK_INVERT | + AIU_CLK_CTRL_LRCLK_SKEW, + val); + + return 0; +} + +static int aiu_encoder_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + struct aiu *aiu = snd_soc_component_get_drvdata(dai->component); + int ret; + + if (WARN_ON(clk_id != 0)) + return -EINVAL; + + if (dir == SND_SOC_CLOCK_IN) + return 0; + + ret = clk_set_rate(aiu->i2s.clks[MCLK].clk, freq); + if (ret) + dev_err(dai->dev, "Failed to set sysclk to %uHz", freq); + + return ret; +} + +static const unsigned int hw_channels[] = {2, 8}; +static const struct snd_pcm_hw_constraint_list hw_channel_constraints = { + .list = hw_channels, + .count = ARRAY_SIZE(hw_channels), + .mask = 0, +}; + +static int aiu_encoder_i2s_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct aiu *aiu = snd_soc_component_get_drvdata(dai->component); + int ret; + + /* Make sure the encoder gets either 2 or 8 channels */ + ret = snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &hw_channel_constraints); + if (ret) { + dev_err(dai->dev, "adding channels constraints failed\n"); + return ret; + } + + ret = clk_bulk_prepare_enable(aiu->i2s.clk_num, aiu->i2s.clks); + if (ret) + dev_err(dai->dev, "failed to enable i2s clocks\n"); + + return ret; +} + +static void aiu_encoder_i2s_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct aiu *aiu = snd_soc_component_get_drvdata(dai->component); + + clk_bulk_disable_unprepare(aiu->i2s.clk_num, aiu->i2s.clks); +} + +const struct snd_soc_dai_ops aiu_encoder_i2s_dai_ops = { + .trigger = aiu_encoder_i2s_trigger, + .hw_params = aiu_encoder_i2s_hw_params, + .hw_free = aiu_encoder_i2s_hw_free, + .set_fmt = aiu_encoder_i2s_set_fmt, + .set_sysclk = aiu_encoder_i2s_set_sysclk, + .startup = aiu_encoder_i2s_startup, + .shutdown = aiu_encoder_i2s_shutdown, +}; + diff --git a/sound/soc/meson/aiu-encoder-spdif.c b/sound/soc/meson/aiu-encoder-spdif.c new file mode 100644 index 000000000000..de850913975f --- /dev/null +++ b/sound/soc/meson/aiu-encoder-spdif.c @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2020 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include +#include +#include + +#include "aiu.h" + +#define AIU_958_MISC_NON_PCM BIT(0) +#define AIU_958_MISC_MODE_16BITS BIT(1) +#define AIU_958_MISC_16BITS_ALIGN GENMASK(6, 5) +#define AIU_958_MISC_MODE_32BITS BIT(7) +#define AIU_958_MISC_U_FROM_STREAM BIT(12) +#define AIU_958_MISC_FORCE_LR BIT(13) +#define AIU_958_CTRL_HOLD_EN BIT(0) +#define AIU_CLK_CTRL_958_DIV_EN BIT(1) +#define AIU_CLK_CTRL_958_DIV GENMASK(5, 4) +#define AIU_CLK_CTRL_958_DIV_MORE BIT(12) + +#define AIU_CS_WORD_LEN 4 +#define AIU_958_INTERNAL_DIV 2 + +static void +aiu_encoder_spdif_divider_enable(struct snd_soc_component *component, + bool enable) +{ + snd_soc_component_update_bits(component, AIU_CLK_CTRL, + AIU_CLK_CTRL_958_DIV_EN, + enable ? AIU_CLK_CTRL_958_DIV_EN : 0); +} + +static void aiu_encoder_spdif_hold(struct snd_soc_component *component, + bool enable) +{ + snd_soc_component_update_bits(component, AIU_958_CTRL, + AIU_958_CTRL_HOLD_EN, + enable ? AIU_958_CTRL_HOLD_EN : 0); +} + +static int +aiu_encoder_spdif_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + aiu_encoder_spdif_hold(component, false); + return 0; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + aiu_encoder_spdif_hold(component, true); + return 0; + + default: + return -EINVAL; + } +} + +static int aiu_encoder_spdif_setup_cs_word(struct snd_soc_component *component, + struct snd_pcm_hw_params *params) +{ + u8 cs[AIU_CS_WORD_LEN]; + unsigned int val; + int ret; + + ret = snd_pcm_create_iec958_consumer_hw_params(params, cs, + AIU_CS_WORD_LEN); + if (ret < 0) + return ret; + + /* Write the 1st half word */ + val = cs[1] | cs[0] << 8; + snd_soc_component_write(component, AIU_958_CHSTAT_L0, val); + snd_soc_component_write(component, AIU_958_CHSTAT_R0, val); + + /* Write the 2nd half word */ + val = cs[3] | cs[2] << 8; + snd_soc_component_write(component, AIU_958_CHSTAT_L1, val); + snd_soc_component_write(component, AIU_958_CHSTAT_R1, val); + + return 0; +} + +static int aiu_encoder_spdif_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct aiu *aiu = snd_soc_component_get_drvdata(component); + unsigned int val = 0, mrate; + int ret; + + /* Disable the clock while changing the settings */ + aiu_encoder_spdif_divider_enable(component, false); + + switch (params_physical_width(params)) { + case 16: + val |= AIU_958_MISC_MODE_16BITS; + val |= FIELD_PREP(AIU_958_MISC_16BITS_ALIGN, 2); + break; + case 32: + val |= AIU_958_MISC_MODE_32BITS; + break; + default: + dev_err(dai->dev, "Unsupport physical width\n"); + return -EINVAL; + } + + snd_soc_component_update_bits(component, AIU_958_MISC, + AIU_958_MISC_NON_PCM | + AIU_958_MISC_MODE_16BITS | + AIU_958_MISC_16BITS_ALIGN | + AIU_958_MISC_MODE_32BITS | + AIU_958_MISC_FORCE_LR | + AIU_958_MISC_U_FROM_STREAM, + val); + + /* Set the stream channel status word */ + ret = aiu_encoder_spdif_setup_cs_word(component, params); + if (ret) { + dev_err(dai->dev, "failed to set channel status word\n"); + return ret; + } + + snd_soc_component_update_bits(component, AIU_CLK_CTRL, + AIU_CLK_CTRL_958_DIV | + AIU_CLK_CTRL_958_DIV_MORE, + FIELD_PREP(AIU_CLK_CTRL_958_DIV, + __ffs(AIU_958_INTERNAL_DIV))); + + /* 2 * 32bits per subframe * 2 channels = 128 */ + mrate = params_rate(params) * 128 * AIU_958_INTERNAL_DIV; + ret = clk_set_rate(aiu->spdif.clks[MCLK].clk, mrate); + if (ret) { + dev_err(dai->dev, "failed to set mclk rate\n"); + return ret; + } + + aiu_encoder_spdif_divider_enable(component, true); + + return 0; +} + +static int aiu_encoder_spdif_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + + aiu_encoder_spdif_divider_enable(component, false); + + return 0; +} + +static int aiu_encoder_spdif_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct aiu *aiu = snd_soc_component_get_drvdata(dai->component); + int ret; + + /* + * NOTE: Make sure the spdif block is on its own divider. + * + * The spdif can be clocked by the i2s master clock or its own + * clock. We should (in theory) change the source depending on the + * origin of the data. + * + * However, considering the clocking scheme used on these platforms, + * the master clocks will pick the same PLL source when they are + * playing from the same FIFO. The clock should be in sync so, it + * should not be necessary to reparent the spdif master clock. + */ + ret = clk_set_parent(aiu->spdif.clks[MCLK].clk, + aiu->spdif_mclk); + if (ret) + return ret; + + ret = clk_bulk_prepare_enable(aiu->spdif.clk_num, aiu->spdif.clks); + if (ret) + dev_err(dai->dev, "failed to enable spdif clocks\n"); + + return ret; +} + +static void aiu_encoder_spdif_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct aiu *aiu = snd_soc_component_get_drvdata(dai->component); + + clk_bulk_disable_unprepare(aiu->spdif.clk_num, aiu->spdif.clks); +} + +const struct snd_soc_dai_ops aiu_encoder_spdif_dai_ops = { + .trigger = aiu_encoder_spdif_trigger, + .hw_params = aiu_encoder_spdif_hw_params, + .hw_free = aiu_encoder_spdif_hw_free, + .startup = aiu_encoder_spdif_startup, + .shutdown = aiu_encoder_spdif_shutdown, +}; diff --git a/sound/soc/meson/aiu-fifo-i2s.c b/sound/soc/meson/aiu-fifo-i2s.c new file mode 100644 index 000000000000..9a5271ce80fe --- /dev/null +++ b/sound/soc/meson/aiu-fifo-i2s.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2020 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include +#include + +#include "aiu.h" +#include "aiu-fifo.h" + +#define AIU_I2S_SOURCE_DESC_MODE_8CH BIT(0) +#define AIU_I2S_SOURCE_DESC_MODE_24BIT BIT(5) +#define AIU_I2S_SOURCE_DESC_MODE_32BIT BIT(9) +#define AIU_I2S_SOURCE_DESC_MODE_SPLIT BIT(11) +#define AIU_MEM_I2S_MASKS_IRQ_BLOCK GENMASK(31, 16) +#define AIU_MEM_I2S_CONTROL_MODE_16BIT BIT(6) +#define AIU_MEM_I2S_BUF_CNTL_INIT BIT(0) +#define AIU_RST_SOFT_I2S_FAST BIT(0) + +#define AIU_FIFO_I2S_BLOCK 256 + +static struct snd_pcm_hardware fifo_i2s_pcm = { + .info = (SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE), + .formats = AIU_FORMATS, + .rate_min = 5512, + .rate_max = 192000, + .channels_min = 2, + .channels_max = 8, + .period_bytes_min = AIU_FIFO_I2S_BLOCK, + .period_bytes_max = AIU_FIFO_I2S_BLOCK * USHRT_MAX, + .periods_min = 2, + .periods_max = UINT_MAX, + + /* No real justification for this */ + .buffer_bytes_max = 1 * 1024 * 1024, +}; + +static int aiu_fifo_i2s_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + unsigned int val; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + snd_soc_component_write(component, AIU_RST_SOFT, + AIU_RST_SOFT_I2S_FAST); + snd_soc_component_read(component, AIU_I2S_SYNC, &val); + break; + } + + return aiu_fifo_trigger(substream, cmd, dai); +} + +static int aiu_fifo_i2s_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + int ret; + + ret = aiu_fifo_prepare(substream, dai); + if (ret) + return ret; + + snd_soc_component_update_bits(component, + AIU_MEM_I2S_BUF_CNTL, + AIU_MEM_I2S_BUF_CNTL_INIT, + AIU_MEM_I2S_BUF_CNTL_INIT); + snd_soc_component_update_bits(component, + AIU_MEM_I2S_BUF_CNTL, + AIU_MEM_I2S_BUF_CNTL_INIT, 0); + + return 0; +} + +static int aiu_fifo_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct aiu_fifo *fifo = dai->playback_dma_data; + unsigned int val; + int ret; + + ret = aiu_fifo_hw_params(substream, params, dai); + if (ret) + return ret; + + switch (params_physical_width(params)) { + case 16: + val = AIU_MEM_I2S_CONTROL_MODE_16BIT; + break; + case 32: + val = 0; + break; + default: + dev_err(dai->dev, "Unsupported physical width %u\n", + params_physical_width(params)); + return -EINVAL; + } + + snd_soc_component_update_bits(component, AIU_MEM_I2S_CONTROL, + AIU_MEM_I2S_CONTROL_MODE_16BIT, + val); + + /* Setup the irq periodicity */ + val = params_period_bytes(params) / fifo->fifo_block; + val = FIELD_PREP(AIU_MEM_I2S_MASKS_IRQ_BLOCK, val); + snd_soc_component_update_bits(component, AIU_MEM_I2S_MASKS, + AIU_MEM_I2S_MASKS_IRQ_BLOCK, val); + + return 0; +} + +const struct snd_soc_dai_ops aiu_fifo_i2s_dai_ops = { + .trigger = aiu_fifo_i2s_trigger, + .prepare = aiu_fifo_i2s_prepare, + .hw_params = aiu_fifo_i2s_hw_params, + .hw_free = aiu_fifo_hw_free, + .startup = aiu_fifo_startup, + .shutdown = aiu_fifo_shutdown, +}; + +int aiu_fifo_i2s_dai_probe(struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct aiu *aiu = snd_soc_component_get_drvdata(component); + struct aiu_fifo *fifo; + int ret; + + ret = aiu_fifo_dai_probe(dai); + if (ret) + return ret; + + fifo = dai->playback_dma_data; + + fifo->pcm = &fifo_i2s_pcm; + fifo->mem_offset = AIU_MEM_I2S_START; + fifo->fifo_block = AIU_FIFO_I2S_BLOCK; + fifo->pclk = aiu->i2s.clks[PCLK].clk; + fifo->irq = aiu->i2s.irq; + + return 0; +} diff --git a/sound/soc/meson/aiu-fifo-spdif.c b/sound/soc/meson/aiu-fifo-spdif.c new file mode 100644 index 000000000000..44eb6faacf44 --- /dev/null +++ b/sound/soc/meson/aiu-fifo-spdif.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2020 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include + +#include "aiu.h" +#include "aiu-fifo.h" + +#define AIU_IEC958_DCU_FF_CTRL_EN BIT(0) +#define AIU_IEC958_DCU_FF_CTRL_AUTO_DISABLE BIT(1) +#define AIU_IEC958_DCU_FF_CTRL_IRQ_MODE GENMASK(3, 2) +#define AIU_IEC958_DCU_FF_CTRL_IRQ_OUT_THD BIT(2) +#define AIU_IEC958_DCU_FF_CTRL_IRQ_FRAME_READ BIT(3) +#define AIU_IEC958_DCU_FF_CTRL_SYNC_HEAD_EN BIT(4) +#define AIU_IEC958_DCU_FF_CTRL_BYTE_SEEK BIT(5) +#define AIU_IEC958_DCU_FF_CTRL_CONTINUE BIT(6) +#define AIU_MEM_IEC958_CONTROL_ENDIAN GENMASK(5, 3) +#define AIU_MEM_IEC958_CONTROL_RD_DDR BIT(6) +#define AIU_MEM_IEC958_CONTROL_MODE_16BIT BIT(7) +#define AIU_MEM_IEC958_CONTROL_MODE_LINEAR BIT(8) +#define AIU_MEM_IEC958_BUF_CNTL_INIT BIT(0) + +#define AIU_FIFO_SPDIF_BLOCK 8 + +static struct snd_pcm_hardware fifo_spdif_pcm = { + .info = (SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE), + .formats = AIU_FORMATS, + .rate_min = 5512, + .rate_max = 192000, + .channels_min = 2, + .channels_max = 2, + .period_bytes_min = AIU_FIFO_SPDIF_BLOCK, + .period_bytes_max = AIU_FIFO_SPDIF_BLOCK * USHRT_MAX, + .periods_min = 2, + .periods_max = UINT_MAX, + + /* No real justification for this */ + .buffer_bytes_max = 1 * 1024 * 1024, +}; + +static void fifo_spdif_dcu_enable(struct snd_soc_component *component, + bool enable) +{ + snd_soc_component_update_bits(component, AIU_IEC958_DCU_FF_CTRL, + AIU_IEC958_DCU_FF_CTRL_EN, + enable ? AIU_IEC958_DCU_FF_CTRL_EN : 0); +} + +static int fifo_spdif_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + int ret; + + ret = aiu_fifo_trigger(substream, cmd, dai); + if (ret) + return ret; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + fifo_spdif_dcu_enable(component, true); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_STOP: + fifo_spdif_dcu_enable(component, false); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int fifo_spdif_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + int ret; + + ret = aiu_fifo_prepare(substream, dai); + if (ret) + return ret; + + snd_soc_component_update_bits(component, + AIU_MEM_IEC958_BUF_CNTL, + AIU_MEM_IEC958_BUF_CNTL_INIT, + AIU_MEM_IEC958_BUF_CNTL_INIT); + snd_soc_component_update_bits(component, + AIU_MEM_IEC958_BUF_CNTL, + AIU_MEM_IEC958_BUF_CNTL_INIT, 0); + + return 0; +} + +static int fifo_spdif_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + unsigned int val; + int ret; + + ret = aiu_fifo_hw_params(substream, params, dai); + if (ret) + return ret; + + val = AIU_MEM_IEC958_CONTROL_RD_DDR | + AIU_MEM_IEC958_CONTROL_MODE_LINEAR; + + switch (params_physical_width(params)) { + case 16: + val |= AIU_MEM_IEC958_CONTROL_MODE_16BIT; + break; + case 32: + break; + default: + dev_err(dai->dev, "Unsupported physical width %u\n", + params_physical_width(params)); + return -EINVAL; + } + + snd_soc_component_update_bits(component, AIU_MEM_IEC958_CONTROL, + AIU_MEM_IEC958_CONTROL_ENDIAN | + AIU_MEM_IEC958_CONTROL_RD_DDR | + AIU_MEM_IEC958_CONTROL_MODE_LINEAR | + AIU_MEM_IEC958_CONTROL_MODE_16BIT, + val); + + /* Number bytes read by the FIFO between each IRQ */ + snd_soc_component_write(component, AIU_IEC958_BPF, + params_period_bytes(params)); + + /* + * AUTO_DISABLE and SYNC_HEAD are enabled by default but + * this should be disabled in PCM (uncompressed) mode + */ + snd_soc_component_update_bits(component, AIU_IEC958_DCU_FF_CTRL, + AIU_IEC958_DCU_FF_CTRL_AUTO_DISABLE | + AIU_IEC958_DCU_FF_CTRL_IRQ_MODE | + AIU_IEC958_DCU_FF_CTRL_SYNC_HEAD_EN, + AIU_IEC958_DCU_FF_CTRL_IRQ_FRAME_READ); + + return 0; +} + +const struct snd_soc_dai_ops aiu_fifo_spdif_dai_ops = { + .trigger = fifo_spdif_trigger, + .prepare = fifo_spdif_prepare, + .hw_params = fifo_spdif_hw_params, + .hw_free = aiu_fifo_hw_free, + .startup = aiu_fifo_startup, + .shutdown = aiu_fifo_shutdown, +}; + +int aiu_fifo_spdif_dai_probe(struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct aiu *aiu = snd_soc_component_get_drvdata(component); + struct aiu_fifo *fifo; + int ret; + + ret = aiu_fifo_dai_probe(dai); + if (ret) + return ret; + + fifo = dai->playback_dma_data; + + fifo->pcm = &fifo_spdif_pcm; + fifo->mem_offset = AIU_MEM_IEC958_START; + fifo->fifo_block = 1; + fifo->pclk = aiu->spdif.clks[PCLK].clk; + fifo->irq = aiu->spdif.irq; + + return 0; +} diff --git a/sound/soc/meson/aiu-fifo.c b/sound/soc/meson/aiu-fifo.c new file mode 100644 index 000000000000..da8c098e8750 --- /dev/null +++ b/sound/soc/meson/aiu-fifo.c @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2020 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include +#include + +#include "aiu-fifo.h" + +#define AIU_MEM_START 0x00 +#define AIU_MEM_RD 0x04 +#define AIU_MEM_END 0x08 +#define AIU_MEM_MASKS 0x0c +#define AIU_MEM_MASK_CH_RD GENMASK(7, 0) +#define AIU_MEM_MASK_CH_MEM GENMASK(15, 8) +#define AIU_MEM_CONTROL 0x10 +#define AIU_MEM_CONTROL_INIT BIT(0) +#define AIU_MEM_CONTROL_FILL_EN BIT(1) +#define AIU_MEM_CONTROL_EMPTY_EN BIT(2) + +static struct snd_soc_dai *aiu_fifo_dai(struct snd_pcm_substream *ss) +{ + struct snd_soc_pcm_runtime *rtd = ss->private_data; + + return rtd->cpu_dai; +} + +snd_pcm_uframes_t aiu_fifo_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_dai *dai = aiu_fifo_dai(substream); + struct aiu_fifo *fifo = dai->playback_dma_data; + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned int addr; + + snd_soc_component_read(component, fifo->mem_offset + AIU_MEM_RD, + &addr); + + return bytes_to_frames(runtime, addr - (unsigned int)runtime->dma_addr); +} + +static void aiu_fifo_enable(struct snd_soc_dai *dai, bool enable) +{ + struct snd_soc_component *component = dai->component; + struct aiu_fifo *fifo = dai->playback_dma_data; + unsigned int en_mask = (AIU_MEM_CONTROL_FILL_EN | + AIU_MEM_CONTROL_EMPTY_EN); + + snd_soc_component_update_bits(component, + fifo->mem_offset + AIU_MEM_CONTROL, + en_mask, enable ? en_mask : 0); +} + +int aiu_fifo_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + aiu_fifo_enable(dai, true); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_STOP: + aiu_fifo_enable(dai, false); + break; + default: + return -EINVAL; + } + + return 0; +} + +int aiu_fifo_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct aiu_fifo *fifo = dai->playback_dma_data; + + snd_soc_component_update_bits(component, + fifo->mem_offset + AIU_MEM_CONTROL, + AIU_MEM_CONTROL_INIT, + AIU_MEM_CONTROL_INIT); + snd_soc_component_update_bits(component, + fifo->mem_offset + AIU_MEM_CONTROL, + AIU_MEM_CONTROL_INIT, 0); + return 0; +} + +int aiu_fifo_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_component *component = dai->component; + struct aiu_fifo *fifo = dai->playback_dma_data; + dma_addr_t end; + int ret; + + ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); + if (ret < 0) + return ret; + + /* Setup the fifo boundaries */ + end = runtime->dma_addr + runtime->dma_bytes - fifo->fifo_block; + snd_soc_component_write(component, fifo->mem_offset + AIU_MEM_START, + runtime->dma_addr); + snd_soc_component_write(component, fifo->mem_offset + AIU_MEM_RD, + runtime->dma_addr); + snd_soc_component_write(component, fifo->mem_offset + AIU_MEM_END, + end); + + /* Setup the fifo to read all the memory - no skip */ + snd_soc_component_update_bits(component, + fifo->mem_offset + AIU_MEM_MASKS, + AIU_MEM_MASK_CH_RD | AIU_MEM_MASK_CH_MEM, + FIELD_PREP(AIU_MEM_MASK_CH_RD, 0xff) | + FIELD_PREP(AIU_MEM_MASK_CH_MEM, 0xff)); + + return 0; +} + +int aiu_fifo_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + return snd_pcm_lib_free_pages(substream); +} + +static irqreturn_t aiu_fifo_isr(int irq, void *dev_id) +{ + struct snd_pcm_substream *playback = dev_id; + + snd_pcm_period_elapsed(playback); + + return IRQ_HANDLED; +} + +int aiu_fifo_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct aiu_fifo *fifo = dai->playback_dma_data; + int ret; + + snd_soc_set_runtime_hwparams(substream, fifo->pcm); + + /* + * Make sure the buffer and period size are multiple of the fifo burst + * size + */ + ret = snd_pcm_hw_constraint_step(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_BUFFER_BYTES, + fifo->fifo_block); + if (ret) + return ret; + + ret = snd_pcm_hw_constraint_step(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, + fifo->fifo_block); + if (ret) + return ret; + + ret = clk_prepare_enable(fifo->pclk); + if (ret) + return ret; + + ret = request_irq(fifo->irq, aiu_fifo_isr, 0, dev_name(dai->dev), + substream); + if (ret) + clk_disable_unprepare(fifo->pclk); + + return ret; +} + +void aiu_fifo_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct aiu_fifo *fifo = dai->playback_dma_data; + + free_irq(fifo->irq, substream); + clk_disable_unprepare(fifo->pclk); +} + +int aiu_fifo_pcm_new(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_dai *dai) +{ + struct snd_pcm_substream *substream = + rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + struct snd_card *card = rtd->card->snd_card; + struct aiu_fifo *fifo = dai->playback_dma_data; + size_t size = fifo->pcm->buffer_bytes_max; + + snd_pcm_lib_preallocate_pages(substream, + SNDRV_DMA_TYPE_DEV, + card->dev, size, size); + + return 0; +} + +int aiu_fifo_dai_probe(struct snd_soc_dai *dai) +{ + struct aiu_fifo *fifo; + + fifo = kzalloc(sizeof(*fifo), GFP_KERNEL); + if (!fifo) + return -ENOMEM; + + dai->playback_dma_data = fifo; + + return 0; +} + +int aiu_fifo_dai_remove(struct snd_soc_dai *dai) +{ + kfree(dai->playback_dma_data); + + return 0; +} + diff --git a/sound/soc/meson/aiu-fifo.h b/sound/soc/meson/aiu-fifo.h new file mode 100644 index 000000000000..42ce266677cc --- /dev/null +++ b/sound/soc/meson/aiu-fifo.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ +/* + * Copyright (c) 2020 BayLibre, SAS. + * Author: Jerome Brunet + */ + +#ifndef _MESON_AIU_FIFO_H +#define _MESON_AIU_FIFO_H + +struct snd_pcm_hardware; +struct snd_soc_component_driver; +struct snd_soc_dai_driver; +struct clk; +struct snd_pcm_ops; +struct snd_pcm_substream; +struct snd_soc_dai; +struct snd_pcm_hw_params; +struct platform_device; + +struct aiu_fifo { + struct snd_pcm_hardware *pcm; + unsigned int mem_offset; + unsigned int fifo_block; + struct clk *pclk; + int irq; +}; + +int aiu_fifo_dai_probe(struct snd_soc_dai *dai); +int aiu_fifo_dai_remove(struct snd_soc_dai *dai); + +snd_pcm_uframes_t aiu_fifo_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream); + +int aiu_fifo_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai); +int aiu_fifo_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai); +int aiu_fifo_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai); +int aiu_fifo_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai); +int aiu_fifo_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai); +void aiu_fifo_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai); +int aiu_fifo_pcm_new(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_dai *dai); + +#endif /* _MESON_AIU_FIFO_H */ diff --git a/sound/soc/meson/aiu.c b/sound/soc/meson/aiu.c new file mode 100644 index 000000000000..a62aced9b687 --- /dev/null +++ b/sound/soc/meson/aiu.c @@ -0,0 +1,348 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2020 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "aiu.h" +#include "aiu-fifo.h" + +#define AIU_I2S_MISC_958_SRC_SHIFT 3 + +static const char * const aiu_spdif_encode_sel_texts[] = { + "SPDIF", "I2S", +}; + +static SOC_ENUM_SINGLE_DECL(aiu_spdif_encode_sel_enum, AIU_I2S_MISC, + AIU_I2S_MISC_958_SRC_SHIFT, + aiu_spdif_encode_sel_texts); + +static const struct snd_kcontrol_new aiu_spdif_encode_mux = + SOC_DAPM_ENUM("SPDIF Buffer Src", aiu_spdif_encode_sel_enum); + +static const struct snd_soc_dapm_widget aiu_cpu_dapm_widgets[] = { + SND_SOC_DAPM_MUX("SPDIF SRC SEL", SND_SOC_NOPM, 0, 0, + &aiu_spdif_encode_mux), +}; + +static const struct snd_soc_dapm_route aiu_cpu_dapm_routes[] = { + { "I2S Encoder Playback", NULL, "I2S FIFO Playback" }, + { "SPDIF SRC SEL", "SPDIF", "SPDIF FIFO Playback" }, + { "SPDIF SRC SEL", "I2S", "I2S FIFO Playback" }, + { "SPDIF Encoder Playback", NULL, "SPDIF SRC SEL" }, +}; + +int aiu_of_xlate_dai_name(struct snd_soc_component *component, + struct of_phandle_args *args, + const char **dai_name, + unsigned int component_id) +{ + struct snd_soc_dai *dai; + int id; + + if (args->args_count != 2) + return -EINVAL; + + if (args->args[0] != component_id) + return -EINVAL; + + id = args->args[1]; + + if (id < 0 || id >= component->num_dai) + return -EINVAL; + + for_each_component_dais(component, dai) { + if (id == 0) + break; + id--; + } + + *dai_name = dai->driver->name; + + return 0; +} + +static int aiu_cpu_of_xlate_dai_name(struct snd_soc_component *component, + struct of_phandle_args *args, + const char **dai_name) +{ + return aiu_of_xlate_dai_name(component, args, dai_name, AIU_CPU); +} + +static int aiu_cpu_component_probe(struct snd_soc_component *component) +{ + struct aiu *aiu = snd_soc_component_get_drvdata(component); + + /* Required for the SPDIF Source control operation */ + return clk_prepare_enable(aiu->i2s.clks[PCLK].clk); +} + +static void aiu_cpu_component_remove(struct snd_soc_component *component) +{ + struct aiu *aiu = snd_soc_component_get_drvdata(component); + + clk_disable_unprepare(aiu->i2s.clks[PCLK].clk); +} + +static const struct snd_soc_component_driver aiu_cpu_component = { + .name = "AIU CPU", + .dapm_widgets = aiu_cpu_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aiu_cpu_dapm_widgets), + .dapm_routes = aiu_cpu_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(aiu_cpu_dapm_routes), + .of_xlate_dai_name = aiu_cpu_of_xlate_dai_name, + .pointer = aiu_fifo_pointer, + .probe = aiu_cpu_component_probe, + .remove = aiu_cpu_component_remove, +}; + +static struct snd_soc_dai_driver aiu_cpu_dai_drv[] = { + [CPU_I2S_FIFO] = { + .name = "I2S FIFO", + .playback = { + .stream_name = "I2S FIFO Playback", + .channels_min = 2, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 5512, + .rate_max = 192000, + .formats = AIU_FORMATS, + }, + .ops = &aiu_fifo_i2s_dai_ops, + .pcm_new = aiu_fifo_pcm_new, + .probe = aiu_fifo_i2s_dai_probe, + .remove = aiu_fifo_dai_remove, + }, + [CPU_SPDIF_FIFO] = { + .name = "SPDIF FIFO", + .playback = { + .stream_name = "SPDIF FIFO Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 5512, + .rate_max = 192000, + .formats = AIU_FORMATS, + }, + .ops = &aiu_fifo_spdif_dai_ops, + .pcm_new = aiu_fifo_pcm_new, + .probe = aiu_fifo_spdif_dai_probe, + .remove = aiu_fifo_dai_remove, + }, + [CPU_I2S_ENCODER] = { + .name = "I2S Encoder", + .playback = { + .stream_name = "I2S Encoder Playback", + .channels_min = 2, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = AIU_FORMATS, + }, + .ops = &aiu_encoder_i2s_dai_ops, + }, + [CPU_SPDIF_ENCODER] = { + .name = "SPDIF Encoder", + .playback = { + .stream_name = "SPDIF Encoder Playback", + .channels_min = 2, + .channels_max = 2, + .rates = (SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_176400 | + SNDRV_PCM_RATE_192000), + .formats = AIU_FORMATS, + }, + .ops = &aiu_encoder_spdif_dai_ops, + } +}; + +static const struct regmap_config aiu_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x2ac, +}; + +static int aiu_clk_bulk_get(struct device *dev, + const char * const *ids, + unsigned int num, + struct aiu_interface *interface) +{ + struct clk_bulk_data *clks; + int i, ret; + + clks = devm_kcalloc(dev, num, sizeof(clks), GFP_KERNEL); + if (!clks) + return -ENOMEM; + + for (i = 0; i < num; i++) + clks[i].id = ids[i]; + + ret = devm_clk_bulk_get(dev, num, clks); + if (ret < 0) + return ret; + + interface->clks = clks; + interface->clk_num = num; + return 0; +} + +static const char * const aiu_i2s_ids[] = { + [PCLK] = "i2s_pclk", + [AOCLK] = "i2s_aoclk", + [MCLK] = "i2s_mclk", + [MIXER] = "i2s_mixer", +}; + +static const char * const aiu_spdif_ids[] = { + [PCLK] = "spdif_pclk", + [AOCLK] = "spdif_aoclk", + [MCLK] = "spdif_mclk_sel" +}; + +static int aiu_clk_get(struct device *dev) +{ + struct aiu *aiu = dev_get_drvdata(dev); + int ret; + + aiu->pclk = devm_clk_get(dev, "pclk"); + if (IS_ERR(aiu->pclk)) { + if (PTR_ERR(aiu->pclk) != -EPROBE_DEFER) + dev_err(dev, "Can't get the aiu pclk\n"); + return PTR_ERR(aiu->pclk); + } + + aiu->spdif_mclk = devm_clk_get(dev, "spdif_mclk"); + if (IS_ERR(aiu->spdif_mclk)) { + if (PTR_ERR(aiu->spdif_mclk) != -EPROBE_DEFER) + dev_err(dev, "Can't get the aiu spdif master clock\n"); + return PTR_ERR(aiu->spdif_mclk); + } + + ret = aiu_clk_bulk_get(dev, aiu_i2s_ids, ARRAY_SIZE(aiu_i2s_ids), + &aiu->i2s); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "Can't get the i2s clocks\n"); + return ret; + } + + ret = aiu_clk_bulk_get(dev, aiu_spdif_ids, ARRAY_SIZE(aiu_spdif_ids), + &aiu->spdif); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "Can't get the spdif clocks\n"); + return ret; + } + + ret = clk_prepare_enable(aiu->pclk); + if (ret) { + dev_err(dev, "peripheral clock enable failed\n"); + return ret; + } + + ret = devm_add_action_or_reset(dev, + (void(*)(void *))clk_disable_unprepare, + aiu->pclk); + if (ret) + dev_err(dev, "failed to add reset action on pclk"); + + return ret; +} + +static int aiu_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + void __iomem *regs; + struct regmap *map; + struct aiu *aiu; + int ret; + + aiu = devm_kzalloc(dev, sizeof(*aiu), GFP_KERNEL); + if (!aiu) + return -ENOMEM; + platform_set_drvdata(pdev, aiu); + + ret = device_reset(dev); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to reset device\n"); + return ret; + } + + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + map = devm_regmap_init_mmio(dev, regs, &aiu_regmap_cfg); + if (IS_ERR(map)) { + dev_err(dev, "failed to init regmap: %ld\n", + PTR_ERR(map)); + return PTR_ERR(map); + } + + aiu->i2s.irq = platform_get_irq_byname(pdev, "i2s"); + if (aiu->i2s.irq < 0) { + dev_err(dev, "Can't get i2s irq\n"); + return aiu->i2s.irq; + } + + aiu->spdif.irq = platform_get_irq_byname(pdev, "spdif"); + if (aiu->spdif.irq < 0) { + dev_err(dev, "Can't get spdif irq\n"); + return aiu->spdif.irq; + } + + ret = aiu_clk_get(dev); + if (ret) + return ret; + + /* Register the cpu component of the aiu */ + ret = snd_soc_register_component(dev, &aiu_cpu_component, + aiu_cpu_dai_drv, + ARRAY_SIZE(aiu_cpu_dai_drv)); + if (ret) + dev_err(dev, "Failed to register cpu component\n"); + + return ret; +} + +static int aiu_remove(struct platform_device *pdev) +{ + snd_soc_unregister_component(&pdev->dev); + + return 0; +} + +static const struct of_device_id aiu_of_match[] = { + { .compatible = "amlogic,aiu-gxbb", }, + { .compatible = "amlogic,aiu-gxl", }, + {} +}; +MODULE_DEVICE_TABLE(of, aiu_of_match); + +static struct platform_driver aiu_pdrv = { + .probe = aiu_probe, + .remove = aiu_remove, + .driver = { + .name = "meson-aiu", + .of_match_table = aiu_of_match, + }, +}; +module_platform_driver(aiu_pdrv); + +MODULE_DESCRIPTION("Meson AIU Driver"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/meson/aiu.h b/sound/soc/meson/aiu.h new file mode 100644 index 000000000000..a3488027b9d5 --- /dev/null +++ b/sound/soc/meson/aiu.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ +/* + * Copyright (c) 2018 BayLibre, SAS. + * Author: Jerome Brunet + */ + +#ifndef _MESON_AIU_H +#define _MESON_AIU_H + +struct clk; +struct clk_bulk_data; +struct device; +struct of_phandle_args; +struct snd_soc_component_driver; +struct snd_soc_dai; +struct snd_soc_dai_driver; +struct snd_soc_dai_ops; + +enum aiu_clk_ids { + PCLK = 0, + AOCLK, + MCLK, + MIXER +}; + +struct aiu_interface { + struct clk_bulk_data *clks; + unsigned int clk_num; + unsigned int irq; +}; + +struct aiu { + struct clk *pclk; + struct clk *spdif_mclk; + struct aiu_interface i2s; + struct aiu_interface spdif; +}; + +#define AIU_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_LE | \ + SNDRV_PCM_FMTBIT_S24_LE) + +int aiu_of_xlate_dai_name(struct snd_soc_component *component, + struct of_phandle_args *args, + const char **dai_name, + unsigned int component_id); + +int aiu_fifo_i2s_dai_probe(struct snd_soc_dai *dai); +int aiu_fifo_spdif_dai_probe(struct snd_soc_dai *dai); + +extern const struct snd_soc_dai_ops aiu_fifo_i2s_dai_ops; +extern const struct snd_soc_dai_ops aiu_fifo_spdif_dai_ops; +extern const struct snd_soc_dai_ops aiu_encoder_i2s_dai_ops; +extern const struct snd_soc_dai_ops aiu_encoder_spdif_dai_ops; + +#define AIU_IEC958_BPF 0x000 +#define AIU_958_MISC 0x010 +#define AIU_IEC958_DCU_FF_CTRL 0x01c +#define AIU_958_CHSTAT_L0 0x020 +#define AIU_958_CHSTAT_L1 0x024 +#define AIU_958_CTRL 0x028 +#define AIU_I2S_SOURCE_DESC 0x034 +#define AIU_I2S_DAC_CFG 0x040 +#define AIU_I2S_SYNC 0x044 +#define AIU_I2S_MISC 0x048 +#define AIU_RST_SOFT 0x054 +#define AIU_CLK_CTRL 0x058 +#define AIU_CLK_CTRL_MORE 0x064 +#define AIU_CODEC_DAC_LRCLK_CTRL 0x0a0 +#define AIU_HDMI_CLK_DATA_CTRL 0x0a8 +#define AIU_ACODEC_CTRL 0x0b0 +#define AIU_958_CHSTAT_R0 0x0c0 +#define AIU_958_CHSTAT_R1 0x0c4 +#define AIU_MEM_I2S_START 0x180 +#define AIU_MEM_I2S_MASKS 0x18c +#define AIU_MEM_I2S_CONTROL 0x190 +#define AIU_MEM_IEC958_START 0x194 +#define AIU_MEM_IEC958_CONTROL 0x1a4 +#define AIU_MEM_I2S_BUF_CNTL 0x1d8 +#define AIU_MEM_IEC958_BUF_CNTL 0x1fc + +#endif /* _MESON_AIU_H */ From b82b734c0e9a75e1b956214ac523a8eb590f51f3 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 13 Feb 2020 16:51:55 +0100 Subject: [PATCH 0297/4444] ASoC: meson: aiu: add hdmi codec control support Add the codec to codec component which handles the routing between the audio producers (PCM and I2S) and the synopsys hdmi controller on the amlogic GX SoC family Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200213155159.3235792-6-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/Kconfig | 2 + sound/soc/meson/Makefile | 1 + sound/soc/meson/aiu-codec-ctrl.c | 152 +++++++++++++++++++++++++++++++ sound/soc/meson/aiu.c | 34 ++++++- sound/soc/meson/aiu.h | 8 ++ 5 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 sound/soc/meson/aiu-codec-ctrl.c diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index ca269dedfc7f..19de97ae4ce9 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -4,7 +4,9 @@ menu "ASoC support for Amlogic platforms" config SND_MESON_AIU tristate "Amlogic AIU" + select SND_MESON_CODEC_GLUE select SND_PCM_IEC958 + imply SND_SOC_HDMI_CODEC if DRM_MESON_DW_HDMI help Select Y or M to add support for the Audio output subsystem found in the Amlogic GX SoC family diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index a7b79d717288..3b21f648e322 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: (GPL-2.0 OR MIT) snd-soc-meson-aiu-objs := aiu.o +snd-soc-meson-aiu-objs += aiu-codec-ctrl.o snd-soc-meson-aiu-objs += aiu-encoder-i2s.o snd-soc-meson-aiu-objs += aiu-encoder-spdif.o snd-soc-meson-aiu-objs += aiu-fifo.o diff --git a/sound/soc/meson/aiu-codec-ctrl.c b/sound/soc/meson/aiu-codec-ctrl.c new file mode 100644 index 000000000000..8646a953e3b3 --- /dev/null +++ b/sound/soc/meson/aiu-codec-ctrl.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2020 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include + +#include +#include "aiu.h" +#include "meson-codec-glue.h" + +#define CTRL_CLK_SEL GENMASK(1, 0) +#define CTRL_DATA_SEL_SHIFT 4 +#define CTRL_DATA_SEL (0x3 << CTRL_DATA_SEL_SHIFT) + +static const char * const aiu_codec_ctrl_mux_texts[] = { + "DISABLED", "PCM", "I2S", +}; + +static int aiu_codec_ctrl_mux_put_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int mux, changed; + + mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]); + changed = snd_soc_component_test_bits(component, e->reg, + CTRL_DATA_SEL, + FIELD_PREP(CTRL_DATA_SEL, mux)); + + if (!changed) + return 0; + + /* Force disconnect of the mux while updating */ + snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL); + + /* Reset the source first */ + snd_soc_component_update_bits(component, e->reg, + CTRL_CLK_SEL | + CTRL_DATA_SEL, + FIELD_PREP(CTRL_CLK_SEL, 0) | + FIELD_PREP(CTRL_DATA_SEL, 0)); + + /* Set the appropriate source */ + snd_soc_component_update_bits(component, e->reg, + CTRL_CLK_SEL | + CTRL_DATA_SEL, + FIELD_PREP(CTRL_CLK_SEL, mux) | + FIELD_PREP(CTRL_DATA_SEL, mux)); + + snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL); + + return 0; +} + +static SOC_ENUM_SINGLE_DECL(aiu_hdmi_ctrl_mux_enum, AIU_HDMI_CLK_DATA_CTRL, + CTRL_DATA_SEL_SHIFT, + aiu_codec_ctrl_mux_texts); + +static const struct snd_kcontrol_new aiu_hdmi_ctrl_mux = + SOC_DAPM_ENUM_EXT("HDMI Source", aiu_hdmi_ctrl_mux_enum, + snd_soc_dapm_get_enum_double, + aiu_codec_ctrl_mux_put_enum); + +static const struct snd_soc_dapm_widget aiu_hdmi_ctrl_widgets[] = { + SND_SOC_DAPM_MUX("HDMI CTRL SRC", SND_SOC_NOPM, 0, 0, + &aiu_hdmi_ctrl_mux), +}; + +static const struct snd_soc_dai_ops aiu_codec_ctrl_input_ops = { + .hw_params = meson_codec_glue_input_hw_params, + .set_fmt = meson_codec_glue_input_set_fmt, +}; + +static const struct snd_soc_dai_ops aiu_codec_ctrl_output_ops = { + .startup = meson_codec_glue_output_startup, +}; + +#define AIU_CODEC_CTRL_FORMATS \ + (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +#define AIU_CODEC_CTRL_STREAM(xname, xsuffix) \ +{ \ + .stream_name = xname " " xsuffix, \ + .channels_min = 1, \ + .channels_max = 8, \ + .rate_min = 5512, \ + .rate_max = 192000, \ + .formats = AIU_CODEC_CTRL_FORMATS, \ +} + +#define AIU_CODEC_CTRL_INPUT(xname) { \ + .name = "CODEC CTRL " xname, \ + .playback = AIU_CODEC_CTRL_STREAM(xname, "Playback"), \ + .ops = &aiu_codec_ctrl_input_ops, \ + .probe = meson_codec_glue_input_dai_probe, \ + .remove = meson_codec_glue_input_dai_remove, \ +} + +#define AIU_CODEC_CTRL_OUTPUT(xname) { \ + .name = "CODEC CTRL " xname, \ + .capture = AIU_CODEC_CTRL_STREAM(xname, "Capture"), \ + .ops = &aiu_codec_ctrl_output_ops, \ +} + +static struct snd_soc_dai_driver aiu_hdmi_ctrl_dai_drv[] = { + [CTRL_I2S] = AIU_CODEC_CTRL_INPUT("HDMI I2S IN"), + [CTRL_PCM] = AIU_CODEC_CTRL_INPUT("HDMI PCM IN"), + [CTRL_OUT] = AIU_CODEC_CTRL_OUTPUT("HDMI OUT"), +}; + +static const struct snd_soc_dapm_route aiu_hdmi_ctrl_routes[] = { + { "HDMI CTRL SRC", "I2S", "HDMI I2S IN Playback" }, + { "HDMI CTRL SRC", "PCM", "HDMI PCM IN Playback" }, + { "HDMI OUT Capture", NULL, "HDMI CTRL SRC" }, +}; + +static int aiu_hdmi_of_xlate_dai_name(struct snd_soc_component *component, + struct of_phandle_args *args, + const char **dai_name) +{ + return aiu_of_xlate_dai_name(component, args, dai_name, AIU_HDMI); +} + +static const struct snd_soc_component_driver aiu_hdmi_ctrl_component = { + .name = "AIU HDMI Codec Control", + .dapm_widgets = aiu_hdmi_ctrl_widgets, + .num_dapm_widgets = ARRAY_SIZE(aiu_hdmi_ctrl_widgets), + .dapm_routes = aiu_hdmi_ctrl_routes, + .num_dapm_routes = ARRAY_SIZE(aiu_hdmi_ctrl_routes), + .of_xlate_dai_name = aiu_hdmi_of_xlate_dai_name, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +int aiu_hdmi_ctrl_register_component(struct device *dev) +{ + return aiu_add_component(dev, &aiu_hdmi_ctrl_component, + aiu_hdmi_ctrl_dai_drv, + ARRAY_SIZE(aiu_hdmi_ctrl_dai_drv), + "hdmi"); +} + diff --git a/sound/soc/meson/aiu.c b/sound/soc/meson/aiu.c index a62aced9b687..b765dfb70726 100644 --- a/sound/soc/meson/aiu.c +++ b/sound/soc/meson/aiu.c @@ -71,6 +71,26 @@ int aiu_of_xlate_dai_name(struct snd_soc_component *component, return 0; } +int aiu_add_component(struct device *dev, + const struct snd_soc_component_driver *component_driver, + struct snd_soc_dai_driver *dai_drv, + int num_dai, + const char *debugfs_prefix) +{ + struct snd_soc_component *component; + + component = devm_kzalloc(dev, sizeof(*component), GFP_KERNEL); + if (!component) + return -ENOMEM; + +#ifdef CONFIG_DEBUG_FS + component->debugfs_prefix = debugfs_prefix; +#endif + + return snd_soc_add_component(dev, component, component_driver, + dai_drv, num_dai); +} + static int aiu_cpu_of_xlate_dai_name(struct snd_soc_component *component, struct of_phandle_args *args, const char **dai_name) @@ -313,9 +333,21 @@ static int aiu_probe(struct platform_device *pdev) ret = snd_soc_register_component(dev, &aiu_cpu_component, aiu_cpu_dai_drv, ARRAY_SIZE(aiu_cpu_dai_drv)); - if (ret) + if (ret) { dev_err(dev, "Failed to register cpu component\n"); + return ret; + } + /* Register the hdmi codec control component */ + ret = aiu_hdmi_ctrl_register_component(dev); + if (ret) { + dev_err(dev, "Failed to register hdmi control component\n"); + goto err; + } + + return 0; +err: + snd_soc_unregister_component(dev); return ret; } diff --git a/sound/soc/meson/aiu.h b/sound/soc/meson/aiu.h index a3488027b9d5..9242ab1ab64b 100644 --- a/sound/soc/meson/aiu.h +++ b/sound/soc/meson/aiu.h @@ -45,6 +45,14 @@ int aiu_of_xlate_dai_name(struct snd_soc_component *component, const char **dai_name, unsigned int component_id); +int aiu_add_component(struct device *dev, + const struct snd_soc_component_driver *component_driver, + struct snd_soc_dai_driver *dai_drv, + int num_dai, + const char *debugfs_prefix); + +int aiu_hdmi_ctrl_register_component(struct device *dev); + int aiu_fifo_i2s_dai_probe(struct snd_soc_dai *dai); int aiu_fifo_spdif_dai_probe(struct snd_soc_dai *dai); From 65816025d46169973d308d83fbcf5c3981ed5621 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 13 Feb 2020 16:51:56 +0100 Subject: [PATCH 0298/4444] ASoC: meson: aiu: add internal dac codec control support Add the codec to codec component which handles the routing between the audio producers and the internal audio DAC found on the amlogic GXL SoC family Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200213155159.3235792-7-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/Makefile | 1 + sound/soc/meson/aiu-acodec-ctrl.c | 205 ++++++++++++++++++++++++++++++ sound/soc/meson/aiu.c | 10 ++ sound/soc/meson/aiu.h | 1 + 4 files changed, 217 insertions(+) create mode 100644 sound/soc/meson/aiu-acodec-ctrl.c diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index 3b21f648e322..80f9113701b3 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: (GPL-2.0 OR MIT) snd-soc-meson-aiu-objs := aiu.o +snd-soc-meson-aiu-objs += aiu-acodec-ctrl.o snd-soc-meson-aiu-objs += aiu-codec-ctrl.o snd-soc-meson-aiu-objs += aiu-encoder-i2s.o snd-soc-meson-aiu-objs += aiu-encoder-spdif.o diff --git a/sound/soc/meson/aiu-acodec-ctrl.c b/sound/soc/meson/aiu-acodec-ctrl.c new file mode 100644 index 000000000000..12d8a4d351a1 --- /dev/null +++ b/sound/soc/meson/aiu-acodec-ctrl.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2020 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include + +#include +#include "aiu.h" +#include "meson-codec-glue.h" + +#define CTRL_DIN_EN 15 +#define CTRL_CLK_INV BIT(14) +#define CTRL_LRCLK_INV BIT(13) +#define CTRL_I2S_IN_BCLK_SRC BIT(11) +#define CTRL_DIN_LRCLK_SRC_SHIFT 6 +#define CTRL_DIN_LRCLK_SRC (0x3 << CTRL_DIN_LRCLK_SRC_SHIFT) +#define CTRL_BCLK_MCLK_SRC GENMASK(5, 4) +#define CTRL_DIN_SKEW GENMASK(3, 2) +#define CTRL_I2S_OUT_LANE_SRC 0 + +#define AIU_ACODEC_OUT_CHMAX 2 + +static const char * const aiu_acodec_ctrl_mux_texts[] = { + "DISABLED", "I2S", "PCM", +}; + +static int aiu_acodec_ctrl_mux_put_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int mux, changed; + + mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]); + changed = snd_soc_component_test_bits(component, e->reg, + CTRL_DIN_LRCLK_SRC, + FIELD_PREP(CTRL_DIN_LRCLK_SRC, + mux)); + + if (!changed) + return 0; + + /* Force disconnect of the mux while updating */ + snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL); + + snd_soc_component_update_bits(component, e->reg, + CTRL_DIN_LRCLK_SRC | + CTRL_BCLK_MCLK_SRC, + FIELD_PREP(CTRL_DIN_LRCLK_SRC, mux) | + FIELD_PREP(CTRL_BCLK_MCLK_SRC, mux)); + + snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL); + + return 0; +} + +static SOC_ENUM_SINGLE_DECL(aiu_acodec_ctrl_mux_enum, AIU_ACODEC_CTRL, + CTRL_DIN_LRCLK_SRC_SHIFT, + aiu_acodec_ctrl_mux_texts); + +static const struct snd_kcontrol_new aiu_acodec_ctrl_mux = + SOC_DAPM_ENUM_EXT("ACodec Source", aiu_acodec_ctrl_mux_enum, + snd_soc_dapm_get_enum_double, + aiu_acodec_ctrl_mux_put_enum); + +static const struct snd_kcontrol_new aiu_acodec_ctrl_out_enable = + SOC_DAPM_SINGLE_AUTODISABLE("Switch", AIU_ACODEC_CTRL, + CTRL_DIN_EN, 1, 0); + +static const struct snd_soc_dapm_widget aiu_acodec_ctrl_widgets[] = { + SND_SOC_DAPM_MUX("ACODEC SRC", SND_SOC_NOPM, 0, 0, + &aiu_acodec_ctrl_mux), + SND_SOC_DAPM_SWITCH("ACODEC OUT EN", SND_SOC_NOPM, 0, 0, + &aiu_acodec_ctrl_out_enable), +}; + +static int aiu_acodec_ctrl_input_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct meson_codec_glue_input *data; + int ret; + + ret = meson_codec_glue_input_hw_params(substream, params, dai); + if (ret) + return ret; + + /* The glue will provide 1 lane out of the 4 to the output */ + data = meson_codec_glue_input_get_data(dai); + data->params.channels_min = min_t(unsigned int, AIU_ACODEC_OUT_CHMAX, + data->params.channels_min); + data->params.channels_max = min_t(unsigned int, AIU_ACODEC_OUT_CHMAX, + data->params.channels_max); + + return 0; +} + +static const struct snd_soc_dai_ops aiu_acodec_ctrl_input_ops = { + .hw_params = aiu_acodec_ctrl_input_hw_params, + .set_fmt = meson_codec_glue_input_set_fmt, +}; + +static const struct snd_soc_dai_ops aiu_acodec_ctrl_output_ops = { + .startup = meson_codec_glue_output_startup, +}; + +#define AIU_ACODEC_CTRL_FORMATS \ + (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +#define AIU_ACODEC_STREAM(xname, xsuffix, xchmax) \ +{ \ + .stream_name = xname " " xsuffix, \ + .channels_min = 1, \ + .channels_max = (xchmax), \ + .rate_min = 5512, \ + .rate_max = 192000, \ + .formats = AIU_ACODEC_CTRL_FORMATS, \ +} + +#define AIU_ACODEC_INPUT(xname) { \ + .name = "ACODEC CTRL " xname, \ + .name = xname, \ + .playback = AIU_ACODEC_STREAM(xname, "Playback", 8), \ + .ops = &aiu_acodec_ctrl_input_ops, \ + .probe = meson_codec_glue_input_dai_probe, \ + .remove = meson_codec_glue_input_dai_remove, \ +} + +#define AIU_ACODEC_OUTPUT(xname) { \ + .name = "ACODEC CTRL " xname, \ + .capture = AIU_ACODEC_STREAM(xname, "Capture", AIU_ACODEC_OUT_CHMAX), \ + .ops = &aiu_acodec_ctrl_output_ops, \ +} + +static struct snd_soc_dai_driver aiu_acodec_ctrl_dai_drv[] = { + [CTRL_I2S] = AIU_ACODEC_INPUT("ACODEC I2S IN"), + [CTRL_PCM] = AIU_ACODEC_INPUT("ACODEC PCM IN"), + [CTRL_OUT] = AIU_ACODEC_OUTPUT("ACODEC OUT"), +}; + +static const struct snd_soc_dapm_route aiu_acodec_ctrl_routes[] = { + { "ACODEC SRC", "I2S", "ACODEC I2S IN Playback" }, + { "ACODEC SRC", "PCM", "ACODEC PCM IN Playback" }, + { "ACODEC OUT EN", "Switch", "ACODEC SRC" }, + { "ACODEC OUT Capture", NULL, "ACODEC OUT EN" }, +}; + +static const struct snd_kcontrol_new aiu_acodec_ctrl_controls[] = { + SOC_SINGLE("ACODEC I2S Lane Select", AIU_ACODEC_CTRL, + CTRL_I2S_OUT_LANE_SRC, 3, 0), +}; + +static int aiu_acodec_of_xlate_dai_name(struct snd_soc_component *component, + struct of_phandle_args *args, + const char **dai_name) +{ + return aiu_of_xlate_dai_name(component, args, dai_name, AIU_ACODEC); +} + +static int aiu_acodec_ctrl_component_probe(struct snd_soc_component *component) +{ + /* + * NOTE: Din Skew setting + * According to the documentation, the following update adds one delay + * to the din line. Without this, the output saturates. This happens + * regardless of the link format (i2s or left_j) so it is not clear what + * it actually does but it seems to be required + */ + snd_soc_component_update_bits(component, AIU_ACODEC_CTRL, + CTRL_DIN_SKEW, + FIELD_PREP(CTRL_DIN_SKEW, 2)); + + return 0; +} + +static const struct snd_soc_component_driver aiu_acodec_ctrl_component = { + .name = "AIU Internal DAC Codec Control", + .probe = aiu_acodec_ctrl_component_probe, + .controls = aiu_acodec_ctrl_controls, + .num_controls = ARRAY_SIZE(aiu_acodec_ctrl_controls), + .dapm_widgets = aiu_acodec_ctrl_widgets, + .num_dapm_widgets = ARRAY_SIZE(aiu_acodec_ctrl_widgets), + .dapm_routes = aiu_acodec_ctrl_routes, + .num_dapm_routes = ARRAY_SIZE(aiu_acodec_ctrl_routes), + .of_xlate_dai_name = aiu_acodec_of_xlate_dai_name, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +int aiu_acodec_ctrl_register_component(struct device *dev) +{ + return aiu_add_component(dev, &aiu_acodec_ctrl_component, + aiu_acodec_ctrl_dai_drv, + ARRAY_SIZE(aiu_acodec_ctrl_dai_drv), + "acodec"); +} diff --git a/sound/soc/meson/aiu.c b/sound/soc/meson/aiu.c index b765dfb70726..5c4845a23a34 100644 --- a/sound/soc/meson/aiu.c +++ b/sound/soc/meson/aiu.c @@ -345,6 +345,16 @@ static int aiu_probe(struct platform_device *pdev) goto err; } + /* Register the internal dac control component on gxl */ + if (of_device_is_compatible(dev->of_node, "amlogic,aiu-gxl")) { + ret = aiu_acodec_ctrl_register_component(dev); + if (ret) { + dev_err(dev, + "Failed to register acodec control component\n"); + goto err; + } + } + return 0; err: snd_soc_unregister_component(dev); diff --git a/sound/soc/meson/aiu.h b/sound/soc/meson/aiu.h index 9242ab1ab64b..a65a576e3400 100644 --- a/sound/soc/meson/aiu.h +++ b/sound/soc/meson/aiu.h @@ -52,6 +52,7 @@ int aiu_add_component(struct device *dev, const char *debugfs_prefix); int aiu_hdmi_ctrl_register_component(struct device *dev); +int aiu_acodec_ctrl_register_component(struct device *dev); int aiu_fifo_i2s_dai_probe(struct snd_soc_dai *dai); int aiu_fifo_spdif_dai_probe(struct snd_soc_dai *dai); From aa9c3b7273a58b5d9b2c1161b76b5fc8ea8c159b Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 13 Feb 2020 16:51:57 +0100 Subject: [PATCH 0299/4444] ASoC: meson: axg: extract sound card utils This prepares the addition of the GX SoC family sound card driver. The GX sound card, while slightly different, will be similar to the AXG one. The purpose of this change is to share the utils common to both sound card driver. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200213155159.3235792-8-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/Kconfig | 4 + sound/soc/meson/Makefile | 2 + sound/soc/meson/axg-card.c | 403 ++--------------------------- sound/soc/meson/meson-card-utils.c | 385 +++++++++++++++++++++++++++ sound/soc/meson/meson-card.h | 55 ++++ 5 files changed, 473 insertions(+), 376 deletions(-) create mode 100644 sound/soc/meson/meson-card-utils.c create mode 100644 sound/soc/meson/meson-card.h diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index 19de97ae4ce9..347fa78e309a 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -59,6 +59,7 @@ config SND_MESON_AXG_TDMOUT config SND_MESON_AXG_SOUND_CARD tristate "Amlogic AXG Sound Card Support" select SND_MESON_AXG_TDM_INTERFACE + select SND_MESON_CARD_UTILS imply SND_MESON_AXG_FRDDR imply SND_MESON_AXG_TODDR imply SND_MESON_AXG_TDMIN @@ -94,6 +95,9 @@ config SND_MESON_AXG_PDM Select Y or M to add support for PDM input embedded in the Amlogic AXG SoC family +config SND_MESON_CARD_UTILS + tristate + config SND_MESON_CODEC_GLUE tristate diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index 80f9113701b3..bef2b72fd7a7 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -19,6 +19,7 @@ snd-soc-meson-axg-sound-card-objs := axg-card.o snd-soc-meson-axg-spdifin-objs := axg-spdifin.o snd-soc-meson-axg-spdifout-objs := axg-spdifout.o snd-soc-meson-axg-pdm-objs := axg-pdm.o +snd-soc-meson-card-utils-objs := meson-card-utils.o snd-soc-meson-codec-glue-objs := meson-codec-glue.o snd-soc-meson-g12a-tohdmitx-objs := g12a-tohdmitx.o @@ -34,5 +35,6 @@ obj-$(CONFIG_SND_MESON_AXG_SOUND_CARD) += snd-soc-meson-axg-sound-card.o obj-$(CONFIG_SND_MESON_AXG_SPDIFIN) += snd-soc-meson-axg-spdifin.o obj-$(CONFIG_SND_MESON_AXG_SPDIFOUT) += snd-soc-meson-axg-spdifout.o obj-$(CONFIG_SND_MESON_AXG_PDM) += snd-soc-meson-axg-pdm.o +obj-$(CONFIG_SND_MESON_CARD_UTILS) += snd-soc-meson-card-utils.o obj-$(CONFIG_SND_MESON_CODEC_GLUE) += snd-soc-meson-codec-glue.o obj-$(CONFIG_SND_MESON_G12A_TOHDMITX) += snd-soc-meson-g12a-tohdmitx.o diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index 1f698adde506..372dc696cc8e 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c @@ -9,11 +9,7 @@ #include #include "axg-tdm.h" - -struct axg_card { - struct snd_soc_card card; - void **link_data; -}; +#include "meson-card.h" struct axg_dai_link_tdm_mask { u32 tx; @@ -41,161 +37,15 @@ static const struct snd_soc_pcm_stream codec_params = { .channels_max = 8, }; -#define PREFIX "amlogic," - -static int axg_card_reallocate_links(struct axg_card *priv, - unsigned int num_links) -{ - struct snd_soc_dai_link *links; - void **ldata; - - links = krealloc(priv->card.dai_link, - num_links * sizeof(*priv->card.dai_link), - GFP_KERNEL | __GFP_ZERO); - ldata = krealloc(priv->link_data, - num_links * sizeof(*priv->link_data), - GFP_KERNEL | __GFP_ZERO); - - if (!links || !ldata) { - dev_err(priv->card.dev, "failed to allocate links\n"); - return -ENOMEM; - } - - priv->card.dai_link = links; - priv->link_data = ldata; - priv->card.num_links = num_links; - return 0; -} - -static int axg_card_parse_dai(struct snd_soc_card *card, - struct device_node *node, - struct device_node **dai_of_node, - const char **dai_name) -{ - struct of_phandle_args args; - int ret; - - if (!dai_name || !dai_of_node || !node) - return -EINVAL; - - ret = of_parse_phandle_with_args(node, "sound-dai", - "#sound-dai-cells", 0, &args); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(card->dev, "can't parse dai %d\n", ret); - return ret; - } - *dai_of_node = args.np; - - return snd_soc_get_dai_name(&args, dai_name); -} - -static int axg_card_set_link_name(struct snd_soc_card *card, - struct snd_soc_dai_link *link, - struct device_node *node, - const char *prefix) -{ - char *name = devm_kasprintf(card->dev, GFP_KERNEL, "%s.%s", - prefix, node->full_name); - if (!name) - return -ENOMEM; - - link->name = name; - link->stream_name = name; - - return 0; -} - -static void axg_card_clean_references(struct axg_card *priv) -{ - struct snd_soc_card *card = &priv->card; - struct snd_soc_dai_link *link; - struct snd_soc_dai_link_component *codec; - struct snd_soc_aux_dev *aux; - int i, j; - - if (card->dai_link) { - for_each_card_prelinks(card, i, link) { - if (link->cpus) - of_node_put(link->cpus->of_node); - for_each_link_codecs(link, j, codec) - of_node_put(codec->of_node); - } - } - - if (card->aux_dev) { - for_each_card_pre_auxs(card, i, aux) - of_node_put(aux->dlc.of_node); - } - - kfree(card->dai_link); - kfree(priv->link_data); -} - -static int axg_card_add_aux_devices(struct snd_soc_card *card) -{ - struct device_node *node = card->dev->of_node; - struct snd_soc_aux_dev *aux; - int num, i; - - num = of_count_phandle_with_args(node, "audio-aux-devs", NULL); - if (num == -ENOENT) { - /* - * It is ok to have no auxiliary devices but for this card it - * is a strange situtation. Let's warn the about it. - */ - dev_warn(card->dev, "card has no auxiliary devices\n"); - return 0; - } else if (num < 0) { - dev_err(card->dev, "error getting auxiliary devices: %d\n", - num); - return num; - } - - aux = devm_kcalloc(card->dev, num, sizeof(*aux), GFP_KERNEL); - if (!aux) - return -ENOMEM; - card->aux_dev = aux; - card->num_aux_devs = num; - - for_each_card_pre_auxs(card, i, aux) { - aux->dlc.of_node = - of_parse_phandle(node, "audio-aux-devs", i); - if (!aux->dlc.of_node) - return -EINVAL; - } - - return 0; -} - static int axg_card_tdm_be_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct axg_card *priv = snd_soc_card_get_drvdata(rtd->card); + struct meson_card *priv = snd_soc_card_get_drvdata(rtd->card); struct axg_dai_link_tdm_data *be = (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num]; - struct snd_soc_dai *codec_dai; - unsigned int mclk; - int ret, i; - if (be->mclk_fs) { - mclk = params_rate(params) * be->mclk_fs; - - for_each_rtd_codec_dai(rtd, i, codec_dai) { - ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, - SND_SOC_CLOCK_IN); - if (ret && ret != -ENOTSUPP) - return ret; - } - - ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, - SND_SOC_CLOCK_OUT); - if (ret && ret != -ENOTSUPP) - return ret; - } - - return 0; + return meson_card_i2s_set_sysclk(substream, params, be->mclk_fs); } static const struct snd_soc_ops axg_card_tdm_be_ops = { @@ -204,7 +54,7 @@ static const struct snd_soc_ops axg_card_tdm_be_ops = { static int axg_card_tdm_dai_init(struct snd_soc_pcm_runtime *rtd) { - struct axg_card *priv = snd_soc_card_get_drvdata(rtd->card); + struct meson_card *priv = snd_soc_card_get_drvdata(rtd->card); struct axg_dai_link_tdm_data *be = (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num]; struct snd_soc_dai *codec_dai; @@ -234,7 +84,7 @@ static int axg_card_tdm_dai_init(struct snd_soc_pcm_runtime *rtd) static int axg_card_tdm_dai_lb_init(struct snd_soc_pcm_runtime *rtd) { - struct axg_card *priv = snd_soc_card_get_drvdata(rtd->card); + struct meson_card *priv = snd_soc_card_get_drvdata(rtd->card); struct axg_dai_link_tdm_data *be = (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num]; int ret; @@ -253,14 +103,14 @@ static int axg_card_tdm_dai_lb_init(struct snd_soc_pcm_runtime *rtd) static int axg_card_add_tdm_loopback(struct snd_soc_card *card, int *index) { - struct axg_card *priv = snd_soc_card_get_drvdata(card); + struct meson_card *priv = snd_soc_card_get_drvdata(card); struct snd_soc_dai_link *pad = &card->dai_link[*index]; struct snd_soc_dai_link *lb; struct snd_soc_dai_link_component *dlc; int ret; /* extend links */ - ret = axg_card_reallocate_links(priv, card->num_links + 1); + ret = meson_card_reallocate_links(card, card->num_links + 1); if (ret) return ret; @@ -304,32 +154,6 @@ static int axg_card_add_tdm_loopback(struct snd_soc_card *card, return 0; } -static unsigned int axg_card_parse_daifmt(struct device_node *node, - struct device_node *cpu_node) -{ - struct device_node *bitclkmaster = NULL; - struct device_node *framemaster = NULL; - unsigned int daifmt; - - daifmt = snd_soc_of_parse_daifmt(node, PREFIX, - &bitclkmaster, &framemaster); - daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK; - - /* If no master is provided, default to cpu master */ - if (!bitclkmaster || bitclkmaster == cpu_node) { - daifmt |= (!framemaster || framemaster == cpu_node) ? - SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBS_CFM; - } else { - daifmt |= (!framemaster || framemaster == cpu_node) ? - SND_SOC_DAIFMT_CBM_CFS : SND_SOC_DAIFMT_CBM_CFM; - } - - of_node_put(bitclkmaster); - of_node_put(framemaster); - - return daifmt; -} - static int axg_card_parse_cpu_tdm_slots(struct snd_soc_card *card, struct snd_soc_dai_link *link, struct device_node *node, @@ -424,7 +248,7 @@ static int axg_card_parse_tdm(struct snd_soc_card *card, struct device_node *node, int *index) { - struct axg_card *priv = snd_soc_card_get_drvdata(card); + struct meson_card *priv = snd_soc_card_get_drvdata(card); struct snd_soc_dai_link *link = &card->dai_link[*index]; struct axg_dai_link_tdm_data *be; int ret; @@ -438,7 +262,7 @@ static int axg_card_parse_tdm(struct snd_soc_card *card, /* Setup tdm link */ link->ops = &axg_card_tdm_be_ops; link->init = axg_card_tdm_dai_init; - link->dai_fmt = axg_card_parse_daifmt(node, link->cpus->of_node); + link->dai_fmt = meson_card_parse_daifmt(node, link->cpus->of_node); of_property_read_u32(node, "mclk-fs", &be->mclk_fs); @@ -462,97 +286,24 @@ static int axg_card_parse_tdm(struct snd_soc_card *card, return 0; } -static int axg_card_set_be_link(struct snd_soc_card *card, - struct snd_soc_dai_link *link, - struct device_node *node) -{ - struct snd_soc_dai_link_component *codec; - struct device_node *np; - int ret, num_codecs; - - link->no_pcm = 1; - link->dpcm_playback = 1; - link->dpcm_capture = 1; - - num_codecs = of_get_child_count(node); - if (!num_codecs) { - dev_err(card->dev, "be link %s has no codec\n", - node->full_name); - return -EINVAL; - } - - codec = devm_kcalloc(card->dev, num_codecs, sizeof(*codec), GFP_KERNEL); - if (!codec) - return -ENOMEM; - - link->codecs = codec; - link->num_codecs = num_codecs; - - for_each_child_of_node(node, np) { - ret = axg_card_parse_dai(card, np, &codec->of_node, - &codec->dai_name); - if (ret) { - of_node_put(np); - return ret; - } - - codec++; - } - - ret = axg_card_set_link_name(card, link, node, "be"); - if (ret) - dev_err(card->dev, "error setting %pOFn link name\n", np); - - return ret; -} - -static int axg_card_set_fe_link(struct snd_soc_card *card, - struct snd_soc_dai_link *link, - struct device_node *node, - bool is_playback) -{ - struct snd_soc_dai_link_component *codec; - - codec = devm_kzalloc(card->dev, sizeof(*codec), GFP_KERNEL); - if (!codec) - return -ENOMEM; - - link->codecs = codec; - link->num_codecs = 1; - - link->dynamic = 1; - link->dpcm_merged_format = 1; - link->dpcm_merged_chan = 1; - link->dpcm_merged_rate = 1; - link->codecs->dai_name = "snd-soc-dummy-dai"; - link->codecs->name = "snd-soc-dummy"; - - if (is_playback) - link->dpcm_playback = 1; - else - link->dpcm_capture = 1; - - return axg_card_set_link_name(card, link, node, "fe"); -} - static int axg_card_cpu_is_capture_fe(struct device_node *np) { - return of_device_is_compatible(np, PREFIX "axg-toddr"); + return of_device_is_compatible(np, DT_PREFIX "axg-toddr"); } static int axg_card_cpu_is_playback_fe(struct device_node *np) { - return of_device_is_compatible(np, PREFIX "axg-frddr"); + return of_device_is_compatible(np, DT_PREFIX "axg-frddr"); } static int axg_card_cpu_is_tdm_iface(struct device_node *np) { - return of_device_is_compatible(np, PREFIX "axg-tdm-iface"); + return of_device_is_compatible(np, DT_PREFIX "axg-tdm-iface"); } static int axg_card_cpu_is_codec(struct device_node *np) { - return of_device_is_compatible(np, PREFIX "g12a-tohdmitx"); + return of_device_is_compatible(np, DT_PREFIX "g12a-tohdmitx"); } static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np, @@ -569,17 +320,17 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np, dai_link->cpus = cpu; dai_link->num_cpus = 1; - ret = axg_card_parse_dai(card, np, &dai_link->cpus->of_node, - &dai_link->cpus->dai_name); + ret = meson_card_parse_dai(card, np, &dai_link->cpus->of_node, + &dai_link->cpus->dai_name); if (ret) return ret; if (axg_card_cpu_is_playback_fe(dai_link->cpus->of_node)) - ret = axg_card_set_fe_link(card, dai_link, np, true); + ret = meson_card_set_fe_link(card, dai_link, np, true); else if (axg_card_cpu_is_capture_fe(dai_link->cpus->of_node)) - ret = axg_card_set_fe_link(card, dai_link, np, false); + ret = meson_card_set_fe_link(card, dai_link, np, false); else - ret = axg_card_set_be_link(card, dai_link, np); + ret = meson_card_set_be_link(card, dai_link, np); if (ret) return ret; @@ -592,121 +343,21 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np, return ret; } -static int axg_card_add_links(struct snd_soc_card *card) -{ - struct axg_card *priv = snd_soc_card_get_drvdata(card); - struct device_node *node = card->dev->of_node; - struct device_node *np; - int num, i, ret; - - num = of_get_child_count(node); - if (!num) { - dev_err(card->dev, "card has no links\n"); - return -EINVAL; - } - - ret = axg_card_reallocate_links(priv, num); - if (ret) - return ret; - - i = 0; - for_each_child_of_node(node, np) { - ret = axg_card_add_link(card, np, &i); - if (ret) { - of_node_put(np); - return ret; - } - - i++; - } - - return 0; -} - -static int axg_card_parse_of_optional(struct snd_soc_card *card, - const char *propname, - int (*func)(struct snd_soc_card *c, - const char *p)) -{ - /* If property is not provided, don't fail ... */ - if (!of_property_read_bool(card->dev->of_node, propname)) - return 0; - - /* ... but do fail if it is provided and the parsing fails */ - return func(card, propname); -} +static const struct meson_card_match_data axg_card_match_data = { + .add_link = axg_card_add_link, +}; static const struct of_device_id axg_card_of_match[] = { - { .compatible = "amlogic,axg-sound-card", }, - {} + { + .compatible = "amlogic,axg-sound-card", + .data = &axg_card_match_data, + }, {} }; MODULE_DEVICE_TABLE(of, axg_card_of_match); -static int axg_card_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct axg_card *priv; - int ret; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - platform_set_drvdata(pdev, priv); - snd_soc_card_set_drvdata(&priv->card, priv); - - priv->card.owner = THIS_MODULE; - priv->card.dev = dev; - - ret = snd_soc_of_parse_card_name(&priv->card, "model"); - if (ret < 0) - return ret; - - ret = axg_card_parse_of_optional(&priv->card, "audio-routing", - snd_soc_of_parse_audio_routing); - if (ret) { - dev_err(dev, "error while parsing routing\n"); - return ret; - } - - ret = axg_card_parse_of_optional(&priv->card, "audio-widgets", - snd_soc_of_parse_audio_simple_widgets); - if (ret) { - dev_err(dev, "error while parsing widgets\n"); - return ret; - } - - ret = axg_card_add_links(&priv->card); - if (ret) - goto out_err; - - ret = axg_card_add_aux_devices(&priv->card); - if (ret) - goto out_err; - - ret = devm_snd_soc_register_card(dev, &priv->card); - if (ret) - goto out_err; - - return 0; - -out_err: - axg_card_clean_references(priv); - return ret; -} - -static int axg_card_remove(struct platform_device *pdev) -{ - struct axg_card *priv = platform_get_drvdata(pdev); - - axg_card_clean_references(priv); - - return 0; -} - static struct platform_driver axg_card_pdrv = { - .probe = axg_card_probe, - .remove = axg_card_remove, + .probe = meson_card_probe, + .remove = meson_card_remove, .driver = { .name = "axg-sound-card", .of_match_table = axg_card_of_match, diff --git a/sound/soc/meson/meson-card-utils.c b/sound/soc/meson/meson-card-utils.c new file mode 100644 index 000000000000..a70d244ef88b --- /dev/null +++ b/sound/soc/meson/meson-card-utils.c @@ -0,0 +1,385 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2020 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include + +#include "meson-card.h" + +int meson_card_i2s_set_sysclk(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + unsigned int mclk_fs) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai; + unsigned int mclk; + int ret, i; + + if (!mclk_fs) + return 0; + + mclk = params_rate(params) * mclk_fs; + + for_each_rtd_codec_dai(rtd, i, codec_dai) { + ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, + SND_SOC_CLOCK_IN); + if (ret && ret != -ENOTSUPP) + return ret; + } + + ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, + SND_SOC_CLOCK_OUT); + if (ret && ret != -ENOTSUPP) + return ret; + + return 0; +} +EXPORT_SYMBOL_GPL(meson_card_i2s_set_sysclk); + +int meson_card_reallocate_links(struct snd_soc_card *card, + unsigned int num_links) +{ + struct meson_card *priv = snd_soc_card_get_drvdata(card); + struct snd_soc_dai_link *links; + void **ldata; + + links = krealloc(priv->card.dai_link, + num_links * sizeof(*priv->card.dai_link), + GFP_KERNEL | __GFP_ZERO); + ldata = krealloc(priv->link_data, + num_links * sizeof(*priv->link_data), + GFP_KERNEL | __GFP_ZERO); + + if (!links || !ldata) { + dev_err(priv->card.dev, "failed to allocate links\n"); + return -ENOMEM; + } + + priv->card.dai_link = links; + priv->link_data = ldata; + priv->card.num_links = num_links; + return 0; +} +EXPORT_SYMBOL_GPL(meson_card_reallocate_links); + +int meson_card_parse_dai(struct snd_soc_card *card, + struct device_node *node, + struct device_node **dai_of_node, + const char **dai_name) +{ + struct of_phandle_args args; + int ret; + + if (!dai_name || !dai_of_node || !node) + return -EINVAL; + + ret = of_parse_phandle_with_args(node, "sound-dai", + "#sound-dai-cells", 0, &args); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(card->dev, "can't parse dai %d\n", ret); + return ret; + } + *dai_of_node = args.np; + + return snd_soc_get_dai_name(&args, dai_name); +} +EXPORT_SYMBOL_GPL(meson_card_parse_dai); + +static int meson_card_set_link_name(struct snd_soc_card *card, + struct snd_soc_dai_link *link, + struct device_node *node, + const char *prefix) +{ + char *name = devm_kasprintf(card->dev, GFP_KERNEL, "%s.%s", + prefix, node->full_name); + if (!name) + return -ENOMEM; + + link->name = name; + link->stream_name = name; + + return 0; +} + +unsigned int meson_card_parse_daifmt(struct device_node *node, + struct device_node *cpu_node) +{ + struct device_node *bitclkmaster = NULL; + struct device_node *framemaster = NULL; + unsigned int daifmt; + + daifmt = snd_soc_of_parse_daifmt(node, DT_PREFIX, + &bitclkmaster, &framemaster); + daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK; + + /* If no master is provided, default to cpu master */ + if (!bitclkmaster || bitclkmaster == cpu_node) { + daifmt |= (!framemaster || framemaster == cpu_node) ? + SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBS_CFM; + } else { + daifmt |= (!framemaster || framemaster == cpu_node) ? + SND_SOC_DAIFMT_CBM_CFS : SND_SOC_DAIFMT_CBM_CFM; + } + + of_node_put(bitclkmaster); + of_node_put(framemaster); + + return daifmt; +} +EXPORT_SYMBOL_GPL(meson_card_parse_daifmt); + +int meson_card_set_be_link(struct snd_soc_card *card, + struct snd_soc_dai_link *link, + struct device_node *node) +{ + struct snd_soc_dai_link_component *codec; + struct device_node *np; + int ret, num_codecs; + + link->no_pcm = 1; + link->dpcm_playback = 1; + link->dpcm_capture = 1; + + num_codecs = of_get_child_count(node); + if (!num_codecs) { + dev_err(card->dev, "be link %s has no codec\n", + node->full_name); + return -EINVAL; + } + + codec = devm_kcalloc(card->dev, num_codecs, sizeof(*codec), GFP_KERNEL); + if (!codec) + return -ENOMEM; + + link->codecs = codec; + link->num_codecs = num_codecs; + + for_each_child_of_node(node, np) { + ret = meson_card_parse_dai(card, np, &codec->of_node, + &codec->dai_name); + if (ret) { + of_node_put(np); + return ret; + } + + codec++; + } + + ret = meson_card_set_link_name(card, link, node, "be"); + if (ret) + dev_err(card->dev, "error setting %pOFn link name\n", np); + + return ret; +} +EXPORT_SYMBOL_GPL(meson_card_set_be_link); + +int meson_card_set_fe_link(struct snd_soc_card *card, + struct snd_soc_dai_link *link, + struct device_node *node, + bool is_playback) +{ + struct snd_soc_dai_link_component *codec; + + codec = devm_kzalloc(card->dev, sizeof(*codec), GFP_KERNEL); + if (!codec) + return -ENOMEM; + + link->codecs = codec; + link->num_codecs = 1; + + link->dynamic = 1; + link->dpcm_merged_format = 1; + link->dpcm_merged_chan = 1; + link->dpcm_merged_rate = 1; + link->codecs->dai_name = "snd-soc-dummy-dai"; + link->codecs->name = "snd-soc-dummy"; + + if (is_playback) + link->dpcm_playback = 1; + else + link->dpcm_capture = 1; + + return meson_card_set_link_name(card, link, node, "fe"); +} +EXPORT_SYMBOL_GPL(meson_card_set_fe_link); + +static int meson_card_add_links(struct snd_soc_card *card) +{ + struct meson_card *priv = snd_soc_card_get_drvdata(card); + struct device_node *node = card->dev->of_node; + struct device_node *np; + int num, i, ret; + + num = of_get_child_count(node); + if (!num) { + dev_err(card->dev, "card has no links\n"); + return -EINVAL; + } + + ret = meson_card_reallocate_links(card, num); + if (ret) + return ret; + + i = 0; + for_each_child_of_node(node, np) { + ret = priv->match_data->add_link(card, np, &i); + if (ret) { + of_node_put(np); + return ret; + } + + i++; + } + + return 0; +} + +static int meson_card_parse_of_optional(struct snd_soc_card *card, + const char *propname, + int (*func)(struct snd_soc_card *c, + const char *p)) +{ + /* If property is not provided, don't fail ... */ + if (!of_property_read_bool(card->dev->of_node, propname)) + return 0; + + /* ... but do fail if it is provided and the parsing fails */ + return func(card, propname); +} + +static int meson_card_add_aux_devices(struct snd_soc_card *card) +{ + struct device_node *node = card->dev->of_node; + struct snd_soc_aux_dev *aux; + int num, i; + + num = of_count_phandle_with_args(node, "audio-aux-devs", NULL); + if (num == -ENOENT) { + return 0; + } else if (num < 0) { + dev_err(card->dev, "error getting auxiliary devices: %d\n", + num); + return num; + } + + aux = devm_kcalloc(card->dev, num, sizeof(*aux), GFP_KERNEL); + if (!aux) + return -ENOMEM; + card->aux_dev = aux; + card->num_aux_devs = num; + + for_each_card_pre_auxs(card, i, aux) { + aux->dlc.of_node = + of_parse_phandle(node, "audio-aux-devs", i); + if (!aux->dlc.of_node) + return -EINVAL; + } + + return 0; +} + +static void meson_card_clean_references(struct meson_card *priv) +{ + struct snd_soc_card *card = &priv->card; + struct snd_soc_dai_link *link; + struct snd_soc_dai_link_component *codec; + struct snd_soc_aux_dev *aux; + int i, j; + + if (card->dai_link) { + for_each_card_prelinks(card, i, link) { + if (link->cpus) + of_node_put(link->cpus->of_node); + for_each_link_codecs(link, j, codec) + of_node_put(codec->of_node); + } + } + + if (card->aux_dev) { + for_each_card_pre_auxs(card, i, aux) + of_node_put(aux->dlc.of_node); + } + + kfree(card->dai_link); + kfree(priv->link_data); +} + +int meson_card_probe(struct platform_device *pdev) +{ + const struct meson_card_match_data *data; + struct device *dev = &pdev->dev; + struct meson_card *priv; + int ret; + + data = of_device_get_match_data(dev); + if (!data) { + dev_err(dev, "failed to match device\n"); + return -ENODEV; + } + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, priv); + snd_soc_card_set_drvdata(&priv->card, priv); + + priv->card.owner = THIS_MODULE; + priv->card.dev = dev; + priv->match_data = data; + + ret = snd_soc_of_parse_card_name(&priv->card, "model"); + if (ret < 0) + return ret; + + ret = meson_card_parse_of_optional(&priv->card, "audio-routing", + snd_soc_of_parse_audio_routing); + if (ret) { + dev_err(dev, "error while parsing routing\n"); + return ret; + } + + ret = meson_card_parse_of_optional(&priv->card, "audio-widgets", + snd_soc_of_parse_audio_simple_widgets); + if (ret) { + dev_err(dev, "error while parsing widgets\n"); + return ret; + } + + ret = meson_card_add_links(&priv->card); + if (ret) + goto out_err; + + ret = meson_card_add_aux_devices(&priv->card); + if (ret) + goto out_err; + + ret = devm_snd_soc_register_card(dev, &priv->card); + if (ret) + goto out_err; + + return 0; + +out_err: + meson_card_clean_references(priv); + return ret; +} +EXPORT_SYMBOL_GPL(meson_card_probe); + +int meson_card_remove(struct platform_device *pdev) +{ + struct meson_card *priv = platform_get_drvdata(pdev); + + meson_card_clean_references(priv); + + return 0; +} +EXPORT_SYMBOL_GPL(meson_card_remove); + +MODULE_DESCRIPTION("Amlogic Sound Card Utils"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/meson/meson-card.h b/sound/soc/meson/meson-card.h new file mode 100644 index 000000000000..74314071c80d --- /dev/null +++ b/sound/soc/meson/meson-card.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 BayLibre, SAS. + * Author: Jerome Brunet + */ + +#ifndef _MESON_SND_CARD_H +#define _MESON_SND_CARD_H + +struct device_node; +struct platform_device; + +struct snd_soc_card; +struct snd_pcm_substream; +struct snd_pcm_hw_params; + +#define DT_PREFIX "amlogic," + +struct meson_card_match_data { + int (*add_link)(struct snd_soc_card *card, + struct device_node *node, + int *index); +}; + +struct meson_card { + const struct meson_card_match_data *match_data; + struct snd_soc_card card; + void **link_data; +}; + +unsigned int meson_card_parse_daifmt(struct device_node *node, + struct device_node *cpu_node); + +int meson_card_i2s_set_sysclk(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + unsigned int mclk_fs); + +int meson_card_reallocate_links(struct snd_soc_card *card, + unsigned int num_links); +int meson_card_parse_dai(struct snd_soc_card *card, + struct device_node *node, + struct device_node **dai_of_node, + const char **dai_name); +int meson_card_set_be_link(struct snd_soc_card *card, + struct snd_soc_dai_link *link, + struct device_node *node); +int meson_card_set_fe_link(struct snd_soc_card *card, + struct snd_soc_dai_link *link, + struct device_node *node, + bool is_playback); + +int meson_card_probe(struct platform_device *pdev); +int meson_card_remove(struct platform_device *pdev); + +#endif /* _MESON_SND_CARD_H */ From fd00366b8e4125d29e32d49053a702ddf77430f6 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 13 Feb 2020 16:51:58 +0100 Subject: [PATCH 0300/4444] ASoC: meson: gx: add sound card dt-binding documentation Add the dt-binding documentation of sound card supporting the amlogic GX SoC family Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200213155159.3235792-9-jbrunet@baylibre.com Signed-off-by: Mark Brown --- .../bindings/sound/amlogic,gx-sound-card.yaml | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/amlogic,gx-sound-card.yaml diff --git a/Documentation/devicetree/bindings/sound/amlogic,gx-sound-card.yaml b/Documentation/devicetree/bindings/sound/amlogic,gx-sound-card.yaml new file mode 100644 index 000000000000..fb374c659be1 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/amlogic,gx-sound-card.yaml @@ -0,0 +1,113 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/amlogic,gx-sound-card.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic GX sound card + +maintainers: + - Jerome Brunet + +properties: + compatible: + items: + - const: amlogic,gx-sound-card + + audio-aux-devs: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: list of auxiliary devices + + audio-routing: + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + minItems: 2 + description: |- + A list of the connections between audio components. Each entry is a + pair of strings, the first being the connection's sink, the second + being the connection's source. + + audio-widgets: + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + minItems: 2 + description: |- + A list off component DAPM widget. Each entry is a pair of strings, + the first being the widget type, the second being the widget name + + model: + $ref: /schemas/types.yaml#/definitions/string + description: User specified audio sound card name + +patternProperties: + "^dai-link-[0-9]+$": + type: object + description: |- + dai-link child nodes: + Container for dai-link level properties and the CODEC sub-nodes. + There should be at least one (and probably more) subnode of this type + + properties: + dai-format: + $ref: /schemas/types.yaml#/definitions/string + enum: [ i2s, left-j, dsp_a ] + + mclk-fs: + $ref: /schemas/types.yaml#/definitions/uint32 + description: |- + Multiplication factor between the frame rate and master clock + rate + + sound-dai: + $ref: /schemas/types.yaml#/definitions/phandle + description: phandle of the CPU DAI + + patternProperties: + "^codec-[0-9]+$": + type: object + description: |- + Codecs: + dai-link representing backend links should have at least one subnode. + One subnode for each codec of the dai-link. dai-link representing + frontend links have no codec, therefore have no subnodes + + properties: + sound-dai: + $ref: /schemas/types.yaml#/definitions/phandle + description: phandle of the codec DAI + + required: + - sound-dai + + required: + - sound-dai + +required: + - model + - dai-link-0 + +examples: + - | + sound { + compatible = "amlogic,gx-sound-card"; + model = "GXL-ACME-S905X-FOO"; + audio-aux-devs = <&>; + audio-routing = "I2S ENCODER I2S IN", "I2S FIFO Playback"; + + dai-link-0 { + sound-dai = <&i2s_fifo>; + }; + + dai-link-1 { + sound-dai = <&i2s_encoder>; + dai-format = "i2s"; + mclk-fs = <256>; + + codec-0 { + sound-dai = <&codec0>; + }; + + codec-1 { + sound-dai = <&codec1>; + }; + }; + }; + From e37a0c313a0f8ba0b8de9c30db98fbc77bd8d446 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 13 Feb 2020 16:51:59 +0100 Subject: [PATCH 0301/4444] ASoC: meson: gx: add sound card support Add support for the sound card used on the amlogic GX SoC family Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200213155159.3235792-10-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/Kconfig | 7 ++ sound/soc/meson/Makefile | 2 + sound/soc/meson/gx-card.c | 141 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 sound/soc/meson/gx-card.c diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index 347fa78e309a..22d2af75b59e 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -101,6 +101,13 @@ config SND_MESON_CARD_UTILS config SND_MESON_CODEC_GLUE tristate +config SND_MESON_GX_SOUND_CARD + tristate "Amlogic GX Sound Card Support" + select SND_MESON_CARD_UTILS + imply SND_MESON_AIU + help + Select Y or M to add support for the GXBB/GXL SoC sound card + config SND_MESON_G12A_TOHDMITX tristate "Amlogic G12A To HDMI TX Control Support" select REGMAP_MMIO diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index bef2b72fd7a7..f9c90c391498 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -21,6 +21,7 @@ snd-soc-meson-axg-spdifout-objs := axg-spdifout.o snd-soc-meson-axg-pdm-objs := axg-pdm.o snd-soc-meson-card-utils-objs := meson-card-utils.o snd-soc-meson-codec-glue-objs := meson-codec-glue.o +snd-soc-meson-gx-sound-card-objs := gx-card.o snd-soc-meson-g12a-tohdmitx-objs := g12a-tohdmitx.o obj-$(CONFIG_SND_MESON_AIU) += snd-soc-meson-aiu.o @@ -37,4 +38,5 @@ obj-$(CONFIG_SND_MESON_AXG_SPDIFOUT) += snd-soc-meson-axg-spdifout.o obj-$(CONFIG_SND_MESON_AXG_PDM) += snd-soc-meson-axg-pdm.o obj-$(CONFIG_SND_MESON_CARD_UTILS) += snd-soc-meson-card-utils.o obj-$(CONFIG_SND_MESON_CODEC_GLUE) += snd-soc-meson-codec-glue.o +obj-$(CONFIG_SND_MESON_GX_SOUND_CARD) += snd-soc-meson-gx-sound-card.o obj-$(CONFIG_SND_MESON_G12A_TOHDMITX) += snd-soc-meson-g12a-tohdmitx.o diff --git a/sound/soc/meson/gx-card.c b/sound/soc/meson/gx-card.c new file mode 100644 index 000000000000..7b01dcb73e5e --- /dev/null +++ b/sound/soc/meson/gx-card.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Copyright (c) 2020 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include + +#include "meson-card.h" + +struct gx_dai_link_i2s_data { + unsigned int mclk_fs; +}; + +/* + * Base params for the codec to codec links + * Those will be over-written by the CPU side of the link + */ +static const struct snd_soc_pcm_stream codec_params = { + .formats = SNDRV_PCM_FMTBIT_S24_LE, + .rate_min = 5525, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 8, +}; + +static int gx_card_i2s_be_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct meson_card *priv = snd_soc_card_get_drvdata(rtd->card); + struct gx_dai_link_i2s_data *be = + (struct gx_dai_link_i2s_data *)priv->link_data[rtd->num]; + + return meson_card_i2s_set_sysclk(substream, params, be->mclk_fs); +} + +static const struct snd_soc_ops gx_card_i2s_be_ops = { + .hw_params = gx_card_i2s_be_hw_params, +}; + +static int gx_card_parse_i2s(struct snd_soc_card *card, + struct device_node *node, + int *index) +{ + struct meson_card *priv = snd_soc_card_get_drvdata(card); + struct snd_soc_dai_link *link = &card->dai_link[*index]; + struct gx_dai_link_i2s_data *be; + + /* Allocate i2s link parameters */ + be = devm_kzalloc(card->dev, sizeof(*be), GFP_KERNEL); + if (!be) + return -ENOMEM; + priv->link_data[*index] = be; + + /* Setup i2s link */ + link->ops = &gx_card_i2s_be_ops; + link->dai_fmt = meson_card_parse_daifmt(node, link->cpus->of_node); + + of_property_read_u32(node, "mclk-fs", &be->mclk_fs); + + return 0; +} + +static int gx_card_cpu_identify(struct snd_soc_dai_link_component *c, + char *match) +{ + if (of_device_is_compatible(c->of_node, DT_PREFIX "aiu")) { + if (strstr(c->dai_name, match)) + return 1; + } + + /* dai not matched */ + return 0; +} + +static int gx_card_add_link(struct snd_soc_card *card, struct device_node *np, + int *index) +{ + struct snd_soc_dai_link *dai_link = &card->dai_link[*index]; + struct snd_soc_dai_link_component *cpu; + int ret; + + cpu = devm_kzalloc(card->dev, sizeof(*cpu), GFP_KERNEL); + if (!cpu) + return -ENOMEM; + + dai_link->cpus = cpu; + dai_link->num_cpus = 1; + + ret = meson_card_parse_dai(card, np, &dai_link->cpus->of_node, + &dai_link->cpus->dai_name); + if (ret) + return ret; + + if (gx_card_cpu_identify(dai_link->cpus, "FIFO")) + ret = meson_card_set_fe_link(card, dai_link, np, true); + else + ret = meson_card_set_be_link(card, dai_link, np); + + if (ret) + return ret; + + /* Check if the cpu is the i2s encoder and parse i2s data */ + if (gx_card_cpu_identify(dai_link->cpus, "I2S Encoder")) + ret = gx_card_parse_i2s(card, np, index); + + /* Or apply codec to codec params if necessary */ + else if (gx_card_cpu_identify(dai_link->cpus, "CODEC CTRL")) + dai_link->params = &codec_params; + + return ret; +} + +static const struct meson_card_match_data gx_card_match_data = { + .add_link = gx_card_add_link, +}; + +static const struct of_device_id gx_card_of_match[] = { + { + .compatible = "amlogic,gx-sound-card", + .data = &gx_card_match_data, + }, {} +}; +MODULE_DEVICE_TABLE(of, gx_card_of_match); + +static struct platform_driver gx_card_pdrv = { + .probe = meson_card_probe, + .remove = meson_card_remove, + .driver = { + .name = "gx-sound-card", + .of_match_table = gx_card_of_match, + }, +}; +module_platform_driver(gx_card_pdrv); + +MODULE_DESCRIPTION("Amlogic GX ALSA machine driver"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("GPL v2"); From 67ccd2b97db276fed5ca4c38c166182327d2f401 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 6 Feb 2020 14:34:54 +0000 Subject: [PATCH 0302/4444] of/address: Move range parser code out of CONFIG_PCI In preparation to make the range parsing code work for non-PCI buses, move the parsing functions out from the CONFIG_PCI #ifdef. Signed-off-by: Rob Herring --- drivers/of/address.c | 215 ++++++++++++++++++++++--------------------- 1 file changed, 109 insertions(+), 106 deletions(-) diff --git a/drivers/of/address.c b/drivers/of/address.c index e8a39c3ec4d4..846045a48395 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -100,6 +100,28 @@ static unsigned int of_bus_default_get_flags(const __be32 *addr) return IORESOURCE_MEM; } +static unsigned int of_bus_pci_get_flags(const __be32 *addr) +{ + unsigned int flags = 0; + u32 w = be32_to_cpup(addr); + + if (!IS_ENABLED(CONFIG_PCI)) + return 0; + + switch((w >> 24) & 0x03) { + case 0x01: + flags |= IORESOURCE_IO; + break; + case 0x02: /* 32 bits */ + case 0x03: /* 64 bits */ + flags |= IORESOURCE_MEM; + break; + } + if (w & 0x40000000) + flags |= IORESOURCE_PREFETCH; + return flags; +} + #ifdef CONFIG_PCI /* * PCI bus specific translator @@ -125,25 +147,6 @@ static void of_bus_pci_count_cells(struct device_node *np, *sizec = 2; } -static unsigned int of_bus_pci_get_flags(const __be32 *addr) -{ - unsigned int flags = 0; - u32 w = be32_to_cpup(addr); - - switch((w >> 24) & 0x03) { - case 0x01: - flags |= IORESOURCE_IO; - break; - case 0x02: /* 32 bits */ - case 0x03: /* 64 bits */ - flags |= IORESOURCE_MEM; - break; - } - if (w & 0x40000000) - flags |= IORESOURCE_PREFETCH; - return flags; -} - static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns, int pna) { @@ -234,93 +237,6 @@ int of_pci_address_to_resource(struct device_node *dev, int bar, } EXPORT_SYMBOL_GPL(of_pci_address_to_resource); -static int parser_init(struct of_pci_range_parser *parser, - struct device_node *node, const char *name) -{ - const int na = 3, ns = 2; - int rlen; - - parser->node = node; - parser->pna = of_n_addr_cells(node); - parser->np = parser->pna + na + ns; - parser->dma = !strcmp(name, "dma-ranges"); - - parser->range = of_get_property(node, name, &rlen); - if (parser->range == NULL) - return -ENOENT; - - parser->end = parser->range + rlen / sizeof(__be32); - - return 0; -} - -int of_pci_range_parser_init(struct of_pci_range_parser *parser, - struct device_node *node) -{ - return parser_init(parser, node, "ranges"); -} -EXPORT_SYMBOL_GPL(of_pci_range_parser_init); - -int of_pci_dma_range_parser_init(struct of_pci_range_parser *parser, - struct device_node *node) -{ - return parser_init(parser, node, "dma-ranges"); -} -EXPORT_SYMBOL_GPL(of_pci_dma_range_parser_init); - -struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, - struct of_pci_range *range) -{ - const int na = 3, ns = 2; - - if (!range) - return NULL; - - if (!parser->range || parser->range + parser->np > parser->end) - return NULL; - - range->pci_space = be32_to_cpup(parser->range); - range->flags = of_bus_pci_get_flags(parser->range); - range->pci_addr = of_read_number(parser->range + 1, ns); - if (parser->dma) - range->cpu_addr = of_translate_dma_address(parser->node, - parser->range + na); - else - range->cpu_addr = of_translate_address(parser->node, - parser->range + na); - range->size = of_read_number(parser->range + parser->pna + na, ns); - - parser->range += parser->np; - - /* Now consume following elements while they are contiguous */ - while (parser->range + parser->np <= parser->end) { - u32 flags; - u64 pci_addr, cpu_addr, size; - - flags = of_bus_pci_get_flags(parser->range); - pci_addr = of_read_number(parser->range + 1, ns); - if (parser->dma) - cpu_addr = of_translate_dma_address(parser->node, - parser->range + na); - else - cpu_addr = of_translate_address(parser->node, - parser->range + na); - size = of_read_number(parser->range + parser->pna + na, ns); - - if (flags != range->flags) - break; - if (pci_addr != range->pci_addr + range->size || - cpu_addr != range->cpu_addr + range->size) - break; - - range->size += size; - parser->range += parser->np; - } - - return range; -} -EXPORT_SYMBOL_GPL(of_pci_range_parser_one); - /* * of_pci_range_to_resource - Create a resource from an of_pci_range * @range: the PCI range that describes the resource @@ -775,6 +691,93 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, } EXPORT_SYMBOL(of_get_address); +static int parser_init(struct of_pci_range_parser *parser, + struct device_node *node, const char *name) +{ + const int na = 3, ns = 2; + int rlen; + + parser->node = node; + parser->pna = of_n_addr_cells(node); + parser->np = parser->pna + na + ns; + parser->dma = !strcmp(name, "dma-ranges"); + + parser->range = of_get_property(node, name, &rlen); + if (parser->range == NULL) + return -ENOENT; + + parser->end = parser->range + rlen / sizeof(__be32); + + return 0; +} + +int of_pci_range_parser_init(struct of_pci_range_parser *parser, + struct device_node *node) +{ + return parser_init(parser, node, "ranges"); +} +EXPORT_SYMBOL_GPL(of_pci_range_parser_init); + +int of_pci_dma_range_parser_init(struct of_pci_range_parser *parser, + struct device_node *node) +{ + return parser_init(parser, node, "dma-ranges"); +} +EXPORT_SYMBOL_GPL(of_pci_dma_range_parser_init); + +struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, + struct of_pci_range *range) +{ + const int na = 3, ns = 2; + + if (!range) + return NULL; + + if (!parser->range || parser->range + parser->np > parser->end) + return NULL; + + range->pci_space = be32_to_cpup(parser->range); + range->flags = of_bus_pci_get_flags(parser->range); + range->pci_addr = of_read_number(parser->range + 1, ns); + if (parser->dma) + range->cpu_addr = of_translate_dma_address(parser->node, + parser->range + na); + else + range->cpu_addr = of_translate_address(parser->node, + parser->range + na); + range->size = of_read_number(parser->range + parser->pna + na, ns); + + parser->range += parser->np; + + /* Now consume following elements while they are contiguous */ + while (parser->range + parser->np <= parser->end) { + u32 flags; + u64 pci_addr, cpu_addr, size; + + flags = of_bus_pci_get_flags(parser->range); + pci_addr = of_read_number(parser->range + 1, ns); + if (parser->dma) + cpu_addr = of_translate_dma_address(parser->node, + parser->range + na); + else + cpu_addr = of_translate_address(parser->node, + parser->range + na); + size = of_read_number(parser->range + parser->pna + na, ns); + + if (flags != range->flags) + break; + if (pci_addr != range->pci_addr + range->size || + cpu_addr != range->cpu_addr + range->size) + break; + + range->size += size; + parser->range += parser->np; + } + + return range; +} +EXPORT_SYMBOL_GPL(of_pci_range_parser_one); + static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr, u64 size) { From a0c15bd5ebbf484924bcb1cf68966ba6d3f82eb0 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 17 Jan 2020 17:08:48 -0600 Subject: [PATCH 0303/4444] ARM: dts: imx: Kill off "simple-panel" compatibles "simple-panel" is a Linux driver and has never been an accepted upstream compatible string, so remove it. Cc: Shawn Guo Cc: Sascha Hauer Cc: Pengutronix Kernel Team Cc: Fabio Estevam Cc: NXP Linux Team Signed-off-by: Rob Herring Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6q-novena.dts | 2 +- arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/imx6q-novena.dts b/arch/arm/boot/dts/imx6q-novena.dts index 61347a545d6c..69f170ff31c5 100644 --- a/arch/arm/boot/dts/imx6q-novena.dts +++ b/arch/arm/boot/dts/imx6q-novena.dts @@ -107,7 +107,7 @@ }; panel: panel { - compatible = "innolux,n133hse-ea1", "simple-panel"; + compatible = "innolux,n133hse-ea1"; backlight = <&backlight>; }; diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts index 3749fdda3611..5d3805b07032 100644 --- a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts +++ b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts @@ -25,7 +25,7 @@ }; panel { - compatible = "auo,g101evn010", "simple-panel"; + compatible = "auo,g101evn010"; power-supply = <&ldo4_ext>; backlight = <&lcd_backlight>; From 4c9403540f2859e848ae90dfae8915bf05d2189b Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Sun, 19 Jan 2020 10:11:32 +0000 Subject: [PATCH 0304/4444] arm64: dts: imx8mm: drop redundant interrupt-parent There is interrupt-parent = <&gic> in root node, there is no need set it again in node ddr-pmu@3d800000. Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mm.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi index 1e5e11592f7b..b3d0b29d7007 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi @@ -896,7 +896,6 @@ ddr-pmu@3d800000 { compatible = "fsl,imx8mm-ddr-pmu", "fsl,imx8m-ddr-pmu"; reg = <0x3d800000 0x400000>; - interrupt-parent = <&gic>; interrupts = ; }; }; From 14875e57d8ea9659916cfff524f6a268e882baf7 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Sun, 19 Jan 2020 10:12:46 +0000 Subject: [PATCH 0305/4444] clk: imx: imx8mp: add ocotp root clk Add ocotp root clk, then when using nvmem to read fuse, clk could be managed. Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index f6c120cca0d4..ee83aa2162d9 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -671,6 +671,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) hws[IMX8MP_CLK_I2C2_ROOT] = imx_clk_hw_gate4("i2c2_root_clk", "i2c2", ccm_base + 0x4180, 0); hws[IMX8MP_CLK_I2C3_ROOT] = imx_clk_hw_gate4("i2c3_root_clk", "i2c3", ccm_base + 0x4190, 0); hws[IMX8MP_CLK_I2C4_ROOT] = imx_clk_hw_gate4("i2c4_root_clk", "i2c4", ccm_base + 0x41a0, 0); + hws[IMX8MP_CLK_OCOTP_ROOT] = imx_clk_hw_gate4("ocotp_root_clk", "ipg_root", ccm_base + 0x4220, 0); hws[IMX8MP_CLK_PCIE_ROOT] = imx_clk_hw_gate4("pcie_root_clk", "pcie_aux", ccm_base + 0x4250, 0); hws[IMX8MP_CLK_PWM1_ROOT] = imx_clk_hw_gate4("pwm1_root_clk", "pwm1", ccm_base + 0x4280, 0); hws[IMX8MP_CLK_PWM2_ROOT] = imx_clk_hw_gate4("pwm2_root_clk", "pwm2", ccm_base + 0x4290, 0); From b5cc96d3bfcbc495a350f78aa2e1295b238d26da Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Mon, 20 Jan 2020 14:51:28 +0200 Subject: [PATCH 0306/4444] soc: imx: gpcv2: include linux/sizes.h This header is included indirectly on arm/arm64 but not on x86 so CONFIG_COMPILE_TEST breaks. Fix by including directly. Signed-off-by: Leonard Crestez Signed-off-by: Shawn Guo --- drivers/soc/imx/gpcv2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index b0dffb06c05d..6cf8a7a412bd 100644 --- a/drivers/soc/imx/gpcv2.c +++ b/drivers/soc/imx/gpcv2.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include From ea38ca9a2607872b5bb515911330df52f9e4934b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Mon, 20 Jan 2020 17:12:55 +0100 Subject: [PATCH 0307/4444] arm64: dts: imx8mq-librem5-devkit: Add proximity sensor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support for the vcnl4040 landet a while ago so add it and the corresponding pinmux. The irq is currently unused in the driver so don't configure it yet. Signed-off-by: Guido Günther Signed-off-by: Shawn Guo --- .../boot/dts/freescale/imx8mq-librem5-devkit.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts index 764a4cb4e125..007c14eec676 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts @@ -441,6 +441,12 @@ VDDIO-supply = <®_1v8_p>; }; + proximity-sensor@60 { + compatible = "vishay,vcnl4040"; + reg = <0x60>; + pinctrl-0 = <&pinctrl_prox>; + }; + accel-gyro@6a { compatible = "st,lsm9ds1-imu"; reg = <0x6a>; @@ -543,6 +549,12 @@ >; }; + pinctrl_prox: proxgrp { + fsl,pins = < + MX8MQ_IOMUXC_GPIO1_IO12_GPIO1_IO12 0x80 /* prox intr */ + >; + }; + pinctrl_pwr_en: pwrengrp { fsl,pins = < MX8MQ_IOMUXC_GPIO1_IO08_GPIO1_IO8 0x06 From 6b4953fe32ff3ac5981a74c5d8c1c61555a9e6ae Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Thu, 23 Jan 2020 10:51:44 +0800 Subject: [PATCH 0308/4444] ARM: dts: imx7ulp-evk: disable usbotg1 overcurrent function At imx7ulp evk, all USBOTG1 OC (Over Current) function pins are used by others, and the USB driver doesn't support OC function through the GPIO, so we disable the OC function for this board as well as delete the pinctrl for it. Reviewed-by: Jun Li Acked-by: Leonard Crestez Signed-off-by: Peter Chen Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx7ulp-evk.dts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/imx7ulp-evk.dts b/arch/arm/boot/dts/imx7ulp-evk.dts index a863a2b337d6..eff51e113db4 100644 --- a/arch/arm/boot/dts/imx7ulp-evk.dts +++ b/arch/arm/boot/dts/imx7ulp-evk.dts @@ -72,7 +72,7 @@ srp-disable; hnp-disable; adp-disable; - over-current-active-low; + disable-over-current; status = "okay"; }; @@ -110,7 +110,6 @@ pinctrl_usbotg1_id: otg1idgrp { fsl,pins = < IMX7ULP_PAD_PTC13__USB0_ID 0x10003 - IMX7ULP_PAD_PTC16__USB1_OC2 0x10003 >; }; From 62668b68dc8e7d4c23cdec60f31d9c8dc1384409 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 28 Jan 2020 05:28:36 +0000 Subject: [PATCH 0309/4444] clk: imx: composite-8m: add imx8m_clk_hw_composite_core There are several clock slices, current composite code only support bus/ip clock slices, it could not support core slice. So introduce a new API imx8m_clk_hw_composite_core to support core slice. To core slice, post divider with 3 bits width and no pre divider. Other fields are same as bus/ip slices. Add a flag IMX_COMPOSITE_CORE for the usecase. Reviewed-by: Abel Vesa Signed-off-by: Peng Fan Reviewed-by: Leonard Crestez Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-composite-8m.c | 18 ++++++++++++++---- drivers/clk/imx/clk.h | 13 +++++++++++-- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/clk/imx/clk-composite-8m.c b/drivers/clk/imx/clk-composite-8m.c index 20f7c91c03d2..4869c16376bf 100644 --- a/drivers/clk/imx/clk-composite-8m.c +++ b/drivers/clk/imx/clk-composite-8m.c @@ -15,6 +15,7 @@ #define PCG_PREDIV_MAX 8 #define PCG_DIV_SHIFT 0 +#define PCG_CORE_DIV_WIDTH 3 #define PCG_DIV_WIDTH 6 #define PCG_DIV_MAX 64 @@ -126,6 +127,7 @@ static const struct clk_ops imx8m_clk_composite_divider_ops = { struct clk_hw *imx8m_clk_hw_composite_flags(const char *name, const char * const *parent_names, int num_parents, void __iomem *reg, + u32 composite_flags, unsigned long flags) { struct clk_hw *hw = ERR_PTR(-ENOMEM), *mux_hw; @@ -133,6 +135,7 @@ struct clk_hw *imx8m_clk_hw_composite_flags(const char *name, struct clk_divider *div = NULL; struct clk_gate *gate = NULL; struct clk_mux *mux = NULL; + const struct clk_ops *divider_ops; mux = kzalloc(sizeof(*mux), GFP_KERNEL); if (!mux) @@ -150,8 +153,16 @@ struct clk_hw *imx8m_clk_hw_composite_flags(const char *name, div_hw = &div->hw; div->reg = reg; - div->shift = PCG_PREDIV_SHIFT; - div->width = PCG_PREDIV_WIDTH; + if (composite_flags & IMX_COMPOSITE_CORE) { + div->shift = PCG_DIV_SHIFT; + div->width = PCG_CORE_DIV_WIDTH; + divider_ops = &clk_divider_ops; + } else { + div->shift = PCG_PREDIV_SHIFT; + div->width = PCG_PREDIV_WIDTH; + divider_ops = &imx8m_clk_composite_divider_ops; + } + div->lock = &imx_ccm_lock; div->flags = CLK_DIVIDER_ROUND_CLOSEST; @@ -166,8 +177,7 @@ struct clk_hw *imx8m_clk_hw_composite_flags(const char *name, hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, mux_hw, &clk_mux_ops, div_hw, - &imx8m_clk_composite_divider_ops, - gate_hw, &clk_gate_ops, flags); + divider_ops, gate_hw, &clk_gate_ops, flags); if (IS_ERR(hw)) goto fail; diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index b05213b91dcf..f074dd8ec42e 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -477,20 +477,29 @@ struct clk_hw *imx_clk_hw_cpu(const char *name, const char *parent_name, struct clk *div, struct clk *mux, struct clk *pll, struct clk *step); +#define IMX_COMPOSITE_CORE BIT(0) + struct clk_hw *imx8m_clk_hw_composite_flags(const char *name, const char * const *parent_names, int num_parents, void __iomem *reg, + u32 composite_flags, unsigned long flags); +#define imx8m_clk_hw_composite_core(name, parent_names, reg) \ + imx8m_clk_hw_composite_flags(name, parent_names, \ + ARRAY_SIZE(parent_names), reg, \ + IMX_COMPOSITE_CORE, \ + CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE) + #define imx8m_clk_composite_flags(name, parent_names, num_parents, reg, \ flags) \ to_clk(imx8m_clk_hw_composite_flags(name, parent_names, \ - num_parents, reg, flags)) + num_parents, reg, 0, flags)) #define __imx8m_clk_hw_composite(name, parent_names, reg, flags) \ imx8m_clk_hw_composite_flags(name, parent_names, \ - ARRAY_SIZE(parent_names), reg, \ + ARRAY_SIZE(parent_names), reg, 0, \ flags | CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE) #define __imx8m_clk_composite(name, parent_names, reg, flags) \ From 7a8d3b90bdfe44d2e90523444ff82f0060d9560e Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 28 Jan 2020 05:28:41 +0000 Subject: [PATCH 0310/4444] clk: imx: imx8mq: use imx8m_clk_hw_composite_core Use imx8m_clk_hw_composite_core to simplify code. Add new definitions, and X_SRC/CG/DIV will be alias to the new definitions for backwards compatibility Reviewed-by: Abel Vesa Signed-off-by: Peng Fan Reviewed-by: Leonard Crestez Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mq.c | 34 +++++++++++++----------- include/dt-bindings/clock/imx8mq-clock.h | 7 ++++- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c index 4c0edca1a6d0..ac9452cd9a82 100644 --- a/drivers/clk/imx/clk-imx8mq.c +++ b/drivers/clk/imx/clk-imx8mq.c @@ -403,22 +403,26 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) /* CORE */ hws[IMX8MQ_CLK_A53_SRC] = imx_clk_hw_mux2("arm_a53_src", base + 0x8000, 24, 3, imx8mq_a53_sels, ARRAY_SIZE(imx8mq_a53_sels)); - hws[IMX8MQ_CLK_M4_SRC] = imx_clk_hw_mux2("arm_m4_src", base + 0x8080, 24, 3, imx8mq_arm_m4_sels, ARRAY_SIZE(imx8mq_arm_m4_sels)); - hws[IMX8MQ_CLK_VPU_SRC] = imx_clk_hw_mux2("vpu_src", base + 0x8100, 24, 3, imx8mq_vpu_sels, ARRAY_SIZE(imx8mq_vpu_sels)); - hws[IMX8MQ_CLK_GPU_CORE_SRC] = imx_clk_hw_mux2("gpu_core_src", base + 0x8180, 24, 3, imx8mq_gpu_core_sels, ARRAY_SIZE(imx8mq_gpu_core_sels)); - hws[IMX8MQ_CLK_GPU_SHADER_SRC] = imx_clk_hw_mux2("gpu_shader_src", base + 0x8200, 24, 3, imx8mq_gpu_shader_sels, ARRAY_SIZE(imx8mq_gpu_shader_sels)); - hws[IMX8MQ_CLK_A53_CG] = imx_clk_hw_gate3_flags("arm_a53_cg", "arm_a53_src", base + 0x8000, 28, CLK_IS_CRITICAL); - hws[IMX8MQ_CLK_M4_CG] = imx_clk_hw_gate3("arm_m4_cg", "arm_m4_src", base + 0x8080, 28); - hws[IMX8MQ_CLK_VPU_CG] = imx_clk_hw_gate3("vpu_cg", "vpu_src", base + 0x8100, 28); - hws[IMX8MQ_CLK_GPU_CORE_CG] = imx_clk_hw_gate3("gpu_core_cg", "gpu_core_src", base + 0x8180, 28); - hws[IMX8MQ_CLK_GPU_SHADER_CG] = imx_clk_hw_gate3("gpu_shader_cg", "gpu_shader_src", base + 0x8200, 28); - hws[IMX8MQ_CLK_A53_DIV] = imx_clk_hw_divider2("arm_a53_div", "arm_a53_cg", base + 0x8000, 0, 3); - hws[IMX8MQ_CLK_M4_DIV] = imx_clk_hw_divider2("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3); - hws[IMX8MQ_CLK_VPU_DIV] = imx_clk_hw_divider2("vpu_div", "vpu_cg", base + 0x8100, 0, 3); - hws[IMX8MQ_CLK_GPU_CORE_DIV] = imx_clk_hw_divider2("gpu_core_div", "gpu_core_cg", base + 0x8180, 0, 3); - hws[IMX8MQ_CLK_GPU_SHADER_DIV] = imx_clk_hw_divider2("gpu_shader_div", "gpu_shader_cg", base + 0x8200, 0, 3); + + hws[IMX8MQ_CLK_M4_CORE] = imx8m_clk_hw_composite_core("arm_m4_core", imx8mq_arm_m4_sels, base + 0x8080); + hws[IMX8MQ_CLK_VPU_CORE] = imx8m_clk_hw_composite_core("vpu_core", imx8mq_vpu_sels, base + 0x8100); + hws[IMX8MQ_CLK_GPU_CORE] = imx8m_clk_hw_composite_core("gpu_core", imx8mq_gpu_core_sels, base + 0x8180); + hws[IMX8MQ_CLK_GPU_SHADER] = imx8m_clk_hw_composite("gpu_shader", imx8mq_gpu_shader_sels, base + 0x8200); + /* For backwards compatibility */ + hws[IMX8MQ_CLK_M4_SRC] = hws[IMX8MQ_CLK_M4_CORE]; + hws[IMX8MQ_CLK_M4_CG] = hws[IMX8MQ_CLK_M4_CORE]; + hws[IMX8MQ_CLK_M4_DIV] = hws[IMX8MQ_CLK_M4_CORE]; + hws[IMX8MQ_CLK_VPU_SRC] = hws[IMX8MQ_CLK_VPU_CORE]; + hws[IMX8MQ_CLK_VPU_CG] = hws[IMX8MQ_CLK_VPU_CORE]; + hws[IMX8MQ_CLK_VPU_DIV] = hws[IMX8MQ_CLK_VPU_CORE]; + hws[IMX8MQ_CLK_GPU_CORE_SRC] = hws[IMX8MQ_CLK_GPU_CORE]; + hws[IMX8MQ_CLK_GPU_CORE_CG] = hws[IMX8MQ_CLK_GPU_CORE]; + hws[IMX8MQ_CLK_GPU_CORE_DIV] = hws[IMX8MQ_CLK_GPU_CORE]; + hws[IMX8MQ_CLK_GPU_SHADER_SRC] = hws[IMX8MQ_CLK_GPU_SHADER]; + hws[IMX8MQ_CLK_GPU_SHADER_CG] = hws[IMX8MQ_CLK_GPU_SHADER]; + hws[IMX8MQ_CLK_GPU_SHADER_DIV] = hws[IMX8MQ_CLK_GPU_SHADER]; /* BUS */ hws[IMX8MQ_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mq_main_axi_sels, base + 0x8800); @@ -567,7 +571,7 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) hws[IMX8MQ_CLK_WDOG2_ROOT] = imx_clk_hw_gate4("wdog2_root_clk", "wdog", base + 0x4540, 0); hws[IMX8MQ_CLK_WDOG3_ROOT] = imx_clk_hw_gate4("wdog3_root_clk", "wdog", base + 0x4550, 0); hws[IMX8MQ_CLK_VPU_G1_ROOT] = imx_clk_hw_gate2_flags("vpu_g1_root_clk", "vpu_g1", base + 0x4560, 0, CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE); - hws[IMX8MQ_CLK_GPU_ROOT] = imx_clk_hw_gate4("gpu_root_clk", "gpu_core_div", base + 0x4570, 0); + hws[IMX8MQ_CLK_GPU_ROOT] = imx_clk_hw_gate4("gpu_root_clk", "gpu_core", base + 0x4570, 0); hws[IMX8MQ_CLK_VPU_G2_ROOT] = imx_clk_hw_gate2_flags("vpu_g2_root_clk", "vpu_g2", base + 0x45a0, 0, CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE); hws[IMX8MQ_CLK_DISP_ROOT] = imx_clk_hw_gate2_shared2("disp_root_clk", "disp_dc8000", base + 0x45d0, 0, &share_count_dcss); hws[IMX8MQ_CLK_DISP_AXI_ROOT] = imx_clk_hw_gate2_shared2("disp_axi_root_clk", "disp_axi", base + 0x45d0, 0, &share_count_dcss); diff --git a/include/dt-bindings/clock/imx8mq-clock.h b/include/dt-bindings/clock/imx8mq-clock.h index 3bab9b21c8d7..2b88723310bd 100644 --- a/include/dt-bindings/clock/imx8mq-clock.h +++ b/include/dt-bindings/clock/imx8mq-clock.h @@ -424,6 +424,11 @@ #define IMX8MQ_SYS2_PLL_500M_CG 283 #define IMX8MQ_SYS2_PLL_1000M_CG 284 -#define IMX8MQ_CLK_END 285 +#define IMX8MQ_CLK_GPU_CORE 285 +#define IMX8MQ_CLK_GPU_SHADER 286 +#define IMX8MQ_CLK_M4_CORE 287 +#define IMX8MQ_CLK_VPU_CORE 288 + +#define IMX8MQ_CLK_END 289 #endif /* __DT_BINDINGS_CLOCK_IMX8MQ_H */ From 811e4171d0f5ac6d1172333adf361c74ce2c8ec5 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 28 Jan 2020 05:28:46 +0000 Subject: [PATCH 0311/4444] clk: imx: imx8mm: use imx8m_clk_hw_composite_core Use imx8m_clk_hw_composite_core to simplify code. Add new definitions, and X_SRC/CG/DIV will be alias to the new definitions for backwards compatibility Reviewed-by: Abel Vesa Signed-off-by: Peng Fan Reviewed-by: Leonard Crestez Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mm.c | 35 ++++++++++++++---------- include/dt-bindings/clock/imx8mm-clock.h | 7 ++++- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c index 2ed93fc25087..f79a5f5d9ed5 100644 --- a/drivers/clk/imx/clk-imx8mm.c +++ b/drivers/clk/imx/clk-imx8mm.c @@ -414,20 +414,27 @@ static int imx8mm_clocks_probe(struct platform_device *pdev) /* Core Slice */ hws[IMX8MM_CLK_A53_SRC] = imx_clk_hw_mux2("arm_a53_src", base + 0x8000, 24, 3, imx8mm_a53_sels, ARRAY_SIZE(imx8mm_a53_sels)); - hws[IMX8MM_CLK_M4_SRC] = imx_clk_hw_mux2("arm_m4_src", base + 0x8080, 24, 3, imx8mm_m4_sels, ARRAY_SIZE(imx8mm_m4_sels)); - hws[IMX8MM_CLK_VPU_SRC] = imx_clk_hw_mux2("vpu_src", base + 0x8100, 24, 3, imx8mm_vpu_sels, ARRAY_SIZE(imx8mm_vpu_sels)); - hws[IMX8MM_CLK_GPU3D_SRC] = imx_clk_hw_mux2("gpu3d_src", base + 0x8180, 24, 3, imx8mm_gpu3d_sels, ARRAY_SIZE(imx8mm_gpu3d_sels)); - hws[IMX8MM_CLK_GPU2D_SRC] = imx_clk_hw_mux2("gpu2d_src", base + 0x8200, 24, 3, imx8mm_gpu2d_sels, ARRAY_SIZE(imx8mm_gpu2d_sels)); hws[IMX8MM_CLK_A53_CG] = imx_clk_hw_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000, 28); - hws[IMX8MM_CLK_M4_CG] = imx_clk_hw_gate3("arm_m4_cg", "arm_m4_src", base + 0x8080, 28); - hws[IMX8MM_CLK_VPU_CG] = imx_clk_hw_gate3("vpu_cg", "vpu_src", base + 0x8100, 28); - hws[IMX8MM_CLK_GPU3D_CG] = imx_clk_hw_gate3("gpu3d_cg", "gpu3d_src", base + 0x8180, 28); - hws[IMX8MM_CLK_GPU2D_CG] = imx_clk_hw_gate3("gpu2d_cg", "gpu2d_src", base + 0x8200, 28); hws[IMX8MM_CLK_A53_DIV] = imx_clk_hw_divider2("arm_a53_div", "arm_a53_cg", base + 0x8000, 0, 3); - hws[IMX8MM_CLK_M4_DIV] = imx_clk_hw_divider2("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3); - hws[IMX8MM_CLK_VPU_DIV] = imx_clk_hw_divider2("vpu_div", "vpu_cg", base + 0x8100, 0, 3); - hws[IMX8MM_CLK_GPU3D_DIV] = imx_clk_hw_divider2("gpu3d_div", "gpu3d_cg", base + 0x8180, 0, 3); - hws[IMX8MM_CLK_GPU2D_DIV] = imx_clk_hw_divider2("gpu2d_div", "gpu2d_cg", base + 0x8200, 0, 3); + + hws[IMX8MM_CLK_M4_CORE] = imx8m_clk_hw_composite_core("arm_m4_core", imx8mm_m4_sels, base + 0x8080); + hws[IMX8MM_CLK_VPU_CORE] = imx8m_clk_hw_composite_core("vpu_core", imx8mm_vpu_sels, base + 0x8100); + hws[IMX8MM_CLK_GPU3D_CORE] = imx8m_clk_hw_composite_core("gpu3d_core", imx8mm_gpu3d_sels, base + 0x8180); + hws[IMX8MM_CLK_GPU2D_CORE] = imx8m_clk_hw_composite_core("gpu2d_core", imx8mm_gpu2d_sels, base + 0x8200); + + /* For backwards compatibility */ + hws[IMX8MM_CLK_M4_SRC] = hws[IMX8MM_CLK_M4_CORE]; + hws[IMX8MM_CLK_M4_CG] = hws[IMX8MM_CLK_M4_CORE]; + hws[IMX8MM_CLK_M4_DIV] = hws[IMX8MM_CLK_M4_CORE]; + hws[IMX8MM_CLK_VPU_SRC] = hws[IMX8MM_CLK_VPU_CORE]; + hws[IMX8MM_CLK_VPU_CG] = hws[IMX8MM_CLK_VPU_CORE]; + hws[IMX8MM_CLK_VPU_DIV] = hws[IMX8MM_CLK_VPU_CORE]; + hws[IMX8MM_CLK_GPU3D_SRC] = hws[IMX8MM_CLK_GPU3D_CORE]; + hws[IMX8MM_CLK_GPU3D_CG] = hws[IMX8MM_CLK_GPU3D_CORE]; + hws[IMX8MM_CLK_GPU3D_DIV] = hws[IMX8MM_CLK_GPU3D_CORE]; + hws[IMX8MM_CLK_GPU2D_SRC] = hws[IMX8MM_CLK_GPU2D_CORE]; + hws[IMX8MM_CLK_GPU2D_CG] = hws[IMX8MM_CLK_GPU2D_CORE]; + hws[IMX8MM_CLK_GPU2D_DIV] = hws[IMX8MM_CLK_GPU2D_CORE]; /* BUS */ hws[IMX8MM_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mm_main_axi_sels, base + 0x8800); @@ -564,7 +571,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev) hws[IMX8MM_CLK_UART3_ROOT] = imx_clk_hw_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0); hws[IMX8MM_CLK_UART4_ROOT] = imx_clk_hw_gate4("uart4_root_clk", "uart4", base + 0x44c0, 0); hws[IMX8MM_CLK_USB1_CTRL_ROOT] = imx_clk_hw_gate4("usb1_ctrl_root_clk", "usb_bus", base + 0x44d0, 0); - hws[IMX8MM_CLK_GPU3D_ROOT] = imx_clk_hw_gate4("gpu3d_root_clk", "gpu3d_div", base + 0x44f0, 0); + hws[IMX8MM_CLK_GPU3D_ROOT] = imx_clk_hw_gate4("gpu3d_root_clk", "gpu3d_core", base + 0x44f0, 0); hws[IMX8MM_CLK_USDHC1_ROOT] = imx_clk_hw_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0); hws[IMX8MM_CLK_USDHC2_ROOT] = imx_clk_hw_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0); hws[IMX8MM_CLK_WDOG1_ROOT] = imx_clk_hw_gate4("wdog1_root_clk", "wdog", base + 0x4530, 0); @@ -586,7 +593,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev) hws[IMX8MM_CLK_SDMA1_ROOT] = imx_clk_hw_gate4("sdma1_clk", "ipg_root", base + 0x43a0, 0); hws[IMX8MM_CLK_SDMA2_ROOT] = imx_clk_hw_gate4("sdma2_clk", "ipg_audio_root", base + 0x43b0, 0); hws[IMX8MM_CLK_SDMA3_ROOT] = imx_clk_hw_gate4("sdma3_clk", "ipg_audio_root", base + 0x45f0, 0); - hws[IMX8MM_CLK_GPU2D_ROOT] = imx_clk_hw_gate4("gpu2d_root_clk", "gpu2d_div", base + 0x4660, 0); + hws[IMX8MM_CLK_GPU2D_ROOT] = imx_clk_hw_gate4("gpu2d_root_clk", "gpu2d_core", base + 0x4660, 0); hws[IMX8MM_CLK_CSI1_ROOT] = imx_clk_hw_gate4("csi1_root_clk", "csi1_core", base + 0x4650, 0); hws[IMX8MM_CLK_GPT_3M] = imx_clk_hw_fixed_factor("gpt_3m", "osc_24m", 1, 8); diff --git a/include/dt-bindings/clock/imx8mm-clock.h b/include/dt-bindings/clock/imx8mm-clock.h index edeece2289f0..038c28d349e8 100644 --- a/include/dt-bindings/clock/imx8mm-clock.h +++ b/include/dt-bindings/clock/imx8mm-clock.h @@ -265,6 +265,11 @@ #define IMX8MM_SYS_PLL2_333M_CG 244 #define IMX8MM_SYS_PLL2_500M_CG 245 -#define IMX8MM_CLK_END 246 +#define IMX8MM_CLK_M4_CORE 246 +#define IMX8MM_CLK_VPU_CORE 247 +#define IMX8MM_CLK_GPU3D_CORE 248 +#define IMX8MM_CLK_GPU2D_CORE 249 + +#define IMX8MM_CLK_END 250 #endif From 33db2ce73e9affe9a25130b166048f5a209d4dc1 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 28 Jan 2020 05:28:50 +0000 Subject: [PATCH 0312/4444] clk: imx: imx8mn: use imx8m_clk_hw_composite_core Use imx8m_clk_hw_composite_core to simplify code. Add new definitions, and X_SRC/CG/DIV will be alias to the new definitions for backwards compatibility Reviewed-by: Abel Vesa Signed-off-by: Peng Fan Reviewed-by: Leonard Crestez Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mn.c | 19 +++++++++++-------- include/dt-bindings/clock/imx8mn-clock.h | 4 +++- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c index a181eb2df876..7eea15a81838 100644 --- a/drivers/clk/imx/clk-imx8mn.c +++ b/drivers/clk/imx/clk-imx8mn.c @@ -413,15 +413,18 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) /* CORE */ hws[IMX8MN_CLK_A53_SRC] = imx_clk_hw_mux2("arm_a53_src", base + 0x8000, 24, 3, imx8mn_a53_sels, ARRAY_SIZE(imx8mn_a53_sels)); - hws[IMX8MN_CLK_GPU_CORE_SRC] = imx_clk_hw_mux2("gpu_core_src", base + 0x8180, 24, 3, imx8mn_gpu_core_sels, ARRAY_SIZE(imx8mn_gpu_core_sels)); - hws[IMX8MN_CLK_GPU_SHADER_SRC] = imx_clk_hw_mux2("gpu_shader_src", base + 0x8200, 24, 3, imx8mn_gpu_shader_sels, ARRAY_SIZE(imx8mn_gpu_shader_sels)); hws[IMX8MN_CLK_A53_CG] = imx_clk_hw_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000, 28); - hws[IMX8MN_CLK_GPU_CORE_CG] = imx_clk_hw_gate3("gpu_core_cg", "gpu_core_src", base + 0x8180, 28); - hws[IMX8MN_CLK_GPU_SHADER_CG] = imx_clk_hw_gate3("gpu_shader_cg", "gpu_shader_src", base + 0x8200, 28); - hws[IMX8MN_CLK_A53_DIV] = imx_clk_hw_divider2("arm_a53_div", "arm_a53_cg", base + 0x8000, 0, 3); - hws[IMX8MN_CLK_GPU_CORE_DIV] = imx_clk_hw_divider2("gpu_core_div", "gpu_core_cg", base + 0x8180, 0, 3); - hws[IMX8MN_CLK_GPU_SHADER_DIV] = imx_clk_hw_divider2("gpu_shader_div", "gpu_shader_cg", base + 0x8200, 0, 3); + + hws[IMX8MN_CLK_GPU_CORE] = imx8m_clk_hw_composite_core("gpu_core", imx8mn_gpu_core_sels, base + 0x8180); + hws[IMX8MN_CLK_GPU_SHADER] = imx8m_clk_hw_composite_core("gpu_shader", imx8mn_gpu_shader_sels, base + 0x8200); + + hws[IMX8MN_CLK_GPU_CORE_SRC] = hws[IMX8MN_CLK_GPU_CORE]; + hws[IMX8MN_CLK_GPU_CORE_CG] = hws[IMX8MN_CLK_GPU_CORE]; + hws[IMX8MN_CLK_GPU_CORE_DIV] = hws[IMX8MN_CLK_GPU_CORE]; + hws[IMX8MN_CLK_GPU_SHADER_SRC] = hws[IMX8MN_CLK_GPU_SHADER]; + hws[IMX8MN_CLK_GPU_SHADER_CG] = hws[IMX8MN_CLK_GPU_SHADER]; + hws[IMX8MN_CLK_GPU_SHADER_DIV] = hws[IMX8MN_CLK_GPU_SHADER]; /* BUS */ hws[IMX8MN_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mn_main_axi_sels, base + 0x8800); @@ -529,7 +532,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) hws[IMX8MN_CLK_UART3_ROOT] = imx_clk_hw_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0); hws[IMX8MN_CLK_UART4_ROOT] = imx_clk_hw_gate4("uart4_root_clk", "uart4", base + 0x44c0, 0); hws[IMX8MN_CLK_USB1_CTRL_ROOT] = imx_clk_hw_gate4("usb1_ctrl_root_clk", "usb_bus", base + 0x44d0, 0); - hws[IMX8MN_CLK_GPU_CORE_ROOT] = imx_clk_hw_gate4("gpu_core_root_clk", "gpu_core_div", base + 0x44f0, 0); + hws[IMX8MN_CLK_GPU_CORE_ROOT] = imx_clk_hw_gate4("gpu_core_root_clk", "gpu_core", base + 0x44f0, 0); hws[IMX8MN_CLK_USDHC1_ROOT] = imx_clk_hw_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0); hws[IMX8MN_CLK_USDHC2_ROOT] = imx_clk_hw_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0); hws[IMX8MN_CLK_WDOG1_ROOT] = imx_clk_hw_gate4("wdog1_root_clk", "wdog", base + 0x4530, 0); diff --git a/include/dt-bindings/clock/imx8mn-clock.h b/include/dt-bindings/clock/imx8mn-clock.h index 43883fe65db5..c42a22d3cf7c 100644 --- a/include/dt-bindings/clock/imx8mn-clock.h +++ b/include/dt-bindings/clock/imx8mn-clock.h @@ -229,7 +229,9 @@ #define IMX8MN_SYS_PLL2_500M_CG 210 #define IMX8MN_CLK_SNVS_ROOT 211 +#define IMX8MN_CLK_GPU_CORE 212 +#define IMX8MN_CLK_GPU_SHADER 213 -#define IMX8MN_CLK_END 212 +#define IMX8MN_CLK_END 214 #endif From 119c98f16e704e4c85522f6e22c9c819c21c4128 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 29 Jan 2020 22:53:36 +0100 Subject: [PATCH 0313/4444] ARM: dts: imx7-colibri: add gpio-line-names Add Colibri SODIMM numbers as GPIO line names on module level. The GPIO lines with a name are all available on the SODIMM edge connector of the Colibri iMX7 module and therefore a customer might use it as a GPIO. The Toradex Evaluation Board has the SODIMM numbers printed on the silk- screen. This allows a customer to quickly control a GPIO on a pin-header by using the name printed next to it. Putting the GPIO line name on module level makes sure that a customer gets a reasonable default. If more meaningful names are available on a custom carrier board, the user can overwrite the line names in a carrier board level device tree. The eMMC based modules share all GPIO names except two GPIOs on bank 6 which are not available on the raw NAND devices. Hence overwrite GPIO line names of bank 6 in the eMMC specific device tree file. Signed-off-by: Stefan Agner Reviewed-by: Philippe Schenker Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx7-colibri.dtsi | 178 ++++++++++++++++++++++ arch/arm/boot/dts/imx7d-colibri-emmc.dtsi | 26 ++++ 2 files changed, 204 insertions(+) diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsi index d05be3f0e2a7..10d8880e8d13 100644 --- a/arch/arm/boot/dts/imx7-colibri.dtsi +++ b/arch/arm/boot/dts/imx7-colibri.dtsi @@ -130,6 +130,184 @@ status = "disabled"; }; +&gpio1 { + gpio-line-names = "SODIMM_43", + "SODIMM_45", + "SODIMM_135", + "SODIMM_22", + "", + "", + "SODIMM_37", + "SODIMM_29", + "SODIMM_59", + "SODIMM_28", + "SODIMM_30", + "SODIMM_67", + "", + "", + "SODIMM_188", + "SODIMM_178"; +}; + +&gpio2 { + gpio-line-names = "SODIMM_111", + "SODIMM_113", + "SODIMM_115", + "SODIMM_117", + "SODIMM_119", + "SODIMM_121", + "SODIMM_123", + "SODIMM_125", + "SODIMM_91", + "SODIMM_89", + "SODIMM_105", + "SODIMM_152", + "SODIMM_150", + "SODIMM_95", + "SODIMM_126", + "SODIMM_107", + "SODIMM_114", + "SODIMM_116", + "SODIMM_118", + "SODIMM_120", + "SODIMM_122", + "SODIMM_124", + "SODIMM_127", + "SODIMM_130", + "SODIMM_132", + "SODIMM_134", + "SODIMM_133", + "SODIMM_104", + "SODIMM_106", + "SODIMM_110", + "SODIMM_112", + "SODIMM_128"; +}; + +&gpio3 { + gpio-line-names = "SODIMM_56", + "SODIMM_44", + "SODIMM_68", + "SODIMM_82", + "SODIMM_93", + "SODIMM_76", + "SODIMM_70", + "SODIMM_60", + "SODIMM_58", + "SODIMM_78", + "SODIMM_72", + "SODIMM_80", + "SODIMM_46", + "SODIMM_62", + "SODIMM_48", + "SODIMM_74", + "SODIMM_50", + "SODIMM_52", + "SODIMM_54", + "SODIMM_66", + "SODIMM_64", + "SODIMM_57", + "SODIMM_61", + "SODIMM_136", + "SODIMM_138", + "SODIMM_140", + "SODIMM_142", + "SODIMM_144", + "SODIMM_146"; +}; + +&gpio4 { + gpio-line-names = "SODIMM_35", + "SODIMM_33", + "SODIMM_38", + "SODIMM_36", + "SODIMM_21", + "SODIMM_19", + "SODIMM_131", + "SODIMM_129", + "SODIMM_90", + "SODIMM_92", + "SODIMM_88", + "SODIMM_86", + "SODIMM_81", + "SODIMM_94", + "SODIMM_96", + "SODIMM_75", + "SODIMM_101", + "SODIMM_103", + "SODIMM_79", + "SODIMM_97", + "SODIMM_67", + "SODIMM_59", + "SODIMM_85", + "SODIMM_65"; +}; + +&gpio5 { + gpio-line-names = "SODIMM_69", + "SODIMM_71", + "SODIMM_73", + "SODIMM_47", + "SODIMM_190", + "SODIMM_192", + "SODIMM_49", + "SODIMM_51", + "SODIMM_53", + "", + "", + "SODIMM_98", + "SODIMM_184", + "SODIMM_186", + "SODIMM_23", + "SODIMM_31", + "SODIMM_100", + "SODIMM_102"; +}; + +&gpio6 { + gpio-line-names = "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "SODIMM_169", + "", + "", + "", + "SODIMM_77", + "SODIMM_24", + "", + "SODIMM_25", + "SODIMM_27", + "SODIMM_32", + "SODIMM_34"; +}; + +&gpio7 { + gpio-line-names = "", + "", + "SODIMM_63", + "SODIMM_55", + "", + "", + "", + "", + "SODIMM_196", + "SODIMM_194", + "", + "SODIMM_99", + "", + "", + "SODIMM_137"; +}; + &gpmi { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_gpmi_nand>; diff --git a/arch/arm/boot/dts/imx7d-colibri-emmc.dtsi b/arch/arm/boot/dts/imx7d-colibri-emmc.dtsi index 898f4b8d7421..af39e5370fa1 100644 --- a/arch/arm/boot/dts/imx7d-colibri-emmc.dtsi +++ b/arch/arm/boot/dts/imx7d-colibri-emmc.dtsi @@ -13,6 +13,32 @@ }; }; +&gpio6 { + gpio-line-names = "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "SODIMM_169", + "SODIMM_157", + "", + "SODIMM_163", + "SODIMM_77", + "SODIMM_24", + "", + "SODIMM_25", + "SODIMM_27", + "SODIMM_32", + "SODIMM_34"; +}; + &usbotg2 { dr_mode = "host"; }; From ccf17617be4ba9b652dbba69cafd93c6ae0e608e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Fri, 31 Jan 2020 08:36:31 +0000 Subject: [PATCH 0314/4444] ARM: dts: imx7d: cl-som-imx7: update pfuze3000 max voltage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The max voltage of SW1A is 3.3V on PF3000 as per http://cache.freescale.com/files/analog/doc/data_sheet/PF3000.pdf?fsrch=1&sr=1&pageNum=1 While at it, remove the unnecessary leading zero from the i2c address. Signed-off-by: André Draszik Cc: Ilya Ledvich Cc: Igor Grinberg Cc: Rob Herring Cc: Mark Rutland Cc: Shawn Guo Cc: Sascha Hauer Cc: Pengutronix Kernel Team Cc: Fabio Estevam Cc: NXP Linux Team Cc: devicetree@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx7d-cl-som-imx7.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/imx7d-cl-som-imx7.dts b/arch/arm/boot/dts/imx7d-cl-som-imx7.dts index 7646284e13a7..89267cd59037 100644 --- a/arch/arm/boot/dts/imx7d-cl-som-imx7.dts +++ b/arch/arm/boot/dts/imx7d-cl-som-imx7.dts @@ -85,12 +85,12 @@ pmic: pmic@8 { compatible = "fsl,pfuze3000"; - reg = <0x08>; + reg = <0x8>; regulators { sw1a_reg: sw1a { regulator-min-microvolt = <700000>; - regulator-max-microvolt = <1475000>; + regulator-max-microvolt = <3300000>; regulator-boot-on; regulator-always-on; regulator-ramp-delay = <6250>; From edc2569b61de3541493489e906e468b5586b2e8c Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 5 Feb 2020 23:42:14 +0100 Subject: [PATCH 0315/4444] ARM: imx: limit errata selection to Cortex-A9 based designs The two erratas 754322 and 775420 are Cortex-A9 specific. The i.MX 6UL SoCs include a Cortex-A7 CPU and hence do not need this erratas enabeld. This patch moves the errata selection from the family Kconfig symbol to the SoC specifc Kconfig symbols where a Cortex-A9 is used. Signed-off-by: Stefan Agner Reviewed-by: Oleksandr Suvorov Reviewed-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/mach-imx/Kconfig | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 95584ee02b55..e7d7b90e2cf8 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -471,8 +471,6 @@ config SOC_IMX53 config SOC_IMX6 bool select ARM_CPU_SUSPEND if (PM || CPU_IDLE) - select ARM_ERRATA_754322 - select ARM_ERRATA_775420 select ARM_GIC select HAVE_IMX_ANATOP select HAVE_IMX_GPC @@ -484,6 +482,8 @@ config SOC_IMX6 config SOC_IMX6Q bool "i.MX6 Quad/DualLite support" select ARM_ERRATA_764369 if SMP + select ARM_ERRATA_754322 + select ARM_ERRATA_775420 select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD select PINCTRL_IMX6Q @@ -494,6 +494,8 @@ config SOC_IMX6Q config SOC_IMX6SL bool "i.MX6 SoloLite support" + select ARM_ERRATA_754322 + select ARM_ERRATA_775420 select PINCTRL_IMX6SL select SOC_IMX6 @@ -502,6 +504,8 @@ config SOC_IMX6SL config SOC_IMX6SLL bool "i.MX6 SoloLiteLite support" + select ARM_ERRATA_754322 + select ARM_ERRATA_775420 select PINCTRL_IMX6SLL select SOC_IMX6 @@ -510,6 +514,8 @@ config SOC_IMX6SLL config SOC_IMX6SX bool "i.MX6 SoloX support" + select ARM_ERRATA_754322 + select ARM_ERRATA_775420 select PINCTRL_IMX6SX select SOC_IMX6 From 4671f9cf78c663f7d58415a87732eaa7a8c8288f Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Tue, 4 Feb 2020 12:09:28 +0800 Subject: [PATCH 0316/4444] arm64: dts: ls1088a: support eMMC HS200 speed mode for RDB board This patch is to add eMMC HS200 speed mode support on ls1088ardb whose controller and peripheral circut support such capability. And clocks dts property is needed for driver to get peripheral clock value used for this speed mode. Signed-off-by: Yangbo Lu Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts | 1 + arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts index 4d77b345cebd..5633e59febc3 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts @@ -83,6 +83,7 @@ }; &esdhc { + mmc-hs200-1_8v; status = "okay"; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi index 594566265e3d..ec6013a8137d 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi @@ -393,6 +393,7 @@ reg = <0x0 0x2140000 0x0 0x10000>; interrupts = <0 28 0x4>; /* Level high type */ clock-frequency = <0>; + clocks = <&clockgen 2 1>; voltage-ranges = <1800 1800 3300 3300>; sdhci,auto-cmd12; little-endian; From e83291d9d66686b27a1e482142147e06772773b1 Mon Sep 17 00:00:00 2001 From: Balakrishna Godavarthi Date: Thu, 13 Feb 2020 16:49:34 +0530 Subject: [PATCH 0317/4444] arm64: dts: qcom: sc7180: Add bluetooth node on SC7180 IDP board Add bluetooth SoC WCN3990 node for SC7180 IDP board. Signed-off-by: Balakrishna Godavarthi Reviewed-by: Matthias Kaehlcke Link: https://lore.kernel.org/r/20200213111934.6205-1-bgodavar@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sc7180-idp.dts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sc7180-idp.dts b/arch/arm64/boot/dts/qcom/sc7180-idp.dts index 388f50ad4fde..d76e83c0a8e1 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-idp.dts +++ b/arch/arm64/boot/dts/qcom/sc7180-idp.dts @@ -17,6 +17,7 @@ compatible = "qcom,sc7180-idp", "qcom,sc7180"; aliases { + bluetooth0 = &bluetooth; hsuart0 = &uart3; serial0 = &uart8; }; @@ -256,6 +257,16 @@ &uart3 { status = "okay"; + + bluetooth: wcn3990-bt { + compatible = "qcom,wcn3990-bt"; + vddio-supply = <&vreg_l10a_1p8>; + vddxo-supply = <&vreg_l1c_1p8>; + vddrf-supply = <&vreg_l2c_1p3>; + vddch0-supply = <&vreg_l10c_3p3>; + max-speed = <3200000>; + clocks = <&rpmhcc RPMH_RF_CLK2>; + }; }; &uart8 { From df636eea2b782589fad7fce3bfea26c6c31e4d14 Mon Sep 17 00:00:00 2001 From: Arun Kumar Neelakantam Date: Wed, 22 Jan 2020 13:53:37 +0530 Subject: [PATCH 0318/4444] soc: qcom: aoss: Use wake_up_all() instead of wake_up_interruptible_all() During the probe the task is waiting in TASK_UNINTERRUPTIBLE state which cannot be woken-up by wake_up_interruptible_all() function. Use wake_up_all() to wake-up both TASK_UNINTERRUPTIBLE and TASK_INTERRUPTIBLE state tasks. Signed-off-by: Arun Kumar Neelakantam Link: https://lore.kernel.org/r/1579681417-1155-1-git-send-email-aneela@codeaurora.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_aoss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index 006ac40c526a..fe79661d28cb 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -200,7 +200,7 @@ static irqreturn_t qmp_intr(int irq, void *data) { struct qmp *qmp = data; - wake_up_interruptible_all(&qmp->event); + wake_up_all(&qmp->event); return IRQ_HANDLED; } From 89e7eddece6140020749932f9647a6068cc0d56d Mon Sep 17 00:00:00 2001 From: Arun Kumar Neelakantam Date: Wed, 22 Jan 2020 13:54:13 +0530 Subject: [PATCH 0319/4444] soc: qcom: aoss: Read back before triggering the IRQ In some device memory used by msm_qmp, there can be an early ack of a write to memory succeeding. This may cause the outgoing interrupt to be triggered before the msgram reflects the write. Add a readback to ensure the data is flushed to device memory before triggering the ipc interrupt. Signed-off-by: Arun Kumar Neelakantam Link: https://lore.kernel.org/r/1579681454-1229-1-git-send-email-aneela@codeaurora.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_aoss.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index fe79661d28cb..f43a2e07ee83 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -225,6 +225,7 @@ static bool qmp_message_empty(struct qmp *qmp) static int qmp_send(struct qmp *qmp, const void *data, size_t len) { long time_left; + size_t tlen; int ret; if (WARN_ON(len + sizeof(u32) > qmp->size)) @@ -239,6 +240,9 @@ static int qmp_send(struct qmp *qmp, const void *data, size_t len) __iowrite32_copy(qmp->msgram + qmp->offset + sizeof(u32), data, len / sizeof(u32)); writel(len, qmp->msgram + qmp->offset); + + /* Read back len to confirm data written in message RAM */ + tlen = readl(qmp->msgram + qmp->offset); qmp_kick(qmp); time_left = wait_event_interruptible_timeout(qmp->event, From 33b8cd0065b4a6759dcc025c7f2fbd0a24858e6a Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Thu, 12 Dec 2019 18:25:13 +0100 Subject: [PATCH 0320/4444] arm64: defconfig: Enable Qualcomm PM8XXX vibrator support The pm8xxx-vibrator driver controls the vibrator motor driver available in the Qualcomm PM8916 PMIC. Build the driver as module so it can be loaded when necessary. Signed-off-by: Stephan Gerhold Signed-off-by: Bjorn Andersson --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 0f212889c931..fca2b43affb7 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -320,6 +320,7 @@ CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ATMEL_MXT=m CONFIG_INPUT_MISC=y CONFIG_INPUT_PM8941_PWRKEY=y +CONFIG_INPUT_PM8XXX_VIBRATOR=m CONFIG_INPUT_HISI_POWERKEY=y # CONFIG_SERIO_SERPORT is not set CONFIG_SERIO_AMBAKMI=y From 24254a8edff59d581fcc67613794c380a2539bf7 Mon Sep 17 00:00:00 2001 From: Veerabhadrarao Badiganti Date: Wed, 8 Jan 2020 20:24:10 +0530 Subject: [PATCH 0321/4444] arm64: dts: qcom: sc7180: Add nodes for eMMC and SD card Add sdhc instances for supporting eMMC and SD-card on sc7180. The regulators should be in HPM state for proper functionality of eMMC and SD-card. Updating corresponding regulators accordingly. Signed-off-by: Veerabhadrarao Badiganti Signed-off-by: Shaik Sajida Bhanu Link: https://lore.kernel.org/r/1578495250-10672-1-git-send-email-sbhanu@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sc7180-idp.dts | 47 ++++++-- arch/arm64/boot/dts/qcom/sc7180.dtsi | 148 ++++++++++++++++++++++++ 2 files changed, 183 insertions(+), 12 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sc7180-idp.dts b/arch/arm64/boot/dts/qcom/sc7180-idp.dts index d76e83c0a8e1..38ca36bd722d 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-idp.dts +++ b/arch/arm64/boot/dts/qcom/sc7180-idp.dts @@ -7,6 +7,7 @@ /dts-v1/; +#include #include #include "sc7180.dtsi" #include "pm6150.dtsi" @@ -102,9 +103,9 @@ }; vreg_l12a_1p8: ldo12 { - regulator-min-microvolt = <1696000>; - regulator-max-microvolt = <1952000>; - regulator-initial-mode = ; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; }; vreg_l13a_1p8: ldo13 { @@ -144,9 +145,9 @@ }; vreg_l19a_2p9: ldo19 { - regulator-min-microvolt = <2696000>; - regulator-max-microvolt = <3304000>; - regulator-initial-mode = ; + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = ; }; }; @@ -190,9 +191,9 @@ }; vreg_l6c_2p9: ldo6 { - regulator-min-microvolt = <2696000>; - regulator-max-microvolt = <3304000>; - regulator-initial-mode = ; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2950000>; + regulator-initial-mode = ; }; vreg_l7c_3p0: ldo7 { @@ -208,9 +209,9 @@ }; vreg_l9c_2p9: ldo9 { - regulator-min-microvolt = <2952000>; - regulator-max-microvolt = <3304000>; - regulator-initial-mode = ; + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = ; }; vreg_l10c_3p3: ldo10 { @@ -255,6 +256,28 @@ status = "okay"; }; +&sdhc_1 { + status = "okay"; + + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sdc1_on>; + pinctrl-1 = <&sdc1_off>; + vmmc-supply = <&vreg_l19a_2p9>; + vqmmc-supply = <&vreg_l12a_1p8>; +}; + +&sdhc_2 { + status = "okay"; + + pinctrl-names = "default","sleep"; + pinctrl-0 = <&sdc2_on>; + pinctrl-1 = <&sdc2_off>; + vmmc-supply = <&vreg_l9c_2p9>; + vqmmc-supply = <&vreg_l6c_2p9>; + + cd-gpios = <&tlmm 69 GPIO_ACTIVE_LOW>; +}; + &uart3 { status = "okay"; diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index cc5a94f1f1ba..b6a998adb3d0 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -330,6 +330,33 @@ }; }; + sdhc_1: sdhci@7c4000 { + compatible = "qcom,sc7180-sdhci", "qcom,sdhci-msm-v5"; + reg = <0 0x7c4000 0 0x1000>, + <0 0x07c5000 0 0x1000>; + reg-names = "hc_mem", "cqhci_mem"; + + iommus = <&apps_smmu 0x60 0x0>; + interrupts = , + ; + interrupt-names = "hc_irq", "pwr_irq"; + + clocks = <&gcc GCC_SDCC1_APPS_CLK>, + <&gcc GCC_SDCC1_AHB_CLK>; + clock-names = "core", "iface"; + + bus-width = <8>; + non-removable; + supports-cqe; + + mmc-ddr-1_8v; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + + status = "disabled"; + }; + qupv3_id_0: geniqup@8c0000 { compatible = "qcom,geni-se-qup"; reg = <0 0x008c0000 0 0x6000>; @@ -1040,6 +1067,127 @@ function = "qup15"; }; }; + + sdc1_on: sdc1-on { + pinconf-clk { + pins = "sdc1_clk"; + bias-disable; + drive-strength = <16>; + }; + + pinconf-cmd { + pins = "sdc1_cmd"; + bias-pull-up; + drive-strength = <10>; + }; + + pinconf-data { + pins = "sdc1_data"; + bias-pull-up; + drive-strength = <10>; + }; + + pinconf-rclk { + pins = "sdc1_rclk"; + bias-pull-down; + }; + }; + + sdc1_off: sdc1-off { + pinconf-clk { + pins = "sdc1_clk"; + bias-disable; + drive-strength = <2>; + }; + + pinconf-cmd { + pins = "sdc1_cmd"; + bias-pull-up; + drive-strength = <2>; + }; + + pinconf-data { + pins = "sdc1_data"; + bias-pull-up; + drive-strength = <2>; + }; + + pinconf-rclk { + pins = "sdc1_rclk"; + bias-pull-down; + }; + }; + + sdc2_on: sdc2-on { + pinconf-clk { + pins = "sdc2_clk"; + bias-disable; + drive-strength = <16>; + }; + + pinconf-cmd { + pins = "sdc2_cmd"; + bias-pull-up; + drive-strength = <10>; + }; + + pinconf-data { + pins = "sdc2_data"; + bias-pull-up; + drive-strength = <10>; + }; + + pinconf-sd-cd { + pins = "gpio69"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + sdc2_off: sdc2-off { + pinconf-clk { + pins = "sdc2_clk"; + bias-disable; + drive-strength = <2>; + }; + + pinconf-cmd { + pins = "sdc2_cmd"; + bias-pull-up; + drive-strength = <2>; + }; + + pinconf-data { + pins = "sdc2_data"; + bias-pull-up; + drive-strength = <2>; + }; + + pinconf-sd-cd { + pins = "gpio69"; + bias-disable; + drive-strength = <2>; + }; + }; + }; + + sdhc_2: sdhci@8804000 { + compatible = "qcom,sc7180-sdhci", "qcom,sdhci-msm-v5"; + reg = <0 0x08804000 0 0x1000>; + reg-names = "hc_mem"; + + iommus = <&apps_smmu 0x80 0>; + interrupts = , + ; + interrupt-names = "hc_irq", "pwr_irq"; + + clocks = <&gcc GCC_SDCC2_APPS_CLK>, + <&gcc GCC_SDCC2_AHB_CLK>; + clock-names = "core", "iface"; + + bus-width = <4>; + + status = "disabled"; }; qspi: spi@88dc000 { From ef71fdb266d78bc800877978ad982e2f004b7bee Mon Sep 17 00:00:00 2001 From: Mathieu Poirier Date: Tue, 11 Feb 2020 11:30:11 -0700 Subject: [PATCH 0322/4444] arm64: dts: msm8916: Properly deal with ETMv4 power management Properly deal with ETMv4 power management by adding the "coresight-loses-context-with-cpu" property. Otherwise tracer configuration is lost when CPUs enter deep idle states, resulting in the failure of the trace session. Signed-off-by: Mathieu Poirier Link: https://lore.kernel.org/r/20200211183011.24720-1-mathieu.poirier@linaro.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/msm8916.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index 9f31064f2374..cabfa3547d28 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -1415,6 +1415,7 @@ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; clock-names = "apb_pclk", "atclk"; + arm,coresight-loses-context-with-cpu; cpu = <&CPU0>; @@ -1433,6 +1434,7 @@ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; clock-names = "apb_pclk", "atclk"; + arm,coresight-loses-context-with-cpu; cpu = <&CPU1>; @@ -1451,6 +1453,7 @@ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; clock-names = "apb_pclk", "atclk"; + arm,coresight-loses-context-with-cpu; cpu = <&CPU2>; @@ -1469,6 +1472,7 @@ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; clock-names = "apb_pclk", "atclk"; + arm,coresight-loses-context-with-cpu; cpu = <&CPU3>; From de8cf61c25c5c008b4442dc4a6427f2b6d46f299 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Tue, 4 Feb 2020 13:11:46 +0200 Subject: [PATCH 0323/4444] ARM: dts: imx7-colibri: add alias for RTC Make sure that the priority of the RTCs is defined. Signed-off-by: Stefan Agner Signed-off-by: Oleksandr Suvorov Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi b/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi index 6aa123cbdadb..9e9e85c10acb 100644 --- a/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi +++ b/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi @@ -41,6 +41,11 @@ */ / { + aliases { + rtc0 = &rtc; + rtc1 = &snvs_rtc; + }; + chosen { stdout-path = "serial0:115200n8"; }; From 7007f2eca0f258710899ca486da00546d03db0ed Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Tue, 4 Feb 2020 13:11:47 +0200 Subject: [PATCH 0324/4444] ARM: dts: imx7-colibri: fix muxing of usbc_det pin USB_C_DET pin shouldn't be in ethernet group. Creating a separate group allows one to use this pin as an USB ID pin. Fixes: b326629f25b7 ("ARM: dts: imx7: add Toradex Colibri iMX7S/iMX7D suppor") Signed-off-by: Oleksandr Suvorov Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx7-colibri.dtsi | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsi index 10d8880e8d13..ad7536da4313 100644 --- a/arch/arm/boot/dts/imx7-colibri.dtsi +++ b/arch/arm/boot/dts/imx7-colibri.dtsi @@ -524,7 +524,7 @@ &iomuxc { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_gpio1 &pinctrl_gpio2 &pinctrl_gpio3 &pinctrl_gpio4 - &pinctrl_gpio7>; + &pinctrl_gpio7 &pinctrl_usbc_det>; pinctrl_gpio1: gpio1-grp { fsl,pins = < @@ -629,7 +629,6 @@ pinctrl_enet1: enet1grp { fsl,pins = < - MX7D_PAD_ENET1_CRS__GPIO7_IO14 0x14 MX7D_PAD_ENET1_RGMII_RX_CTL__ENET1_RGMII_RX_CTL 0x73 MX7D_PAD_ENET1_RGMII_RD0__ENET1_RGMII_RD0 0x73 MX7D_PAD_ENET1_RGMII_RD1__ENET1_RGMII_RD1 0x73 @@ -827,6 +826,12 @@ >; }; + pinctrl_usbc_det: gpio-usbc-det { + fsl,pins = < + MX7D_PAD_ENET1_CRS__GPIO7_IO14 0x14 + >; + }; + pinctrl_usbh_reg: gpio-usbh-vbus { fsl,pins = < MX7D_PAD_UART3_CTS_B__GPIO4_IO7 0x14 /* SODIMM 129 USBH PEN */ From 8cf1eb848e26deb117e5faa813e718697192a4f9 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Tue, 4 Feb 2020 13:11:49 +0200 Subject: [PATCH 0325/4444] ARM: imx_v6_v7_defconfig: Enable TOUCHSCREEN_ATMEL_MXT Toradex iMX6/iMX7-based modules and boards support LCDs with an MicroChip ATMXT1066T2 touchscreen controller. This patch enables the TOUCHSCREEN_ATMEL_MXT which supports MXT-series controllers, including the ATMXT1066T2. Signed-off-by: Oleksandr Suvorov Signed-off-by: Shawn Guo --- arch/arm/configs/imx_v6_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 8f216a599735..7cf452ddaa0a 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -179,6 +179,7 @@ CONFIG_MOUSE_PS2=m CONFIG_MOUSE_PS2_ELANTECH=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ADS7846=y +CONFIG_TOUCHSCREEN_ATMEL_MXT=y CONFIG_TOUCHSCREEN_DA9052=y CONFIG_TOUCHSCREEN_EGALAX=y CONFIG_TOUCHSCREEN_GOODIX=y From e4ac6b1829d4b1899bb4d61cad5a81f28e9c6308 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Tue, 4 Feb 2020 13:11:50 +0200 Subject: [PATCH 0326/4444] ARM: imx_v6_v7_defconfig: Enable TOUCHSCREEN_AD7879 The Computer on module Colibri iMX7S/iMX7D has an AD7879 touchscreen controller. This patch enables the TOUCHSCREEN_AD7879 and TOUCHSCREEN_AD7879_I2C which support the mentioned controller in i2c mode. Signed-off-by: Oleksandr Suvorov Signed-off-by: Shawn Guo --- arch/arm/configs/imx_v6_v7_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 7cf452ddaa0a..5a20d12d62bd 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -179,6 +179,8 @@ CONFIG_MOUSE_PS2=m CONFIG_MOUSE_PS2_ELANTECH=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ADS7846=y +CONFIG_TOUCHSCREEN_AD7879=y +CONFIG_TOUCHSCREEN_AD7879_I2C=y CONFIG_TOUCHSCREEN_ATMEL_MXT=y CONFIG_TOUCHSCREEN_DA9052=y CONFIG_TOUCHSCREEN_EGALAX=y From ce35e21d82bcac8b3fd5128888f9e233f8444293 Mon Sep 17 00:00:00 2001 From: Bibby Hsieh Date: Fri, 14 Feb 2020 12:35:45 +0800 Subject: [PATCH 0327/4444] soc: mediatek: knows_txdone needs to be set in Mediatek CMDQ helper Mediatek CMDQ driver have a mechanism to do TXDONE_BY_ACK, so we should set knows_txdone. Fixes:576f1b4bc802 ("soc: mediatek: Add Mediatek CMDQ helper") Cc: stable@vger.kernel.org # v5.0+ Signed-off-by: Bibby Hsieh Reviewed-by: CK Hu Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-cmdq-helper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index de20e6cba83b..db37144ae98c 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -78,6 +78,7 @@ struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 timeout) client->pkt_cnt = 0; client->client.dev = dev; client->client.tx_block = false; + client->client.knows_txdone = true; client->chan = mbox_request_channel(&client->client, index); if (IS_ERR(client->chan)) { From eed1015c4c4240780789556d8fbf71df68ce6508 Mon Sep 17 00:00:00 2001 From: Sricharan R Date: Sun, 19 Jan 2020 18:43:17 +0530 Subject: [PATCH 0328/4444] dt-bindings: pinctrl: qcom: Add ipq6018 pinctrl bindings Add device tree binding Documentation details for ipq6018 pinctrl driver. Co-developed-by: Rajkumar Ayyasamy Signed-off-by: Rajkumar Ayyasamy Co-developed-by: Selvam Sathappan Periakaruppan Signed-off-by: Selvam Sathappan Periakaruppan Co-developed-by: Sivaprakash Murugesan Signed-off-by: Sivaprakash Murugesan Signed-off-by: Sricharan R Signed-off-by: Sivaprakash Murugesan Link: https://lore.kernel.org/r/1579439601-14810-2-git-send-email-sricharan@codeaurora.org Reviewed-by: Rob Herring Signed-off-by: Linus Walleij --- .../pinctrl/qcom,ipq6018-pinctrl.yaml | 153 ++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/qcom,ipq6018-pinctrl.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,ipq6018-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,ipq6018-pinctrl.yaml new file mode 100644 index 000000000000..63d1cfe86c6e --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/qcom,ipq6018-pinctrl.yaml @@ -0,0 +1,153 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/qcom,ipq6018-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Technologies, Inc. IPQ6018 TLMM block + +maintainers: + - Sricharan R + +description: | + This binding describes the Top Level Mode Multiplexer block found in the + IPQ6018 platform. + +properties: + compatible: + const: qcom,ipq6018-pinctrl + + reg: + maxItems: 1 + + interrupts: + description: Specifies the TLMM summary IRQ + maxItems: 1 + + interrupt-controller: true + + '#interrupt-cells': + description: + Specifies the PIN numbers and Flags, as defined in defined in + include/dt-bindings/interrupt-controller/irq.h + const: 2 + + gpio-controller: true + + '#gpio-cells': + description: Specifying the pin number and flags, as defined in + include/dt-bindings/gpio/gpio.h + const: 2 + + gpio-ranges: + maxItems: 1 + +#PIN CONFIGURATION NODES +patternProperties: + '-pinmux$': + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + allOf: + - $ref: "/schemas/pinctrl/pincfg-node.yaml" + + properties: + pins: + description: + List of gpio pins affected by the properties specified in this + subnode. + items: + oneOf: + - pattern: "^gpio([1-9]|[1-7][0-9]|80)$" + - enum: [ sdc1_clk, sdc1_cmd, sdc1_data, sdc2_clk, sdc2_cmd, + sdc2_data, qdsd_cmd, qdsd_data0, qdsd_data1, qdsd_data2, + qdsd_data3 ] + minItems: 1 + maxItems: 4 + + function: + description: + Specify the alternative function to be configured for the specified + pins. + enum: [ adsp_ext, alsp_int, atest_bbrx0, atest_bbrx1, atest_char, + atest_char0, atest_char1, atest_char2, atest_char3, atest_combodac, + atest_gpsadc0, atest_gpsadc1, atest_tsens, atest_wlan0, + atest_wlan1, backlight_en, bimc_dte0, bimc_dte1, blsp1_i2c, + blsp2_i2c, blsp3_i2c, blsp4_i2c, blsp5_i2c, blsp6_i2c, blsp1_spi, + blsp1_spi_cs1, blsp1_spi_cs2, blsp1_spi_cs3, blsp2_spi, + blsp2_spi_cs1, blsp2_spi_cs2, blsp2_spi_cs3, blsp3_spi, + blsp3_spi_cs1, blsp3_spi_cs2, blsp3_spi_cs3, blsp4_spi, blsp5_spi, + blsp6_spi, blsp1_uart, blsp2_uart, blsp1_uim, blsp2_uim, cam1_rst, + cam1_standby, cam_mclk0, cam_mclk1, cci_async, cci_i2c, cci_timer0, + cci_timer1, cci_timer2, cdc_pdm0, codec_mad, dbg_out, display_5v, + dmic0_clk, dmic0_data, dsi_rst, ebi0_wrcdc, euro_us, ext_lpass, + flash_strobe, gcc_gp1_clk_a, gcc_gp1_clk_b, gcc_gp2_clk_a, + gcc_gp2_clk_b, gcc_gp3_clk_a, gcc_gp3_clk_b, gpio, gsm0_tx0, + gsm0_tx1, gsm1_tx0, gsm1_tx1, gyro_accl, kpsns0, kpsns1, kpsns2, + ldo_en, ldo_update, mag_int, mdp_vsync, modem_tsync, m_voc, + nav_pps, nav_tsync, pa_indicator, pbs0, pbs1, pbs2, pri_mi2s, + pri_mi2s_ws, prng_rosc, pwr_crypto_enabled_a, pwr_crypto_enabled_b, + pwr_modem_enabled_a, pwr_modem_enabled_b, pwr_nav_enabled_a, + pwr_nav_enabled_b, qdss_ctitrig_in_a0, qdss_ctitrig_in_a1, + qdss_ctitrig_in_b0, qdss_ctitrig_in_b1, qdss_ctitrig_out_a0, + qdss_ctitrig_out_a1, qdss_ctitrig_out_b0, qdss_ctitrig_out_b1, + qdss_traceclk_a, qdss_traceclk_b, qdss_tracectl_a, qdss_tracectl_b, + qdss_tracedata_a, qdss_tracedata_b, reset_n, sd_card, sd_write, + sec_mi2s, smb_int, ssbi_wtr0, ssbi_wtr1, uim1, uim2, uim3, + uim_batt, wcss_bt, wcss_fm, wcss_wlan, webcam1_rst ] + + drive-strength: + enum: [2, 4, 6, 8, 10, 12, 14, 16] + default: 2 + description: + Selects the drive strength for the specified pins, in mA. + + bias-pull-down: true + + bias-pull-up: true + + bias-disable: true + + output-high: true + + output-low: true + + required: + - pins + - function + + additionalProperties: false + +required: + - compatible + - reg + - interrupts + - interrupt-controller + - '#interrupt-cells' + - gpio-controller + - '#gpio-cells' + - gpio-ranges + +additionalProperties: false + +examples: + - | + #include + tlmm: pinctrl@1000000 { + compatible = "qcom,ipq6018-pinctrl"; + reg = <0x01000000 0x300000>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&tlmm 0 80>; + + serial3-pinmux { + pins = "gpio44", "gpio45"; + function = "blsp2_uart"; + drive-strength = <8>; + bias-pull-down; + }; + }; From ef1ea54eab0ecb072700f59701387f839c8c760d Mon Sep 17 00:00:00 2001 From: Sricharan R Date: Sun, 19 Jan 2020 18:43:18 +0530 Subject: [PATCH 0329/4444] pinctrl: qcom: Add ipq6018 pinctrl driver Add initial pinctrl driver to support pin configuration with pinctrl framework for ipq6018. Co-developed-by: Rajkumar Ayyasamy Signed-off-by: Rajkumar Ayyasamy Co-developed-by: Selvam Sathappan Periakaruppan Signed-off-by: Selvam Sathappan Periakaruppan Co-developed-by: Sivaprakash Murugesan Signed-off-by: Sivaprakash Murugesan Reviewed-by: Bjorn Andersson Signed-off-by: Sricharan R Link: https://lore.kernel.org/r/1579439601-14810-3-git-send-email-sricharan@codeaurora.org Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/Kconfig | 10 + drivers/pinctrl/qcom/Makefile | 1 + drivers/pinctrl/qcom/pinctrl-ipq6018.c | 1107 ++++++++++++++++++++++++ 3 files changed, 1118 insertions(+) create mode 100644 drivers/pinctrl/qcom/pinctrl-ipq6018.c diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index 811af2f81c39..c5d4428f1f94 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -50,6 +50,16 @@ config PINCTRL_IPQ8074 Qualcomm Technologies Inc. IPQ8074 platform. Select this for IPQ8074. +config PINCTRL_IPQ6018 + tristate "Qualcomm Technologies, Inc. IPQ6018 pin controller driver" + depends on GPIOLIB && OF + select PINCTRL_MSM + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for + the Qualcomm Technologies Inc. TLMM block found on the + Qualcomm Technologies Inc. IPQ6018 platform. Select this for + IPQ6018. + config PINCTRL_MSM8660 tristate "Qualcomm 8660 pin controller driver" depends on GPIOLIB && OF diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index c2c2f9ad6827..d9e09045a776 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_PINCTRL_APQ8084) += pinctrl-apq8084.o obj-$(CONFIG_PINCTRL_IPQ4019) += pinctrl-ipq4019.o obj-$(CONFIG_PINCTRL_IPQ8064) += pinctrl-ipq8064.o obj-$(CONFIG_PINCTRL_IPQ8074) += pinctrl-ipq8074.o +obj-$(CONFIG_PINCTRL_IPQ6018) += pinctrl-ipq6018.o obj-$(CONFIG_PINCTRL_MSM8660) += pinctrl-msm8660.o obj-$(CONFIG_PINCTRL_MSM8960) += pinctrl-msm8960.o obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o diff --git a/drivers/pinctrl/qcom/pinctrl-ipq6018.c b/drivers/pinctrl/qcom/pinctrl-ipq6018.c new file mode 100644 index 000000000000..38c33a778cb8 --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-ipq6018.c @@ -0,0 +1,1107 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +#include "pinctrl-msm.h" + +#define FUNCTION(fname) \ + [msm_mux_##fname] = { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +#define REG_SIZE 0x1000 +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ + { \ + .name = "gpio" #id, \ + .pins = gpio##id##_pins, \ + .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .funcs = (int[]){ \ + msm_mux_gpio, /* gpio mode */ \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9 \ + }, \ + .nfuncs = 10, \ + .ctl_reg = REG_SIZE * id, \ + .io_reg = 0x4 + REG_SIZE * id, \ + .intr_cfg_reg = 0x8 + REG_SIZE * id, \ + .intr_status_reg = 0xc + REG_SIZE * id, \ + .intr_target_reg = 0x8 + REG_SIZE * id, \ + .mux_bit = 2, \ + .pull_bit = 0, \ + .drv_bit = 6, \ + .oe_bit = 9, \ + .in_bit = 0, \ + .out_bit = 1, \ + .intr_enable_bit = 0, \ + .intr_status_bit = 0, \ + .intr_target_bit = 5, \ + .intr_target_kpss_val = 3, \ + .intr_raw_status_bit = 4, \ + .intr_polarity_bit = 1, \ + .intr_detection_bit = 2, \ + .intr_detection_width = 2, \ + } + +static const struct pinctrl_pin_desc ipq6018_pins[] = { + PINCTRL_PIN(0, "GPIO_0"), + PINCTRL_PIN(1, "GPIO_1"), + PINCTRL_PIN(2, "GPIO_2"), + PINCTRL_PIN(3, "GPIO_3"), + PINCTRL_PIN(4, "GPIO_4"), + PINCTRL_PIN(5, "GPIO_5"), + PINCTRL_PIN(6, "GPIO_6"), + PINCTRL_PIN(7, "GPIO_7"), + PINCTRL_PIN(8, "GPIO_8"), + PINCTRL_PIN(9, "GPIO_9"), + PINCTRL_PIN(10, "GPIO_10"), + PINCTRL_PIN(11, "GPIO_11"), + PINCTRL_PIN(12, "GPIO_12"), + PINCTRL_PIN(13, "GPIO_13"), + PINCTRL_PIN(14, "GPIO_14"), + PINCTRL_PIN(15, "GPIO_15"), + PINCTRL_PIN(16, "GPIO_16"), + PINCTRL_PIN(17, "GPIO_17"), + PINCTRL_PIN(18, "GPIO_18"), + PINCTRL_PIN(19, "GPIO_19"), + PINCTRL_PIN(20, "GPIO_20"), + PINCTRL_PIN(21, "GPIO_21"), + PINCTRL_PIN(22, "GPIO_22"), + PINCTRL_PIN(23, "GPIO_23"), + PINCTRL_PIN(24, "GPIO_24"), + PINCTRL_PIN(25, "GPIO_25"), + PINCTRL_PIN(26, "GPIO_26"), + PINCTRL_PIN(27, "GPIO_27"), + PINCTRL_PIN(28, "GPIO_28"), + PINCTRL_PIN(29, "GPIO_29"), + PINCTRL_PIN(30, "GPIO_30"), + PINCTRL_PIN(31, "GPIO_31"), + PINCTRL_PIN(32, "GPIO_32"), + PINCTRL_PIN(33, "GPIO_33"), + PINCTRL_PIN(34, "GPIO_34"), + PINCTRL_PIN(35, "GPIO_35"), + PINCTRL_PIN(36, "GPIO_36"), + PINCTRL_PIN(37, "GPIO_37"), + PINCTRL_PIN(38, "GPIO_38"), + PINCTRL_PIN(39, "GPIO_39"), + PINCTRL_PIN(40, "GPIO_40"), + PINCTRL_PIN(41, "GPIO_41"), + PINCTRL_PIN(42, "GPIO_42"), + PINCTRL_PIN(43, "GPIO_43"), + PINCTRL_PIN(44, "GPIO_44"), + PINCTRL_PIN(45, "GPIO_45"), + PINCTRL_PIN(46, "GPIO_46"), + PINCTRL_PIN(47, "GPIO_47"), + PINCTRL_PIN(48, "GPIO_48"), + PINCTRL_PIN(49, "GPIO_49"), + PINCTRL_PIN(50, "GPIO_50"), + PINCTRL_PIN(51, "GPIO_51"), + PINCTRL_PIN(52, "GPIO_52"), + PINCTRL_PIN(53, "GPIO_53"), + PINCTRL_PIN(54, "GPIO_54"), + PINCTRL_PIN(55, "GPIO_55"), + PINCTRL_PIN(56, "GPIO_56"), + PINCTRL_PIN(57, "GPIO_57"), + PINCTRL_PIN(58, "GPIO_58"), + PINCTRL_PIN(59, "GPIO_59"), + PINCTRL_PIN(60, "GPIO_60"), + PINCTRL_PIN(61, "GPIO_61"), + PINCTRL_PIN(62, "GPIO_62"), + PINCTRL_PIN(63, "GPIO_63"), + PINCTRL_PIN(64, "GPIO_64"), + PINCTRL_PIN(65, "GPIO_65"), + PINCTRL_PIN(66, "GPIO_66"), + PINCTRL_PIN(67, "GPIO_67"), + PINCTRL_PIN(68, "GPIO_68"), + PINCTRL_PIN(69, "GPIO_69"), + PINCTRL_PIN(70, "GPIO_70"), + PINCTRL_PIN(71, "GPIO_71"), + PINCTRL_PIN(72, "GPIO_72"), + PINCTRL_PIN(73, "GPIO_73"), + PINCTRL_PIN(74, "GPIO_74"), + PINCTRL_PIN(75, "GPIO_75"), + PINCTRL_PIN(76, "GPIO_76"), + PINCTRL_PIN(77, "GPIO_77"), + PINCTRL_PIN(78, "GPIO_78"), + PINCTRL_PIN(79, "GPIO_79"), +}; + +#define DECLARE_MSM_GPIO_PINS(pin) \ + static const unsigned int gpio##pin##_pins[] = { pin } +DECLARE_MSM_GPIO_PINS(0); +DECLARE_MSM_GPIO_PINS(1); +DECLARE_MSM_GPIO_PINS(2); +DECLARE_MSM_GPIO_PINS(3); +DECLARE_MSM_GPIO_PINS(4); +DECLARE_MSM_GPIO_PINS(5); +DECLARE_MSM_GPIO_PINS(6); +DECLARE_MSM_GPIO_PINS(7); +DECLARE_MSM_GPIO_PINS(8); +DECLARE_MSM_GPIO_PINS(9); +DECLARE_MSM_GPIO_PINS(10); +DECLARE_MSM_GPIO_PINS(11); +DECLARE_MSM_GPIO_PINS(12); +DECLARE_MSM_GPIO_PINS(13); +DECLARE_MSM_GPIO_PINS(14); +DECLARE_MSM_GPIO_PINS(15); +DECLARE_MSM_GPIO_PINS(16); +DECLARE_MSM_GPIO_PINS(17); +DECLARE_MSM_GPIO_PINS(18); +DECLARE_MSM_GPIO_PINS(19); +DECLARE_MSM_GPIO_PINS(20); +DECLARE_MSM_GPIO_PINS(21); +DECLARE_MSM_GPIO_PINS(22); +DECLARE_MSM_GPIO_PINS(23); +DECLARE_MSM_GPIO_PINS(24); +DECLARE_MSM_GPIO_PINS(25); +DECLARE_MSM_GPIO_PINS(26); +DECLARE_MSM_GPIO_PINS(27); +DECLARE_MSM_GPIO_PINS(28); +DECLARE_MSM_GPIO_PINS(29); +DECLARE_MSM_GPIO_PINS(30); +DECLARE_MSM_GPIO_PINS(31); +DECLARE_MSM_GPIO_PINS(32); +DECLARE_MSM_GPIO_PINS(33); +DECLARE_MSM_GPIO_PINS(34); +DECLARE_MSM_GPIO_PINS(35); +DECLARE_MSM_GPIO_PINS(36); +DECLARE_MSM_GPIO_PINS(37); +DECLARE_MSM_GPIO_PINS(38); +DECLARE_MSM_GPIO_PINS(39); +DECLARE_MSM_GPIO_PINS(40); +DECLARE_MSM_GPIO_PINS(41); +DECLARE_MSM_GPIO_PINS(42); +DECLARE_MSM_GPIO_PINS(43); +DECLARE_MSM_GPIO_PINS(44); +DECLARE_MSM_GPIO_PINS(45); +DECLARE_MSM_GPIO_PINS(46); +DECLARE_MSM_GPIO_PINS(47); +DECLARE_MSM_GPIO_PINS(48); +DECLARE_MSM_GPIO_PINS(49); +DECLARE_MSM_GPIO_PINS(50); +DECLARE_MSM_GPIO_PINS(51); +DECLARE_MSM_GPIO_PINS(52); +DECLARE_MSM_GPIO_PINS(53); +DECLARE_MSM_GPIO_PINS(54); +DECLARE_MSM_GPIO_PINS(55); +DECLARE_MSM_GPIO_PINS(56); +DECLARE_MSM_GPIO_PINS(57); +DECLARE_MSM_GPIO_PINS(58); +DECLARE_MSM_GPIO_PINS(59); +DECLARE_MSM_GPIO_PINS(60); +DECLARE_MSM_GPIO_PINS(61); +DECLARE_MSM_GPIO_PINS(62); +DECLARE_MSM_GPIO_PINS(63); +DECLARE_MSM_GPIO_PINS(64); +DECLARE_MSM_GPIO_PINS(65); +DECLARE_MSM_GPIO_PINS(66); +DECLARE_MSM_GPIO_PINS(67); +DECLARE_MSM_GPIO_PINS(68); +DECLARE_MSM_GPIO_PINS(69); +DECLARE_MSM_GPIO_PINS(70); +DECLARE_MSM_GPIO_PINS(71); +DECLARE_MSM_GPIO_PINS(72); +DECLARE_MSM_GPIO_PINS(73); +DECLARE_MSM_GPIO_PINS(74); +DECLARE_MSM_GPIO_PINS(75); +DECLARE_MSM_GPIO_PINS(76); +DECLARE_MSM_GPIO_PINS(77); +DECLARE_MSM_GPIO_PINS(78); +DECLARE_MSM_GPIO_PINS(79); + +enum ipq6018_functions { + msm_mux_atest_char, + msm_mux_atest_char0, + msm_mux_atest_char1, + msm_mux_atest_char2, + msm_mux_atest_char3, + msm_mux_audio0, + msm_mux_audio1, + msm_mux_audio2, + msm_mux_audio3, + msm_mux_audio_rxbclk, + msm_mux_audio_rxfsync, + msm_mux_audio_rxmclk, + msm_mux_audio_rxmclkin, + msm_mux_audio_txbclk, + msm_mux_audio_txfsync, + msm_mux_audio_txmclk, + msm_mux_audio_txmclkin, + msm_mux_blsp0_i2c, + msm_mux_blsp0_spi, + msm_mux_blsp0_uart, + msm_mux_blsp1_i2c, + msm_mux_blsp1_spi, + msm_mux_blsp1_uart, + msm_mux_blsp2_i2c, + msm_mux_blsp2_spi, + msm_mux_blsp2_uart, + msm_mux_blsp3_i2c, + msm_mux_blsp3_spi, + msm_mux_blsp3_uart, + msm_mux_blsp4_i2c, + msm_mux_blsp4_spi, + msm_mux_blsp4_uart, + msm_mux_blsp5_i2c, + msm_mux_blsp5_uart, + msm_mux_burn0, + msm_mux_burn1, + msm_mux_cri_trng, + msm_mux_cri_trng0, + msm_mux_cri_trng1, + msm_mux_cxc0, + msm_mux_cxc1, + msm_mux_dbg_out, + msm_mux_gcc_plltest, + msm_mux_gcc_tlmm, + msm_mux_gpio, + msm_mux_lpass_aud, + msm_mux_lpass_aud0, + msm_mux_lpass_aud1, + msm_mux_lpass_aud2, + msm_mux_lpass_pcm, + msm_mux_lpass_pdm, + msm_mux_mac00, + msm_mux_mac01, + msm_mux_mac10, + msm_mux_mac11, + msm_mux_mac12, + msm_mux_mac13, + msm_mux_mac20, + msm_mux_mac21, + msm_mux_mdc, + msm_mux_mdio, + msm_mux_pcie0_clk, + msm_mux_pcie0_rst, + msm_mux_pcie0_wake, + msm_mux_prng_rosc, + msm_mux_pta1_0, + msm_mux_pta1_1, + msm_mux_pta1_2, + msm_mux_pta2_0, + msm_mux_pta2_1, + msm_mux_pta2_2, + msm_mux_pwm00, + msm_mux_pwm01, + msm_mux_pwm02, + msm_mux_pwm03, + msm_mux_pwm04, + msm_mux_pwm10, + msm_mux_pwm11, + msm_mux_pwm12, + msm_mux_pwm13, + msm_mux_pwm14, + msm_mux_pwm20, + msm_mux_pwm21, + msm_mux_pwm22, + msm_mux_pwm23, + msm_mux_pwm24, + msm_mux_pwm30, + msm_mux_pwm31, + msm_mux_pwm32, + msm_mux_pwm33, + msm_mux_qdss_cti_trig_in_a0, + msm_mux_qdss_cti_trig_in_a1, + msm_mux_qdss_cti_trig_out_a0, + msm_mux_qdss_cti_trig_out_a1, + msm_mux_qdss_cti_trig_in_b0, + msm_mux_qdss_cti_trig_in_b1, + msm_mux_qdss_cti_trig_out_b0, + msm_mux_qdss_cti_trig_out_b1, + msm_mux_qdss_traceclk_a, + msm_mux_qdss_tracectl_a, + msm_mux_qdss_tracedata_a, + msm_mux_qdss_traceclk_b, + msm_mux_qdss_tracectl_b, + msm_mux_qdss_tracedata_b, + msm_mux_qpic_pad, + msm_mux_rx0, + msm_mux_rx1, + msm_mux_rx_swrm, + msm_mux_rx_swrm0, + msm_mux_rx_swrm1, + msm_mux_sd_card, + msm_mux_sd_write, + msm_mux_tsens_max, + msm_mux_tx_swrm, + msm_mux_tx_swrm0, + msm_mux_tx_swrm1, + msm_mux_tx_swrm2, + msm_mux_wci20, + msm_mux_wci21, + msm_mux_wci22, + msm_mux_wci23, + msm_mux_wsa_swrm, + msm_mux__, +}; + +static const char * const blsp3_uart_groups[] = { + "gpio73", "gpio74", "gpio75", "gpio76", +}; + +static const char * const blsp3_i2c_groups[] = { + "gpio73", "gpio74", +}; + +static const char * const blsp3_spi_groups[] = { + "gpio73", "gpio74", "gpio75", "gpio76", "gpio77", "gpio78", "gpio79", +}; + +static const char * const wci20_groups[] = { + "gpio0", "gpio2", +}; + +static const char * const qpic_pad_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio9", "gpio10", + "gpio11", "gpio17", +}; + +static const char * const burn0_groups[] = { + "gpio0", +}; + +static const char * const mac12_groups[] = { + "gpio1", "gpio11", +}; + +static const char * const qdss_tracectl_b_groups[] = { + "gpio1", +}; + +static const char * const burn1_groups[] = { + "gpio1", +}; + +static const char * const qdss_traceclk_b_groups[] = { + "gpio0", +}; + +static const char * const qdss_tracedata_b_groups[] = { + "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", "gpio8", "gpio9", + "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", "gpio15", "gpio16", + "gpio17", +}; + +static const char * const mac01_groups[] = { + "gpio3", "gpio4", +}; + +static const char * const mac21_groups[] = { + "gpio5", "gpio6", +}; + +static const char * const atest_char_groups[] = { + "gpio9", +}; + +static const char * const cxc0_groups[] = { + "gpio9", "gpio16", +}; + +static const char * const mac13_groups[] = { + "gpio9", "gpio16", +}; + +static const char * const dbg_out_groups[] = { + "gpio9", +}; + +static const char * const wci22_groups[] = { + "gpio11", "gpio17", +}; + +static const char * const pwm00_groups[] = { + "gpio18", +}; + +static const char * const atest_char0_groups[] = { + "gpio18", +}; + +static const char * const wci23_groups[] = { + "gpio18", "gpio19", +}; + +static const char * const mac11_groups[] = { + "gpio18", "gpio19", +}; + +static const char * const pwm10_groups[] = { + "gpio19", +}; + +static const char * const atest_char1_groups[] = { + "gpio19", +}; + +static const char * const pwm20_groups[] = { + "gpio20", +}; + +static const char * const atest_char2_groups[] = { + "gpio20", +}; + +static const char * const pwm30_groups[] = { + "gpio21", +}; + +static const char * const atest_char3_groups[] = { + "gpio21", +}; + +static const char * const audio_txmclk_groups[] = { + "gpio22", +}; + +static const char * const audio_txmclkin_groups[] = { + "gpio22", +}; + +static const char * const pwm02_groups[] = { + "gpio22", +}; + +static const char * const tx_swrm0_groups[] = { + "gpio22", +}; + +static const char * const qdss_cti_trig_out_b0_groups[] = { + "gpio22", +}; + +static const char * const audio_txbclk_groups[] = { + "gpio23", +}; + +static const char * const pwm12_groups[] = { + "gpio23", +}; + +static const char * const wsa_swrm_groups[] = { + "gpio23", "gpio24", +}; + +static const char * const tx_swrm1_groups[] = { + "gpio23", +}; + +static const char * const qdss_cti_trig_in_b0_groups[] = { + "gpio23", +}; + +static const char * const audio_txfsync_groups[] = { + "gpio24", +}; + +static const char * const pwm22_groups[] = { + "gpio24", +}; + +static const char * const tx_swrm2_groups[] = { + "gpio24", +}; + +static const char * const qdss_cti_trig_out_b1_groups[] = { + "gpio24", +}; + +static const char * const audio0_groups[] = { + "gpio25", "gpio32", +}; + +static const char * const pwm32_groups[] = { + "gpio25", +}; + +static const char * const tx_swrm_groups[] = { + "gpio25", +}; + +static const char * const qdss_cti_trig_in_b1_groups[] = { + "gpio25", +}; + +static const char * const audio1_groups[] = { + "gpio26", "gpio33", +}; + +static const char * const pwm04_groups[] = { + "gpio26", +}; + +static const char * const audio2_groups[] = { + "gpio27", +}; + +static const char * const pwm14_groups[] = { + "gpio27", +}; + +static const char * const audio3_groups[] = { + "gpio28", +}; + +static const char * const pwm24_groups[] = { + "gpio28", +}; + +static const char * const audio_rxmclk_groups[] = { + "gpio29", +}; + +static const char * const audio_rxmclkin_groups[] = { + "gpio29", +}; + +static const char * const pwm03_groups[] = { + "gpio29", +}; + +static const char * const lpass_pdm_groups[] = { + "gpio29", "gpio30", "gpio31", "gpio32", +}; + +static const char * const lpass_aud_groups[] = { + "gpio29", +}; + +static const char * const qdss_cti_trig_in_a1_groups[] = { + "gpio29", +}; + +static const char * const audio_rxbclk_groups[] = { + "gpio30", +}; + +static const char * const pwm13_groups[] = { + "gpio30", +}; + +static const char * const lpass_aud0_groups[] = { + "gpio30", +}; + +static const char * const rx_swrm_groups[] = { + "gpio30", +}; + +static const char * const qdss_cti_trig_out_a1_groups[] = { + "gpio30", +}; + +static const char * const audio_rxfsync_groups[] = { + "gpio31", +}; + +static const char * const pwm23_groups[] = { + "gpio31", +}; + +static const char * const lpass_aud1_groups[] = { + "gpio31", +}; + +static const char * const rx_swrm0_groups[] = { + "gpio31", +}; + +static const char * const qdss_cti_trig_in_a0_groups[] = { + "gpio31", +}; + +static const char * const pwm33_groups[] = { + "gpio32", +}; + +static const char * const lpass_aud2_groups[] = { + "gpio32", +}; + +static const char * const rx_swrm1_groups[] = { + "gpio32", +}; + +static const char * const qdss_cti_trig_out_a0_groups[] = { + "gpio32", +}; + +static const char * const lpass_pcm_groups[] = { + "gpio34", "gpio35", "gpio36", "gpio37", +}; + +static const char * const mac10_groups[] = { + "gpio34", "gpio35", +}; + +static const char * const mac00_groups[] = { + "gpio34", "gpio35", +}; + +static const char * const mac20_groups[] = { + "gpio36", "gpio37", +}; + +static const char * const blsp0_uart_groups[] = { + "gpio38", "gpio39", "gpio40", "gpio41", +}; + +static const char * const blsp0_i2c_groups[] = { + "gpio38", "gpio39", +}; + +static const char * const blsp0_spi_groups[] = { + "gpio38", "gpio39", "gpio40", "gpio41", +}; + +static const char * const blsp2_uart_groups[] = { + "gpio42", "gpio43", "gpio44", "gpio45", +}; + +static const char * const blsp2_i2c_groups[] = { + "gpio42", "gpio43", +}; + +static const char * const blsp2_spi_groups[] = { + "gpio42", "gpio43", "gpio44", "gpio45", +}; + +static const char * const blsp5_i2c_groups[] = { + "gpio46", "gpio47", +}; + +static const char * const blsp5_uart_groups[] = { + "gpio48", "gpio49", +}; + +static const char * const qdss_traceclk_a_groups[] = { + "gpio48", +}; + +static const char * const qdss_tracectl_a_groups[] = { + "gpio49", +}; + +static const char * const pwm01_groups[] = { + "gpio50", +}; + +static const char * const pta1_1_groups[] = { + "gpio51", +}; + +static const char * const pwm11_groups[] = { + "gpio51", +}; + +static const char * const rx1_groups[] = { + "gpio51", +}; + +static const char * const pta1_2_groups[] = { + "gpio52", +}; + +static const char * const pwm21_groups[] = { + "gpio52", +}; + +static const char * const pta1_0_groups[] = { + "gpio53", +}; + +static const char * const pwm31_groups[] = { + "gpio53", +}; + +static const char * const prng_rosc_groups[] = { + "gpio53", +}; + +static const char * const blsp4_uart_groups[] = { + "gpio55", "gpio56", "gpio57", "gpio58", +}; + +static const char * const blsp4_i2c_groups[] = { + "gpio55", "gpio56", +}; + +static const char * const blsp4_spi_groups[] = { + "gpio55", "gpio56", "gpio57", "gpio58", +}; + +static const char * const pcie0_clk_groups[] = { + "gpio59", +}; + +static const char * const cri_trng0_groups[] = { + "gpio59", +}; + +static const char * const pcie0_rst_groups[] = { + "gpio60", +}; + +static const char * const cri_trng1_groups[] = { + "gpio60", +}; + +static const char * const pcie0_wake_groups[] = { + "gpio61", +}; + +static const char * const cri_trng_groups[] = { + "gpio61", +}; + +static const char * const sd_card_groups[] = { + "gpio62", +}; + +static const char * const sd_write_groups[] = { + "gpio63", +}; + +static const char * const rx0_groups[] = { + "gpio63", +}; + +static const char * const tsens_max_groups[] = { + "gpio63", +}; + +static const char * const mdc_groups[] = { + "gpio64", +}; + +static const char * const qdss_tracedata_a_groups[] = { + "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", + "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77", + "gpio78", "gpio79", +}; + +static const char * const mdio_groups[] = { + "gpio65", +}; + +static const char * const pta2_0_groups[] = { + "gpio66", +}; + +static const char * const wci21_groups[] = { + "gpio66", "gpio68", +}; + +static const char * const cxc1_groups[] = { + "gpio66", "gpio68", +}; + +static const char * const pta2_1_groups[] = { + "gpio67", +}; + +static const char * const pta2_2_groups[] = { + "gpio68", +}; + +static const char * const blsp1_uart_groups[] = { + "gpio69", "gpio70", "gpio71", "gpio72", +}; + +static const char * const blsp1_i2c_groups[] = { + "gpio69", "gpio70", +}; + +static const char * const blsp1_spi_groups[] = { + "gpio69", "gpio70", "gpio71", "gpio72", +}; + +static const char * const gcc_plltest_groups[] = { + "gpio69", "gpio71", +}; + +static const char * const gcc_tlmm_groups[] = { + "gpio70", +}; + +static const char * const gpio_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", + "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", + "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", + "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", + "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", + "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", + "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49", + "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56", + "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63", + "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", + "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77", + "gpio78", "gpio79", +}; + +static const struct msm_function ipq6018_functions[] = { + FUNCTION(atest_char), + FUNCTION(atest_char0), + FUNCTION(atest_char1), + FUNCTION(atest_char2), + FUNCTION(atest_char3), + FUNCTION(audio0), + FUNCTION(audio1), + FUNCTION(audio2), + FUNCTION(audio3), + FUNCTION(audio_rxbclk), + FUNCTION(audio_rxfsync), + FUNCTION(audio_rxmclk), + FUNCTION(audio_rxmclkin), + FUNCTION(audio_txbclk), + FUNCTION(audio_txfsync), + FUNCTION(audio_txmclk), + FUNCTION(audio_txmclkin), + FUNCTION(blsp0_i2c), + FUNCTION(blsp0_spi), + FUNCTION(blsp0_uart), + FUNCTION(blsp1_i2c), + FUNCTION(blsp1_spi), + FUNCTION(blsp1_uart), + FUNCTION(blsp2_i2c), + FUNCTION(blsp2_spi), + FUNCTION(blsp2_uart), + FUNCTION(blsp3_i2c), + FUNCTION(blsp3_spi), + FUNCTION(blsp3_uart), + FUNCTION(blsp4_i2c), + FUNCTION(blsp4_spi), + FUNCTION(blsp4_uart), + FUNCTION(blsp5_i2c), + FUNCTION(blsp5_uart), + FUNCTION(burn0), + FUNCTION(burn1), + FUNCTION(cri_trng), + FUNCTION(cri_trng0), + FUNCTION(cri_trng1), + FUNCTION(cxc0), + FUNCTION(cxc1), + FUNCTION(dbg_out), + FUNCTION(gcc_plltest), + FUNCTION(gcc_tlmm), + FUNCTION(gpio), + FUNCTION(lpass_aud), + FUNCTION(lpass_aud0), + FUNCTION(lpass_aud1), + FUNCTION(lpass_aud2), + FUNCTION(lpass_pcm), + FUNCTION(lpass_pdm), + FUNCTION(mac00), + FUNCTION(mac01), + FUNCTION(mac10), + FUNCTION(mac11), + FUNCTION(mac12), + FUNCTION(mac13), + FUNCTION(mac20), + FUNCTION(mac21), + FUNCTION(mdc), + FUNCTION(mdio), + FUNCTION(pcie0_clk), + FUNCTION(pcie0_rst), + FUNCTION(pcie0_wake), + FUNCTION(prng_rosc), + FUNCTION(pta1_0), + FUNCTION(pta1_1), + FUNCTION(pta1_2), + FUNCTION(pta2_0), + FUNCTION(pta2_1), + FUNCTION(pta2_2), + FUNCTION(pwm00), + FUNCTION(pwm01), + FUNCTION(pwm02), + FUNCTION(pwm03), + FUNCTION(pwm04), + FUNCTION(pwm10), + FUNCTION(pwm11), + FUNCTION(pwm12), + FUNCTION(pwm13), + FUNCTION(pwm14), + FUNCTION(pwm20), + FUNCTION(pwm21), + FUNCTION(pwm22), + FUNCTION(pwm23), + FUNCTION(pwm24), + FUNCTION(pwm30), + FUNCTION(pwm31), + FUNCTION(pwm32), + FUNCTION(pwm33), + FUNCTION(qdss_cti_trig_in_a0), + FUNCTION(qdss_cti_trig_in_a1), + FUNCTION(qdss_cti_trig_out_a0), + FUNCTION(qdss_cti_trig_out_a1), + FUNCTION(qdss_cti_trig_in_b0), + FUNCTION(qdss_cti_trig_in_b1), + FUNCTION(qdss_cti_trig_out_b0), + FUNCTION(qdss_cti_trig_out_b1), + FUNCTION(qdss_traceclk_a), + FUNCTION(qdss_tracectl_a), + FUNCTION(qdss_tracedata_a), + FUNCTION(qdss_traceclk_b), + FUNCTION(qdss_tracectl_b), + FUNCTION(qdss_tracedata_b), + FUNCTION(qpic_pad), + FUNCTION(rx0), + FUNCTION(rx1), + FUNCTION(rx_swrm), + FUNCTION(rx_swrm0), + FUNCTION(rx_swrm1), + FUNCTION(sd_card), + FUNCTION(sd_write), + FUNCTION(tsens_max), + FUNCTION(tx_swrm), + FUNCTION(tx_swrm0), + FUNCTION(tx_swrm1), + FUNCTION(tx_swrm2), + FUNCTION(wci20), + FUNCTION(wci21), + FUNCTION(wci22), + FUNCTION(wci23), + FUNCTION(wsa_swrm), +}; + +static const struct msm_pingroup ipq6018_groups[] = { + PINGROUP(0, qpic_pad, wci20, qdss_traceclk_b, _, burn0, _, _, _, _), + PINGROUP(1, qpic_pad, mac12, qdss_tracectl_b, _, burn1, _, _, _, _), + PINGROUP(2, qpic_pad, wci20, qdss_tracedata_b, _, _, _, _, _, _), + PINGROUP(3, qpic_pad, mac01, qdss_tracedata_b, _, _, _, _, _, _), + PINGROUP(4, qpic_pad, mac01, qdss_tracedata_b, _, _, _, _, _, _), + PINGROUP(5, qpic_pad, mac21, qdss_tracedata_b, _, _, _, _, _, _), + PINGROUP(6, qpic_pad, mac21, qdss_tracedata_b, _, _, _, _, _, _), + PINGROUP(7, qpic_pad, qdss_tracedata_b, _, _, _, _, _, _, _), + PINGROUP(8, qpic_pad, qdss_tracedata_b, _, _, _, _, _, _, _), + PINGROUP(9, qpic_pad, atest_char, cxc0, mac13, dbg_out, qdss_tracedata_b, _, _, _), + PINGROUP(10, qpic_pad, qdss_tracedata_b, _, _, _, _, _, _, _), + PINGROUP(11, qpic_pad, wci22, mac12, qdss_tracedata_b, _, _, _, _, _), + PINGROUP(12, qpic_pad, qdss_tracedata_b, _, _, _, _, _, _, _), + PINGROUP(13, qpic_pad, qdss_tracedata_b, _, _, _, _, _, _, _), + PINGROUP(14, qpic_pad, qdss_tracedata_b, _, _, _, _, _, _, _), + PINGROUP(15, qpic_pad, qdss_tracedata_b, _, _, _, _, _, _, _), + PINGROUP(16, qpic_pad, cxc0, mac13, qdss_tracedata_b, _, _, _, _, _), + PINGROUP(17, qpic_pad, qdss_tracedata_b, wci22, _, _, _, _, _, _), + PINGROUP(18, pwm00, atest_char0, wci23, mac11, _, _, _, _, _), + PINGROUP(19, pwm10, atest_char1, wci23, mac11, _, _, _, _, _), + PINGROUP(20, pwm20, atest_char2, _, _, _, _, _, _, _), + PINGROUP(21, pwm30, atest_char3, _, _, _, _, _, _, _), + PINGROUP(22, audio_txmclk, audio_txmclkin, pwm02, tx_swrm0, _, qdss_cti_trig_out_b0, _, _, _), + PINGROUP(23, audio_txbclk, pwm12, wsa_swrm, tx_swrm1, _, qdss_cti_trig_in_b0, _, _, _), + PINGROUP(24, audio_txfsync, pwm22, wsa_swrm, tx_swrm2, _, qdss_cti_trig_out_b1, _, _, _), + PINGROUP(25, audio0, pwm32, tx_swrm, _, qdss_cti_trig_in_b1, _, _, _, _), + PINGROUP(26, audio1, pwm04, _, _, _, _, _, _, _), + PINGROUP(27, audio2, pwm14, _, _, _, _, _, _, _), + PINGROUP(28, audio3, pwm24, _, _, _, _, _, _, _), + PINGROUP(29, audio_rxmclk, audio_rxmclkin, pwm03, lpass_pdm, lpass_aud, qdss_cti_trig_in_a1, _, _, _), + PINGROUP(30, audio_rxbclk, pwm13, lpass_pdm, lpass_aud0, rx_swrm, _, qdss_cti_trig_out_a1, _, _), + PINGROUP(31, audio_rxfsync, pwm23, lpass_pdm, lpass_aud1, rx_swrm0, _, qdss_cti_trig_in_a0, _, _), + PINGROUP(32, audio0, pwm33, lpass_pdm, lpass_aud2, rx_swrm1, _, qdss_cti_trig_out_a0, _, _), + PINGROUP(33, audio1, _, _, _, _, _, _, _, _), + PINGROUP(34, lpass_pcm, mac10, mac00, _, _, _, _, _, _), + PINGROUP(35, lpass_pcm, mac10, mac00, _, _, _, _, _, _), + PINGROUP(36, lpass_pcm, mac20, _, _, _, _, _, _, _), + PINGROUP(37, lpass_pcm, mac20, _, _, _, _, _, _, _), + PINGROUP(38, blsp0_uart, blsp0_i2c, blsp0_spi, _, _, _, _, _, _), + PINGROUP(39, blsp0_uart, blsp0_i2c, blsp0_spi, _, _, _, _, _, _), + PINGROUP(40, blsp0_uart, blsp0_spi, _, _, _, _, _, _, _), + PINGROUP(41, blsp0_uart, blsp0_spi, _, _, _, _, _, _, _), + PINGROUP(42, blsp2_uart, blsp2_i2c, blsp2_spi, _, _, _, _, _, _), + PINGROUP(43, blsp2_uart, blsp2_i2c, blsp2_spi, _, _, _, _, _, _), + PINGROUP(44, blsp2_uart, blsp2_spi, _, _, _, _, _, _, _), + PINGROUP(45, blsp2_uart, blsp2_spi, _, _, _, _, _, _, _), + PINGROUP(46, blsp5_i2c, _, _, _, _, _, _, _, _), + PINGROUP(47, blsp5_i2c, _, _, _, _, _, _, _, _), + PINGROUP(48, blsp5_uart, _, qdss_traceclk_a, _, _, _, _, _, _), + PINGROUP(49, blsp5_uart, _, qdss_tracectl_a, _, _, _, _, _, _), + PINGROUP(50, pwm01, _, _, _, _, _, _, _, _), + PINGROUP(51, pta1_1, pwm11, _, rx1, _, _, _, _, _), + PINGROUP(52, pta1_2, pwm21, _, _, _, _, _, _, _), + PINGROUP(53, pta1_0, pwm31, prng_rosc, _, _, _, _, _, _), + PINGROUP(54, _, _, _, _, _, _, _, _, _), + PINGROUP(55, blsp4_uart, blsp4_i2c, blsp4_spi, _, _, _, _, _, _), + PINGROUP(56, blsp4_uart, blsp4_i2c, blsp4_spi, _, _, _, _, _, _), + PINGROUP(57, blsp4_uart, blsp4_spi, _, _, _, _, _, _, _), + PINGROUP(58, blsp4_uart, blsp4_spi, _, _, _, _, _, _, _), + PINGROUP(59, pcie0_clk, _, _, cri_trng0, _, _, _, _, _), + PINGROUP(60, pcie0_rst, _, _, cri_trng1, _, _, _, _, _), + PINGROUP(61, pcie0_wake, _, _, cri_trng, _, _, _, _, _), + PINGROUP(62, sd_card, _, _, _, _, _, _, _, _), + PINGROUP(63, sd_write, rx0, _, tsens_max, _, _, _, _, _), + PINGROUP(64, mdc, _, qdss_tracedata_a, _, _, _, _, _, _), + PINGROUP(65, mdio, _, qdss_tracedata_a, _, _, _, _, _, _), + PINGROUP(66, pta2_0, wci21, cxc1, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(67, pta2_1, qdss_tracedata_a, _, _, _, _, _, _, _), + PINGROUP(68, pta2_2, wci21, cxc1, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(69, blsp1_uart, blsp1_i2c, blsp1_spi, gcc_plltest, qdss_tracedata_a, _, _, _, _), + PINGROUP(70, blsp1_uart, blsp1_i2c, blsp1_spi, gcc_tlmm, qdss_tracedata_a, _, _, _, _), + PINGROUP(71, blsp1_uart, blsp1_spi, gcc_plltest, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(72, blsp1_uart, blsp1_spi, qdss_tracedata_a, _, _, _, _, _, _), + PINGROUP(73, blsp3_uart, blsp3_i2c, blsp3_spi, _, qdss_tracedata_a, _, _, _, _), + PINGROUP(74, blsp3_uart, blsp3_i2c, blsp3_spi, _, qdss_tracedata_a, _, _, _, _), + PINGROUP(75, blsp3_uart, blsp3_spi, _, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(76, blsp3_uart, blsp3_spi, _, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(77, blsp3_spi, _, qdss_tracedata_a, _, _, _, _, _, _), + PINGROUP(78, blsp3_spi, _, qdss_tracedata_a, _, _, _, _, _, _), + PINGROUP(79, blsp3_spi, _, qdss_tracedata_a, _, _, _, _, _, _), +}; + +static const struct msm_pinctrl_soc_data ipq6018_pinctrl = { + .pins = ipq6018_pins, + .npins = ARRAY_SIZE(ipq6018_pins), + .functions = ipq6018_functions, + .nfunctions = ARRAY_SIZE(ipq6018_functions), + .groups = ipq6018_groups, + .ngroups = ARRAY_SIZE(ipq6018_groups), + .ngpios = 80, +}; + +static int ipq6018_pinctrl_probe(struct platform_device *pdev) +{ + return msm_pinctrl_probe(pdev, &ipq6018_pinctrl); +} + +static const struct of_device_id ipq6018_pinctrl_of_match[] = { + { .compatible = "qcom,ipq6018-pinctrl", }, + { }, +}; + +static struct platform_driver ipq6018_pinctrl_driver = { + .driver = { + .name = "ipq6018-pinctrl", + .of_match_table = ipq6018_pinctrl_of_match, + }, + .probe = ipq6018_pinctrl_probe, + .remove = msm_pinctrl_remove, +}; + +static int __init ipq6018_pinctrl_init(void) +{ + return platform_driver_register(&ipq6018_pinctrl_driver); +} +arch_initcall(ipq6018_pinctrl_init); + +static void __exit ipq6018_pinctrl_exit(void) +{ + platform_driver_unregister(&ipq6018_pinctrl_driver); +} +module_exit(ipq6018_pinctrl_exit); + +MODULE_DESCRIPTION("QTI ipq6018 pinctrl driver"); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(of, ipq6018_pinctrl_of_match); From 3de7deefce693bb9783bca4cb42a81653ebec4e9 Mon Sep 17 00:00:00 2001 From: Light Hsieh Date: Wed, 22 Jan 2020 14:53:09 +0800 Subject: [PATCH 0330/4444] pinctrl: mediatek: Check gpio pin number and use binary search in mtk_hw_pin_field_lookup() 1. Check if gpio pin number is in valid range to prevent from get invalid pointer 'desc' in the following code: desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; 2. Improve mtk_hw_pin_field_lookup() 2.1 Modify mtk_hw_pin_field_lookup() to use binary search for accelerating search. 2.2 Correct message after the following check fail: if (hw->soc->reg_cal && hw->soc->reg_cal[field].range) { rc = &hw->soc->reg_cal[field]; The original message is: "Not support field %d for pin %d (%s)\n" However, the check is on soc chip level, not on pin level yet. So the message is corrected as: "Not support field %d for this soc\n" Signed-off-by: Light Hsieh Link: https://lore.kernel.org/r/1579675994-7001-1-git-send-email-light.hsieh@mediatek.com Acked-by: Sean Wang Signed-off-by: Linus Walleij --- .../pinctrl/mediatek/pinctrl-mtk-common-v2.c | 27 ++++++++++++++----- drivers/pinctrl/mediatek/pinctrl-paris.c | 25 +++++++++++++++++ 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c index 20e1c890e73b..d63e05e4b819 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c @@ -68,32 +68,44 @@ static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw, { const struct mtk_pin_field_calc *c, *e; const struct mtk_pin_reg_calc *rc; + int start = 0, end, check; + bool found = false; u32 bits; if (hw->soc->reg_cal && hw->soc->reg_cal[field].range) { rc = &hw->soc->reg_cal[field]; } else { dev_dbg(hw->dev, - "Not support field %d for pin %d (%s)\n", - field, desc->number, desc->name); + "Not support field %d for this soc\n", field); return -ENOTSUPP; } + end = rc->nranges - 1; c = rc->range; e = c + rc->nranges; - while (c < e) { - if (desc->number >= c->s_pin && desc->number <= c->e_pin) + while (start <= end) { + check = (start + end) >> 1; + if (desc->number >= rc->range[check].s_pin + && desc->number <= rc->range[check].e_pin) { + found = true; break; - c++; + } else if (start == end) + break; + else if (desc->number < rc->range[check].s_pin) + end = check - 1; + else + start = check + 1; } - if (c >= e) { + if (!found) { dev_dbg(hw->dev, "Not support field %d for pin = %d (%s)\n", field, desc->number, desc->name); return -ENOTSUPP; } + c = rc->range + check; + if (c->i_base > hw->nbase - 1) { dev_err(hw->dev, "Invalid base for field %d for pin = %d (%s)\n", @@ -182,6 +194,9 @@ int mtk_hw_set_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, if (err) return err; + if (value < 0 || value > pf.mask) + return -EINVAL; + if (!pf.next) mtk_rmw(hw, pf.index, pf.offset, pf.mask << pf.bitpos, (value & pf.mask) << pf.bitpos); diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c index 923264d0e9ef..3e13ae712c5c 100644 --- a/drivers/pinctrl/mediatek/pinctrl-paris.c +++ b/drivers/pinctrl/mediatek/pinctrl-paris.c @@ -81,6 +81,8 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, int val, val2, err, reg, ret = 1; const struct mtk_pin_desc *desc; + if (pin >= hw->soc->npins) + return -EINVAL; desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; switch (param) { @@ -206,6 +208,10 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, int err = 0; u32 reg; + if (pin >= hw->soc->npins) { + err = -EINVAL; + goto err; + } desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; switch ((u32)param) { @@ -693,6 +699,9 @@ static int mtk_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio) const struct mtk_pin_desc *desc; int value, err; + if (gpio > hw->soc->npins) + return -EINVAL; + desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &value); @@ -708,6 +717,9 @@ static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio) const struct mtk_pin_desc *desc; int value, err; + if (gpio > hw->soc->npins) + return -EINVAL; + desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value); @@ -722,6 +734,9 @@ static void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value) struct mtk_pinctrl *hw = gpiochip_get_data(chip); const struct mtk_pin_desc *desc; + if (gpio > hw->soc->npins) + return; + desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, !!value); @@ -729,12 +744,22 @@ static void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value) static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio) { + struct mtk_pinctrl *hw = gpiochip_get_data(chip); + + if (gpio > hw->soc->npins) + return -EINVAL; + return pinctrl_gpio_direction_input(chip->base + gpio); } static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio, int value) { + struct mtk_pinctrl *hw = gpiochip_get_data(chip); + + if (gpio > hw->soc->npins) + return -EINVAL; + mtk_gpio_set(chip, gpio, value); return pinctrl_gpio_direction_output(chip->base + gpio); From 5f755e1f1efe5ca3b475b14169e6e85bf1411bb5 Mon Sep 17 00:00:00 2001 From: Light Hsieh Date: Wed, 22 Jan 2020 14:53:10 +0800 Subject: [PATCH 0331/4444] pinctrl: mediatek: Supporting driving setting without mapping current to register value MediaTek's smartphone project actual usage does need to know current value (in mA) in procedure of finding the best driving setting. The steps in the procedure is like as follow: 1. set driving setting field in setting register as 0, measure waveform, perform test, and etc. 2. set driving setting field in setting register as 1, measure waveform, perform test, and etc. ... n. set driving setting field in setting register as n-1, measure waveform, perform test, and etc. Check the results of steps 1~n and adopt the setting that get best result. This procedure does need to know the mapping between current to register value. Therefore, setting driving without mapping current is more practical for MediaTek's smartphone usage. Signed-off-by: Light Hsieh Link: https://lore.kernel.org/r/1579675994-7001-2-git-send-email-light.hsieh@mediatek.com Acked-by: Sean Wang Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-mt6765.c | 4 ++-- drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c | 12 ++++++++++++ drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h | 5 +++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6765.c b/drivers/pinctrl/mediatek/pinctrl-mt6765.c index 32451e8693be..12122646bbc2 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt6765.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt6765.c @@ -1077,8 +1077,8 @@ static const struct mtk_pin_soc mt6765_data = { .bias_disable_get = mtk_pinconf_bias_disable_get, .bias_set = mtk_pinconf_bias_set, .bias_get = mtk_pinconf_bias_get, - .drive_set = mtk_pinconf_drive_set_rev1, - .drive_get = mtk_pinconf_drive_get_rev1, + .drive_set = mtk_pinconf_drive_set_raw, + .drive_get = mtk_pinconf_drive_get_raw, .adv_pull_get = mtk_pinconf_adv_pull_get, .adv_pull_set = mtk_pinconf_adv_pull_set, }; diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c index d63e05e4b819..2247eae8eaf0 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c @@ -608,6 +608,18 @@ int mtk_pinconf_drive_get_rev1(struct mtk_pinctrl *hw, return 0; } +int mtk_pinconf_drive_set_raw(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, u32 arg) +{ + return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV, arg); +} + +int mtk_pinconf_drive_get_raw(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, int *val) +{ + return mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV, val); +} + int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, bool pullup, u32 arg) diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h index 1b7da42aa1d5..75d0e0712c03 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h @@ -288,6 +288,11 @@ int mtk_pinconf_drive_set_rev1(struct mtk_pinctrl *hw, int mtk_pinconf_drive_get_rev1(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, int *val); +int mtk_pinconf_drive_set_raw(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, u32 arg); +int mtk_pinconf_drive_get_raw(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, int *val); + int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, bool pullup, u32 arg); From 3599cc525486be6681640ff3083376c001264c61 Mon Sep 17 00:00:00 2001 From: Light Hsieh Date: Wed, 22 Jan 2020 14:53:11 +0800 Subject: [PATCH 0332/4444] pinctrl: mediatek: Refine mtk_pinconf_get() and mtk_pinconf_set() 1.Refine mtk_pinconf_get(): Use only one occurrence of return at end of this function. 2.Refine mtk_pinconf_set(): 2.1 Use only one occurrence of return at end of this function. 2.2 Modify case of PIN_CONFIG_INPUT_ENABLE - 2.2.1 Regard all non-zero setting value as enable, instead of always enable. 2.2.2 Remove check of ies_present flag and always invoke mtk_hw_set_value() since mtk_hw_pin_field_lookup() invoked inside mtk_hw_set_value() has the same effect of checking if ies control is supported. [The rationale is that: available of a control is always checked in mtk_hw_pin_field_lookup() and no need to add ies_present flag specially for ies control.] 2.3 Simply code logic for case of PIN_CONFIG_INPUT_SCHMITT. 2.4 Add case for PIN_CONFIG_INPUT_SCHMITT_ENABLE and process it with the same code for case of PIN_CONFIG_INPUT_SCHMITT. Signed-off-by: Light Hsieh Link: https://lore.kernel.org/r/1579675994-7001-3-git-send-email-light.hsieh@mediatek.com Acked-by: Sean Wang Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-mt6765.c | 1 - drivers/pinctrl/mediatek/pinctrl-mt8183.c | 1 - drivers/pinctrl/mediatek/pinctrl-paris.c | 171 ++++++++-------------- 3 files changed, 65 insertions(+), 108 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6765.c b/drivers/pinctrl/mediatek/pinctrl-mt6765.c index 12122646bbc2..7fae397fe27c 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt6765.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt6765.c @@ -1070,7 +1070,6 @@ static const struct mtk_pin_soc mt6765_data = { .ngrps = ARRAY_SIZE(mtk_pins_mt6765), .eint_hw = &mt6765_eint_hw, .gpio_m = 0, - .ies_present = true, .base_names = mt6765_pinctrl_register_base_names, .nbase_names = ARRAY_SIZE(mt6765_pinctrl_register_base_names), .bias_disable_set = mtk_pinconf_bias_disable_set, diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8183.c b/drivers/pinctrl/mediatek/pinctrl-mt8183.c index 9a74d5025be6..4eca81864a96 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt8183.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt8183.c @@ -554,7 +554,6 @@ static const struct mtk_pin_soc mt8183_data = { .ngrps = ARRAY_SIZE(mtk_pins_mt8183), .eint_hw = &mt8183_eint_hw, .gpio_m = 0, - .ies_present = true, .base_names = mt8183_pinctrl_register_base_names, .nbase_names = ARRAY_SIZE(mt8183_pinctrl_register_base_names), .bias_disable_set = mtk_pinconf_bias_disable_set_rev1, diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c index 3e13ae712c5c..2f0750092fa0 100644 --- a/drivers/pinctrl/mediatek/pinctrl-paris.c +++ b/drivers/pinctrl/mediatek/pinctrl-paris.c @@ -81,37 +81,30 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, int val, val2, err, reg, ret = 1; const struct mtk_pin_desc *desc; - if (pin >= hw->soc->npins) - return -EINVAL; + if (pin >= hw->soc->npins) { + err = -EINVAL; + goto out; + } desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; switch (param) { case PIN_CONFIG_BIAS_DISABLE: - if (hw->soc->bias_disable_get) { + if (hw->soc->bias_disable_get) err = hw->soc->bias_disable_get(hw, desc, &ret); - if (err) - return err; - } else { - return -ENOTSUPP; - } + else + err = -ENOTSUPP; break; case PIN_CONFIG_BIAS_PULL_UP: - if (hw->soc->bias_get) { + if (hw->soc->bias_get) err = hw->soc->bias_get(hw, desc, 1, &ret); - if (err) - return err; - } else { - return -ENOTSUPP; - } + else + err = -ENOTSUPP; break; case PIN_CONFIG_BIAS_PULL_DOWN: - if (hw->soc->bias_get) { + if (hw->soc->bias_get) err = hw->soc->bias_get(hw, desc, 0, &ret); - if (err) - return err; - } else { - return -ENOTSUPP; - } + else + err = -ENOTSUPP; break; case PIN_CONFIG_SLEW_RATE: err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &val); @@ -126,12 +119,16 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, case PIN_CONFIG_OUTPUT_ENABLE: err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val); if (err) - return err; - - /* HW takes input mode as zero; output mode as non-zero */ - if ((val && param == PIN_CONFIG_INPUT_ENABLE) || - (!val && param == PIN_CONFIG_OUTPUT_ENABLE)) - return -EINVAL; + goto out; + /* CONFIG Current direction return value + * ------------- ----------------- ---------------------- + * OUTPUT_ENABLE output 1 (= HW value) + * input 0 (= HW value) + * INPUT_ENABLE output 0 (= reverse HW value) + * input 1 (= reverse HW value) + */ + if (param == PIN_CONFIG_INPUT_ENABLE) + val = !val; break; case PIN_CONFIG_INPUT_SCHMITT_ENABLE: @@ -148,13 +145,10 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, break; case PIN_CONFIG_DRIVE_STRENGTH: - if (hw->soc->drive_get) { + if (hw->soc->drive_get) err = hw->soc->drive_get(hw, desc, &ret); - if (err) - return err; - } else { + else err = -ENOTSUPP; - } break; case MTK_PIN_CONFIG_TDSEL: case MTK_PIN_CONFIG_RDSEL: @@ -175,28 +169,24 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, pullup = param == MTK_PIN_CONFIG_PU_ADV; err = hw->soc->adv_pull_get(hw, desc, pullup, &ret); - if (err) - return err; - } else { - return -ENOTSUPP; - } + } else + err = -ENOTSUPP; break; case MTK_PIN_CONFIG_DRV_ADV: - if (hw->soc->adv_drive_get) { + if (hw->soc->adv_drive_get) err = hw->soc->adv_drive_get(hw, desc, &ret); - if (err) - return err; - } else { - return -ENOTSUPP; - } + else + err = -ENOTSUPP; break; default: - return -ENOTSUPP; + err = -ENOTSUPP; } - *config = pinconf_to_config_packed(param, ret); +out: + if (!err) + *config = pinconf_to_config_packed(param, ret); - return 0; + return err; } static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, @@ -216,60 +206,47 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, switch ((u32)param) { case PIN_CONFIG_BIAS_DISABLE: - if (hw->soc->bias_disable_set) { + if (hw->soc->bias_disable_set) err = hw->soc->bias_disable_set(hw, desc); - if (err) - return err; - } else { - return -ENOTSUPP; - } + else + err = -ENOTSUPP; break; case PIN_CONFIG_BIAS_PULL_UP: - if (hw->soc->bias_set) { + if (hw->soc->bias_set) err = hw->soc->bias_set(hw, desc, 1); - if (err) - return err; - } else { - return -ENOTSUPP; - } + else + err = -ENOTSUPP; break; case PIN_CONFIG_BIAS_PULL_DOWN: - if (hw->soc->bias_set) { + if (hw->soc->bias_set) err = hw->soc->bias_set(hw, desc, 0); - if (err) - return err; - } else { - return -ENOTSUPP; - } + else + err = -ENOTSUPP; break; case PIN_CONFIG_OUTPUT_ENABLE: err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, MTK_DISABLE); - if (err) + /* Keep set direction to consider the case that a GPIO pin + * does not have SMT control + */ + if (err != -ENOTSUPP) goto err; err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, MTK_OUTPUT); - if (err) - goto err; break; case PIN_CONFIG_INPUT_ENABLE: - if (hw->soc->ies_present) { - mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES, - MTK_ENABLE); - } + /* regard all non-zero value as enable */ + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES, !!arg); + if (err) + goto err; err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, MTK_INPUT); - if (err) - goto err; break; case PIN_CONFIG_SLEW_RATE: - err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR, - arg); - if (err) - goto err; - + /* regard all non-zero value as enable */ + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR, !!arg); break; case PIN_CONFIG_OUTPUT: err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, @@ -279,41 +256,29 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, arg); - if (err) - goto err; break; + case PIN_CONFIG_INPUT_SCHMITT: case PIN_CONFIG_INPUT_SCHMITT_ENABLE: /* arg = 1: Input mode & SMT enable ; * arg = 0: Output mode & SMT disable */ - arg = arg ? 2 : 1; - err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, - arg & 1); + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, !arg); if (err) goto err; - err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, - !!(arg & 2)); - if (err) - goto err; + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, !!arg); break; case PIN_CONFIG_DRIVE_STRENGTH: - if (hw->soc->drive_set) { + if (hw->soc->drive_set) err = hw->soc->drive_set(hw, desc, arg); - if (err) - return err; - } else { - return -ENOTSUPP; - } + else + err = -ENOTSUPP; break; case MTK_PIN_CONFIG_TDSEL: case MTK_PIN_CONFIG_RDSEL: reg = (param == MTK_PIN_CONFIG_TDSEL) ? PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL; - err = mtk_hw_set_value(hw, desc, reg, arg); - if (err) - goto err; break; case MTK_PIN_CONFIG_PU_ADV: case MTK_PIN_CONFIG_PD_ADV: @@ -323,20 +288,14 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, pullup = param == MTK_PIN_CONFIG_PU_ADV; err = hw->soc->adv_pull_set(hw, desc, pullup, arg); - if (err) - return err; - } else { - return -ENOTSUPP; - } + } else + err = -ENOTSUPP; break; case MTK_PIN_CONFIG_DRV_ADV: - if (hw->soc->adv_drive_set) { + if (hw->soc->adv_drive_set) err = hw->soc->adv_drive_set(hw, desc, arg); - if (err) - return err; - } else { - return -ENOTSUPP; - } + else + err = -ENOTSUPP; break; default: err = -ENOTSUPP; From 1bea6afbc84206cd939ae227cf81d6c824af6fd7 Mon Sep 17 00:00:00 2001 From: Light Hsieh Date: Wed, 22 Jan 2020 14:53:12 +0800 Subject: [PATCH 0333/4444] pinctrl: mediatek: Refine mtk_pinconf_get() Correct cases for PIN_CONFIG_SLEW_RATE, PIN_CONFIG_INPUT_SCHMITT_ENABLE, and PIN_CONFIG_OUTPUT_ENABLE - Use variable ret to receive value in mtk_hw_get_value() (instead of variable val) since pinconf_to_config_packed() at end of this function use variable ret to pack config value. Signed-off-by: Light Hsieh Link: https://lore.kernel.org/r/1579675994-7001-4-git-send-email-light.hsieh@mediatek.com Acked-by: Sean Wang Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-paris.c | 40 +++++++++--------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c index 2f0750092fa0..d09a726beece 100644 --- a/drivers/pinctrl/mediatek/pinctrl-paris.c +++ b/drivers/pinctrl/mediatek/pinctrl-paris.c @@ -78,7 +78,7 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, { struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); u32 param = pinconf_to_config_param(*config); - int val, val2, err, reg, ret = 1; + int err, reg, ret = 1; const struct mtk_pin_desc *desc; if (pin >= hw->soc->npins) { @@ -107,17 +107,11 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, err = -ENOTSUPP; break; case PIN_CONFIG_SLEW_RATE: - err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &val); - if (err) - return err; - - if (!val) - return -EINVAL; - + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &ret); break; case PIN_CONFIG_INPUT_ENABLE: case PIN_CONFIG_OUTPUT_ENABLE: - err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val); + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret); if (err) goto out; /* CONFIG Current direction return value @@ -128,20 +122,22 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, * input 1 (= reverse HW value) */ if (param == PIN_CONFIG_INPUT_ENABLE) - val = !val; + ret = !ret; break; case PIN_CONFIG_INPUT_SCHMITT_ENABLE: - err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val); + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret); if (err) - return err; + goto out; + /* return error when in output mode + * because schmitt trigger only work in input mode + */ + if (ret) { + err = -EINVAL; + goto out; + } - err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &val2); - if (err) - return err; - - if (val || !val2) - return -EINVAL; + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &ret); break; case PIN_CONFIG_DRIVE_STRENGTH: @@ -154,13 +150,7 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, case MTK_PIN_CONFIG_RDSEL: reg = (param == MTK_PIN_CONFIG_TDSEL) ? PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL; - - err = mtk_hw_get_value(hw, desc, reg, &val); - if (err) - return err; - - ret = val; - + err = mtk_hw_get_value(hw, desc, reg, &ret); break; case MTK_PIN_CONFIG_PU_ADV: case MTK_PIN_CONFIG_PD_ADV: From cafe19db7751269bf6b4dd2148cbfa9fbe91d651 Mon Sep 17 00:00:00 2001 From: Light Hsieh Date: Wed, 22 Jan 2020 14:53:13 +0800 Subject: [PATCH 0334/4444] pinctrl: mediatek: Backward compatible to previous Mediatek's bias-pull usage Refine mtk_pinconf_set()/mtk_pinconf_get() for backward compatibility to previous MediaTek's bias-pull usage. In PINCTRL_MTK that use pinctrl-mtk-common.c, bias-pull setting for pins with 2 pull resistors can be specified as value for bias-pull-up and bias-pull-down. For example: bias-pull-up = ; bias-pull-up = ; bias-pull-up = ; bias-pull-up = ; bias-pull-down = ; bias-pull-down = ; bias-pull-down = ; bias-pull-down = ; On the other hand, PINCTRL_MTK_PARIS use customized properties "mediatek,pull-up-adv" and "mediatek,pull-down-adv" to specify bias-pull setting for pins with 2 pull resistors. This introduce in-compatibility in device tree and increase porting effort to MediaTek's customer that had already used PINCTRL_MTK version. Besides, if customers are not aware of this change and still write devicetree for PINCTRL_MTK version, they may encounter runtime failure with pinctrl and spent time to debug. This patch adds backward compatible to previous MediaTek's bias-pull usage so that Mediatek's customer need not use a new devicetree property name. The rationale is that: changing driver implementation had better leave interface unchanged. Signed-off-by: Light Hsieh Link: https://lore.kernel.org/r/1579675994-7001-5-git-send-email-light.hsieh@mediatek.com Acked-by: Sean Wang Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-mt6765.c | 6 +- drivers/pinctrl/mediatek/pinctrl-mt8183.c | 6 +- .../pinctrl/mediatek/pinctrl-mtk-common-v2.c | 221 ++++++++++++++++++ .../pinctrl/mediatek/pinctrl-mtk-common-v2.h | 11 + drivers/pinctrl/mediatek/pinctrl-paris.c | 49 ++-- 5 files changed, 265 insertions(+), 28 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6765.c b/drivers/pinctrl/mediatek/pinctrl-mt6765.c index 7fae397fe27c..905dae8c3fd8 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt6765.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt6765.c @@ -1072,10 +1072,8 @@ static const struct mtk_pin_soc mt6765_data = { .gpio_m = 0, .base_names = mt6765_pinctrl_register_base_names, .nbase_names = ARRAY_SIZE(mt6765_pinctrl_register_base_names), - .bias_disable_set = mtk_pinconf_bias_disable_set, - .bias_disable_get = mtk_pinconf_bias_disable_get, - .bias_set = mtk_pinconf_bias_set, - .bias_get = mtk_pinconf_bias_get, + .bias_set_combo = mtk_pinconf_bias_set_combo, + .bias_get_combo = mtk_pinconf_bias_get_combo, .drive_set = mtk_pinconf_drive_set_raw, .drive_get = mtk_pinconf_drive_get_raw, .adv_pull_get = mtk_pinconf_adv_pull_get, diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8183.c b/drivers/pinctrl/mediatek/pinctrl-mt8183.c index 4eca81864a96..60318339b618 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt8183.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt8183.c @@ -556,10 +556,8 @@ static const struct mtk_pin_soc mt8183_data = { .gpio_m = 0, .base_names = mt8183_pinctrl_register_base_names, .nbase_names = ARRAY_SIZE(mt8183_pinctrl_register_base_names), - .bias_disable_set = mtk_pinconf_bias_disable_set_rev1, - .bias_disable_get = mtk_pinconf_bias_disable_get_rev1, - .bias_set = mtk_pinconf_bias_set_rev1, - .bias_get = mtk_pinconf_bias_get_rev1, + .bias_set_combo = mtk_pinconf_bias_set_combo, + .bias_get_combo = mtk_pinconf_bias_get_combo, .drive_set = mtk_pinconf_drive_set_rev1, .drive_get = mtk_pinconf_drive_get_rev1, .adv_pull_get = mtk_pinconf_adv_pull_get, diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c index 2247eae8eaf0..1da942548ff4 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c @@ -6,6 +6,7 @@ * */ +#include #include #include #include @@ -517,6 +518,226 @@ int mtk_pinconf_bias_get_rev1(struct mtk_pinctrl *hw, return 0; } +/* Combo for the following pull register type: + * 1. PU + PD + * 2. PULLSEL + PULLEN + * 3. PUPD + R0 + R1 + */ +static int mtk_pinconf_bias_set_pu_pd(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 pullup, u32 arg) +{ + int err, pu, pd; + + if (arg == MTK_DISABLE) { + pu = 0; + pd = 0; + } else if ((arg == MTK_ENABLE) && pullup) { + pu = 1; + pd = 0; + } else if ((arg == MTK_ENABLE) && !pullup) { + pu = 0; + pd = 1; + } else { + err = -EINVAL; + goto out; + } + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PU, pu); + if (err) + goto out; + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD, pd); + +out: + return err; +} + +static int mtk_pinconf_bias_set_pullsel_pullen(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 pullup, u32 arg) +{ + int err, enable; + + if (arg == MTK_DISABLE) + enable = 0; + else if (arg == MTK_ENABLE) + enable = 1; + else { + err = -EINVAL; + goto out; + } + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLEN, enable); + if (err) + goto out; + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, pullup); + +out: + return err; +} + +static int mtk_pinconf_bias_set_pupd_r1_r0(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 pullup, u32 arg) +{ + int err, r0, r1; + + if ((arg == MTK_DISABLE) || (arg == MTK_PUPD_SET_R1R0_00)) { + pullup = 0; + r0 = 0; + r1 = 0; + } else if (arg == MTK_PUPD_SET_R1R0_01) { + r0 = 1; + r1 = 0; + } else if (arg == MTK_PUPD_SET_R1R0_10) { + r0 = 0; + r1 = 1; + } else if (arg == MTK_PUPD_SET_R1R0_11) { + r0 = 1; + r1 = 1; + } else { + err = -EINVAL; + goto out; + } + + /* MTK HW PUPD bit: 1 for pull-down, 0 for pull-up */ + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PUPD, !pullup); + if (err) + goto out; + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R0, r0); + if (err) + goto out; + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R1, r1); + +out: + return err; +} + +static int mtk_pinconf_bias_get_pu_pd(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 *pullup, u32 *enable) +{ + int err, pu, pd; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PU, &pu); + if (err) + goto out; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PD, &pd); + if (err) + goto out; + + if (pu == 0 && pd == 0) { + *pullup = 0; + *enable = MTK_DISABLE; + } else if (pu == 1 && pd == 0) { + *pullup = 1; + *enable = MTK_ENABLE; + } else if (pu == 0 && pd == 1) { + *pullup = 0; + *enable = MTK_ENABLE; + } else + err = -EINVAL; + +out: + return err; +} + +static int mtk_pinconf_bias_get_pullsel_pullen(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 *pullup, u32 *enable) +{ + int err; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, pullup); + if (err) + goto out; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLEN, enable); + +out: + return err; +} + +static int mtk_pinconf_bias_get_pupd_r1_r0(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 *pullup, u32 *enable) +{ + int err, r0, r1; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PUPD, pullup); + if (err) + goto out; + /* MTK HW PUPD bit: 1 for pull-down, 0 for pull-up */ + *pullup = !(*pullup); + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R0, &r0); + if (err) + goto out; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R1, &r1); + if (err) + goto out; + + if ((r1 == 0) && (r0 == 0)) + *enable = MTK_PUPD_SET_R1R0_00; + else if ((r1 == 0) && (r0 == 1)) + *enable = MTK_PUPD_SET_R1R0_01; + else if ((r1 == 1) && (r0 == 0)) + *enable = MTK_PUPD_SET_R1R0_10; + else if ((r1 == 1) && (r0 == 1)) + *enable = MTK_PUPD_SET_R1R0_11; + else + err = -EINVAL; + +out: + return err; +} + +int mtk_pinconf_bias_set_combo(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 pullup, u32 arg) +{ + int err; + + err = mtk_pinconf_bias_set_pu_pd(hw, desc, pullup, arg); + if (!err) + goto out; + + err = mtk_pinconf_bias_set_pullsel_pullen(hw, desc, pullup, arg); + if (!err) + goto out; + + err = mtk_pinconf_bias_set_pupd_r1_r0(hw, desc, pullup, arg); + +out: + return err; +} + +int mtk_pinconf_bias_get_combo(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 *pullup, u32 *enable) +{ + int err; + + err = mtk_pinconf_bias_get_pu_pd(hw, desc, pullup, enable); + if (!err) + goto out; + + err = mtk_pinconf_bias_get_pullsel_pullen(hw, desc, pullup, enable); + if (!err) + goto out; + + err = mtk_pinconf_bias_get_pupd_r1_r0(hw, desc, pullup, enable); + +out: + return err; +} + /* Revision 0 */ int mtk_pinconf_drive_set(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, u32 arg) diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h index 75d0e0712c03..27df08736396 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h @@ -216,6 +216,11 @@ struct mtk_pin_soc { int (*bias_get)(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, bool pullup, int *res); + int (*bias_set_combo)(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, u32 pullup, u32 arg); + int (*bias_get_combo)(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, u32 *pullup, u32 *arg); + int (*drive_set)(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, u32 arg); int (*drive_get)(struct mtk_pinctrl *hw, @@ -277,6 +282,12 @@ int mtk_pinconf_bias_set_rev1(struct mtk_pinctrl *hw, int mtk_pinconf_bias_get_rev1(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, bool pullup, int *res); +int mtk_pinconf_bias_set_combo(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 pullup, u32 enable); +int mtk_pinconf_bias_get_combo(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 *pullup, u32 *enable); int mtk_pinconf_drive_set(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, u32 arg); diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c index d09a726beece..115ebc19fc44 100644 --- a/drivers/pinctrl/mediatek/pinctrl-paris.c +++ b/drivers/pinctrl/mediatek/pinctrl-paris.c @@ -78,7 +78,7 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, { struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); u32 param = pinconf_to_config_param(*config); - int err, reg, ret = 1; + int pullup, err, reg, ret = 1; const struct mtk_pin_desc *desc; if (pin >= hw->soc->npins) { @@ -89,22 +89,31 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, switch (param) { case PIN_CONFIG_BIAS_DISABLE: - if (hw->soc->bias_disable_get) - err = hw->soc->bias_disable_get(hw, desc, &ret); - else - err = -ENOTSUPP; - break; case PIN_CONFIG_BIAS_PULL_UP: - if (hw->soc->bias_get) - err = hw->soc->bias_get(hw, desc, 1, &ret); - else - err = -ENOTSUPP; - break; case PIN_CONFIG_BIAS_PULL_DOWN: - if (hw->soc->bias_get) - err = hw->soc->bias_get(hw, desc, 0, &ret); - else + if (hw->soc->bias_get_combo) { + err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret); + if (err) + goto out; + if (param == PIN_CONFIG_BIAS_DISABLE) { + if (ret == MTK_PUPD_SET_R1R0_00) + ret = MTK_DISABLE; + } else if (param == PIN_CONFIG_BIAS_PULL_UP) { + /* When desire to get pull-up value, return + * error if current setting is pull-down + */ + if (!pullup) + err = -EINVAL; + } else if (param == PIN_CONFIG_BIAS_PULL_DOWN) { + /* When desire to get pull-down value, return + * error if current setting is pull-up + */ + if (pullup) + err = -EINVAL; + } + } else { err = -ENOTSUPP; + } break; case PIN_CONFIG_SLEW_RATE: err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &ret); @@ -196,20 +205,20 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, switch ((u32)param) { case PIN_CONFIG_BIAS_DISABLE: - if (hw->soc->bias_disable_set) - err = hw->soc->bias_disable_set(hw, desc); + if (hw->soc->bias_set_combo) + err = hw->soc->bias_set_combo(hw, desc, 0, MTK_DISABLE); else err = -ENOTSUPP; break; case PIN_CONFIG_BIAS_PULL_UP: - if (hw->soc->bias_set) - err = hw->soc->bias_set(hw, desc, 1); + if (hw->soc->bias_set_combo) + err = hw->soc->bias_set_combo(hw, desc, 1, arg); else err = -ENOTSUPP; break; case PIN_CONFIG_BIAS_PULL_DOWN: - if (hw->soc->bias_set) - err = hw->soc->bias_set(hw, desc, 0); + if (hw->soc->bias_set_combo) + err = hw->soc->bias_set_combo(hw, desc, 0, arg); else err = -ENOTSUPP; break; From 184d8e13f9b13313f711f028ca2465f973459046 Mon Sep 17 00:00:00 2001 From: Light Hsieh Date: Wed, 22 Jan 2020 14:53:14 +0800 Subject: [PATCH 0335/4444] pinctrl: mediatek: Add support for pin configuration dump via debugfs. Add support for pin configuration dump via catting /sys/kernel/debug/pinctrl/$platform_dependent_path/pinconf-pins. pinctrl framework had already support such dump. This patch implement the operation function pointer to fullfill this dump. Signed-off-by: Light Hsieh Link: https://lore.kernel.org/r/1579675994-7001-6-git-send-email-light.hsieh@mediatek.com Acked-by: Sean Wang Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-paris.c | 109 +++++++++++++++++++++++ drivers/pinctrl/mediatek/pinctrl-paris.h | 3 + 2 files changed, 112 insertions(+) diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c index 115ebc19fc44..83bf29c7ce7e 100644 --- a/drivers/pinctrl/mediatek/pinctrl-paris.c +++ b/drivers/pinctrl/mediatek/pinctrl-paris.c @@ -539,12 +539,120 @@ static int mtk_pctrl_get_group_pins(struct pinctrl_dev *pctldev, return 0; } +static int mtk_hw_get_value_wrap(struct mtk_pinctrl *hw, unsigned int gpio, int field) +{ + const struct mtk_pin_desc *desc; + int value, err; + + if (gpio > hw->soc->npins) + return -EINVAL; + + desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; + + err = mtk_hw_get_value(hw, desc, field, &value); + if (err) + return err; + + return value; +} + +#define mtk_pctrl_get_pinmux(hw, gpio) \ + mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_MODE) + +#define mtk_pctrl_get_direction(hw, gpio) \ + mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_DIR) + +#define mtk_pctrl_get_out(hw, gpio) \ + mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_DO) + +#define mtk_pctrl_get_in(hw, gpio) \ + mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_DI) + +#define mtk_pctrl_get_smt(hw, gpio) \ + mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_SMT) + +#define mtk_pctrl_get_ies(hw, gpio) \ + mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_IES) + +#define mtk_pctrl_get_driving(hw, gpio) \ + mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_DRV) + +ssize_t mtk_pctrl_show_one_pin(struct mtk_pinctrl *hw, + unsigned int gpio, char *buf, unsigned int bufLen) +{ + int pinmux, pullup, pullen, len = 0, r1 = -1, r0 = -1; + const struct mtk_pin_desc *desc; + + if (gpio > hw->soc->npins) + return -EINVAL; + + desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; + pinmux = mtk_pctrl_get_pinmux(hw, gpio); + if (pinmux >= hw->soc->nfuncs) + pinmux -= hw->soc->nfuncs; + + mtk_pinconf_bias_get_combo(hw, desc, &pullup, &pullen); + if (pullen == MTK_PUPD_SET_R1R0_00) { + pullen = 0; + r1 = 0; + r0 = 0; + } else if (pullen == MTK_PUPD_SET_R1R0_01) { + pullen = 1; + r1 = 0; + r0 = 1; + } else if (pullen == MTK_PUPD_SET_R1R0_10) { + pullen = 1; + r1 = 1; + r0 = 0; + } else if (pullen == MTK_PUPD_SET_R1R0_11) { + pullen = 1; + r1 = 1; + r0 = 1; + } else if (pullen != MTK_DISABLE && pullen != MTK_ENABLE) { + pullen = 0; + } + len += snprintf(buf + len, bufLen - len, + "%03d: %1d%1d%1d%1d%02d%1d%1d%1d%1d", + gpio, + pinmux, + mtk_pctrl_get_direction(hw, gpio), + mtk_pctrl_get_out(hw, gpio), + mtk_pctrl_get_in(hw, gpio), + mtk_pctrl_get_driving(hw, gpio), + mtk_pctrl_get_smt(hw, gpio), + mtk_pctrl_get_ies(hw, gpio), + pullen, + pullup); + + if (r1 != -1) { + len += snprintf(buf + len, bufLen - len, " (%1d %1d)\n", + r1, r0); + } else { + len += snprintf(buf + len, bufLen - len, "\n"); + } + + return len; +} + +#define PIN_DBG_BUF_SZ 96 +static void mtk_pctrl_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, + unsigned int gpio) +{ + struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); + char buf[PIN_DBG_BUF_SZ]; + + (void)mtk_pctrl_show_one_pin(hw, gpio, buf, PIN_DBG_BUF_SZ); + + seq_printf(s, "%s", buf); +} + static const struct pinctrl_ops mtk_pctlops = { .dt_node_to_map = mtk_pctrl_dt_node_to_map, .dt_free_map = pinctrl_utils_free_map, .get_groups_count = mtk_pctrl_get_groups_count, .get_group_name = mtk_pctrl_get_group_name, .get_group_pins = mtk_pctrl_get_group_pins, + .pin_dbg_show = mtk_pctrl_dbg_show, }; static int mtk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) @@ -641,6 +749,7 @@ static const struct pinconf_ops mtk_confops = { .pin_config_get = mtk_pinconf_get, .pin_config_group_get = mtk_pconf_group_get, .pin_config_group_set = mtk_pconf_group_set, + .is_generic = true, }; static struct pinctrl_desc mtk_desc = { diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.h b/drivers/pinctrl/mediatek/pinctrl-paris.h index 3d43771074e6..afb7650fd25b 100644 --- a/drivers/pinctrl/mediatek/pinctrl-paris.h +++ b/drivers/pinctrl/mediatek/pinctrl-paris.h @@ -60,6 +60,9 @@ int mtk_paris_pinctrl_probe(struct platform_device *pdev, const struct mtk_pin_soc *soc); +ssize_t mtk_pctrl_show_one_pin(struct mtk_pinctrl *hw, + unsigned int gpio, char *buf, unsigned int bufLen); + extern const struct dev_pm_ops mtk_paris_pinctrl_pm_ops; #endif /* __PINCTRL_PARIS_H */ From 6f87359e8bcaf88381b9c9c038929e0e6872d308 Mon Sep 17 00:00:00 2001 From: Matheus Castello Date: Fri, 24 Jan 2020 10:37:58 -0300 Subject: [PATCH 0336/4444] pinctrl: actions: Fix functions groups names for S700 SoC Group names by function do not match their respective structures and documentation defined names. This fixes following errors when groups names defined on documentation are used: [ 4.262778] pinctrl-s700 e01b0000.pinctrl: invalid group "sd0_d1_mfp" for function "sd0" [ 4.271394] pinctrl-s700 e01b0000.pinctrl: invalid group "sd0_d2_d3_mfp" for function "sd0" [ 4.280248] pinctrl-s700 e01b0000.pinctrl: invalid group "sd1_d0_d3_mfp" for function "sd0" [ 4.289122] pinctrl-s700 e01b0000.pinctrl: invalid group "sd0_cmd_mfp" for function "sd0" Fixes: 81c9d563cc74 (pinctrl: actions: Add Actions Semi S700 pinctrl driver) Signed-off-by: Matheus Castello Link: https://lore.kernel.org/r/20200124133758.10089-1-matheus@castello.eng.br Reviewed-by: Manivannan Sadhasivam Signed-off-by: Linus Walleij --- drivers/pinctrl/actions/pinctrl-s700.c | 510 ++++++++++++------------- 1 file changed, 255 insertions(+), 255 deletions(-) diff --git a/drivers/pinctrl/actions/pinctrl-s700.c b/drivers/pinctrl/actions/pinctrl-s700.c index 771d6fd50b45..47a4ccd9fed4 100644 --- a/drivers/pinctrl/actions/pinctrl-s700.c +++ b/drivers/pinctrl/actions/pinctrl-s700.c @@ -1125,317 +1125,317 @@ static const struct owl_pingroup s700_groups[] = { }; static const char * const nor_groups[] = { - "lcd0_d18", - "i2s_d0", - "i2s0_pcm0", - "i2s1_pcm0", - "i2s_d1", - "ks_in2", - "ks_in1", - "ks_in0", - "ks_in3", - "ks_out0", - "ks_out1", - "ks_out2", - "lcd0_d2", - "lvds_ee_pn", - "uart2_rx_tx", - "spi0_i2c_pcm", - "lvds_e_pn", - "sd0_d0", - "sd0_d1", - "sd0_d2_d3", - "sd1_d0_d3", - "sd0_cmd", - "sd1_cmd", - "sens0_ckout", - "sen0_pclk", + "lcd0_d18_mfp", + "i2s_d0_mfp", + "i2s0_pcm0_mfp", + "i2s1_pcm0_mfp", + "i2s_d1_mfp", + "ks_in2_mfp", + "ks_in1_mfp", + "ks_in0_mfp", + "ks_in3_mfp", + "ks_out0_mfp", + "ks_out1_mfp", + "ks_out2_mfp", + "lcd0_d2_mfp", + "lvds_ee_pn_mfp", + "uart2_rx_tx_mfp", + "spi0_i2c_pcm_mfp", + "lvds_e_pn_mfp", + "sd0_d0_mfp", + "sd0_d1_mfp", + "sd0_d2_d3_mfp", + "sd1_d0_d3_mfp", + "sd0_cmd_mfp", + "sd1_cmd_mfp", + "sens0_ckout_mfp", + "sen0_pclk_mfp", }; static const char * const eth_rmii_groups[] = { - "rgmii_txd23", - "rgmii_rxd2", - "rgmii_rxd3", - "rgmii_txd01", - "rgmii_txd0", - "rgmii_txd1", - "rgmii_txen", - "rgmii_rxen", - "rgmii_rxd1", - "rgmii_rxd0", - "rgmii_ref_clk", + "rgmii_txd23_mfp", + "rgmii_rxd2_mfp", + "rgmii_rxd3_mfp", + "rgmii_txd01_mfp", + "rgmii_txd0_mfp", + "rgmii_txd1_mfp", + "rgmii_txen_mfp", + "rgmii_rxen_mfp", + "rgmii_rxd1_mfp", + "rgmii_rxd0_mfp", + "rgmii_ref_clk_mfp", "eth_smi_dummy", }; static const char * const eth_smii_groups[] = { - "rgmii_txd0", - "rgmii_txd1", - "rgmii_rxd0", - "rgmii_rxd1", - "rgmii_ref_clk", + "rgmii_txd0_mfp", + "rgmii_txd1_mfp", + "rgmii_rxd0_mfp", + "rgmii_rxd1_mfp", + "rgmii_ref_clk_mfp", "eth_smi_dummy", }; static const char * const spi0_groups[] = { - "dsi_dn0", - "dsi_dp2", - "dsi_dp0", - "uart2_rx_tx", - "spi0_i2c_pcm", - "dsi_dn2", + "dsi_dn0_mfp", + "dsi_dp2_mfp", + "dsi_dp0_mfp", + "uart2_rx_tx_mfp", + "spi0_i2c_pcm_mfp", + "dsi_dn2_mfp", }; static const char * const spi1_groups[] = { - "uart0_rx", - "uart0_tx", + "uart0_rx_mfp", + "uart0_tx_mfp", "i2c0_mfp", }; static const char * const spi2_groups[] = { - "rgmii_txd01", - "rgmii_txd0", - "rgmii_txd1", - "rgmii_ref_clk", - "dnand_acle_ce0", + "rgmii_txd01_mfp", + "rgmii_txd0_mfp", + "rgmii_txd1_mfp", + "rgmii_ref_clk_mfp", + "dnand_acle_ce0_mfp", }; static const char * const spi3_groups[] = { - "rgmii_txen", - "rgmii_rxen", - "rgmii_rxd1", - "rgmii_rxd0", + "rgmii_txen_mfp", + "rgmii_rxen_mfp", + "rgmii_rxd1_mfp", + "rgmii_rxd0_mfp", }; static const char * const sens0_groups[] = { - "csi_cn_cp", - "sens0_ckout", - "csi_dn_dp", - "sen0_pclk", + "csi_cn_cp_mfp", + "sens0_ckout_mfp", + "csi_dn_dp_mfp", + "sen0_pclk_mfp", }; static const char * const sens1_groups[] = { - "lcd0_d18", - "ks_in2", - "ks_in1", - "ks_in0", - "ks_in3", - "ks_out0", - "ks_out1", - "ks_out2", - "sens0_ckout", - "pcm1_in", - "pcm1_clk", - "pcm1_sync", - "pcm1_out", + "lcd0_d18_mfp", + "ks_in2_mfp", + "ks_in1_mfp", + "ks_in0_mfp", + "ks_in3_mfp", + "ks_out0_mfp", + "ks_out1_mfp", + "ks_out2_mfp", + "sens0_ckout_mfp", + "pcm1_in_mfp", + "pcm1_clk_mfp", + "pcm1_sync_mfp", + "pcm1_out_mfp", }; static const char * const uart0_groups[] = { - "uart2_rtsb", - "uart2_ctsb", - "uart0_rx", - "uart0_tx", + "uart2_rtsb_mfp", + "uart2_ctsb_mfp", + "uart0_rx_mfp", + "uart0_tx_mfp", }; static const char * const uart1_groups[] = { - "sd0_d2_d3", + "sd0_d2_d3_mfp", "i2c0_mfp", }; static const char * const uart2_groups[] = { - "rgmii_txen", - "rgmii_rxen", - "rgmii_rxd1", - "rgmii_rxd0", - "dsi_dn0", - "dsi_dp2", - "dsi_dp0", - "uart2_rx_tx", - "dsi_dn2", - "uart2_rtsb", - "uart2_ctsb", - "sd0_d0", - "sd0_d1", - "sd0_d2_d3", - "uart0_rx", - "uart0_tx", + "rgmii_txen_mfp", + "rgmii_rxen_mfp", + "rgmii_rxd1_mfp", + "rgmii_rxd0_mfp", + "dsi_dn0_mfp", + "dsi_dp2_mfp", + "dsi_dp0_mfp", + "uart2_rx_tx_mfp", + "dsi_dn2_mfp", + "uart2_rtsb_mfp", + "uart2_ctsb_mfp", + "sd0_d0_mfp", + "sd0_d1_mfp", + "sd0_d2_d3_mfp", + "uart0_rx_mfp", + "uart0_tx_mfp", "i2c0_mfp", "uart2_dummy" }; static const char * const uart3_groups[] = { - "rgmii_txd23", - "rgmii_rxd2", - "rgmii_rxd3", - "uart3_rtsb", - "uart3_ctsb", + "rgmii_txd23_mfp", + "rgmii_rxd2_mfp", + "rgmii_rxd3_mfp", + "uart3_rtsb_mfp", + "uart3_ctsb_mfp", "uart3_dummy" }; static const char * const uart4_groups[] = { - "rgmii_txd01", - "rgmii_ref_clk", - "ks_out0", - "ks_out1", + "rgmii_txd01_mfp", + "rgmii_ref_clk_mfp", + "ks_out0_mfp", + "ks_out1_mfp", }; static const char * const uart5_groups[] = { - "rgmii_rxd1", - "rgmii_rxd0", - "ks_out0", - "ks_out2", - "uart3_rtsb", - "uart3_ctsb", - "sd0_d0", - "sd0_d1", + "rgmii_rxd1_mfp", + "rgmii_rxd0_mfp", + "ks_out0_mfp", + "ks_out2_mfp", + "uart3_rtsb_mfp", + "uart3_ctsb_mfp", + "sd0_d0_mfp", + "sd0_d1_mfp", }; static const char * const uart6_groups[] = { - "rgmii_txd0", - "rgmii_txd1", + "rgmii_txd0_mfp", + "rgmii_txd1_mfp", }; static const char * const i2s0_groups[] = { - "i2s_d0", - "i2s_pcm1", - "i2s0_pcm0", + "i2s_d0_mfp", + "i2s_pcm1_mfp", + "i2s0_pcm0_mfp", }; static const char * const i2s1_groups[] = { - "i2s1_pcm0", - "i2s_d1", + "i2s1_pcm0_mfp", + "i2s_d1_mfp", "i2s1_dummy", - "spi0_i2c_pcm", - "uart0_rx", - "uart0_tx", + "spi0_i2c_pcm_mfp", + "uart0_rx_mfp", + "uart0_tx_mfp", }; static const char * const pcm1_groups[] = { - "i2s_pcm1", - "spi0_i2c_pcm", - "uart0_rx", - "uart0_tx", - "pcm1_in", - "pcm1_clk", - "pcm1_sync", - "pcm1_out", + "i2s_pcm1_mfp", + "spi0_i2c_pcm_mfp", + "uart0_rx_mfp", + "uart0_tx_mfp", + "pcm1_in_mfp", + "pcm1_clk_mfp", + "pcm1_sync_mfp", + "pcm1_out_mfp", }; static const char * const pcm0_groups[] = { - "i2s0_pcm0", - "i2s1_pcm0", - "uart2_rx_tx", - "spi0_i2c_pcm", + "i2s0_pcm0_mfp", + "i2s1_pcm0_mfp", + "uart2_rx_tx_mfp", + "spi0_i2c_pcm_mfp", }; static const char * const ks_groups[] = { - "ks_in2", - "ks_in1", - "ks_in0", - "ks_in3", - "ks_out0", - "ks_out1", - "ks_out2", + "ks_in2_mfp", + "ks_in1_mfp", + "ks_in0_mfp", + "ks_in3_mfp", + "ks_out0_mfp", + "ks_out1_mfp", + "ks_out2_mfp", }; static const char * const jtag_groups[] = { - "ks_in2", - "ks_in1", - "ks_in0", - "ks_in3", - "ks_out1", - "sd0_d0", - "sd0_d2_d3", - "sd0_cmd", - "sd0_clk", + "ks_in2_mfp", + "ks_in1_mfp", + "ks_in0_mfp", + "ks_in3_mfp", + "ks_out1_mfp", + "sd0_d0_mfp", + "sd0_d2_d3_mfp", + "sd0_cmd_mfp", + "sd0_clk_mfp", }; static const char * const pwm0_groups[] = { - "rgmii_rxd2", - "rgmii_txen", - "ks_in2", - "sen0_pclk", + "rgmii_rxd2_mfp", + "rgmii_txen_mfp", + "ks_in2_mfp", + "sen0_pclk_mfp", }; static const char * const pwm1_groups[] = { - "rgmii_rxen", - "ks_in1", - "ks_in3", - "sens0_ckout", + "rgmii_rxen_mfp", + "ks_in1_mfp", + "ks_in3_mfp", + "sens0_ckout_mfp", }; static const char * const pwm2_groups[] = { - "lcd0_d18", - "rgmii_rxd3", - "rgmii_rxd1", - "ks_out0", - "ks_out2", + "lcd0_d18_mfp", + "rgmii_rxd3_mfp", + "rgmii_rxd1_mfp", + "ks_out0_mfp", + "ks_out2_mfp", }; static const char * const pwm3_groups[] = { - "rgmii_rxd0", - "ks_out1", - "lcd0_d2", + "rgmii_rxd0_mfp", + "ks_out1_mfp", + "lcd0_d2_mfp", }; static const char * const pwm4_groups[] = { - "lcd0_d18", - "rgmii_txd01", - "rgmii_txd0", - "ks_in0", - "pcm1_in", - "nand_ceb3", + "lcd0_d18_mfp", + "rgmii_txd01_mfp", + "rgmii_txd0_mfp", + "ks_in0_mfp", + "pcm1_in_mfp", + "nand_ceb3_mfp", }; static const char * const pwm5_groups[] = { - "rgmii_txd1", - "ks_in1", - "pcm1_clk", - "nand_ceb2", + "rgmii_txd1_mfp", + "ks_in1_mfp", + "pcm1_clk_mfp", + "nand_ceb2_mfp", }; static const char * const p0_groups[] = { - "ks_in2", - "ks_in0", + "ks_in2_mfp", + "ks_in0_mfp", }; static const char * const sd0_groups[] = { - "ks_out0", - "ks_out1", - "ks_out2", - "lcd0_d2", - "dsi_dp3", - "dsi_dp0", - "sd0_d0", - "sd0_d1", - "sd0_d2_d3", - "sd1_d0_d3", - "sd0_cmd", - "sd0_clk", + "ks_out0_mfp", + "ks_out1_mfp", + "ks_out2_mfp", + "lcd0_d2_mfp", + "dsi_dp3_mfp", + "dsi_dp0_mfp", + "sd0_d0_mfp", + "sd0_d1_mfp", + "sd0_d2_d3_mfp", + "sd1_d0_d3_mfp", + "sd0_cmd_mfp", + "sd0_clk_mfp", }; static const char * const sd1_groups[] = { - "dsi_dp2", - "mfp1_16_14", - "lcd0_d2", - "mfp1_16_14_d17", - "dsi_dp3", - "dsi_dn3", - "dsi_dnp1_cp_d2", - "dsi_dnp1_cp_d17", - "dsi_dn2", - "sd1_d0_d3", - "sd1_cmd", + "dsi_dp2_mfp", + "mfp1_16_14_mfp", + "lcd0_d2_mfp", + "mfp1_16_14_d17_mfp", + "dsi_dp3_mfp", + "dsi_dn3_mfp", + "dsi_dnp1_cp_d2_mfp", + "dsi_dnp1_cp_d17_mfp", + "dsi_dn2_mfp", + "sd1_d0_d3_mfp", + "sd1_cmd_mfp", "sd1_dummy", }; static const char * const sd2_groups[] = { - "dnand_data_wr", + "dnand_data_wr_mfp", }; static const char * const i2c0_groups[] = { - "uart0_rx", - "uart0_tx", - "i2c0_mfp", + "uart0_rx_mfp", + "uart0_tx_mfp", + "i2c0_mfp_mfp", }; static const char * const i2c1_groups[] = { @@ -1448,85 +1448,85 @@ static const char * const i2c2_groups[] = { }; static const char * const i2c3_groups[] = { - "uart2_rx_tx", - "pcm1_sync", - "pcm1_out", + "uart2_rx_tx_mfp", + "pcm1_sync_mfp", + "pcm1_out_mfp", }; static const char * const lvds_groups[] = { - "lvds_o_pn", - "lvds_ee_pn", - "lvds_e_pn", + "lvds_o_pn_mfp", + "lvds_ee_pn_mfp", + "lvds_e_pn_mfp", }; static const char * const bt_groups[] = { - "i2s_pcm1", - "i2s0_pcm0", - "i2s1_pcm0", - "ks_in2", - "ks_in1", - "ks_in0", - "ks_in3", - "ks_out0", - "ks_out1", - "ks_out2", - "lvds_o_pn", - "lvds_ee_pn", - "pcm1_in", - "pcm1_clk", - "pcm1_sync", - "pcm1_out", + "i2s_pcm1_mfp", + "i2s0_pcm0_mfp", + "i2s1_pcm0_mfp", + "ks_in2_mfp", + "ks_in1_mfp", + "ks_in0_mfp", + "ks_in3_mfp", + "ks_out0_mfp", + "ks_out1_mfp", + "ks_out2_mfp", + "lvds_o_pn_mfp", + "lvds_ee_pn_mfp", + "pcm1_in_mfp", + "pcm1_clk_mfp", + "pcm1_sync_mfp", + "pcm1_out_mfp", }; static const char * const lcd0_groups[] = { - "lcd0_d18", - "lcd0_d2", - "mfp1_16_14_d17", - "lvds_o_pn", - "dsi_dp3", - "dsi_dn3", - "lvds_ee_pn", - "dsi_dnp1_cp_d2", - "dsi_dnp1_cp_d17", - "lvds_e_pn", + "lcd0_d18_mfp", + "lcd0_d2_mfp", + "mfp1_16_14_d17_mfp", + "lvds_o_pn_mfp", + "dsi_dp3_mfp", + "dsi_dn3_mfp", + "lvds_ee_pn_mfp", + "dsi_dnp1_cp_d2_mfp", + "dsi_dnp1_cp_d17_mfp", + "lvds_e_pn_mfp", }; static const char * const usb30_groups[] = { - "ks_in1", + "ks_in1_mfp", }; static const char * const clko_25m_groups[] = { - "clko_25m", + "clko_25m_mfp", }; static const char * const mipi_csi_groups[] = { - "csi_cn_cp", - "csi_dn_dp", + "csi_cn_cp_mfp", + "csi_dn_dp_mfp", }; static const char * const dsi_groups[] = { - "dsi_dn0", - "dsi_dp2", - "dsi_dp3", - "dsi_dn3", - "dsi_dp0", - "dsi_dnp1_cp_d2", - "dsi_dnp1_cp_d17", - "dsi_dn2", + "dsi_dn0_mfp", + "dsi_dp2_mfp", + "dsi_dp3_mfp", + "dsi_dn3_mfp", + "dsi_dp0_mfp", + "dsi_dnp1_cp_d2_mfp", + "dsi_dnp1_cp_d17_mfp", + "dsi_dn2_mfp", "dsi_dummy", }; static const char * const nand_groups[] = { - "dnand_data_wr", - "dnand_acle_ce0", - "nand_ceb2", - "nand_ceb3", + "dnand_data_wr_mfp", + "dnand_acle_ce0_mfp", + "nand_ceb2_mfp", + "nand_ceb3_mfp", "nand_dummy", }; static const char * const spdif_groups[] = { - "uart0_tx", + "uart0_tx_mfp", }; static const char * const sirq0_groups[] = { From be30d5de0a5a52c6ee2cc453a51301037ab94aa4 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Mon, 27 Jan 2020 19:15:05 +0100 Subject: [PATCH 0337/4444] pinctrl: bcm2835: Drop unused define There is no usage for this define, so drop it. Signed-off-by: Stefan Wahren Link: https://lore.kernel.org/r/1580148908-4863-2-git-send-email-stefan.wahren@i2se.com Reviewed-by: Nicolas Saenz Julienne Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 0de1a3a96984..3fc26389a573 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -40,9 +40,6 @@ #define BCM2835_NUM_BANKS 2 #define BCM2835_NUM_IRQS 3 -#define BCM2835_PIN_BITMAP_SZ \ - DIV_ROUND_UP(BCM2835_NUM_GPIOS, sizeof(unsigned long) * 8) - /* GPIO register offsets */ #define GPFSEL0 0x0 /* Function Select */ #define GPSET0 0x1c /* Pin Output Set */ From 90bfaf028d61a6d523c685b63c2bcc94eebb8057 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sat, 8 Feb 2020 14:02:53 +0100 Subject: [PATCH 0338/4444] pinctrl: bcm2835: Refactor platform data This prepares the platform data to be easier to extend for more GPIOs. Except of this there is no functional change. Signed-off-by: Stefan Wahren Link: https://lore.kernel.org/r/1581166975-22949-3-git-send-email-stefan.wahren@i2se.com Reviewed-by: Nicolas Saenz Julienne Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 57 +++++++++++++++++++++------ 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 3fc26389a573..7f0a9c647927 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -82,6 +82,7 @@ struct bcm2835_pinctrl { struct pinctrl_dev *pctl_dev; struct gpio_chip gpio_chip; + struct pinctrl_desc pctl_desc; struct pinctrl_gpio_range gpio_range; raw_spinlock_t irq_lock[BCM2835_NUM_BANKS]; @@ -1051,7 +1052,7 @@ static const struct pinconf_ops bcm2711_pinconf_ops = { .pin_config_set = bcm2711_pinconf_set, }; -static struct pinctrl_desc bcm2835_pinctrl_desc = { +static const struct pinctrl_desc bcm2835_pinctrl_desc = { .name = MODULE_NAME, .pins = bcm2835_gpio_pins, .npins = ARRAY_SIZE(bcm2835_gpio_pins), @@ -1061,19 +1062,47 @@ static struct pinctrl_desc bcm2835_pinctrl_desc = { .owner = THIS_MODULE, }; -static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = { +static const struct pinctrl_desc bcm2711_pinctrl_desc = { + .name = MODULE_NAME, + .pins = bcm2835_gpio_pins, + .npins = ARRAY_SIZE(bcm2835_gpio_pins), + .pctlops = &bcm2835_pctl_ops, + .pmxops = &bcm2835_pmx_ops, + .confops = &bcm2711_pinconf_ops, + .owner = THIS_MODULE, +}; + +static const struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = { .name = MODULE_NAME, .npins = BCM2835_NUM_GPIOS, }; +struct bcm_plat_data { + const struct gpio_chip *gpio_chip; + const struct pinctrl_desc *pctl_desc; + const struct pinctrl_gpio_range *gpio_range; +}; + +static const struct bcm_plat_data bcm2835_plat_data = { + .gpio_chip = &bcm2835_gpio_chip, + .pctl_desc = &bcm2835_pinctrl_desc, + .gpio_range = &bcm2835_pinctrl_gpio_range, +}; + +static const struct bcm_plat_data bcm2711_plat_data = { + .gpio_chip = &bcm2835_gpio_chip, + .pctl_desc = &bcm2711_pinctrl_desc, + .gpio_range = &bcm2835_pinctrl_gpio_range, +}; + static const struct of_device_id bcm2835_pinctrl_match[] = { { .compatible = "brcm,bcm2835-gpio", - .data = &bcm2835_pinconf_ops, + .data = &bcm2835_plat_data, }, { .compatible = "brcm,bcm2711-gpio", - .data = &bcm2711_pinconf_ops, + .data = &bcm2711_plat_data, }, {} }; @@ -1082,6 +1111,7 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; + const struct bcm_plat_data *pdata; struct bcm2835_pinctrl *pc; struct gpio_irq_chip *girq; struct resource iomem; @@ -1108,7 +1138,13 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) if (IS_ERR(pc->base)) return PTR_ERR(pc->base); - pc->gpio_chip = bcm2835_gpio_chip; + match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node); + if (!match) + return -EINVAL; + + pdata = match->data; + + pc->gpio_chip = *pdata->gpio_chip; pc->gpio_chip.parent = dev; pc->gpio_chip.of_node = np; @@ -1159,19 +1195,14 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) return err; } - match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node); - if (match) { - bcm2835_pinctrl_desc.confops = - (const struct pinconf_ops *)match->data; - } - - pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc); + pc->pctl_desc = *pdata->pctl_desc; + pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc); if (IS_ERR(pc->pctl_dev)) { gpiochip_remove(&pc->gpio_chip); return PTR_ERR(pc->pctl_dev); } - pc->gpio_range = bcm2835_pinctrl_gpio_range; + pc->gpio_range = *pdata->gpio_range; pc->gpio_range.base = pc->gpio_chip.base; pc->gpio_range.gc = &pc->gpio_chip; pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); From b1d84a3d0a26c5844a22bc09a42704b9371208bb Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sat, 8 Feb 2020 14:02:54 +0100 Subject: [PATCH 0339/4444] pinctrl: bcm2835: Add support for all GPIOs on BCM2711 The BCM2711 supports 58 GPIOs. So extend pinctrl and GPIOs accordingly. Signed-off-by: Stefan Wahren Link: https://lore.kernel.org/r/1581166975-22949-4-git-send-email-stefan.wahren@i2se.com Reviewed-by: Nicolas Saenz Julienne Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 54 +++++++++++++++++++++------ 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 7f0a9c647927..061e70ed17a7 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -37,6 +37,7 @@ #define MODULE_NAME "pinctrl-bcm2835" #define BCM2835_NUM_GPIOS 54 +#define BCM2711_NUM_GPIOS 58 #define BCM2835_NUM_BANKS 2 #define BCM2835_NUM_IRQS 3 @@ -78,7 +79,7 @@ struct bcm2835_pinctrl { /* note: locking assumes each bank will have its own unsigned long */ unsigned long enabled_irq_map[BCM2835_NUM_BANKS]; - unsigned int irq_type[BCM2835_NUM_GPIOS]; + unsigned int irq_type[BCM2711_NUM_GPIOS]; struct pinctrl_dev *pctl_dev; struct gpio_chip gpio_chip; @@ -145,6 +146,10 @@ static struct pinctrl_pin_desc bcm2835_gpio_pins[] = { BCM2835_GPIO_PIN(51), BCM2835_GPIO_PIN(52), BCM2835_GPIO_PIN(53), + BCM2835_GPIO_PIN(54), + BCM2835_GPIO_PIN(55), + BCM2835_GPIO_PIN(56), + BCM2835_GPIO_PIN(57), }; /* one pin per group */ @@ -203,6 +208,10 @@ static const char * const bcm2835_gpio_groups[] = { "gpio51", "gpio52", "gpio53", + "gpio54", + "gpio55", + "gpio56", + "gpio57", }; enum bcm2835_fsel { @@ -353,6 +362,22 @@ static const struct gpio_chip bcm2835_gpio_chip = { .can_sleep = false, }; +static const struct gpio_chip bcm2711_gpio_chip = { + .label = "pinctrl-bcm2711", + .owner = THIS_MODULE, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, + .direction_input = bcm2835_gpio_direction_input, + .direction_output = bcm2835_gpio_direction_output, + .get_direction = bcm2835_gpio_get_direction, + .get = bcm2835_gpio_get, + .set = bcm2835_gpio_set, + .set_config = gpiochip_generic_config, + .base = -1, + .ngpio = BCM2711_NUM_GPIOS, + .can_sleep = false, +}; + static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc, unsigned int bank, u32 mask) { @@ -399,7 +424,7 @@ static void bcm2835_gpio_irq_handler(struct irq_desc *desc) bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000); bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff); break; - case 2: /* IRQ2 covers GPIOs 46-53 */ + case 2: /* IRQ2 covers GPIOs 46-57 */ bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000); break; } @@ -618,7 +643,7 @@ static struct irq_chip bcm2835_gpio_irq_chip = { static int bcm2835_pctl_get_groups_count(struct pinctrl_dev *pctldev) { - return ARRAY_SIZE(bcm2835_gpio_groups); + return BCM2835_NUM_GPIOS; } static const char *bcm2835_pctl_get_group_name(struct pinctrl_dev *pctldev, @@ -776,7 +801,7 @@ static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, err = of_property_read_u32_index(np, "brcm,pins", i, &pin); if (err) goto out; - if (pin >= ARRAY_SIZE(bcm2835_gpio_pins)) { + if (pin >= pc->pctl_desc.npins) { dev_err(pc->dev, "%pOF: invalid brcm,pins value %d\n", np, pin); err = -EINVAL; @@ -852,7 +877,7 @@ static int bcm2835_pmx_get_function_groups(struct pinctrl_dev *pctldev, { /* every pin can do every function */ *groups = bcm2835_gpio_groups; - *num_groups = ARRAY_SIZE(bcm2835_gpio_groups); + *num_groups = BCM2835_NUM_GPIOS; return 0; } @@ -1055,7 +1080,7 @@ static const struct pinconf_ops bcm2711_pinconf_ops = { static const struct pinctrl_desc bcm2835_pinctrl_desc = { .name = MODULE_NAME, .pins = bcm2835_gpio_pins, - .npins = ARRAY_SIZE(bcm2835_gpio_pins), + .npins = BCM2835_NUM_GPIOS, .pctlops = &bcm2835_pctl_ops, .pmxops = &bcm2835_pmx_ops, .confops = &bcm2835_pinconf_ops, @@ -1063,9 +1088,9 @@ static const struct pinctrl_desc bcm2835_pinctrl_desc = { }; static const struct pinctrl_desc bcm2711_pinctrl_desc = { - .name = MODULE_NAME, + .name = "pinctrl-bcm2711", .pins = bcm2835_gpio_pins, - .npins = ARRAY_SIZE(bcm2835_gpio_pins), + .npins = BCM2711_NUM_GPIOS, .pctlops = &bcm2835_pctl_ops, .pmxops = &bcm2835_pmx_ops, .confops = &bcm2711_pinconf_ops, @@ -1077,6 +1102,11 @@ static const struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = { .npins = BCM2835_NUM_GPIOS, }; +static const struct pinctrl_gpio_range bcm2711_pinctrl_gpio_range = { + .name = "pinctrl-bcm2711", + .npins = BCM2711_NUM_GPIOS, +}; + struct bcm_plat_data { const struct gpio_chip *gpio_chip; const struct pinctrl_desc *pctl_desc; @@ -1090,9 +1120,9 @@ static const struct bcm_plat_data bcm2835_plat_data = { }; static const struct bcm_plat_data bcm2711_plat_data = { - .gpio_chip = &bcm2835_gpio_chip, + .gpio_chip = &bcm2711_gpio_chip, .pctl_desc = &bcm2711_pinctrl_desc, - .gpio_range = &bcm2835_pinctrl_gpio_range, + .gpio_range = &bcm2711_pinctrl_gpio_range, }; static const struct of_device_id bcm2835_pinctrl_match[] = { @@ -1118,8 +1148,8 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) int err, i; const struct of_device_id *match; - BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2835_NUM_GPIOS); - BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2835_NUM_GPIOS); + BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2711_NUM_GPIOS); + BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2711_NUM_GPIOS); pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL); if (!pc) From c93214689f0c70b6942ba1d12b8371b9fc60ae41 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 28 Jan 2020 17:49:49 +0200 Subject: [PATCH 0340/4444] MAINTAINERS: Sort entries in database for PIN CONTROLLER Run parse-maintainers.pl and choose PIN CONTROLLER records. Fix them accordingly. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200128154949.66521-1-andriy.shevchenko@linux.intel.com Reviewed-by: Geert Uytterhoeven Signed-off-by: Linus Walleij --- MAINTAINERS | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 38fe2f3f7b6f..408fd7c660aa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2725,8 +2725,8 @@ L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers) L: openbmc@lists.ozlabs.org (moderated for non-subscribers) L: linux-gpio@vger.kernel.org S: Maintained -F: drivers/pinctrl/aspeed/ F: Documentation/devicetree/bindings/pinctrl/aspeed,* +F: drivers/pinctrl/aspeed/ ASPEED SCU INTERRUPT CONTROLLER DRIVER M: Eddie James @@ -13168,21 +13168,13 @@ K: \b(clone_args|kernel_clone_args)\b PIN CONTROL SUBSYSTEM M: Linus Walleij L: linux-gpio@vger.kernel.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git F: Documentation/devicetree/bindings/pinctrl/ F: Documentation/driver-api/pinctl.rst F: drivers/pinctrl/ F: include/linux/pinctrl/ -PIN CONTROLLER - MICROCHIP AT91 -M: Ludovic Desroches -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -L: linux-gpio@vger.kernel.org -S: Supported -F: drivers/pinctrl/pinctrl-at91* -F: drivers/gpio/gpio-sama5d2-piobu.c - PIN CONTROLLER - FREESCALE M: Dong Aisheng M: Fabio Estevam @@ -13191,14 +13183,14 @@ M: Stefan Agner R: Pengutronix Kernel Team L: linux-gpio@vger.kernel.org S: Maintained -F: drivers/pinctrl/freescale/ F: Documentation/devicetree/bindings/pinctrl/fsl,* +F: drivers/pinctrl/freescale/ PIN CONTROLLER - INTEL M: Mika Westerberg M: Andy Shevchenko -T: git git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/intel.git S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/intel.git F: drivers/pinctrl/intel/ PIN CONTROLLER - MEDIATEK @@ -13209,18 +13201,26 @@ F: Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt F: Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt F: drivers/pinctrl/mediatek/ +PIN CONTROLLER - MICROCHIP AT91 +M: Ludovic Desroches +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +L: linux-gpio@vger.kernel.org +S: Supported +F: drivers/gpio/gpio-sama5d2-piobu.c +F: drivers/pinctrl/pinctrl-at91* + PIN CONTROLLER - QUALCOMM M: Bjorn Andersson -S: Maintained L: linux-arm-msm@vger.kernel.org +S: Maintained F: Documentation/devicetree/bindings/pinctrl/qcom,*.txt F: drivers/pinctrl/qcom/ PIN CONTROLLER - RENESAS M: Geert Uytterhoeven L: linux-renesas-soc@vger.kernel.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git sh-pfc S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git sh-pfc F: drivers/pinctrl/pinctrl-rz* F: drivers/pinctrl/sh-pfc/ @@ -13230,12 +13230,12 @@ M: Krzysztof Kozlowski M: Sylwester Nawrocki L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers) -Q: https://patchwork.kernel.org/project/linux-samsung-soc/list/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/samsung.git S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/samsung.git +Q: https://patchwork.kernel.org/project/linux-samsung-soc/list/ +F: Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt F: drivers/pinctrl/samsung/ F: include/dt-bindings/pinctrl/samsung.h -F: Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt PIN CONTROLLER - SINGLE M: Tony Lindgren @@ -13248,8 +13248,8 @@ F: drivers/pinctrl/pinctrl-single.c PIN CONTROLLER - ST SPEAR M: Viresh Kumar L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -W: http://www.st.com/spear S: Maintained +W: http://www.st.com/spear F: drivers/pinctrl/spear/ PISTACHIO SOC SUPPORT From fc976f50ae77c6a841803d816b057417b9b14293 Mon Sep 17 00:00:00 2001 From: Bastian Germann Date: Fri, 14 Feb 2020 12:10:02 +0100 Subject: [PATCH 0341/4444] dt-bindings: arm: sunxi: Add Linutronix Testbox Add device tree bindings for the newly added Linutronix Testbox board. Signed-off-by: Bastian Germann Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/arm/sunxi.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml index 159060b65c5d..1e63c9867749 100644 --- a/Documentation/devicetree/bindings/arm/sunxi.yaml +++ b/Documentation/devicetree/bindings/arm/sunxi.yaml @@ -394,6 +394,12 @@ properties: - const: linksprite,pcduino3-nano - const: allwinner,sun7i-a20 + - description: Linutronix Testbox v2 + items: + - const: linutronix,testbox-v2 + - const: lamobo,lamobo-r1 + - const: allwinner,sun7i-a20 + - description: HAOYU Electronics Marsboard A10 items: - const: haoyu,a10-marsboard From 4c2bc78fe9d1c9aecc8a777221e3eb9d067987a8 Mon Sep 17 00:00:00 2001 From: Bastian Germann Date: Fri, 14 Feb 2020 12:10:03 +0100 Subject: [PATCH 0342/4444] ARM: dts: sun7i: Add Linutronix Testbox v2 board The Testbox board is an open hardware enhancement for the Lamobo R1 router board. The Testbox board is used in the CI-RT project to manage devices under test (https://ci-rt.linutronix.de). The hardware project is located at https://github.com/ci-rt/testbox-shield The Testbox v2 expands the Lamobo R1 router board with - a power supply, - a CAN bus PHY, - a power control, - a relay, - an I2C EEPROM, - a secure key storage (ATECC608a) and - two RS232 compliant serial ports. Co-developed-by: Benedikt Spranger Signed-off-by: Benedikt Spranger Signed-off-by: Bastian Germann [Maxime: Removed unused pinctrl node] Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 1 + .../dts/sun7i-a20-linutronix-testbox-v2.dts | 47 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 arch/arm/boot/dts/sun7i-a20-linutronix-testbox-v2.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index d6546d2676b9..e9ddca2946ce 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1086,6 +1086,7 @@ dtb-$(CONFIG_MACH_SUN7I) += \ sun7i-a20-i12-tvbox.dtb \ sun7i-a20-icnova-swac.dtb \ sun7i-a20-lamobo-r1.dtb \ + sun7i-a20-linutronix-testbox-v2.dtb \ sun7i-a20-m3.dtb \ sun7i-a20-mk808c.dtb \ sun7i-a20-olimex-som-evb.dtb \ diff --git a/arch/arm/boot/dts/sun7i-a20-linutronix-testbox-v2.dts b/arch/arm/boot/dts/sun7i-a20-linutronix-testbox-v2.dts new file mode 100644 index 000000000000..da5a2eea4ce3 --- /dev/null +++ b/arch/arm/boot/dts/sun7i-a20-linutronix-testbox-v2.dts @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2020 Linutronix GmbH + * Author: Benedikt Spranger + */ + +/dts-v1/; +#include "sun7i-a20-lamobo-r1.dts" + +/ { + model = "Lamobo R1"; + compatible = "linutronix,testbox-v2", "lamobo,lamobo-r1", "allwinner,sun7i-a20"; + + leds { + led-opto1 { + label = "lamobo_r1:opto:powerswitch"; + gpios = <&pio 7 3 GPIO_ACTIVE_HIGH>; + }; + + led-opto2 { + label = "lamobo_r1:opto:relay"; + gpios = <&pio 7 5 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&i2c2 { + clock-frequency = <100000>; + status = "okay"; + + eeprom: eeprom@50 { + compatible = "atmel,24c08"; + reg = <0x50>; + status = "okay"; + }; + + atecc508a@60 { + compatible = "atmel,atecc508a"; + reg = <0x60>; + }; +}; + +&can0 { + pinctrl-names = "default"; + pinctrl-0 = <&can_ph_pins>; + status = "okay"; +}; From ae0feb88430024938242cc657df48c0657e60bc3 Mon Sep 17 00:00:00 2001 From: Ley Foon Tan Date: Fri, 14 Feb 2020 02:00:27 +0800 Subject: [PATCH 0343/4444] ARM: dts: socfpga: arria10: Increase boot partition size for NAND Increase boot partition size to 32MB to support bigger size kernel image and FPGA bitstream. Signed-off-by: Ley Foon Tan Signed-off-by: Dinh Nguyen --- arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts b/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts index 9bd9e04c7361..9aa897b79544 100644 --- a/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts +++ b/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts @@ -16,11 +16,11 @@ partition@0 { label = "Boot and fpga data"; - reg = <0x0 0x1C00000>; + reg = <0x0 0x02000000>; }; partition@1c00000 { label = "Root Filesystem - JFFS2"; - reg = <0x1C00000 0x6400000>; + reg = <0x02000000 0x06000000>; }; }; }; From e9a0ef0b5ddcbc0d56c65aefc0f18d16e6f71207 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 14 Feb 2020 15:49:28 +0100 Subject: [PATCH 0344/4444] ALSA: usb-audio: Don't create a mixer element with bogus volume range Some USB-audio descriptors provide a bogus volume range (e.g. volume min and max are identical), which confuses user-space. This patch makes the driver skipping such a control element. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=206221 Link: https://lore.kernel.org/r/20200214144928.23628-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index d659fdb475e2..96e20488804d 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1666,6 +1666,16 @@ static void __build_feature_ctl(struct usb_mixer_interface *mixer, /* get min/max values */ get_min_max_with_quirks(cval, 0, kctl); + /* skip a bogus volume range */ + if (cval->max <= cval->min) { + usb_audio_dbg(mixer->chip, + "[%d] FU [%s] skipped due to invalid volume\n", + cval->head.id, kctl->id.name); + snd_ctl_free_one(kctl); + return; + } + + if (control == UAC_FU_VOLUME) { check_mapped_dB(map, cval); if (cval->dBmin < cval->dBmax || !cval->initialized) { From 4e0e6a626bf4c35e043b4d547e91447f06139d27 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 19 Jan 2020 10:30:58 -0600 Subject: [PATCH 0345/4444] arm64: dts: allwinner: pinebook: Remove unused AXP803 regulators The Pinebook does not use the CSI bus on the A64. In fact it does not use GPIO port E for anything at all. Thus the following regulators are not used and do not need voltages set: - ALDO1: Connected to VCC-PE only - DLDO3: Not connected - ELDO3: Not connected Signed-off-by: Samuel Holland Signed-off-by: Maxime Ripard --- .../boot/dts/allwinner/sun50i-a64-pinebook.dts | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts index c06c540e6c08..12e513ba8f50 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts @@ -217,9 +217,7 @@ }; ®_aldo1 { - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - regulator-name = "vcc-csi"; + regulator-name = "vcc-pe"; }; ®_aldo2 { @@ -282,12 +280,6 @@ regulator-name = "vcc-edp"; }; -®_dldo3 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-name = "avdd-csi"; -}; - ®_dldo4 { regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; @@ -301,12 +293,6 @@ regulator-name = "cpvdd"; }; -®_eldo3 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "vdd-1v8-csi"; -}; - ®_fldo1 { regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; From b2354e4009a773c00054b964d937e1b81cb92078 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 14 Feb 2020 14:47:04 +0100 Subject: [PATCH 0346/4444] ASoC: core: ensure component names are unique Make sure each ASoC component is registered with a unique name. The component is derived from the device name. If a device registers more than one component, the component names will be the same. This usually brings up a warning about the debugfs directory creation of the component since directory already exists. In such case, start numbering the component of the device so the names don't collide anymore. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200214134704.342501-1-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 03b87427faa7..6a58a8f6e3c4 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2446,6 +2446,33 @@ err: return ret; } +static char *snd_soc_component_unique_name(struct device *dev, + struct snd_soc_component *component) +{ + struct snd_soc_component *pos; + int count = 0; + char *name, *unique; + + name = fmt_single_name(dev, &component->id); + if (!name) + return name; + + /* Count the number of components registred by the device */ + for_each_component(pos) { + if (dev == pos->dev) + count++; + } + + /* Keep naming as it is for the 1st component */ + if (!count) + return name; + + unique = devm_kasprintf(dev, GFP_KERNEL, "%s-%d", name, count); + devm_kfree(dev, name); + + return unique; +} + static int snd_soc_component_initialize(struct snd_soc_component *component, const struct snd_soc_component_driver *driver, struct device *dev) { @@ -2454,7 +2481,7 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, INIT_LIST_HEAD(&component->card_list); mutex_init(&component->io_mutex); - component->name = fmt_single_name(dev, &component->id); + component->name = snd_soc_component_unique_name(dev, component); if (!component->name) { dev_err(dev, "ASoC: Failed to allocate name\n"); return -ENOMEM; From 1031eb90c17700d1fd1df6d720afbadcd5768b11 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 11 Feb 2020 16:29:41 -0600 Subject: [PATCH 0347/4444] char: virtio: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertenly introduced[3] to the codebase from now on. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200211222941.GA7657@embeddedor Signed-off-by: Greg Kroah-Hartman --- drivers/char/virtio_console.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 4df9b40d6342..3cbaec925606 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -112,7 +112,7 @@ struct port_buffer { unsigned int sgpages; /* sg is used if spages > 0. sg must be the last in is struct */ - struct scatterlist sg[0]; + struct scatterlist sg[]; }; /* From 06e33595e96f212811066df192ae8bf802174296 Mon Sep 17 00:00:00 2001 From: Huang Zijiang Date: Wed, 12 Feb 2020 17:54:07 +0800 Subject: [PATCH 0348/4444] misc: Use kzalloc() instead of kmalloc() with flag GFP_ZERO. Use kzalloc instead of manually setting kmalloc with flag GFP_ZERO since kzalloc sets allocated memory to zero. Signed-off-by: Huang Zijiang Signed-off-by: Yi Wang Link: https://lore.kernel.org/r/1581501247-5479-1-git-send-email-wang.yi59@zte.com.cn Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/host/mic_boot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c index 4f2d9212432c..fb5b3989753d 100644 --- a/drivers/misc/mic/host/mic_boot.c +++ b/drivers/misc/mic/host/mic_boot.c @@ -137,7 +137,7 @@ static void *__mic_dma_alloc(struct device *dev, size_t size, struct scif_hw_dev *scdev = dev_get_drvdata(dev); struct mic_device *mdev = scdev_to_mdev(scdev); dma_addr_t tmp; - void *va = kmalloc(size, gfp | __GFP_ZERO); + void *va = kzalloc(size, gfp); if (va) { tmp = mic_map_single(mdev, va, size); From 146f66975bafbcfab349901c9f9c9f521ac96cbb Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 14 Feb 2020 18:16:43 +0100 Subject: [PATCH 0349/4444] ALSA: pcm: oss: Unlock mutex temporarily for sleeping at read/write ALSA PCM OSS layer calls the generic __snd_pcm_lib_xfer() helper for the actual transfer of the audio data. The xfer helper may sleep long for waiting for the enough space becoming empty for read/write, and it does unlock/relock for the substream lock. This works fine, so far, but a slight problem specific to OSS layer is that OSS layer wraps yet more mutex (runtime->oss.params_lock) over __snd_pcm_lib_xfer() call; so this mutex is still locked during a possible long sleep, and it prevents the whole ioctl and other actions applied to the given stream. This patch adds the temporarily unlock and relock of the mutex around __snd_pcm_lib_xfer() call in the OSS layer to be more friendly to the concurrent accesses. The long mutex protection itself shouldn't be a real issue for the normal systems, and its influence appears only on strange things like fuzzers. Link: https://lore.kernel.org/r/20200214171643.26212-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/oss/pcm_oss.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 707eb2a9d50c..930def8201f4 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1217,8 +1217,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const if (ret < 0) break; } + mutex_unlock(&runtime->oss.params_lock); ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true, frames, in_kernel); + mutex_lock(&runtime->oss.params_lock); if (ret != -EPIPE && ret != -ESTRPIPE) break; /* test, if we can't store new data, because the stream */ @@ -1254,8 +1256,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p ret = snd_pcm_oss_capture_position_fixup(substream, &delay); if (ret < 0) break; + mutex_unlock(&runtime->oss.params_lock); ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true, frames, in_kernel); + mutex_lock(&runtime->oss.params_lock); if (ret == -EPIPE) { if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); From fe98d0ff5d5c43ee179e801275bb37641d398c6e Mon Sep 17 00:00:00 2001 From: Jianxin Pan Date: Wed, 15 Jan 2020 19:30:28 +0800 Subject: [PATCH 0350/4444] firmware: meson_sm: Add secure power domain support The Amlogic Meson A1/C1 Secure Monitor implements calls to control power domain. Signed-off-by: Jianxin Pan Signed-off-by: Kevin Hilman Link: https://lore.kernel.org/r/1579087831-94965-2-git-send-email-jianxin.pan@amlogic.com --- drivers/firmware/meson/meson_sm.c | 2 ++ include/linux/firmware/meson/meson_sm.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/firmware/meson/meson_sm.c b/drivers/firmware/meson/meson_sm.c index 1d5b4d74f96d..2854b56f6e0b 100644 --- a/drivers/firmware/meson/meson_sm.c +++ b/drivers/firmware/meson/meson_sm.c @@ -44,6 +44,8 @@ static const struct meson_sm_chip gxbb_chip = { CMD(SM_EFUSE_WRITE, 0x82000031), CMD(SM_EFUSE_USER_MAX, 0x82000033), CMD(SM_GET_CHIP_ID, 0x82000044), + CMD(SM_A1_PWRC_SET, 0x82000093), + CMD(SM_A1_PWRC_GET, 0x82000095), { /* sentinel */ }, }, }; diff --git a/include/linux/firmware/meson/meson_sm.h b/include/linux/firmware/meson/meson_sm.h index 6669e2a1d5fd..95b0da2326a9 100644 --- a/include/linux/firmware/meson/meson_sm.h +++ b/include/linux/firmware/meson/meson_sm.h @@ -12,6 +12,8 @@ enum { SM_EFUSE_WRITE, SM_EFUSE_USER_MAX, SM_GET_CHIP_ID, + SM_A1_PWRC_SET, + SM_A1_PWRC_GET, }; struct meson_sm_firmware; From 165b5fb294e878f00015b7beb91cb00e36e4f8b8 Mon Sep 17 00:00:00 2001 From: Jianxin Pan Date: Wed, 15 Jan 2020 19:30:29 +0800 Subject: [PATCH 0351/4444] dt-bindings: power: add Amlogic secure power domains bindings Add the bindings for the Amlogic Secure power domains, controlling the secure power domains. The bindings targets the Amlogic A1 and C1 compatible SoCs, in which the power domain registers are in secure world. Signed-off-by: Jianxin Pan Signed-off-by: Kevin Hilman Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/1579087831-94965-3-git-send-email-jianxin.pan@amlogic.com --- .../power/amlogic,meson-sec-pwrc.yaml | 40 +++++++++++++++++++ include/dt-bindings/power/meson-a1-power.h | 32 +++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml create mode 100644 include/dt-bindings/power/meson-a1-power.h diff --git a/Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml b/Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml new file mode 100644 index 000000000000..af32209218bb --- /dev/null +++ b/Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: (GPL-2.0+ OR MIT) +# Copyright (c) 2019 Amlogic, Inc +# Author: Jianxin Pan +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/power/amlogic,meson-sec-pwrc.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Amlogic Meson Secure Power Domains + +maintainers: + - Jianxin Pan + +description: |+ + Secure Power Domains used in Meson A1/C1 SoCs, and should be the child node + of secure-monitor. + +properties: + compatible: + enum: + - amlogic,meson-a1-pwrc + + "#power-domain-cells": + const: 1 + +required: + - compatible + - "#power-domain-cells" + +examples: + - | + secure-monitor { + compatible = "amlogic,meson-gxbb-sm"; + + pwrc: power-controller { + compatible = "amlogic,meson-a1-pwrc"; + #power-domain-cells = <1>; + }; + } + diff --git a/include/dt-bindings/power/meson-a1-power.h b/include/dt-bindings/power/meson-a1-power.h new file mode 100644 index 000000000000..6cf50bfb8ccf --- /dev/null +++ b/include/dt-bindings/power/meson-a1-power.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */ +/* + * Copyright (c) 2019 Amlogic, Inc. + * Author: Jianxin Pan + */ + +#ifndef _DT_BINDINGS_MESON_A1_POWER_H +#define _DT_BINDINGS_MESON_A1_POWER_H + +#define PWRC_DSPA_ID 8 +#define PWRC_DSPB_ID 9 +#define PWRC_UART_ID 10 +#define PWRC_DMC_ID 11 +#define PWRC_I2C_ID 12 +#define PWRC_PSRAM_ID 13 +#define PWRC_ACODEC_ID 14 +#define PWRC_AUDIO_ID 15 +#define PWRC_OTP_ID 16 +#define PWRC_DMA_ID 17 +#define PWRC_SD_EMMC_ID 18 +#define PWRC_RAMA_ID 19 +#define PWRC_RAMB_ID 20 +#define PWRC_IR_ID 21 +#define PWRC_SPICC_ID 22 +#define PWRC_SPIFC_ID 23 +#define PWRC_USB_ID 24 +#define PWRC_NIC_ID 25 +#define PWRC_PDMIN_ID 26 +#define PWRC_RSA_ID 27 +#define PWRC_MAX_ID 28 + +#endif From b3dde5013e13d44799b3477cd0bf0c9ad34fe5e9 Mon Sep 17 00:00:00 2001 From: Jianxin Pan Date: Wed, 15 Jan 2020 19:30:30 +0800 Subject: [PATCH 0352/4444] soc: amlogic: Add support for Secure power domains controller Add support for the Amlogic Secure Power controller. In A1/C1 series, power control registers are in secure domain, and should be accessed by smc. Signed-off-by: Jianxin Pan Signed-off-by: Kevin Hilman Link: https://lore.kernel.org/r/1579087831-94965-4-git-send-email-jianxin.pan@amlogic.com --- drivers/soc/amlogic/Kconfig | 13 ++ drivers/soc/amlogic/Makefile | 1 + drivers/soc/amlogic/meson-secure-pwrc.c | 204 ++++++++++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100644 drivers/soc/amlogic/meson-secure-pwrc.c diff --git a/drivers/soc/amlogic/Kconfig b/drivers/soc/amlogic/Kconfig index bc2c912949bd..6cb06e7b5e63 100644 --- a/drivers/soc/amlogic/Kconfig +++ b/drivers/soc/amlogic/Kconfig @@ -48,6 +48,19 @@ config MESON_EE_PM_DOMAINS Say yes to expose Amlogic Meson Everything-Else Power Domains as Generic Power Domains. +config MESON_SECURE_PM_DOMAINS + bool "Amlogic Meson Secure Power Domains driver" + depends on ARCH_MESON || COMPILE_TEST + depends on PM && OF + depends on HAVE_ARM_SMCCC + default ARCH_MESON + select PM_GENERIC_DOMAINS + select PM_GENERIC_DOMAINS_OF + help + Support for the power controller on Amlogic A1/C1 series. + Say yes to expose Amlogic Meson Secure Power Domains as Generic + Power Domains. + config MESON_MX_SOCINFO bool "Amlogic Meson MX SoC Information driver" depends on ARCH_MESON || COMPILE_TEST diff --git a/drivers/soc/amlogic/Makefile b/drivers/soc/amlogic/Makefile index de79d044b545..7b8c5d323f5c 100644 --- a/drivers/soc/amlogic/Makefile +++ b/drivers/soc/amlogic/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o obj-$(CONFIG_MESON_MX_SOCINFO) += meson-mx-socinfo.o obj-$(CONFIG_MESON_EE_PM_DOMAINS) += meson-ee-pwrc.o +obj-$(CONFIG_MESON_SECURE_PM_DOMAINS) += meson-secure-pwrc.o diff --git a/drivers/soc/amlogic/meson-secure-pwrc.c b/drivers/soc/amlogic/meson-secure-pwrc.c new file mode 100644 index 000000000000..5fb29a475879 --- /dev/null +++ b/drivers/soc/amlogic/meson-secure-pwrc.c @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Amlogic, Inc. + * Author: Jianxin Pan + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include + +#define PWRC_ON 1 +#define PWRC_OFF 0 + +struct meson_secure_pwrc_domain { + struct generic_pm_domain base; + unsigned int index; + struct meson_secure_pwrc *pwrc; +}; + +struct meson_secure_pwrc { + struct meson_secure_pwrc_domain *domains; + struct genpd_onecell_data xlate; + struct meson_sm_firmware *fw; +}; + +struct meson_secure_pwrc_domain_desc { + unsigned int index; + unsigned int flags; + char *name; + bool (*is_off)(struct meson_secure_pwrc_domain *pwrc_domain); +}; + +struct meson_secure_pwrc_domain_data { + unsigned int count; + struct meson_secure_pwrc_domain_desc *domains; +}; + +static bool pwrc_secure_is_off(struct meson_secure_pwrc_domain *pwrc_domain) +{ + int is_off = 1; + + if (meson_sm_call(pwrc_domain->pwrc->fw, SM_A1_PWRC_GET, &is_off, + pwrc_domain->index, 0, 0, 0, 0) < 0) + pr_err("failed to get power domain status\n"); + + return is_off; +} + +static int meson_secure_pwrc_off(struct generic_pm_domain *domain) +{ + int ret = 0; + struct meson_secure_pwrc_domain *pwrc_domain = + container_of(domain, struct meson_secure_pwrc_domain, base); + + if (meson_sm_call(pwrc_domain->pwrc->fw, SM_A1_PWRC_SET, NULL, + pwrc_domain->index, PWRC_OFF, 0, 0, 0) < 0) { + pr_err("failed to set power domain off\n"); + ret = -EINVAL; + } + + return ret; +} + +static int meson_secure_pwrc_on(struct generic_pm_domain *domain) +{ + int ret = 0; + struct meson_secure_pwrc_domain *pwrc_domain = + container_of(domain, struct meson_secure_pwrc_domain, base); + + if (meson_sm_call(pwrc_domain->pwrc->fw, SM_A1_PWRC_SET, NULL, + pwrc_domain->index, PWRC_ON, 0, 0, 0) < 0) { + pr_err("failed to set power domain on\n"); + ret = -EINVAL; + } + + return ret; +} + +#define SEC_PD(__name, __flag) \ +[PWRC_##__name##_ID] = \ +{ \ + .name = #__name, \ + .index = PWRC_##__name##_ID, \ + .is_off = pwrc_secure_is_off, \ + .flags = __flag, \ +} + +static struct meson_secure_pwrc_domain_desc a1_pwrc_domains[] = { + SEC_PD(DSPA, 0), + SEC_PD(DSPB, 0), + /* UART should keep working in ATF after suspend and before resume */ + SEC_PD(UART, GENPD_FLAG_ALWAYS_ON), + /* DMC is for DDR PHY ana/dig and DMC, and should be always on */ + SEC_PD(DMC, GENPD_FLAG_ALWAYS_ON), + SEC_PD(I2C, 0), + SEC_PD(PSRAM, 0), + SEC_PD(ACODEC, 0), + SEC_PD(AUDIO, 0), + SEC_PD(OTP, 0), + SEC_PD(DMA, 0), + SEC_PD(SD_EMMC, 0), + SEC_PD(RAMA, 0), + /* SRAMB is used as ATF runtime memory, and should be always on */ + SEC_PD(RAMB, GENPD_FLAG_ALWAYS_ON), + SEC_PD(IR, 0), + SEC_PD(SPICC, 0), + SEC_PD(SPIFC, 0), + SEC_PD(USB, 0), + /* NIC is for the Arm NIC-400 interconnect, and should be always on */ + SEC_PD(NIC, GENPD_FLAG_ALWAYS_ON), + SEC_PD(PDMIN, 0), + SEC_PD(RSA, 0), +}; + +static int meson_secure_pwrc_probe(struct platform_device *pdev) +{ + int i; + struct device_node *sm_np; + struct meson_secure_pwrc *pwrc; + const struct meson_secure_pwrc_domain_data *match; + + match = of_device_get_match_data(&pdev->dev); + if (!match) { + dev_err(&pdev->dev, "failed to get match data\n"); + return -ENODEV; + } + + sm_np = of_find_compatible_node(NULL, NULL, "amlogic,meson-gxbb-sm"); + if (!sm_np) { + dev_err(&pdev->dev, "no secure-monitor node\n"); + return -ENODEV; + } + + pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL); + if (!pwrc) + return -ENOMEM; + + pwrc->fw = meson_sm_get(sm_np); + of_node_put(sm_np); + if (!pwrc->fw) + return -EPROBE_DEFER; + + pwrc->xlate.domains = devm_kcalloc(&pdev->dev, match->count, + sizeof(*pwrc->xlate.domains), + GFP_KERNEL); + if (!pwrc->xlate.domains) + return -ENOMEM; + + pwrc->domains = devm_kcalloc(&pdev->dev, match->count, + sizeof(*pwrc->domains), GFP_KERNEL); + if (!pwrc->domains) + return -ENOMEM; + + pwrc->xlate.num_domains = match->count; + platform_set_drvdata(pdev, pwrc); + + for (i = 0 ; i < match->count ; ++i) { + struct meson_secure_pwrc_domain *dom = &pwrc->domains[i]; + + if (!match->domains[i].index) + continue; + + dom->pwrc = pwrc; + dom->index = match->domains[i].index; + dom->base.name = match->domains[i].name; + dom->base.flags = match->domains[i].flags; + dom->base.power_on = meson_secure_pwrc_on; + dom->base.power_off = meson_secure_pwrc_off; + + pm_genpd_init(&dom->base, NULL, match->domains[i].is_off(dom)); + + pwrc->xlate.domains[i] = &dom->base; + } + + return of_genpd_add_provider_onecell(pdev->dev.of_node, &pwrc->xlate); +} + +static struct meson_secure_pwrc_domain_data meson_secure_a1_pwrc_data = { + .domains = a1_pwrc_domains, + .count = ARRAY_SIZE(a1_pwrc_domains), +}; + +static const struct of_device_id meson_secure_pwrc_match_table[] = { + { + .compatible = "amlogic,meson-a1-pwrc", + .data = &meson_secure_a1_pwrc_data, + }, + { /* sentinel */ } +}; + +static struct platform_driver meson_secure_pwrc_driver = { + .probe = meson_secure_pwrc_probe, + .driver = { + .name = "meson_secure_pwrc", + .of_match_table = meson_secure_pwrc_match_table, + }, +}; +builtin_platform_driver(meson_secure_pwrc_driver); From 04dd0b6584cd0f40540b51e45e92771b334d2725 Mon Sep 17 00:00:00 2001 From: Jianxin Pan Date: Wed, 15 Jan 2020 19:30:31 +0800 Subject: [PATCH 0353/4444] arm64: dts: meson: a1: add secure power domain controller Enable power domain controller for Meson A1 SoC. Signed-off-by: Jianxin Pan Link: https://lore.kernel.org/r/1579087831-94965-5-git-send-email-jianxin.pan@amlogic.com Signed-off-by: Kevin Hilman --- arch/arm64/boot/dts/amlogic/meson-a1.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi index 4dec518c4dde..755b4ad15184 100644 --- a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi @@ -60,6 +60,12 @@ sm: secure-monitor { compatible = "amlogic,meson-gxbb-sm"; + + pwrc: power-controller { + compatible = "amlogic,meson-a1-pwrc"; + #power-domain-cells = <1>; + status = "okay"; + }; }; soc { From e252d2937e6c9ea6b259a960624e27a46686b4e3 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 13 Feb 2020 17:18:59 -0600 Subject: [PATCH 0354/4444] microblaze: Drop using struct of_pci_range.pci_space field Let's use the struct of_pci_range.flags field instead so we can remove the pci_space field. Just drop the debug prints as there's plenty of debug output in drivers/of/address.c which can be enabled. Cc: Michal Simek Signed-off-by: Rob Herring --- arch/microblaze/pci/pci-common.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index 58cc4965bd3e..60a58c0015f2 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c @@ -433,10 +433,6 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose, pr_debug("Parsing ranges property...\n"); for_each_of_pci_range(&parser, &range) { /* Read next ranges element */ - pr_debug("pci_space: 0x%08x pci_addr:0x%016llx ", - range.pci_space, range.pci_addr); - pr_debug("cpu_addr:0x%016llx size:0x%016llx\n", - range.cpu_addr, range.size); /* If we failed translation or got a zero-sized region * (some FW try to feed us with non sensical zero sized regions @@ -486,7 +482,7 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose, pr_info(" MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n", range.cpu_addr, range.cpu_addr + range.size - 1, range.pci_addr, - (range.pci_space & 0x40000000) ? + (range.flags & IORESOURCE_PREFETCH) ? "Prefetch" : ""); /* We support only 3 memory ranges */ @@ -1121,4 +1117,3 @@ int early_find_capability(struct pci_controller *hose, int bus, int devfn, { return pci_bus_find_capability(fake_pci_bus(hose, bus), devfn, cap); } - From 6a9166b5beb82bbfcf86b9215785c6b74a4608ff Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 13 Feb 2020 17:19:19 -0600 Subject: [PATCH 0355/4444] powerpc: Drop using struct of_pci_range.pci_space field Let's use the struct of_pci_range.flags field instead so we can remove the pci_space field. Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Rob Herring --- arch/powerpc/kernel/pci-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index c6c03416a151..d0074ad73aa3 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -728,7 +728,7 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose, " MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n", range.cpu_addr, range.cpu_addr + range.size - 1, range.pci_addr, - (range.pci_space & 0x40000000) ? + (range.flags & IORESOURCE_PREFETCH) ? "Prefetch" : ""); /* We support only 3 memory ranges */ From c67f3df88ffca45531a12214e8faffbdab1fa422 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 13 Feb 2020 17:20:20 -0600 Subject: [PATCH 0356/4444] of: Drop struct of_pci_range.pci_space field There's no more users of struct of_pci_range.pci_space field, so remove it. Signed-off-by: Rob Herring --- drivers/of/address.c | 1 - include/linux/of_address.h | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/of/address.c b/drivers/of/address.c index 846045a48395..5d608d7c10d6 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -736,7 +736,6 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, if (!parser->range || parser->range + parser->np > parser->end) return NULL; - range->pci_space = be32_to_cpup(parser->range); range->flags = of_bus_pci_get_flags(parser->range); range->pci_addr = of_read_number(parser->range + 1, ns); if (parser->dma) diff --git a/include/linux/of_address.h b/include/linux/of_address.h index eac7ab109df4..8d12bf18e80b 100644 --- a/include/linux/of_address.h +++ b/include/linux/of_address.h @@ -16,7 +16,6 @@ struct of_pci_range_parser { }; struct of_pci_range { - u32 pci_space; u64 pci_addr; u64 cpu_addr; u64 size; From bc5e522ec47174770a75df0a76d90f9ebb20132e Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 6 Feb 2020 14:01:05 +0000 Subject: [PATCH 0357/4444] of/address: Rework of_pci_range parsing for non-PCI buses The only PCI specific part of of_pci_range_parser_one() is the handling of the 3rd address cell. Rework it to work on regular 1 and 2 cell addresses. Use defines and a union to avoid a treewide renaming of the parsing helpers and struct. Signed-off-by: Rob Herring --- drivers/of/address.c | 33 +++++++++++++++++++++------------ include/linux/of_address.h | 12 +++++++++--- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/drivers/of/address.c b/drivers/of/address.c index 5d608d7c10d6..6d33f849f114 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -694,12 +694,12 @@ EXPORT_SYMBOL(of_get_address); static int parser_init(struct of_pci_range_parser *parser, struct device_node *node, const char *name) { - const int na = 3, ns = 2; int rlen; parser->node = node; parser->pna = of_n_addr_cells(node); - parser->np = parser->pna + na + ns; + parser->na = of_bus_n_addr_cells(node); + parser->ns = of_bus_n_size_cells(node); parser->dma = !strcmp(name, "dma-ranges"); parser->range = of_get_property(node, name, &rlen); @@ -724,20 +724,28 @@ int of_pci_dma_range_parser_init(struct of_pci_range_parser *parser, return parser_init(parser, node, "dma-ranges"); } EXPORT_SYMBOL_GPL(of_pci_dma_range_parser_init); +#define of_dma_range_parser_init of_pci_dma_range_parser_init struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, struct of_pci_range *range) { - const int na = 3, ns = 2; + int na = parser->na; + int ns = parser->ns; + int np = parser->pna + na + ns; if (!range) return NULL; - if (!parser->range || parser->range + parser->np > parser->end) + if (!parser->range || parser->range + np > parser->end) return NULL; - range->flags = of_bus_pci_get_flags(parser->range); - range->pci_addr = of_read_number(parser->range + 1, ns); + if (parser->na == 3) + range->flags = of_bus_pci_get_flags(parser->range); + else + range->flags = 0; + + range->pci_addr = of_read_number(parser->range, na); + if (parser->dma) range->cpu_addr = of_translate_dma_address(parser->node, parser->range + na); @@ -746,15 +754,16 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, parser->range + na); range->size = of_read_number(parser->range + parser->pna + na, ns); - parser->range += parser->np; + parser->range += np; /* Now consume following elements while they are contiguous */ - while (parser->range + parser->np <= parser->end) { - u32 flags; + while (parser->range + np <= parser->end) { + u32 flags = 0; u64 pci_addr, cpu_addr, size; - flags = of_bus_pci_get_flags(parser->range); - pci_addr = of_read_number(parser->range + 1, ns); + if (parser->na == 3) + flags = of_bus_pci_get_flags(parser->range); + pci_addr = of_read_number(parser->range, na); if (parser->dma) cpu_addr = of_translate_dma_address(parser->node, parser->range + na); @@ -770,7 +779,7 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, break; range->size += size; - parser->range += parser->np; + parser->range += np; } return range; diff --git a/include/linux/of_address.h b/include/linux/of_address.h index 8d12bf18e80b..763022ed3456 100644 --- a/include/linux/of_address.h +++ b/include/linux/of_address.h @@ -10,20 +10,27 @@ struct of_pci_range_parser { struct device_node *node; const __be32 *range; const __be32 *end; - int np; + int na; + int ns; int pna; bool dma; }; +#define of_range_parser of_pci_range_parser struct of_pci_range { - u64 pci_addr; + union { + u64 pci_addr; + u64 bus_addr; + }; u64 cpu_addr; u64 size; u32 flags; }; +#define of_range of_pci_range #define for_each_of_pci_range(parser, range) \ for (; of_pci_range_parser_one(parser, range);) +#define for_each_of_range for_each_of_pci_range /* Translate a DMA address from device space to CPU space */ extern u64 of_translate_dma_address(struct device_node *dev, @@ -142,4 +149,3 @@ static inline int of_pci_range_to_resource(struct of_pci_range *range, #endif /* CONFIG_OF_ADDRESS && CONFIG_PCI */ #endif /* __OF_ADDRESS_H */ - From 51c366e38aaa6b298ba1e6ceef0f2c3de1180b29 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 14 Feb 2020 14:13:46 +0100 Subject: [PATCH 0358/4444] ASoC: meson: aiu: remove unused encoder structure Remove an unused structure definition which slipped through the initial driver submission. Fixes: 6ae9ca9ce986 ("ASoC: meson: aiu: add i2s and spdif support") Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200214131350.337968-2-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/aiu-encoder-i2s.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encoder-i2s.c index 13bf029086a9..4900e38e7e49 100644 --- a/sound/soc/meson/aiu-encoder-i2s.c +++ b/sound/soc/meson/aiu-encoder-i2s.c @@ -28,13 +28,6 @@ #define AIU_CLK_CTRL_MORE_I2S_DIV GENMASK(5, 0) #define AIU_CODEC_DAC_LRCLK_CTRL_DIV GENMASK(11, 0) -struct aiu_encoder_i2s { - struct clk *aoclk; - struct clk *mclk; - struct clk *mixer; - struct clk *pclk; -}; - static void aiu_encoder_i2s_divider_enable(struct snd_soc_component *component, bool enable) { From 269f00171273e47eebc915cc6ee8ceececa37a3a Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 14 Feb 2020 14:13:47 +0100 Subject: [PATCH 0359/4444] ASoC: meson: aiu: fix clk bulk size allocation Fix the size of allocated memory for the clock bulk data Fixes: 6ae9ca9ce986 ("ASoC: meson: aiu: add i2s and spdif support") Reported-by: kbuild test robot Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200214131350.337968-3-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/aiu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/meson/aiu.c b/sound/soc/meson/aiu.c index 5c4845a23a34..de678a9d5cab 100644 --- a/sound/soc/meson/aiu.c +++ b/sound/soc/meson/aiu.c @@ -203,7 +203,7 @@ static int aiu_clk_bulk_get(struct device *dev, struct clk_bulk_data *clks; int i, ret; - clks = devm_kcalloc(dev, num, sizeof(clks), GFP_KERNEL); + clks = devm_kcalloc(dev, num, sizeof(*clks), GFP_KERNEL); if (!clks) return -ENOMEM; From 6e700f0672199f773ad645c2b7e886c1d2e2046e Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 14 Feb 2020 14:13:48 +0100 Subject: [PATCH 0360/4444] ASoC: meson: aiu: fix irq registration The aiu stored the irq in an unsigned integer which may have discarded an error returned by platform_get_irq_byname(). This is incorrect and should have been a signed integer. Also drop the irq error traces from the probe function as this is already done by platform_get_irq_byname(). Fixes: 6ae9ca9ce986 ("ASoC: meson: aiu: add i2s and spdif support") Reported-by: kbuild test robot Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200214131350.337968-4-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/aiu.c | 8 ++------ sound/soc/meson/aiu.h | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/sound/soc/meson/aiu.c b/sound/soc/meson/aiu.c index de678a9d5cab..34b40b8b8299 100644 --- a/sound/soc/meson/aiu.c +++ b/sound/soc/meson/aiu.c @@ -314,16 +314,12 @@ static int aiu_probe(struct platform_device *pdev) } aiu->i2s.irq = platform_get_irq_byname(pdev, "i2s"); - if (aiu->i2s.irq < 0) { - dev_err(dev, "Can't get i2s irq\n"); + if (aiu->i2s.irq < 0) return aiu->i2s.irq; - } aiu->spdif.irq = platform_get_irq_byname(pdev, "spdif"); - if (aiu->spdif.irq < 0) { - dev_err(dev, "Can't get spdif irq\n"); + if (aiu->spdif.irq < 0) return aiu->spdif.irq; - } ret = aiu_clk_get(dev); if (ret) diff --git a/sound/soc/meson/aiu.h b/sound/soc/meson/aiu.h index a65a576e3400..097c26de7b7c 100644 --- a/sound/soc/meson/aiu.h +++ b/sound/soc/meson/aiu.h @@ -26,7 +26,7 @@ enum aiu_clk_ids { struct aiu_interface { struct clk_bulk_data *clks; unsigned int clk_num; - unsigned int irq; + int irq; }; struct aiu { From 74a56f2a4a9ec72ef1daceeb2dda8b41370c1419 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 14 Feb 2020 14:13:49 +0100 Subject: [PATCH 0361/4444] ASoC: meson: aiu: fix acodec dai input name init Remove the double initialization of the dai input name as reported by sparse. Fixes: 65816025d461 ("ASoC: meson: aiu: add internal dac codec control support") Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200214131350.337968-5-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/aiu-acodec-ctrl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/meson/aiu-acodec-ctrl.c b/sound/soc/meson/aiu-acodec-ctrl.c index 12d8a4d351a1..b8e88b1a4fc8 100644 --- a/sound/soc/meson/aiu-acodec-ctrl.c +++ b/sound/soc/meson/aiu-acodec-ctrl.c @@ -128,7 +128,6 @@ static const struct snd_soc_dai_ops aiu_acodec_ctrl_output_ops = { #define AIU_ACODEC_INPUT(xname) { \ .name = "ACODEC CTRL " xname, \ - .name = xname, \ .playback = AIU_ACODEC_STREAM(xname, "Playback", 8), \ .ops = &aiu_acodec_ctrl_input_ops, \ .probe = meson_codec_glue_input_dai_probe, \ From 3cd23f021e2e5f3350125abcb39f12430df87d06 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 14 Feb 2020 14:13:50 +0100 Subject: [PATCH 0362/4444] ASoC: meson: codec-glue: fix pcm format cast warning Clarify the cast of snd_pcm_format_t and fix the sparse warning: restricted snd_pcm_format_t degrades to integer Fixes: 9c29fd9bdf92 ("ASoC: meson: g12a: extract codec-to-codec utils") Reported-by: kbuild test robot Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200214131350.337968-6-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/meson-codec-glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/meson/meson-codec-glue.c b/sound/soc/meson/meson-codec-glue.c index 97bbc967e176..524a33472337 100644 --- a/sound/soc/meson/meson-codec-glue.c +++ b/sound/soc/meson/meson-codec-glue.c @@ -74,7 +74,7 @@ int meson_codec_glue_input_hw_params(struct snd_pcm_substream *substream, data->params.rates = snd_pcm_rate_to_rate_bit(params_rate(params)); data->params.rate_min = params_rate(params); data->params.rate_max = params_rate(params); - data->params.formats = 1 << params_format(params); + data->params.formats = 1ULL << (__force int) params_format(params); data->params.channels_min = params_channels(params); data->params.channels_max = params_channels(params); data->params.sig_bits = dai->driver->playback.sig_bits; From 7a8b64d17e35810dc3176fe61208b45c15d25402 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 6 Feb 2020 14:02:30 +0000 Subject: [PATCH 0363/4444] of/address: use range parser for of_dma_get_range of_dma_get_range() does the same ranges parsing as of_pci_range_parser_one(), so let's refactor of_dma_get_range() to use it instead. This commit is no functional change. Subsequent commits will parse more than the 1st dma-ranges entry. Signed-off-by: Rob Herring --- drivers/of/address.c | 40 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/drivers/of/address.c b/drivers/of/address.c index 6d33f849f114..a2c45812a50e 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -939,10 +939,11 @@ int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *siz { struct device_node *node = of_node_get(np); const __be32 *ranges = NULL; - int len, naddr, nsize, pna; + int len; int ret = 0; bool found_dma_ranges = false; - u64 dmaaddr; + struct of_range_parser parser; + struct of_range range; while (node) { ranges = of_get_property(node, "dma-ranges", &len); @@ -967,33 +968,20 @@ int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *siz goto out; } - naddr = of_bus_n_addr_cells(node); - nsize = of_bus_n_size_cells(node); - pna = of_n_addr_cells(node); - if ((len / sizeof(__be32)) % (pna + naddr + nsize)) { - ret = -EINVAL; + of_dma_range_parser_init(&parser, node); + + for_each_of_range(&parser, &range) { + pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n", + range.bus_addr, range.cpu_addr, range.size); + + *dma_addr = range.bus_addr; + *paddr = range.cpu_addr; + *size = range.size; + goto out; } - /* dma-ranges format: - * DMA addr : naddr cells - * CPU addr : pna cells - * size : nsize cells - */ - dmaaddr = of_read_number(ranges, naddr); - *paddr = of_translate_dma_address(node, ranges + naddr); - if (*paddr == OF_BAD_ADDR) { - pr_err("translation of DMA address(%llx) to CPU address failed node(%pOF)\n", - dmaaddr, np); - ret = -EINVAL; - goto out; - } - *dma_addr = dmaaddr; - - *size = of_read_number(ranges + naddr + pna, nsize); - - pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n", - *dma_addr, *paddr, *size); + pr_err("translation of DMA ranges failed on node(%pOF)\n", np); out: of_node_put(node); From 9d55bebd9816903b821a403a69a94190442ac043 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 6 Feb 2020 14:26:40 +0000 Subject: [PATCH 0364/4444] of/address: Support multiple 'dma-ranges' entries Currently, the DMA offset and mask for a device are set based only on the first 'dma-ranges' entry. We should really be using all the entries. The kernel doesn't yet support multiple offsets and sizes, so the best we can do is to find the biggest size for a single offset. The algorithm is copied from acpi_dma_get_range(). If there's different offsets from the first entry, then we warn and continue. It really should be an error, but this will likely break existing DTs. Signed-off-by: Rob Herring --- drivers/of/address.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/of/address.c b/drivers/of/address.c index a2c45812a50e..8eea3f6e29a4 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -944,6 +944,7 @@ int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *siz bool found_dma_ranges = false; struct of_range_parser parser; struct of_range range; + u64 dma_start = U64_MAX, dma_end = 0, dma_offset = 0; while (node) { ranges = of_get_property(node, "dma-ranges", &len); @@ -974,14 +975,33 @@ int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *siz pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n", range.bus_addr, range.cpu_addr, range.size); - *dma_addr = range.bus_addr; - *paddr = range.cpu_addr; - *size = range.size; + if (dma_offset && range.cpu_addr - range.bus_addr != dma_offset) { + pr_warn("Can't handle multiple dma-ranges with different offsets on node(%pOF)\n", node); + /* Don't error out as we'd break some existing DTs */ + continue; + } + dma_offset = range.cpu_addr - range.bus_addr; + /* Take lower and upper limits */ + if (range.bus_addr < dma_start) + dma_start = range.bus_addr; + if (range.bus_addr + range.size > dma_end) + dma_end = range.bus_addr + range.size; + } + + if (dma_start >= dma_end) { + ret = -EINVAL; + pr_debug("Invalid DMA ranges configuration on node(%pOF)\n", + node); goto out; } - pr_err("translation of DMA ranges failed on node(%pOF)\n", np); + *dma_addr = dma_start; + *size = dma_end - dma_start; + *paddr = dma_start + dma_offset; + + pr_debug("final: dma_addr(%llx) cpu_addr(%llx) size(%llx)\n", + *dma_addr, *paddr, *size); out: of_node_put(node); From 8dc5efe3d17cd572328ac4f1ebde629c83317f54 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sat, 15 Feb 2020 03:23:35 +0200 Subject: [PATCH 0365/4444] ALSA: usb-audio: Add support for Presonus Studio 1810c This patch adds support for Presonus Studio 1810c, a usb interface that's UAC2 compliant with a few quirks and a few extra hw-specific controls. I've tested all 3 altsettings and the added switch controls and they work as expected. More infos on the card: https://www.presonus.com/products/Studio-1810c Note that this work is based on packet inspection with usbmon. I just wanted to get this card to work for using it on our open-source radio station: https://github.com/UoC-Radio v2 address issues reported by Takashi: * Properly get/set enum type controls * Prevent race condition on switch_get/set * Various control naming changes * Various coding style fixes v3 improve readability of sample rate filtering and some other minor changes. Signed-off-by: Nick Kossifidis Link: https://lore.kernel.org/r/5e47481a.1c69fb81.befb3.8dac@mx.google.com Signed-off-by: Takashi Iwai --- sound/usb/Makefile | 1 + sound/usb/format.c | 37 +++ sound/usb/mixer_quirks.c | 5 + sound/usb/mixer_s1810c.c | 595 +++++++++++++++++++++++++++++++++++++++ sound/usb/mixer_s1810c.h | 7 + sound/usb/quirks.c | 36 +++ 6 files changed, 681 insertions(+) create mode 100644 sound/usb/mixer_s1810c.c create mode 100644 sound/usb/mixer_s1810c.h diff --git a/sound/usb/Makefile b/sound/usb/Makefile index 78edd7d2f418..56031026b113 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile @@ -13,6 +13,7 @@ snd-usb-audio-objs := card.o \ mixer_scarlett.o \ mixer_scarlett_gen2.o \ mixer_us16x08.o \ + mixer_s1810c.o \ pcm.o \ power.o \ proc.o \ diff --git a/sound/usb/format.c b/sound/usb/format.c index 9260136e4c9b..51e9fca1f3dc 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -226,6 +226,36 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof return 0; } + +/* + * Presonus Studio 1810c supports a limited set of sampling + * rates per altsetting but reports the full set each time. + * If we don't filter out the unsupported rates and attempt + * to configure the card, it will hang refusing to do any + * further audio I/O until a hard reset is performed. + * + * The list of supported rates per altsetting (set of available + * I/O channels) is described in the owner's manual, section 2.2. + */ +static bool s1810c_valid_sample_rate(struct audioformat *fp, + unsigned int rate) +{ + switch (fp->altsetting) { + case 1: + /* All ADAT ports available */ + return rate <= 48000; + case 2: + /* Half of ADAT ports available */ + return (rate == 88200 || rate == 96000); + case 3: + /* Analog I/O only (no S/PDIF nor ADAT) */ + return rate >= 176400; + default: + return false; + } + return false; +} + /* * Helper function to walk the array of sample rate triplets reported by * the device. The problem is that we need to parse whole array first to @@ -262,6 +292,12 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip, } for (rate = min; rate <= max; rate += res) { + + /* Filter out invalid rates on Presonus Studio 1810c */ + if (chip->usb_id == USB_ID(0x0194f, 0x010c) && + !s1810c_valid_sample_rate(fp, rate)) + goto skip_rate; + if (fp->rate_table) fp->rate_table[nr_rates] = rate; if (!fp->rate_min || rate < fp->rate_min) @@ -276,6 +312,7 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip, break; } +skip_rate: /* avoid endless loop */ if (res == 0) break; diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index c237e24f08d9..02b036b2aefb 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -34,6 +34,7 @@ #include "mixer_scarlett.h" #include "mixer_scarlett_gen2.h" #include "mixer_us16x08.h" +#include "mixer_s1810c.h" #include "helper.h" struct std_mono_table { @@ -2277,6 +2278,10 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) case USB_ID(0x2a39, 0x3fd4): /* RME */ err = snd_rme_controls_create(mixer); break; + + case USB_ID(0x0194f, 0x010c): /* Presonus Studio 1810c */ + err = snd_sc1810_init_mixer(mixer); + break; } return err; diff --git a/sound/usb/mixer_s1810c.c b/sound/usb/mixer_s1810c.c new file mode 100644 index 000000000000..816879a07f82 --- /dev/null +++ b/sound/usb/mixer_s1810c.c @@ -0,0 +1,595 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Presonus Studio 1810c driver for ALSA + * Copyright (C) 2019 Nick Kossifidis + * + * Based on reverse engineering of the communication protocol + * between the windows driver / Univeral Control (UC) program + * and the device, through usbmon. + * + * For now this bypasses the mixer, with all channels split, + * so that the software can mix with greater flexibility. + * It also adds controls for the 4 buttons on the front of + * the device. + */ + +#include +#include +#include +#include +#include + +#include "usbaudio.h" +#include "mixer.h" +#include "mixer_quirks.h" +#include "helper.h" +#include "mixer_s1810c.h" + +#define SC1810C_CMD_REQ 160 +#define SC1810C_CMD_REQTYPE \ + (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT) +#define SC1810C_CMD_F1 0x50617269 +#define SC1810C_CMD_F2 0x14 + +/* + * DISCLAIMER: These are just guesses based on the + * dumps I got. + * + * It seems like a selects between + * device (0), mixer (0x64) and output (0x65) + * + * For mixer (0x64): + * * b selects an input channel (see below). + * * c selects an output channel pair (see below). + * * d selects left (0) or right (1) of that pair. + * * e 0-> disconnect, 0x01000000-> connect, + * 0x0109-> used for stereo-linking channels, + * e is also used for setting volume levels + * in which case b is also set so I guess + * this way it is possible to set the volume + * level from the specified input to the + * specified output. + * + * IN Channels: + * 0 - 7 Mic/Inst/Line (Analog inputs) + * 8 - 9 S/PDIF + * 10 - 17 ADAT + * 18 - 35 DAW (Inputs from the host) + * + * OUT Channels (pairs): + * 0 -> Main out + * 1 -> Line1/2 + * 2 -> Line3/4 + * 3 -> S/PDIF + * 4 -> ADAT? + * + * For device (0): + * * b and c are not used, at least not on the + * dumps I got. + * * d sets the control id to be modified + * (see below). + * * e sets the setting for that control. + * (so for the switches I was interested + * in it's 0/1) + * + * For output (0x65): + * * b is the output channel (see above). + * * c is zero. + * * e I guess the same as with mixer except 0x0109 + * which I didn't see in my dumps. + * + * The two fixed fields have the same values for + * mixer and output but a different set for device. + */ +struct s1810c_ctl_packet { + u32 a; + u32 b; + u32 fixed1; + u32 fixed2; + u32 c; + u32 d; + u32 e; +}; + +#define SC1810C_CTL_LINE_SW 0 +#define SC1810C_CTL_MUTE_SW 1 +#define SC1810C_CTL_AB_SW 3 +#define SC1810C_CTL_48V_SW 4 + +#define SC1810C_SET_STATE_REQ 161 +#define SC1810C_SET_STATE_REQTYPE SC1810C_CMD_REQTYPE +#define SC1810C_SET_STATE_F1 0x64656D73 +#define SC1810C_SET_STATE_F2 0xF4 + +#define SC1810C_GET_STATE_REQ 162 +#define SC1810C_GET_STATE_REQTYPE \ + (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN) +#define SC1810C_GET_STATE_F1 SC1810C_SET_STATE_F1 +#define SC1810C_GET_STATE_F2 SC1810C_SET_STATE_F2 + +#define SC1810C_STATE_F1_IDX 2 +#define SC1810C_STATE_F2_IDX 3 + +/* + * This packet includes mixer volumes and + * various other fields, it's an extended + * version of ctl_packet, with a and b + * being zero and different f1/f2. + */ +struct s1810c_state_packet { + u32 fields[63]; +}; + +#define SC1810C_STATE_48V_SW 58 +#define SC1810C_STATE_LINE_SW 59 +#define SC1810C_STATE_MUTE_SW 60 +#define SC1810C_STATE_AB_SW 62 + +struct s1810_mixer_state { + uint16_t seqnum; + struct mutex usb_mutex; + struct mutex data_mutex; +}; + +static int +snd_s1810c_send_ctl_packet(struct usb_device *dev, u32 a, + u32 b, u32 c, u32 d, u32 e) +{ + struct s1810c_ctl_packet pkt = { 0 }; + int ret = 0; + + pkt.fixed1 = SC1810C_CMD_F1; + pkt.fixed2 = SC1810C_CMD_F2; + + pkt.a = a; + pkt.b = b; + pkt.c = c; + pkt.d = d; + /* + * Value for settings 0/1 for this + * output channel is always 0 (probably because + * there is no ADAT output on 1810c) + */ + pkt.e = (c == 4) ? 0 : e; + + ret = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + SC1810C_CMD_REQ, + SC1810C_CMD_REQTYPE, 0, 0, &pkt, sizeof(pkt)); + if (ret < 0) { + dev_warn(&dev->dev, "could not send ctl packet\n"); + return ret; + } + return 0; +} + +/* + * When opening Universal Control the program periodicaly + * sends and receives state packets for syncinc state between + * the device and the host. + * + * Note that if we send only the request to get data back we'll + * get an error, we need to first send an empty state packet and + * then ask to receive a filled. Their seqnumbers must also match. + */ +static int +snd_sc1810c_get_status_field(struct usb_device *dev, + u32 *field, int field_idx, uint16_t *seqnum) +{ + struct s1810c_state_packet pkt_out = { 0 }; + struct s1810c_state_packet pkt_in = { 0 }; + int ret = 0; + + pkt_out.fields[SC1810C_STATE_F1_IDX] = SC1810C_SET_STATE_F1; + pkt_out.fields[SC1810C_STATE_F2_IDX] = SC1810C_SET_STATE_F2; + ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), + SC1810C_SET_STATE_REQ, + SC1810C_SET_STATE_REQTYPE, + (*seqnum), 0, &pkt_out, sizeof(pkt_out)); + if (ret < 0) { + dev_warn(&dev->dev, "could not send state packet (%d)\n", ret); + return ret; + } + + ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), + SC1810C_GET_STATE_REQ, + SC1810C_GET_STATE_REQTYPE, + (*seqnum), 0, &pkt_in, sizeof(pkt_in)); + if (ret < 0) { + dev_warn(&dev->dev, "could not get state field %u (%d)\n", + field_idx, ret); + return ret; + } + + (*field) = pkt_in.fields[field_idx]; + (*seqnum)++; + return 0; +} + +/* + * This is what I got when bypassing the mixer with + * all channels split. I'm not 100% sure of what's going + * on, I could probably clean this up based on my observations + * but I prefer to keep the same behavior as the windows driver. + */ +static int snd_s1810c_init_mixer_maps(struct snd_usb_audio *chip) +{ + u32 a, b, c, e, n, off; + struct usb_device *dev = chip->dev; + + /* Set initial volume levels ? */ + a = 0x64; + e = 0xbc; + for (n = 0; n < 2; n++) { + off = n * 18; + for (b = off, c = 0; b < 18 + off; b++) { + /* This channel to all outputs ? */ + for (c = 0; c <= 8; c++) { + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e); + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e); + } + /* This channel to main output (again) */ + snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e); + snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e); + } + /* + * I noticed on UC that DAW channels have different + * initial volumes, so this makes sense. + */ + e = 0xb53bf0; + } + + /* Connect analog outputs ? */ + a = 0x65; + e = 0x01000000; + for (b = 1; b < 3; b++) { + snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e); + snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e); + } + snd_s1810c_send_ctl_packet(dev, a, 0, 0, 0, e); + snd_s1810c_send_ctl_packet(dev, a, 0, 0, 1, e); + + /* Set initial volume levels for S/PDIF mappings ? */ + a = 0x64; + e = 0xbc; + c = 3; + for (n = 0; n < 2; n++) { + off = n * 18; + for (b = off; b < 18 + off; b++) { + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e); + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e); + } + e = 0xb53bf0; + } + + /* Connect S/PDIF output ? */ + a = 0x65; + e = 0x01000000; + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e); + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e); + + /* Connect all outputs (again) ? */ + a = 0x65; + e = 0x01000000; + for (b = 0; b < 4; b++) { + snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e); + snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e); + } + + /* Basic routing to get sound out of the device */ + a = 0x64; + e = 0x01000000; + for (c = 0; c < 4; c++) { + for (b = 0; b < 36; b++) { + if ((c == 0 && b == 18) || /* DAW1/2 -> Main */ + (c == 1 && b == 20) || /* DAW3/4 -> Line3/4 */ + (c == 2 && b == 22) || /* DAW4/5 -> Line5/6 */ + (c == 3 && b == 24)) { /* DAW5/6 -> S/PDIF */ + /* Left */ + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e); + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, 0); + b++; + /* Right */ + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, 0); + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e); + } else { + /* Leave the rest disconnected */ + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, 0); + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, 0); + } + } + } + + /* Set initial volume levels for S/PDIF (again) ? */ + a = 0x64; + e = 0xbc; + c = 3; + for (n = 0; n < 2; n++) { + off = n * 18; + for (b = off; b < 18 + off; b++) { + snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e); + snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e); + } + e = 0xb53bf0; + } + + /* Connect S/PDIF outputs (again) ? */ + a = 0x65; + e = 0x01000000; + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e); + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e); + + /* Again ? */ + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e); + snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e); + + return 0; +} + +/* + * Sync state with the device and retrieve the requested field, + * whose index is specified in (kctl->private_value & 0xFF), + * from the received fields array. + */ +static int +snd_s1810c_get_switch_state(struct usb_mixer_interface *mixer, + struct snd_kcontrol *kctl, u32 *state) +{ + struct snd_usb_audio *chip = mixer->chip; + struct s1810_mixer_state *private = mixer->private_data; + u32 field = 0; + u32 ctl_idx = (u32) (kctl->private_value & 0xFF); + int ret = 0; + + mutex_lock(&private->usb_mutex); + ret = snd_sc1810c_get_status_field(chip->dev, &field, + ctl_idx, &private->seqnum); + if (ret < 0) + goto unlock; + + *state = field; + unlock: + mutex_unlock(&private->usb_mutex); + return ret ? ret : 0; +} + +/* + * Send a control packet to the device for the control id + * specified in (kctl->private_value >> 8) with value + * specified in (kctl->private_value >> 16). + */ +static int +snd_s1810c_set_switch_state(struct usb_mixer_interface *mixer, + struct snd_kcontrol *kctl) +{ + struct snd_usb_audio *chip = mixer->chip; + struct s1810_mixer_state *private = mixer->private_data; + u32 pval = (u32) kctl->private_value; + u32 ctl_id = (pval >> 8) & 0xFF; + u32 ctl_val = (pval >> 16) & 0x1; + int ret = 0; + + mutex_lock(&private->usb_mutex); + ret = snd_s1810c_send_ctl_packet(chip->dev, 0, 0, 0, ctl_id, ctl_val); + mutex_unlock(&private->usb_mutex); + return ret; +} + +/* Generic get/set/init functions for switch controls */ + +static int +snd_s1810c_switch_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ctl_elem) +{ + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl); + struct usb_mixer_interface *mixer = list->mixer; + struct s1810_mixer_state *private = mixer->private_data; + u32 pval = (u32) kctl->private_value; + u32 ctl_idx = pval & 0xFF; + u32 state = 0; + int ret = 0; + + mutex_lock(&private->data_mutex); + ret = snd_s1810c_get_switch_state(mixer, kctl, &state); + if (ret < 0) + goto unlock; + + switch (ctl_idx) { + case SC1810C_STATE_LINE_SW: + case SC1810C_STATE_AB_SW: + ctl_elem->value.enumerated.item[0] = (int)state; + break; + default: + ctl_elem->value.integer.value[0] = (long)state; + } + + unlock: + mutex_unlock(&private->data_mutex); + return (ret < 0) ? ret : 0; +} + +static int +snd_s1810c_switch_set(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ctl_elem) +{ + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl); + struct usb_mixer_interface *mixer = list->mixer; + struct s1810_mixer_state *private = mixer->private_data; + u32 pval = (u32) kctl->private_value; + u32 ctl_idx = pval & 0xFF; + u32 curval = 0; + u32 newval = 0; + int ret = 0; + + mutex_lock(&private->data_mutex); + ret = snd_s1810c_get_switch_state(mixer, kctl, &curval); + if (ret < 0) + goto unlock; + + switch (ctl_idx) { + case SC1810C_STATE_LINE_SW: + case SC1810C_STATE_AB_SW: + newval = (u32) ctl_elem->value.enumerated.item[0]; + break; + default: + newval = (u32) ctl_elem->value.integer.value[0]; + } + + if (curval == newval) + goto unlock; + + kctl->private_value &= ~(0x1 << 16); + kctl->private_value |= (unsigned int)(newval & 0x1) << 16; + ret = snd_s1810c_set_switch_state(mixer, kctl); + + unlock: + mutex_unlock(&private->data_mutex); + return (ret < 0) ? 0 : 1; +} + +static int +snd_s1810c_switch_init(struct usb_mixer_interface *mixer, + const struct snd_kcontrol_new *new_kctl) +{ + struct snd_kcontrol *kctl; + struct usb_mixer_elem_info *elem; + + elem = kzalloc(sizeof(struct usb_mixer_elem_info), GFP_KERNEL); + if (!elem) + return -ENOMEM; + + elem->head.mixer = mixer; + elem->control = 0; + elem->head.id = 0; + elem->channels = 1; + + kctl = snd_ctl_new1(new_kctl, elem); + if (!kctl) { + kfree(elem); + return -ENOMEM; + } + kctl->private_free = snd_usb_mixer_elem_free; + + return snd_usb_mixer_add_control(&elem->head, kctl); +} + +static int +snd_s1810c_line_sw_info(struct snd_kcontrol *kctl, + struct snd_ctl_elem_info *uinfo) +{ + static const char *const texts[2] = { + "Preamp On (Mic/Inst)", + "Preamp Off (Line in)" + }; + + return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts); +} + +static const struct snd_kcontrol_new snd_s1810c_line_sw = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Line 1/2 Source Type", + .info = snd_s1810c_line_sw_info, + .get = snd_s1810c_switch_get, + .put = snd_s1810c_switch_set, + .private_value = (SC1810C_STATE_LINE_SW | SC1810C_CTL_LINE_SW << 8) +}; + +static const struct snd_kcontrol_new snd_s1810c_mute_sw = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Mute Main Out Switch", + .info = snd_ctl_boolean_mono_info, + .get = snd_s1810c_switch_get, + .put = snd_s1810c_switch_set, + .private_value = (SC1810C_STATE_MUTE_SW | SC1810C_CTL_MUTE_SW << 8) +}; + +static const struct snd_kcontrol_new snd_s1810c_48v_sw = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "48V Phantom Power On Mic Inputs Switch", + .info = snd_ctl_boolean_mono_info, + .get = snd_s1810c_switch_get, + .put = snd_s1810c_switch_set, + .private_value = (SC1810C_STATE_48V_SW | SC1810C_CTL_48V_SW << 8) +}; + +static int +snd_s1810c_ab_sw_info(struct snd_kcontrol *kctl, + struct snd_ctl_elem_info *uinfo) +{ + static const char *const texts[2] = { + "1/2", + "3/4" + }; + + return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts); +} + +static const struct snd_kcontrol_new snd_s1810c_ab_sw = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Headphone 1 Source Route", + .info = snd_s1810c_ab_sw_info, + .get = snd_s1810c_switch_get, + .put = snd_s1810c_switch_set, + .private_value = (SC1810C_STATE_AB_SW | SC1810C_CTL_AB_SW << 8) +}; + +static void snd_sc1810_mixer_state_free(struct usb_mixer_interface *mixer) +{ + struct s1810_mixer_state *private = mixer->private_data; + kfree(private); + mixer->private_data = NULL; +} + +/* Entry point, called from mixer_quirks.c */ +int snd_sc1810_init_mixer(struct usb_mixer_interface *mixer) +{ + struct s1810_mixer_state *private = NULL; + struct snd_usb_audio *chip = mixer->chip; + struct usb_device *dev = chip->dev; + int ret = 0; + + /* Run this only once */ + if (!list_empty(&chip->mixer_list)) + return 0; + + dev_info(&dev->dev, + "Presonus Studio 1810c, device_setup: %u\n", chip->setup); + if (chip->setup == 1) + dev_info(&dev->dev, "(8out/18in @ 48KHz)\n"); + else if (chip->setup == 2) + dev_info(&dev->dev, "(6out/8in @ 192KHz)\n"); + else + dev_info(&dev->dev, "(8out/14in @ 96KHz)\n"); + + ret = snd_s1810c_init_mixer_maps(chip); + if (ret < 0) + return ret; + + private = kzalloc(sizeof(struct s1810_mixer_state), GFP_KERNEL); + if (!private) + return -ENOMEM; + + mutex_init(&private->usb_mutex); + mutex_init(&private->data_mutex); + + mixer->private_data = private; + mixer->private_free = snd_sc1810_mixer_state_free; + + private->seqnum = 1; + + ret = snd_s1810c_switch_init(mixer, &snd_s1810c_line_sw); + if (ret < 0) + return ret; + + ret = snd_s1810c_switch_init(mixer, &snd_s1810c_mute_sw); + if (ret < 0) + return ret; + + ret = snd_s1810c_switch_init(mixer, &snd_s1810c_48v_sw); + if (ret < 0) + return ret; + + ret = snd_s1810c_switch_init(mixer, &snd_s1810c_ab_sw); + if (ret < 0) + return ret; + return ret; +} diff --git a/sound/usb/mixer_s1810c.h b/sound/usb/mixer_s1810c.h new file mode 100644 index 000000000000..a79a3743cff3 --- /dev/null +++ b/sound/usb/mixer_s1810c.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Presonus Studio 1810c driver for ALSA + * Copyright (C) 2019 Nick Kossifidis + */ + +int snd_sc1810_init_mixer(struct usb_mixer_interface *mixer); diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 3a5242e383b2..58761d408759 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1252,6 +1252,38 @@ static int fasttrackpro_skip_setting_quirk(struct snd_usb_audio *chip, return 0; /* keep this altsetting */ } +static int s1810c_skip_setting_quirk(struct snd_usb_audio *chip, + int iface, int altno) +{ + /* + * Altno settings: + * + * Playback (Interface 1): + * 1: 6 Analog + 2 S/PDIF + * 2: 6 Analog + 2 S/PDIF + * 3: 6 Analog + * + * Capture (Interface 2): + * 1: 8 Analog + 2 S/PDIF + 8 ADAT + * 2: 8 Analog + 2 S/PDIF + 4 ADAT + * 3: 8 Analog + */ + + /* + * I'll leave 2 as the default one and + * use device_setup to switch to the + * other two. + */ + if ((chip->setup == 0 || chip->setup > 2) && altno != 2) + return 1; + else if (chip->setup == 1 && altno != 1) + return 1; + else if (chip->setup == 2 && altno != 3) + return 1; + + return 0; +} + int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip, int iface, int altno) @@ -1265,6 +1297,10 @@ int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip, /* fasttrackpro usb: skip altsets incompatible with device_setup */ if (chip->usb_id == USB_ID(0x0763, 0x2012)) return fasttrackpro_skip_setting_quirk(chip, iface, altno); + /* presonus studio 1810c: skip altsets incompatible with device_setup */ + if (chip->usb_id == USB_ID(0x0194f, 0x010c)) + return s1810c_skip_setting_quirk(chip, iface, altno); + return 0; } From 5b24efe7d55a4bea6992ae1ee00707d77ec22575 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 1 Feb 2020 23:55:08 +0300 Subject: [PATCH 0366/4444] mtd: spi-nor: use le32_to_cpu_array() The driver calls le32_to_cpu() to convert the little-endian tables to a CPU endianness, where le32_to_cpus() should have been called. Was going to use that one... and then discovered a whole array converter, le32_to_cpu_array()! :-) Signed-off-by: Sergei Shtylyov Signed-off-by: Tudor Ambarus --- drivers/mtd/spi-nor/spi-nor.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 4fc632ec18fe..864ed6f49e87 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -3598,8 +3598,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, return err; /* Fix endianness of the BFPT DWORDs. */ - for (i = 0; i < BFPT_DWORD_MAX; i++) - bfpt.dwords[i] = le32_to_cpu(bfpt.dwords[i]); + le32_to_cpu_array(bfpt.dwords, BFPT_DWORD_MAX); /* Number of address bytes. */ switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) { @@ -4057,7 +4056,7 @@ static int spi_nor_parse_smpt(struct spi_nor *nor, u32 *smpt; size_t len; u32 addr; - int i, ret; + int ret; /* Read the Sector Map Parameter Table. */ len = smpt_header->length * sizeof(*smpt); @@ -4071,8 +4070,7 @@ static int spi_nor_parse_smpt(struct spi_nor *nor, goto out; /* Fix endianness of the SMPT DWORDs. */ - for (i = 0; i < smpt_header->length; i++) - smpt[i] = le32_to_cpu(smpt[i]); + le32_to_cpu_array(smpt, smpt_header->length); sector_map = spi_nor_get_map_in_use(nor, smpt, smpt_header->length); if (IS_ERR(sector_map)) { @@ -4165,8 +4163,7 @@ static int spi_nor_parse_4bait(struct spi_nor *nor, goto out; /* Fix endianness of the 4BAIT DWORDs. */ - for (i = 0; i < SFDP_4BAIT_DWORD_MAX; i++) - dwords[i] = le32_to_cpu(dwords[i]); + le32_to_cpu_array(dwords, SFDP_4BAIT_DWORD_MAX); /* * Compute the subset of (Fast) Read commands for which the 4-byte From 8c79fa6c44deac8042bd747527fea06a32738158 Mon Sep 17 00:00:00 2001 From: Jungseung Lee Date: Mon, 13 Jan 2020 14:59:05 +0900 Subject: [PATCH 0367/4444] mtd: spi-nor: introduce SR_BP_SHIFT define The shift variable of SR_BP is conclusive because the first bit of SR_BP is fixed on all known flashes. Replace ffs operation with SR_BP_SHIFT. Signed-off-by: Jungseung Lee Signed-off-by: Tudor Ambarus --- drivers/mtd/spi-nor/spi-nor.c | 11 +++++------ include/linux/mtd/spi-nor.h | 2 ++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 864ed6f49e87..b5ef17b2897a 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1767,7 +1767,6 @@ static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs, struct mtd_info *mtd = &nor->mtd; u8 mask = SR_BP2 | SR_BP1 | SR_BP0; u8 tb_mask = SR_TB_BIT5; - int shift = ffs(mask) - 1; int pow; if (nor->flags & SNOR_F_HAS_SR_TB_BIT6) @@ -1778,7 +1777,7 @@ static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs, *ofs = 0; *len = 0; } else { - pow = ((sr & mask) ^ mask) >> shift; + pow = ((sr & mask) ^ mask) >> SR_BP_SHIFT; *len = mtd->size >> pow; if (nor->flags & SNOR_F_HAS_SR_TB && sr & tb_mask) *ofs = 0; @@ -1860,7 +1859,7 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) int ret, status_old, status_new; u8 mask = SR_BP2 | SR_BP1 | SR_BP0; u8 tb_mask = SR_TB_BIT5; - u8 shift = ffs(mask) - 1, pow, val; + u8 pow, val; loff_t lock_len; bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; bool use_top; @@ -1909,7 +1908,7 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) */ pow = ilog2(mtd->size) - ilog2(lock_len); - val = mask - (pow << shift); + val = mask - (pow << SR_BP_SHIFT); if (val & ~mask) return -EINVAL; /* Don't "lock" with no region! */ @@ -1946,7 +1945,7 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) int ret, status_old, status_new; u8 mask = SR_BP2 | SR_BP1 | SR_BP0; u8 tb_mask = SR_TB_BIT5; - u8 shift = ffs(mask) - 1, pow, val; + u8 pow, val; loff_t lock_len; bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; bool use_top; @@ -1997,7 +1996,7 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) if (lock_len == 0) { val = 0; /* fully unlocked */ } else { - val = mask - (pow << shift); + val = mask - (pow << SR_BP_SHIFT); /* Some power-of-two sizes are not supported */ if (val & ~mask) return -EINVAL; diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 5abd91cc6dfa..61be6ed33097 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -137,6 +137,8 @@ #define SR1_QUAD_EN_BIT6 BIT(6) +#define SR_BP_SHIFT 2 + /* Enhanced Volatile Configuration Register bits */ #define EVCR_QUAD_EN_MICRON BIT(7) /* Micron Quad I/O */ From 18432e863b8cd08164dbfbe2e9591f1f88f5a709 Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Tue, 4 Feb 2020 22:52:29 +0100 Subject: [PATCH 0368/4444] ARM: dts: imx25-pinfunc: add another cspi3 config This patch adds defines for another cspi3 configuration. The defines have been tested on an out-of-tree board. Signed-off-by: Martin Kaiser Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx25-pinfunc.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/imx25-pinfunc.h b/arch/arm/boot/dts/imx25-pinfunc.h index f4516ccf2c1a..b5a12412440e 100644 --- a/arch/arm/boot/dts/imx25-pinfunc.h +++ b/arch/arm/boot/dts/imx25-pinfunc.h @@ -82,6 +82,7 @@ #define MX25_PAD_EB0__EB0 0x040 0x258 0x000 0x00 0x000 #define MX25_PAD_EB0__AUD4_TXD 0x040 0x258 0x464 0x04 0x000 #define MX25_PAD_EB0__GPIO_2_12 0x040 0x258 0x000 0x05 0x000 +#define MX25_PAD_EB0__CSPI3_SS0 0x040 0x258 0x4bc 0x06 0x000 #define MX25_PAD_EB1__EB1 0x044 0x25c 0x000 0x00 0x000 #define MX25_PAD_EB1__AUD4_RXD 0x044 0x25c 0x460 0x04 0x000 @@ -102,11 +103,13 @@ #define MX25_PAD_CS4__NF_CE1 0x054 0x264 0x000 0x01 0x000 #define MX25_PAD_CS4__UART5_CTS 0x054 0x264 0x000 0x03 0x000 #define MX25_PAD_CS4__GPIO_3_20 0x054 0x264 0x000 0x05 0x000 +#define MX25_PAD_CS4__CSPI3_MOSI 0x054 0x264 0x4b8 0x06 0x000 #define MX25_PAD_CS5__CS5 0x058 0x268 0x000 0x00 0x000 #define MX25_PAD_CS5__NF_CE2 0x058 0x268 0x000 0x01 0x000 #define MX25_PAD_CS5__UART5_RTS 0x058 0x268 0x574 0x03 0x000 #define MX25_PAD_CS5__GPIO_3_21 0x058 0x268 0x000 0x05 0x000 +#define MX25_PAD_CS5__CSPI3_MISO 0x058 0x268 0x4b4 0x06 0x000 #define MX25_PAD_NF_CE0__NF_CE0 0x05c 0x26c 0x000 0x00 0x000 #define MX25_PAD_NF_CE0__GPIO_3_22 0x05c 0x26c 0x000 0x05 0x000 @@ -114,6 +117,7 @@ #define MX25_PAD_ECB__ECB 0x060 0x270 0x000 0x00 0x000 #define MX25_PAD_ECB__UART5_TXD 0x060 0x270 0x000 0x03 0x000 #define MX25_PAD_ECB__GPIO_3_23 0x060 0x270 0x000 0x05 0x000 +#define MX25_PAD_ECB__CSPI3_SCLK 0x060 0x270 0x4ac 0x06 0x000 #define MX25_PAD_LBA__LBA 0x064 0x274 0x000 0x00 0x000 #define MX25_PAD_LBA__UART5_RXD 0x064 0x274 0x578 0x03 0x000 From bcacd6f7c94abb99300e365a6aef93212fc24f15 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 11 Feb 2020 00:08:12 -0300 Subject: [PATCH 0369/4444] clk: imx8mm: Fix the CLKO1 source select list The CLKO1 clock source select list is the following as per the i.MX8MM Reference Manual (put in increasing order): 000 - 24M_REF_CLK 001 - SYSTEM_PLL1_CLK 010 - None 011 - SYSTEM_PLL1_DIV4 100 - AUDIO_PLL2_CLK 101 - SYSTEM_PLL2_DIV2 110 - VPU_PLL_CLK 111 - SYSTEM_PLL1_DIV10 Fix it accordingly. Fixes: ba5625c3e272 ("clk: imx: Add clock driver support for imx8mm") Signed-off-by: Fabio Estevam Reviewed-by: Abel Vesa Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c index f79a5f5d9ed5..523a5b15ae7d 100644 --- a/drivers/clk/imx/clk-imx8mm.c +++ b/drivers/clk/imx/clk-imx8mm.c @@ -283,8 +283,8 @@ static const char *imx8mm_vpu_h1_sels[] = {"osc_24m", "vpu_pll_out", "sys_pll1_8 static const char *imx8mm_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", }; -static const char *imx8mm_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "osc_27m", "sys_pll1_200m", "audio_pll2_out", - "vpu_pll", "sys_pll1_80m", }; +static const char *imx8mm_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "dummy", "sys_pll1_200m", + "audio_pll2_out", "sys_pll2_500m", "vpu_pll", "sys_pll1_80m", }; static struct clk_hw_onecell_data *clk_hw_data; static struct clk_hw **hws; From 9c07ae6983d434841bb19bea0a75bd0fd925a75c Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 17 Feb 2020 13:49:38 +0800 Subject: [PATCH 0370/4444] clk: imx8mm: Add CLKO2 support Add CLKO2 support, which is useful for debugging purposes. Signed-off-by: Fabio Estevam Reviewed-by: Abel Vesa Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mm.c | 3 +++ include/dt-bindings/clock/imx8mm-clock.h | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c index 523a5b15ae7d..6dbdc1a1b5eb 100644 --- a/drivers/clk/imx/clk-imx8mm.c +++ b/drivers/clk/imx/clk-imx8mm.c @@ -285,6 +285,8 @@ static const char *imx8mm_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", } static const char *imx8mm_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "dummy", "sys_pll1_200m", "audio_pll2_out", "sys_pll2_500m", "vpu_pll", "sys_pll1_80m", }; +static const char *imx8mm_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_400m", "sys_pll2_166m", + "sys_pll3_out", "audio_pll1_out", "video_pll1_out", "osc_32k", }; static struct clk_hw_onecell_data *clk_hw_data; static struct clk_hw **hws; @@ -511,6 +513,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev) hws[IMX8MM_CLK_WDOG] = imx8m_clk_hw_composite("wdog", imx8mm_wdog_sels, base + 0xb900); hws[IMX8MM_CLK_WRCLK] = imx8m_clk_hw_composite("wrclk", imx8mm_wrclk_sels, base + 0xb980); hws[IMX8MM_CLK_CLKO1] = imx8m_clk_hw_composite("clko1", imx8mm_clko1_sels, base + 0xba00); + hws[IMX8MM_CLK_CLKO2] = imx8m_clk_hw_composite("clko2", imx8mm_clko2_sels, base + 0xba80); hws[IMX8MM_CLK_DSI_CORE] = imx8m_clk_hw_composite("dsi_core", imx8mm_dsi_core_sels, base + 0xbb00); hws[IMX8MM_CLK_DSI_PHY_REF] = imx8m_clk_hw_composite("dsi_phy_ref", imx8mm_dsi_phy_sels, base + 0xbb80); hws[IMX8MM_CLK_DSI_DBI] = imx8m_clk_hw_composite("dsi_dbi", imx8mm_dsi_dbi_sels, base + 0xbc00); diff --git a/include/dt-bindings/clock/imx8mm-clock.h b/include/dt-bindings/clock/imx8mm-clock.h index 038c28d349e8..dbfee6579d6c 100644 --- a/include/dt-bindings/clock/imx8mm-clock.h +++ b/include/dt-bindings/clock/imx8mm-clock.h @@ -270,6 +270,8 @@ #define IMX8MM_CLK_GPU3D_CORE 248 #define IMX8MM_CLK_GPU2D_CORE 249 -#define IMX8MM_CLK_END 250 +#define IMX8MM_CLK_CLKO2 250 + +#define IMX8MM_CLK_END 251 #endif From ab84bad5bb891b1d4dd4ea5cfaedf34190d10ff4 Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Tue, 11 Feb 2020 12:57:58 +0800 Subject: [PATCH 0371/4444] arm64: dts: ls1028a: support external trigger timestamp fifo of PTP timer There is an external trigger timestamp fifo for PTP timer of LS1028A. Add property fsl,extts-fifo for that. Signed-off-by: Yangbo Lu Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi index 0bf375ec959b..da3906858430 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi @@ -722,6 +722,7 @@ reg = <0x000400 0 0 0 0>; clocks = <&clockgen 4 0>; little-endian; + fsl,extts-fifo; }; }; }; From 3b375426d4a0077ae10e48039912a2e3cecd7888 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 11 Feb 2020 20:48:27 +0800 Subject: [PATCH 0372/4444] dt-bindings: arm: imx: Add the i.MX8MP EVK board Add board binding for i.MX8MP EVK board. Signed-off-by: Anson Huang Reviewed-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 49ab2d83b744..e654a6376bc4 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -324,6 +324,12 @@ properties: - fsl,imx8mn-evk # i.MX8MN LPDDR4 EVK Board - const: fsl,imx8mn + - description: i.MX8MP based Boards + items: + - enum: + - fsl,imx8mp-evk # i.MX8MP EVK Board + - const: fsl,imx8mp + - description: i.MX8MQ based Boards items: - enum: From 6d9b8d20431f12cc102117a71178a18e1eecca71 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 11 Feb 2020 20:48:25 +0800 Subject: [PATCH 0373/4444] arm64: dts: freescale: Add i.MX8MP dtsi support The i.MX8M Plus Media Applications Processor is part of the growing mScale family targeting the consumer and industrial market. It brings an effective Machine Learning and AI accelerator that enables a new class of applications. It is built in Samsung 14LPP to achieve both high performance and low power consumption and relies on a powerful fully coherent core complex based on a quad core ARM Cortex-A53 cluster and Cortex-M7 low-power coprocessor, audio digital signal processor, machine learning and graphics accelerators. Add the basic dtsi support for i.MX8MP. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- .../arm64/boot/dts/freescale/imx8mp-pinfunc.h | 931 ++++++++++++++++++ arch/arm64/boot/dts/freescale/imx8mp.dtsi | 608 ++++++++++++ 2 files changed, 1539 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-pinfunc.h create mode 100644 arch/arm64/boot/dts/freescale/imx8mp.dtsi diff --git a/arch/arm64/boot/dts/freescale/imx8mp-pinfunc.h b/arch/arm64/boot/dts/freescale/imx8mp-pinfunc.h new file mode 100644 index 000000000000..da78f89b6c98 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-pinfunc.h @@ -0,0 +1,931 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2019 NXP + */ + +#ifndef __DTS_IMX8MP_PINFUNC_H +#define __DTS_IMX8MP_PINFUNC_H + +/* + * The pin function ID is a tuple of + * + */ +#define MX8MP_IOMUXC_GPIO1_IO00__GPIO1_IO00 0x014 0x274 0x000 0x0 0x0 +#define MX8MP_IOMUXC_GPIO1_IO00__CCMSRCGPCMIX_ENET_PHY_REF_CLK_ROOT 0x014 0x274 0x000 0x1 0x0 +#define MX8MP_IOMUXC_GPIO1_IO00__MEDIAMIX_ISP_FL_TRIG_0 0x014 0x274 0x5D4 0x3 0x0 +#define MX8MP_IOMUXC_GPIO1_IO00__ANAMIX_REF_CLK_32K 0x014 0x274 0x000 0x5 0x0 +#define MX8MP_IOMUXC_GPIO1_IO00__CCMSRCGPCMIX_EXT_CLK1 0x014 0x274 0x000 0x6 0x0 +#define MX8MP_IOMUXC_GPIO1_IO00__SJC_FAIL 0x014 0x274 0x000 0x7 0x0 +#define MX8MP_IOMUXC_GPIO1_IO01__GPIO1_IO01 0x018 0x278 0x000 0x0 0x0 +#define MX8MP_IOMUXC_GPIO1_IO01__PWM1_OUT 0x018 0x278 0x000 0x1 0x0 +#define MX8MP_IOMUXC_GPIO1_IO01__MEDIAMIX_ISP_SHUTTER_TRIG_0 0x018 0x278 0x5DC 0x3 0x0 +#define MX8MP_IOMUXC_GPIO1_IO01__ANAMIX_REF_CLK_24M 0x018 0x278 0x000 0x5 0x0 +#define MX8MP_IOMUXC_GPIO1_IO01__CCMSRCGPCMIX_EXT_CLK2 0x018 0x278 0x000 0x6 0x0 +#define MX8MP_IOMUXC_GPIO1_IO01__SJC_ACTIVE 0x018 0x278 0x000 0x7 0x0 +#define MX8MP_IOMUXC_GPIO1_IO02__GPIO1_IO02 0x01C 0x27C 0x000 0x0 0x0 +#define MX8MP_IOMUXC_GPIO1_IO02__WDOG1_WDOG_B 0x01C 0x27C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_GPIO1_IO02__MEDIAMIX_ISP_FLASH_TRIG_0 0x01C 0x27C 0x000 0x3 0x0 +#define MX8MP_IOMUXC_GPIO1_IO02__WDOG1_WDOG_ANY 0x01C 0x27C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_GPIO1_IO02__SJC_DE_B 0x01C 0x27C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_GPIO1_IO03__GPIO1_IO03 0x020 0x280 0x000 0x0 0x0 +#define MX8MP_IOMUXC_GPIO1_IO03__USDHC1_VSELECT 0x020 0x280 0x000 0x1 0x0 +#define MX8MP_IOMUXC_GPIO1_IO03__MEDIAMIX_ISP_PRELIGHT_TRIG_0 0x020 0x280 0x000 0x3 0x0 +#define MX8MP_IOMUXC_GPIO1_IO03__SDMA1_EXT_EVENT00 0x020 0x280 0x000 0x5 0x0 +#define MX8MP_IOMUXC_GPIO1_IO03__ANAMIX_XTAL_OK 0x020 0x280 0x000 0x6 0x0 +#define MX8MP_IOMUXC_GPIO1_IO03__SJC_DONE 0x020 0x280 0x000 0x7 0x0 +#define MX8MP_IOMUXC_GPIO1_IO04__GPIO1_IO04 0x024 0x284 0x000 0x0 0x0 +#define MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0x024 0x284 0x000 0x1 0x0 +#define MX8MP_IOMUXC_GPIO1_IO04__MEDIAMIX_ISP_SHUTTER_OPEN_0 0x024 0x284 0x000 0x3 0x0 +#define MX8MP_IOMUXC_GPIO1_IO04__SDMA1_EXT_EVENT01 0x024 0x284 0x000 0x5 0x0 +#define MX8MP_IOMUXC_GPIO1_IO04__ANAMIX_XTAL_OK_LV 0x024 0x284 0x000 0x6 0x0 +#define MX8MP_IOMUXC_GPIO1_IO04__USDHC1_TEST_TRIG 0x024 0x284 0x000 0x7 0x0 +#define MX8MP_IOMUXC_GPIO1_IO05__GPIO1_IO05 0x028 0x288 0x000 0x0 0x0 +#define MX8MP_IOMUXC_GPIO1_IO05__M7_NMI 0x028 0x288 0x000 0x1 0x0 +#define MX8MP_IOMUXC_GPIO1_IO05__MEDIAMIX_ISP_FL_TRIG_1 0x028 0x288 0x5D8 0x3 0x0 +#define MX8MP_IOMUXC_GPIO1_IO05__CCMSRCGPCMIX_PMIC_READY 0x028 0x288 0x554 0x5 0x0 +#define MX8MP_IOMUXC_GPIO1_IO05__CCMSRCGPCMIX_INT_BOOT 0x028 0x288 0x000 0x6 0x0 +#define MX8MP_IOMUXC_GPIO1_IO05__USDHC2_TEST_TRIG 0x028 0x288 0x000 0x7 0x0 +#define MX8MP_IOMUXC_GPIO1_IO06__GPIO1_IO06 0x02C 0x28C 0x000 0x0 0x0 +#define MX8MP_IOMUXC_GPIO1_IO06__ENET_QOS_MDC 0x02C 0x28C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_GPIO1_IO06__MEDIAMIX_ISP_SHUTTER_TRIG_1 0x02C 0x28C 0x5E0 0x3 0x0 +#define MX8MP_IOMUXC_GPIO1_IO06__USDHC1_CD_B 0x02C 0x28C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_GPIO1_IO06__CCMSRCGPCMIX_EXT_CLK3 0x02C 0x28C 0x000 0x6 0x0 +#define MX8MP_IOMUXC_GPIO1_IO06__ECSPI1_TEST_TRIG 0x02C 0x28C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_GPIO1_IO07__GPIO1_IO07 0x030 0x290 0x000 0x0 0x0 +#define MX8MP_IOMUXC_GPIO1_IO07__ENET_QOS_MDIO 0x030 0x290 0x590 0x1 0x0 +#define MX8MP_IOMUXC_GPIO1_IO07__MEDIAMIX_ISP_FLASH_TRIG_1 0x030 0x290 0x000 0x3 0x0 +#define MX8MP_IOMUXC_GPIO1_IO07__USDHC1_WP 0x030 0x290 0x000 0x5 0x0 +#define MX8MP_IOMUXC_GPIO1_IO07__CCMSRCGPCMIX_EXT_CLK4 0x030 0x290 0x000 0x6 0x0 +#define MX8MP_IOMUXC_GPIO1_IO07__ECSPI2_TEST_TRIG 0x030 0x290 0x000 0x7 0x0 +#define MX8MP_IOMUXC_GPIO1_IO08__GPIO1_IO08 0x034 0x294 0x000 0x0 0x0 +#define MX8MP_IOMUXC_GPIO1_IO08__ENET_QOS_1588_EVENT0_IN 0x034 0x294 0x000 0x1 0x0 +#define MX8MP_IOMUXC_GPIO1_IO08__PWM1_OUT 0x034 0x294 0x000 0x2 0x0 +#define MX8MP_IOMUXC_GPIO1_IO08__MEDIAMIX_ISP_PRELIGHT_TRIG_1 0x034 0x294 0x000 0x3 0x0 +#define MX8MP_IOMUXC_GPIO1_IO08__ENET_QOS_1588_EVENT0_AUX_IN 0x034 0x294 0x000 0x4 0x0 +#define MX8MP_IOMUXC_GPIO1_IO08__USDHC2_RESET_B 0x034 0x294 0x000 0x5 0x0 +#define MX8MP_IOMUXC_GPIO1_IO08__CCMSRCGPCMIX_WAIT 0x034 0x294 0x000 0x6 0x0 +#define MX8MP_IOMUXC_GPIO1_IO08__FLEXSPI_TEST_TRIG 0x034 0x294 0x000 0x7 0x0 +#define MX8MP_IOMUXC_GPIO1_IO09__GPIO1_IO09 0x038 0x298 0x000 0x0 0x0 +#define MX8MP_IOMUXC_GPIO1_IO09__ENET_QOS_1588_EVENT0_OUT 0x038 0x298 0x000 0x1 0x0 +#define MX8MP_IOMUXC_GPIO1_IO09__PWM2_OUT 0x038 0x298 0x000 0x2 0x0 +#define MX8MP_IOMUXC_GPIO1_IO09__MEDIAMIX_ISP_SHUTTER_OPEN_1 0x038 0x298 0x000 0x3 0x0 +#define MX8MP_IOMUXC_GPIO1_IO09__USDHC3_RESET_B 0x038 0x298 0x000 0x4 0x0 +#define MX8MP_IOMUXC_GPIO1_IO09__AUDIOMIX_EXT_EVENT00 0x038 0x298 0x000 0x5 0x0 +#define MX8MP_IOMUXC_GPIO1_IO09__CCMSRCGPCMIX_STOP 0x038 0x298 0x000 0x6 0x0 +#define MX8MP_IOMUXC_GPIO1_IO09__RAWNAND_TEST_TRIG 0x038 0x298 0x000 0x7 0x0 +#define MX8MP_IOMUXC_GPIO1_IO10__GPIO1_IO10 0x03C 0x29C 0x000 0x0 0x0 +#define MX8MP_IOMUXC_GPIO1_IO10__HSIOMIX_usb1_OTG_ID 0x03C 0x29C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_GPIO1_IO10__PWM3_OUT 0x03C 0x29C 0x000 0x2 0x0 +#define MX8MP_IOMUXC_GPIO1_IO10__OCOTP_FUSE_LATCHED 0x03C 0x29C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_GPIO1_IO11__GPIO1_IO11 0x040 0x2A0 0x000 0x0 0x0 +#define MX8MP_IOMUXC_GPIO1_IO11__HSIOMIX_usb2_OTG_ID 0x040 0x2A0 0x000 0x1 0x0 +#define MX8MP_IOMUXC_GPIO1_IO11__PWM2_OUT 0x040 0x2A0 0x000 0x2 0x0 +#define MX8MP_IOMUXC_GPIO1_IO11__USDHC3_VSELECT 0x040 0x2A0 0x000 0x4 0x0 +#define MX8MP_IOMUXC_GPIO1_IO11__CCMSRCGPCMIX_PMIC_READY 0x040 0x2A0 0x554 0x5 0x1 +#define MX8MP_IOMUXC_GPIO1_IO11__CCMSRCGPCMIX_OUT0 0x040 0x2A0 0x000 0x6 0x0 +#define MX8MP_IOMUXC_GPIO1_IO11__CAAM_RNG_OSC_OBS 0x040 0x2A0 0x000 0x7 0x0 +#define MX8MP_IOMUXC_GPIO1_IO12__GPIO1_IO12 0x044 0x2A4 0x000 0x0 0x0 +#define MX8MP_IOMUXC_GPIO1_IO12__HSIOMIX_usb1_OTG_PWR 0x044 0x2A4 0x000 0x1 0x0 +#define MX8MP_IOMUXC_GPIO1_IO12__AUDIOMIX_EXT_EVENT01 0x044 0x2A4 0x000 0x5 0x0 +#define MX8MP_IOMUXC_GPIO1_IO12__CCMSRCGPCMIX_OUT1 0x044 0x2A4 0x000 0x6 0x0 +#define MX8MP_IOMUXC_GPIO1_IO12__CSU_CSU_ALARM_AUT00 0x044 0x2A4 0x000 0x7 0x0 +#define MX8MP_IOMUXC_GPIO1_IO13__GPIO1_IO13 0x048 0x2A8 0x000 0x0 0x0 +#define MX8MP_IOMUXC_GPIO1_IO13__HSIOMIX_usb1_OTG_OC 0x048 0x2A8 0x000 0x1 0x0 +#define MX8MP_IOMUXC_GPIO1_IO13__PWM2_OUT 0x048 0x2A8 0x000 0x5 0x0 +#define MX8MP_IOMUXC_GPIO1_IO13__CCMSRCGPCMIX_OUT2 0x048 0x2A8 0x000 0x6 0x0 +#define MX8MP_IOMUXC_GPIO1_IO13__CSU_CSU_ALARM_AUT01 0x048 0x2A8 0x000 0x7 0x0 +#define MX8MP_IOMUXC_GPIO1_IO14__GPIO1_IO14 0x04C 0x2AC 0x000 0x0 0x0 +#define MX8MP_IOMUXC_GPIO1_IO14__HSIOMIX_usb2_OTG_PWR 0x04C 0x2AC 0x000 0x1 0x0 +#define MX8MP_IOMUXC_GPIO1_IO14__USDHC3_CD_B 0x04C 0x2AC 0x608 0x4 0x0 +#define MX8MP_IOMUXC_GPIO1_IO14__PWM3_OUT 0x04C 0x2AC 0x000 0x5 0x0 +#define MX8MP_IOMUXC_GPIO1_IO14__CCMSRCGPCMIX_CLKO1 0x04C 0x2AC 0x000 0x6 0x0 +#define MX8MP_IOMUXC_GPIO1_IO14__CSU_CSU_ALARM_AUT02 0x04C 0x2AC 0x000 0x7 0x0 +#define MX8MP_IOMUXC_GPIO1_IO15__GPIO1_IO15 0x050 0x2B0 0x000 0x0 0x0 +#define MX8MP_IOMUXC_GPIO1_IO15__HSIOMIX_usb2_OTG_OC 0x050 0x2B0 0x000 0x1 0x0 +#define MX8MP_IOMUXC_GPIO1_IO15__USDHC3_WP 0x050 0x2B0 0x634 0x4 0x0 +#define MX8MP_IOMUXC_GPIO1_IO15__PWM4_OUT 0x050 0x2B0 0x000 0x5 0x0 +#define MX8MP_IOMUXC_GPIO1_IO15__CCMSRCGPCMIX_CLKO2 0x050 0x2B0 0x000 0x6 0x0 +#define MX8MP_IOMUXC_GPIO1_IO15__CSU_CSU_INT_DEB 0x050 0x2B0 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC 0x054 0x2B4 0x000 0x0 0x0 +#define MX8MP_IOMUXC_ENET_MDC__AUDIOMIX_SAI6_TX_DATA00 0x054 0x2B4 0x000 0x2 0x0 +#define MX8MP_IOMUXC_ENET_MDC__GPIO1_IO16 0x054 0x2B4 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ENET_MDC__USDHC3_STROBE 0x054 0x2B4 0x630 0x6 0x0 +#define MX8MP_IOMUXC_ENET_MDC__SIM_M_HADDR15 0x054 0x2B4 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ENET_MDIO__ENET_QOS_MDIO 0x058 0x2B8 0x590 0x0 0x1 +#define MX8MP_IOMUXC_ENET_MDIO__AUDIOMIX_SAI6_TX_SYNC 0x058 0x2B8 0x528 0x2 0x0 +#define MX8MP_IOMUXC_ENET_MDIO__GPIO1_IO17 0x058 0x2B8 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ENET_MDIO__USDHC3_DATA5 0x058 0x2B8 0x624 0x6 0x0 +#define MX8MP_IOMUXC_ENET_MDIO__SIM_M_HADDR16 0x058 0x2B8 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ENET_TD3__ENET_QOS_RGMII_TD3 0x05C 0x2BC 0x000 0x0 0x0 +#define MX8MP_IOMUXC_ENET_TD3__AUDIOMIX_SAI6_TX_BCLK 0x05C 0x2BC 0x524 0x2 0x0 +#define MX8MP_IOMUXC_ENET_TD3__GPIO1_IO18 0x05C 0x2BC 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ENET_TD3__USDHC3_DATA6 0x05C 0x2BC 0x628 0x6 0x0 +#define MX8MP_IOMUXC_ENET_TD3__SIM_M_HADDR17 0x05C 0x2BC 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ENET_TD2__ENET_QOS_RGMII_TD2 0x060 0x2C0 0x000 0x0 0x0 +#define MX8MP_IOMUXC_ENET_TD2__CCM_ENET_QOS_CLOCK_GENERATE_REF_CLK 0x060 0x2C0 0x000 0x1 0x0 +#define MX8MP_IOMUXC_ENET_TD2__AUDIOMIX_SAI6_RX_DATA00 0x060 0x2C0 0x51C 0x2 0x0 +#define MX8MP_IOMUXC_ENET_TD2__GPIO1_IO19 0x060 0x2C0 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ENET_TD2__USDHC3_DATA7 0x060 0x2C0 0x62C 0x6 0x0 +#define MX8MP_IOMUXC_ENET_TD2__SIM_M_HADDR18 0x060 0x2C0 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ENET_TD1__ENET_QOS_RGMII_TD1 0x064 0x2C4 0x000 0x0 0x0 +#define MX8MP_IOMUXC_ENET_TD1__AUDIOMIX_SAI6_RX_SYNC 0x064 0x2C4 0x520 0x2 0x0 +#define MX8MP_IOMUXC_ENET_TD1__GPIO1_IO20 0x064 0x2C4 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ENET_TD1__USDHC3_CD_B 0x064 0x2C4 0x608 0x6 0x1 +#define MX8MP_IOMUXC_ENET_TD1__SIM_M_HADDR19 0x064 0x2C4 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ENET_TD0__ENET_QOS_RGMII_TD0 0x068 0x2C8 0x000 0x0 0x0 +#define MX8MP_IOMUXC_ENET_TD0__AUDIOMIX_SAI6_RX_BCLK 0x068 0x2C8 0x518 0x2 0x0 +#define MX8MP_IOMUXC_ENET_TD0__GPIO1_IO21 0x068 0x2C8 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ENET_TD0__USDHC3_WP 0x068 0x2C8 0x634 0x6 0x1 +#define MX8MP_IOMUXC_ENET_TD0__SIM_M_HADDR20 0x068 0x2C8 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ENET_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x06C 0x2CC 0x000 0x0 0x0 +#define MX8MP_IOMUXC_ENET_TX_CTL__AUDIOMIX_SAI6_MCLK 0x06C 0x2CC 0x514 0x2 0x0 +#define MX8MP_IOMUXC_ENET_TX_CTL__AUDIOMIX_SPDIF_OUT 0x06C 0x2CC 0x000 0x3 0x0 +#define MX8MP_IOMUXC_ENET_TX_CTL__GPIO1_IO22 0x06C 0x2CC 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ENET_TX_CTL__USDHC3_DATA0 0x06C 0x2CC 0x610 0x6 0x0 +#define MX8MP_IOMUXC_ENET_TX_CTL__SIM_M_HADDR21 0x06C 0x2CC 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ENET_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x070 0x2D0 0x000 0x0 0x0 +#define MX8MP_IOMUXC_ENET_TXC__ENET_QOS_TX_ER 0x070 0x2D0 0x000 0x1 0x0 +#define MX8MP_IOMUXC_ENET_TXC__AUDIOMIX_SAI7_TX_DATA00 0x070 0x2D0 0x000 0x2 0x0 +#define MX8MP_IOMUXC_ENET_TXC__GPIO1_IO23 0x070 0x2D0 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ENET_TXC__USDHC3_DATA1 0x070 0x2D0 0x614 0x6 0x0 +#define MX8MP_IOMUXC_ENET_TXC__SIM_M_HADDR22 0x070 0x2D0 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ENET_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x074 0x2D4 0x000 0x0 0x0 +#define MX8MP_IOMUXC_ENET_RX_CTL__AUDIOMIX_SAI7_TX_SYNC 0x074 0x2D4 0x540 0x2 0x0 +#define MX8MP_IOMUXC_ENET_RX_CTL__AUDIOMIX_BIT_STREAM03 0x074 0x2D4 0x4CC 0x3 0x0 +#define MX8MP_IOMUXC_ENET_RX_CTL__GPIO1_IO24 0x074 0x2D4 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ENET_RX_CTL__USDHC3_DATA2 0x074 0x2D4 0x618 0x6 0x0 +#define MX8MP_IOMUXC_ENET_RX_CTL__SIM_M_HADDR23 0x074 0x2D4 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ENET_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x078 0x2D8 0x000 0x0 0x0 +#define MX8MP_IOMUXC_ENET_RXC__ENET_QOS_RX_ER 0x078 0x2D8 0x000 0x1 0x0 +#define MX8MP_IOMUXC_ENET_RXC__AUDIOMIX_SAI7_TX_BCLK 0x078 0x2D8 0x53C 0x2 0x0 +#define MX8MP_IOMUXC_ENET_RXC__AUDIOMIX_BIT_STREAM02 0x078 0x2D8 0x4C8 0x3 0x0 +#define MX8MP_IOMUXC_ENET_RXC__GPIO1_IO25 0x078 0x2D8 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ENET_RXC__USDHC3_DATA3 0x078 0x2D8 0x61C 0x6 0x0 +#define MX8MP_IOMUXC_ENET_RXC__SIM_M_HADDR24 0x078 0x2D8 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ENET_RD0__ENET_QOS_RGMII_RD0 0x07C 0x2DC 0x000 0x0 0x0 +#define MX8MP_IOMUXC_ENET_RD0__AUDIOMIX_SAI7_RX_DATA00 0x07C 0x2DC 0x534 0x2 0x0 +#define MX8MP_IOMUXC_ENET_RD0__AUDIOMIX_BIT_STREAM01 0x07C 0x2DC 0x4C4 0x3 0x0 +#define MX8MP_IOMUXC_ENET_RD0__GPIO1_IO26 0x07C 0x2DC 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ENET_RD0__USDHC3_DATA4 0x07C 0x2DC 0x620 0x6 0x0 +#define MX8MP_IOMUXC_ENET_RD0__SIM_M_HADDR25 0x07C 0x2DC 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ENET_RD1__ENET_QOS_RGMII_RD1 0x080 0x2E0 0x000 0x0 0x0 +#define MX8MP_IOMUXC_ENET_RD1__AUDIOMIX_SAI7_RX_SYNC 0x080 0x2E0 0x538 0x2 0x0 +#define MX8MP_IOMUXC_ENET_RD1__AUDIOMIX_BIT_STREAM00 0x080 0x2E0 0x4C0 0x3 0x0 +#define MX8MP_IOMUXC_ENET_RD1__GPIO1_IO27 0x080 0x2E0 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ENET_RD1__USDHC3_RESET_B 0x080 0x2E0 0x000 0x6 0x0 +#define MX8MP_IOMUXC_ENET_RD1__SIM_M_HADDR26 0x080 0x2E0 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ENET_RD2__ENET_QOS_RGMII_RD2 0x084 0x2E4 0x000 0x0 0x0 +#define MX8MP_IOMUXC_ENET_RD2__AUDIOMIX_SAI7_RX_BCLK 0x084 0x2E4 0x530 0x2 0x0 +#define MX8MP_IOMUXC_ENET_RD2__AUDIOMIX_CLK 0x084 0x2E4 0x000 0x3 0x0 +#define MX8MP_IOMUXC_ENET_RD2__GPIO1_IO28 0x084 0x2E4 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ENET_RD2__USDHC3_CLK 0x084 0x2E4 0x604 0x6 0x0 +#define MX8MP_IOMUXC_ENET_RD2__SIM_M_HADDR27 0x084 0x2E4 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ENET_RD3__ENET_QOS_RGMII_RD3 0x088 0x2E8 0x000 0x0 0x0 +#define MX8MP_IOMUXC_ENET_RD3__AUDIOMIX_SAI7_MCLK 0x088 0x2E8 0x52C 0x2 0x0 +#define MX8MP_IOMUXC_ENET_RD3__AUDIOMIX_SPDIF_IN 0x088 0x2E8 0x544 0x3 0x0 +#define MX8MP_IOMUXC_ENET_RD3__GPIO1_IO29 0x088 0x2E8 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ENET_RD3__USDHC3_CMD 0x088 0x2E8 0x60C 0x6 0x0 +#define MX8MP_IOMUXC_ENET_RD3__SIM_M_HADDR28 0x088 0x2E8 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD1_CLK__USDHC1_CLK 0x08C 0x2EC 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD1_CLK__ENET1_MDC 0x08C 0x2EC 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SD1_CLK__I2C5_SCL 0x08C 0x2EC 0x5C4 0x3 0x0 +#define MX8MP_IOMUXC_SD1_CLK__UART1_DCE_TX 0x08C 0x2EC 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SD1_CLK__UART1_DTE_RX 0x08C 0x2EC 0x5E8 0x4 0x0 +#define MX8MP_IOMUXC_SD1_CLK__GPIO2_IO00 0x08C 0x2EC 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD1_CLK__SIM_M_HADDR29 0x08C 0x2EC 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD1_CMD__USDHC1_CMD 0x090 0x2F0 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD1_CMD__ENET1_MDIO 0x090 0x2F0 0x57C 0x1 0x0 +#define MX8MP_IOMUXC_SD1_CMD__I2C5_SDA 0x090 0x2F0 0x5C8 0x3 0x0 +#define MX8MP_IOMUXC_SD1_CMD__UART1_DCE_RX 0x090 0x2F0 0x5E8 0x4 0x1 +#define MX8MP_IOMUXC_SD1_CMD__UART1_DTE_TX 0x090 0x2F0 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SD1_CMD__GPIO2_IO01 0x090 0x2F0 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD1_CMD__SIM_M_HADDR30 0x090 0x2F0 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD1_DATA0__USDHC1_DATA0 0x094 0x2F4 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD1_DATA0__ENET1_RGMII_TD1 0x094 0x2F4 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SD1_DATA0__I2C6_SCL 0x094 0x2F4 0x5CC 0x3 0x0 +#define MX8MP_IOMUXC_SD1_DATA0__UART1_DCE_RTS 0x094 0x2F4 0x5E4 0x4 0x0 +#define MX8MP_IOMUXC_SD1_DATA0__UART1_DTE_CTS 0x094 0x2F4 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SD1_DATA0__GPIO2_IO02 0x094 0x2F4 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD1_DATA0__SIM_M_HADDR31 0x094 0x2F4 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x098 0x2F8 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD1_DATA1__ENET1_RGMII_TD0 0x098 0x2F8 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SD1_DATA1__I2C6_SDA 0x098 0x2F8 0x5D0 0x3 0x0 +#define MX8MP_IOMUXC_SD1_DATA1__UART1_DCE_CTS 0x098 0x2F8 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SD1_DATA1__UART1_DTE_RTS 0x098 0x2F8 0x5E4 0x4 0x1 +#define MX8MP_IOMUXC_SD1_DATA1__GPIO2_IO03 0x098 0x2F8 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD1_DATA1__SIM_M_HBURST00 0x098 0x2F8 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x09C 0x2FC 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD1_DATA2__ENET1_RGMII_RD0 0x09C 0x2FC 0x580 0x1 0x0 +#define MX8MP_IOMUXC_SD1_DATA2__I2C4_SCL 0x09C 0x2FC 0x5BC 0x3 0x0 +#define MX8MP_IOMUXC_SD1_DATA2__UART2_DCE_TX 0x09C 0x2FC 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SD1_DATA2__UART2_DTE_RX 0x09C 0x2FC 0x5F0 0x4 0x0 +#define MX8MP_IOMUXC_SD1_DATA2__GPIO2_IO04 0x09C 0x2FC 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD1_DATA2__SIM_M_HBURST01 0x09C 0x2FC 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x0A0 0x300 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD1_DATA3__ENET1_RGMII_RD1 0x0A0 0x300 0x584 0x1 0x0 +#define MX8MP_IOMUXC_SD1_DATA3__I2C4_SDA 0x0A0 0x300 0x5C0 0x3 0x0 +#define MX8MP_IOMUXC_SD1_DATA3__UART2_DCE_RX 0x0A0 0x300 0x5F0 0x4 0x1 +#define MX8MP_IOMUXC_SD1_DATA3__UART2_DTE_TX 0x0A0 0x300 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SD1_DATA3__GPIO2_IO05 0x0A0 0x300 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD1_DATA3__SIM_M_HBURST02 0x0A0 0x300 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD1_DATA4__USDHC1_DATA4 0x0A4 0x304 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD1_DATA4__ENET1_RGMII_TX_CTL 0x0A4 0x304 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SD1_DATA4__I2C1_SCL 0x0A4 0x304 0x5A4 0x3 0x0 +#define MX8MP_IOMUXC_SD1_DATA4__UART2_DCE_RTS 0x0A4 0x304 0x5EC 0x4 0x0 +#define MX8MP_IOMUXC_SD1_DATA4__UART2_DTE_CTS 0x0A4 0x304 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SD1_DATA4__GPIO2_IO06 0x0A4 0x304 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD1_DATA4__SIM_M_HRESP 0x0A4 0x304 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD1_DATA5__USDHC1_DATA5 0x0A8 0x308 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD1_DATA5__ENET1_TX_ER 0x0A8 0x308 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SD1_DATA5__I2C1_SDA 0x0A8 0x308 0x5A8 0x3 0x0 +#define MX8MP_IOMUXC_SD1_DATA5__UART2_DCE_CTS 0x0A8 0x308 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SD1_DATA5__UART2_DTE_RTS 0x0A8 0x308 0x5EC 0x4 0x1 +#define MX8MP_IOMUXC_SD1_DATA5__GPIO2_IO07 0x0A8 0x308 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD1_DATA5__TPSMP_HDATA05 0x0A8 0x308 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD1_DATA6__USDHC1_DATA6 0x0AC 0x30C 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD1_DATA6__ENET1_RGMII_RX_CTL 0x0AC 0x30C 0x588 0x1 0x0 +#define MX8MP_IOMUXC_SD1_DATA6__I2C2_SCL 0x0AC 0x30C 0x5AC 0x3 0x0 +#define MX8MP_IOMUXC_SD1_DATA6__UART3_DCE_TX 0x0AC 0x30C 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SD1_DATA6__UART3_DTE_RX 0x0AC 0x30C 0x5F8 0x4 0x0 +#define MX8MP_IOMUXC_SD1_DATA6__GPIO2_IO08 0x0AC 0x30C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD1_DATA6__TPSMP_HDATA06 0x0AC 0x30C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD1_DATA7__USDHC1_DATA7 0x0B0 0x310 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD1_DATA7__ENET1_RX_ER 0x0B0 0x310 0x58C 0x1 0x0 +#define MX8MP_IOMUXC_SD1_DATA7__I2C2_SDA 0x0B0 0x310 0x5B0 0x3 0x0 +#define MX8MP_IOMUXC_SD1_DATA7__UART3_DCE_RX 0x0B0 0x310 0x5F8 0x4 0x1 +#define MX8MP_IOMUXC_SD1_DATA7__UART3_DTE_TX 0x0B0 0x310 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SD1_DATA7__GPIO2_IO09 0x0B0 0x310 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD1_DATA7__TPSMP_HDATA07 0x0B0 0x310 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD1_RESET_B__USDHC1_RESET_B 0x0B4 0x314 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD1_RESET_B__ENET1_TX_CLK 0x0B4 0x314 0x578 0x1 0x0 +#define MX8MP_IOMUXC_SD1_RESET_B__I2C3_SCL 0x0B4 0x314 0x5B4 0x3 0x0 +#define MX8MP_IOMUXC_SD1_RESET_B__UART3_DCE_RTS 0x0B4 0x314 0x5F4 0x4 0x0 +#define MX8MP_IOMUXC_SD1_RESET_B__UART3_DTE_CTS 0x0B4 0x314 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SD1_RESET_B__GPIO2_IO10 0x0B4 0x314 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD1_RESET_B__ECSPI3_TEST_TRIG 0x0B4 0x314 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD1_STROBE__USDHC1_STROBE 0x0B8 0x318 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD1_STROBE__I2C3_SDA 0x0B8 0x318 0x5B8 0x3 0x0 +#define MX8MP_IOMUXC_SD1_STROBE__UART3_DCE_CTS 0x0B8 0x318 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SD1_STROBE__UART3_DTE_RTS 0x0B8 0x318 0x5F4 0x4 0x1 +#define MX8MP_IOMUXC_SD1_STROBE__GPIO2_IO11 0x0B8 0x318 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD1_STROBE__USDHC3_TEST_TRIG 0x0B8 0x318 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD2_CD_B__USDHC2_CD_B 0x0BC 0x31C 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD2_CD_B__GPIO2_IO12 0x0BC 0x31C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD2_CD_B__CCMSRCGPCMIX_TESTER_ACK 0x0BC 0x31C 0x000 0x6 0x0 +#define MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x0C0 0x320 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD2_CLK__ECSPI2_SCLK 0x0C0 0x320 0x568 0x2 0x0 +#define MX8MP_IOMUXC_SD2_CLK__UART4_DCE_RX 0x0C0 0x320 0x600 0x3 0x0 +#define MX8MP_IOMUXC_SD2_CLK__UART4_DTE_TX 0x0C0 0x320 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SD2_CLK__GPIO2_IO13 0x0C0 0x320 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD2_CLK__CCMSRCGPCMIX_OBSERVE0 0x0C0 0x320 0x000 0x6 0x0 +#define MX8MP_IOMUXC_SD2_CLK__OBSERVE_MUX_OUT00 0x0C0 0x320 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x0C4 0x324 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD2_CMD__ECSPI2_MOSI 0x0C4 0x324 0x570 0x2 0x0 +#define MX8MP_IOMUXC_SD2_CMD__UART4_DCE_TX 0x0C4 0x324 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SD2_CMD__UART4_DTE_RX 0x0C4 0x324 0x600 0x3 0x1 +#define MX8MP_IOMUXC_SD2_CMD__AUDIOMIX_CLK 0x0C4 0x324 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SD2_CMD__GPIO2_IO14 0x0C4 0x324 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD2_CMD__CCMSRCGPCMIX_OBSERVE1 0x0C4 0x324 0x000 0x6 0x0 +#define MX8MP_IOMUXC_SD2_CMD__OBSERVE_MUX_OUT01 0x0C4 0x324 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x0C8 0x328 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD2_DATA0__I2C4_SDA 0x0C8 0x328 0x5C0 0x2 0x1 +#define MX8MP_IOMUXC_SD2_DATA0__UART2_DCE_RX 0x0C8 0x328 0x5F0 0x3 0x2 +#define MX8MP_IOMUXC_SD2_DATA0__UART2_DTE_TX 0x0C8 0x328 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SD2_DATA0__AUDIOMIX_BIT_STREAM00 0x0C8 0x328 0x4C0 0x4 0x1 +#define MX8MP_IOMUXC_SD2_DATA0__GPIO2_IO15 0x0C8 0x328 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD2_DATA0__CCMSRCGPCMIX_OBSERVE2 0x0C8 0x328 0x000 0x6 0x0 +#define MX8MP_IOMUXC_SD2_DATA0__OBSERVE_MUX_OUT02 0x0C8 0x328 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x0CC 0x32C 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD2_DATA1__I2C4_SCL 0x0CC 0x32C 0x5BC 0x2 0x1 +#define MX8MP_IOMUXC_SD2_DATA1__UART2_DCE_TX 0x0CC 0x32C 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SD2_DATA1__UART2_DTE_RX 0x0CC 0x32C 0x5F0 0x3 0x3 +#define MX8MP_IOMUXC_SD2_DATA1__AUDIOMIX_BIT_STREAM01 0x0CC 0x32C 0x4C4 0x4 0x1 +#define MX8MP_IOMUXC_SD2_DATA1__GPIO2_IO16 0x0CC 0x32C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD2_DATA1__CCMSRCGPCMIX_WAIT 0x0CC 0x32C 0x000 0x6 0x0 +#define MX8MP_IOMUXC_SD2_DATA1__OBSERVE_MUX_OUT03 0x0CC 0x32C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x0D0 0x330 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD2_DATA2__ECSPI2_SS0 0x0D0 0x330 0x574 0x2 0x0 +#define MX8MP_IOMUXC_SD2_DATA2__AUDIOMIX_SPDIF_OUT 0x0D0 0x330 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SD2_DATA2__AUDIOMIX_BIT_STREAM02 0x0D0 0x330 0x4C8 0x4 0x1 +#define MX8MP_IOMUXC_SD2_DATA2__GPIO2_IO17 0x0D0 0x330 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD2_DATA2__CCMSRCGPCMIX_STOP 0x0D0 0x330 0x000 0x6 0x0 +#define MX8MP_IOMUXC_SD2_DATA2__OBSERVE_MUX_OUT04 0x0D0 0x330 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x0D4 0x334 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD2_DATA3__ECSPI2_MISO 0x0D4 0x334 0x56C 0x2 0x0 +#define MX8MP_IOMUXC_SD2_DATA3__AUDIOMIX_SPDIF_IN 0x0D4 0x334 0x544 0x3 0x1 +#define MX8MP_IOMUXC_SD2_DATA3__AUDIOMIX_BIT_STREAM03 0x0D4 0x334 0x4CC 0x4 0x1 +#define MX8MP_IOMUXC_SD2_DATA3__GPIO2_IO18 0x0D4 0x334 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD2_DATA3__CCMSRCGPCMIX_EARLY_RESET 0x0D4 0x334 0x000 0x6 0x0 +#define MX8MP_IOMUXC_SD2_RESET_B__USDHC2_RESET_B 0x0D8 0x338 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19 0x0D8 0x338 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD2_RESET_B__CCMSRCGPCMIX_SYSTEM_RESET 0x0D8 0x338 0x000 0x6 0x0 +#define MX8MP_IOMUXC_SD2_WP__USDHC2_WP 0x0DC 0x33C 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SD2_WP__GPIO2_IO20 0x0DC 0x33C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SD2_WP__CORESIGHT_EVENTI 0x0DC 0x33C 0x000 0x6 0x0 +#define MX8MP_IOMUXC_SD2_WP__SIM_M_HMASTLOCK 0x0DC 0x33C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_ALE__RAWNAND_ALE 0x0E0 0x340 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_ALE__FLEXSPI_A_SCLK 0x0E0 0x340 0x000 0x1 0x0 +#define MX8MP_IOMUXC_NAND_ALE__AUDIOMIX_SAI3_TX_BCLK 0x0E0 0x340 0x4E8 0x2 0x0 +#define MX8MP_IOMUXC_NAND_ALE__MEDIAMIX_ISP_FL_TRIG_0 0x0E0 0x340 0x5D4 0x3 0x1 +#define MX8MP_IOMUXC_NAND_ALE__UART3_DCE_RX 0x0E0 0x340 0x5F8 0x4 0x2 +#define MX8MP_IOMUXC_NAND_ALE__UART3_DTE_TX 0x0E0 0x340 0x000 0x4 0x0 +#define MX8MP_IOMUXC_NAND_ALE__GPIO3_IO00 0x0E0 0x340 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_ALE__CORESIGHT_TRACE_CLK 0x0E0 0x340 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_ALE__SIM_M_HPROT00 0x0E0 0x340 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_CE0_B__RAWNAND_CE0_B 0x0E4 0x344 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_CE0_B__FLEXSPI_A_SS0_B 0x0E4 0x344 0x000 0x1 0x0 +#define MX8MP_IOMUXC_NAND_CE0_B__AUDIOMIX_SAI3_TX_DATA00 0x0E4 0x344 0x000 0x2 0x0 +#define MX8MP_IOMUXC_NAND_CE0_B__MEDIAMIX_ISP_SHUTTER_TRIG_0 0x0E4 0x344 0x5DC 0x3 0x1 +#define MX8MP_IOMUXC_NAND_CE0_B__UART3_DCE_TX 0x0E4 0x344 0x000 0x4 0x0 +#define MX8MP_IOMUXC_NAND_CE0_B__UART3_DTE_RX 0x0E4 0x344 0x5F8 0x4 0x3 +#define MX8MP_IOMUXC_NAND_CE0_B__GPIO3_IO01 0x0E4 0x344 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_CE0_B__CORESIGHT_TRACE_CTL 0x0E4 0x344 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_CE0_B__SIM_M_HPROT01 0x0E4 0x344 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_CE1_B__RAWNAND_CE1_B 0x0E8 0x348 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_CE1_B__FLEXSPI_A_SS1_B 0x0E8 0x348 0x000 0x1 0x0 +#define MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x0E8 0x348 0x630 0x2 0x1 +#define MX8MP_IOMUXC_NAND_CE1_B__I2C4_SCL 0x0E8 0x348 0x5BC 0x4 0x2 +#define MX8MP_IOMUXC_NAND_CE1_B__GPIO3_IO02 0x0E8 0x348 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_CE1_B__CORESIGHT_TRACE00 0x0E8 0x348 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_CE1_B__SIM_M_HPROT02 0x0E8 0x348 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_CE2_B__RAWNAND_CE2_B 0x0EC 0x34C 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_CE2_B__FLEXSPI_B_SS0_B 0x0EC 0x34C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x0EC 0x34C 0x624 0x2 0x1 +#define MX8MP_IOMUXC_NAND_CE2_B__I2C4_SDA 0x0EC 0x34C 0x5C0 0x4 0x2 +#define MX8MP_IOMUXC_NAND_CE2_B__GPIO3_IO03 0x0EC 0x34C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_CE2_B__CORESIGHT_TRACE01 0x0EC 0x34C 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_CE2_B__SIM_M_HPROT03 0x0EC 0x34C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_CE3_B__RAWNAND_CE3_B 0x0F0 0x350 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_CE3_B__FLEXSPI_B_SS1_B 0x0F0 0x350 0x000 0x1 0x0 +#define MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x0F0 0x350 0x628 0x2 0x1 +#define MX8MP_IOMUXC_NAND_CE3_B__I2C3_SDA 0x0F0 0x350 0x5B8 0x4 0x1 +#define MX8MP_IOMUXC_NAND_CE3_B__GPIO3_IO04 0x0F0 0x350 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_CE3_B__CORESIGHT_TRACE02 0x0F0 0x350 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_CE3_B__SIM_M_HADDR00 0x0F0 0x350 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_CLE__RAWNAND_CLE 0x0F4 0x354 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_CLE__FLEXSPI_B_SCLK 0x0F4 0x354 0x000 0x1 0x0 +#define MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x0F4 0x354 0x62C 0x2 0x1 +#define MX8MP_IOMUXC_NAND_CLE__UART4_DCE_RX 0x0F4 0x354 0x600 0x4 0x2 +#define MX8MP_IOMUXC_NAND_CLE__UART4_DTE_TX 0x0F4 0x354 0x000 0x4 0x0 +#define MX8MP_IOMUXC_NAND_CLE__GPIO3_IO05 0x0F4 0x354 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_CLE__CORESIGHT_TRACE03 0x0F4 0x354 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_CLE__SIM_M_HADDR01 0x0F4 0x354 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_DATA00__RAWNAND_DATA00 0x0F8 0x358 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_DATA00__FLEXSPI_A_DATA00 0x0F8 0x358 0x000 0x1 0x0 +#define MX8MP_IOMUXC_NAND_DATA00__AUDIOMIX_SAI3_RX_DATA00 0x0F8 0x358 0x4E4 0x2 0x0 +#define MX8MP_IOMUXC_NAND_DATA00__MEDIAMIX_ISP_FLASH_TRIG_0 0x0F8 0x358 0x000 0x3 0x0 +#define MX8MP_IOMUXC_NAND_DATA00__UART4_DCE_RX 0x0F8 0x358 0x600 0x4 0x3 +#define MX8MP_IOMUXC_NAND_DATA00__UART4_DTE_TX 0x0F8 0x358 0x000 0x4 0x0 +#define MX8MP_IOMUXC_NAND_DATA00__GPIO3_IO06 0x0F8 0x358 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_DATA00__CORESIGHT_TRACE04 0x0F8 0x358 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_DATA00__SIM_M_HADDR02 0x0F8 0x358 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_DATA01__RAWNAND_DATA01 0x0FC 0x35C 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_DATA01__FLEXSPI_A_DATA01 0x0FC 0x35C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_NAND_DATA01__AUDIOMIX_SAI3_TX_SYNC 0x0FC 0x35C 0x4EC 0x2 0x0 +#define MX8MP_IOMUXC_NAND_DATA01__MEDIAMIX_ISP_PRELIGHT_TRIG_0 0x0FC 0x35C 0x000 0x3 0x0 +#define MX8MP_IOMUXC_NAND_DATA01__UART4_DCE_TX 0x0FC 0x35C 0x000 0x4 0x0 +#define MX8MP_IOMUXC_NAND_DATA01__UART4_DTE_RX 0x0FC 0x35C 0x600 0x4 0x4 +#define MX8MP_IOMUXC_NAND_DATA01__GPIO3_IO07 0x0FC 0x35C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_DATA01__CORESIGHT_TRACE05 0x0FC 0x35C 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_DATA01__SIM_M_HADDR03 0x0FC 0x35C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_DATA02__RAWNAND_DATA02 0x100 0x360 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_DATA02__FLEXSPI_A_DATA02 0x100 0x360 0x000 0x1 0x0 +#define MX8MP_IOMUXC_NAND_DATA02__USDHC3_CD_B 0x100 0x360 0x608 0x2 0x2 +#define MX8MP_IOMUXC_NAND_DATA02__UART4_DCE_CTS 0x100 0x360 0x000 0x3 0x0 +#define MX8MP_IOMUXC_NAND_DATA02__UART4_DTE_RTS 0x100 0x360 0x5FC 0x3 0x0 +#define MX8MP_IOMUXC_NAND_DATA02__I2C4_SDA 0x100 0x360 0x5C0 0x4 0x3 +#define MX8MP_IOMUXC_NAND_DATA02__GPIO3_IO08 0x100 0x360 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_DATA02__CORESIGHT_TRACE06 0x100 0x360 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_DATA02__SIM_M_HADDR04 0x100 0x360 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_DATA03__RAWNAND_DATA03 0x104 0x364 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_DATA03__FLEXSPI_A_DATA03 0x104 0x364 0x000 0x1 0x0 +#define MX8MP_IOMUXC_NAND_DATA03__USDHC3_WP 0x104 0x364 0x634 0x2 0x2 +#define MX8MP_IOMUXC_NAND_DATA03__UART4_DCE_RTS 0x104 0x364 0x5FC 0x3 0x1 +#define MX8MP_IOMUXC_NAND_DATA03__UART4_DTE_CTS 0x104 0x364 0x000 0x3 0x0 +#define MX8MP_IOMUXC_NAND_DATA03__MEDIAMIX_ISP_FL_TRIG_1 0x104 0x364 0x5D8 0x4 0x1 +#define MX8MP_IOMUXC_NAND_DATA03__GPIO3_IO09 0x104 0x364 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_DATA03__CORESIGHT_TRACE07 0x104 0x364 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_DATA03__SIM_M_HADDR05 0x104 0x364 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_DATA04__RAWNAND_DATA04 0x108 0x368 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_DATA04__FLEXSPI_B_DATA00 0x108 0x368 0x000 0x1 0x0 +#define MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x108 0x368 0x610 0x2 0x1 +#define MX8MP_IOMUXC_NAND_DATA04__FLEXSPI_A_DATA04 0x108 0x368 0x000 0x3 0x0 +#define MX8MP_IOMUXC_NAND_DATA04__MEDIAMIX_ISP_SHUTTER_TRIG_1 0x108 0x368 0x5E0 0x4 0x1 +#define MX8MP_IOMUXC_NAND_DATA04__GPIO3_IO10 0x108 0x368 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_DATA04__CORESIGHT_TRACE08 0x108 0x368 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_DATA04__SIM_M_HADDR06 0x108 0x368 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_DATA05__RAWNAND_DATA05 0x10C 0x36C 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_DATA05__FLEXSPI_B_DATA01 0x10C 0x36C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x10C 0x36C 0x614 0x2 0x1 +#define MX8MP_IOMUXC_NAND_DATA05__FLEXSPI_A_DATA05 0x10C 0x36C 0x000 0x3 0x0 +#define MX8MP_IOMUXC_NAND_DATA05__MEDIAMIX_ISP_FLASH_TRIG_1 0x10C 0x36C 0x000 0x4 0x0 +#define MX8MP_IOMUXC_NAND_DATA05__GPIO3_IO11 0x10C 0x36C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_DATA05__CORESIGHT_TRACE09 0x10C 0x36C 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_DATA05__SIM_M_HADDR07 0x10C 0x36C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_DATA06__RAWNAND_DATA06 0x110 0x370 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_DATA06__FLEXSPI_B_DATA02 0x110 0x370 0x000 0x1 0x0 +#define MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x110 0x370 0x618 0x2 0x1 +#define MX8MP_IOMUXC_NAND_DATA06__FLEXSPI_A_DATA06 0x110 0x370 0x000 0x3 0x0 +#define MX8MP_IOMUXC_NAND_DATA06__MEDIAMIX_ISP_PRELIGHT_TRIG_1 0x110 0x370 0x000 0x4 0x0 +#define MX8MP_IOMUXC_NAND_DATA06__GPIO3_IO12 0x110 0x370 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_DATA06__CORESIGHT_TRACE10 0x110 0x370 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_DATA06__SIM_M_HADDR08 0x110 0x370 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_DATA07__RAWNAND_DATA07 0x114 0x374 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_DATA07__FLEXSPI_B_DATA03 0x114 0x374 0x000 0x1 0x0 +#define MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x114 0x374 0x61C 0x2 0x1 +#define MX8MP_IOMUXC_NAND_DATA07__FLEXSPI_A_DATA07 0x114 0x374 0x000 0x3 0x0 +#define MX8MP_IOMUXC_NAND_DATA07__MEDIAMIX_ISP_SHUTTER_OPEN_1 0x114 0x374 0x000 0x4 0x0 +#define MX8MP_IOMUXC_NAND_DATA07__GPIO3_IO13 0x114 0x374 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_DATA07__CORESIGHT_TRACE11 0x114 0x374 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_DATA07__SIM_M_HADDR09 0x114 0x374 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_DQS__RAWNAND_DQS 0x118 0x378 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_DQS__FLEXSPI_A_DQS 0x118 0x378 0x000 0x1 0x0 +#define MX8MP_IOMUXC_NAND_DQS__AUDIOMIX_SAI3_MCLK 0x118 0x378 0x4E0 0x2 0x0 +#define MX8MP_IOMUXC_NAND_DQS__MEDIAMIX_ISP_SHUTTER_OPEN_0 0x118 0x378 0x000 0x3 0x0 +#define MX8MP_IOMUXC_NAND_DQS__I2C3_SCL 0x118 0x378 0x5B4 0x4 0x1 +#define MX8MP_IOMUXC_NAND_DQS__GPIO3_IO14 0x118 0x378 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_DQS__CORESIGHT_TRACE12 0x118 0x378 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_DQS__SIM_M_HADDR10 0x118 0x378 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_RE_B__RAWNAND_RE_B 0x11C 0x37C 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_RE_B__FLEXSPI_B_DQS 0x11C 0x37C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x11C 0x37C 0x620 0x2 0x1 +#define MX8MP_IOMUXC_NAND_RE_B__UART4_DCE_TX 0x11C 0x37C 0x000 0x4 0x0 +#define MX8MP_IOMUXC_NAND_RE_B__UART4_DTE_RX 0x11C 0x37C 0x600 0x4 0x5 +#define MX8MP_IOMUXC_NAND_RE_B__GPIO3_IO15 0x11C 0x37C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_RE_B__CORESIGHT_TRACE13 0x11C 0x37C 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_RE_B__SIM_M_HADDR11 0x11C 0x37C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_READY_B__RAWNAND_READY_B 0x120 0x380 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_READY_B__USDHC3_RESET_B 0x120 0x380 0x000 0x2 0x0 +#define MX8MP_IOMUXC_NAND_READY_B__I2C3_SCL 0x120 0x380 0x5B4 0x4 0x2 +#define MX8MP_IOMUXC_NAND_READY_B__GPIO3_IO16 0x120 0x380 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_READY_B__CORESIGHT_TRACE14 0x120 0x380 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_READY_B__SIM_M_HADDR12 0x120 0x380 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_WE_B__RAWNAND_WE_B 0x124 0x384 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x124 0x384 0x604 0x2 0x1 +#define MX8MP_IOMUXC_NAND_WE_B__I2C3_SDA 0x124 0x384 0x5B8 0x4 0x2 +#define MX8MP_IOMUXC_NAND_WE_B__GPIO3_IO17 0x124 0x384 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_WE_B__CORESIGHT_TRACE15 0x124 0x384 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_WE_B__SIM_M_HADDR13 0x124 0x384 0x000 0x7 0x0 +#define MX8MP_IOMUXC_NAND_WP_B__RAWNAND_WP_B 0x128 0x388 0x000 0x0 0x0 +#define MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x128 0x388 0x60C 0x2 0x1 +#define MX8MP_IOMUXC_NAND_WP_B__I2C4_SCL 0x128 0x388 0x5BC 0x4 0x3 +#define MX8MP_IOMUXC_NAND_WP_B__GPIO3_IO18 0x128 0x388 0x000 0x5 0x0 +#define MX8MP_IOMUXC_NAND_WP_B__CORESIGHT_EVENTO 0x128 0x388 0x000 0x6 0x0 +#define MX8MP_IOMUXC_NAND_WP_B__SIM_M_HADDR14 0x128 0x388 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SAI5_RXFS__AUDIOMIX_SAI5_RX_SYNC 0x12C 0x38C 0x508 0x0 0x0 +#define MX8MP_IOMUXC_SAI5_RXFS__AUDIOMIX_SAI1_TX_DATA00 0x12C 0x38C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI5_RXFS__PWM4_OUT 0x12C 0x38C 0x000 0x2 0x0 +#define MX8MP_IOMUXC_SAI5_RXFS__I2C6_SCL 0x12C 0x38C 0x5CC 0x3 0x1 +#define MX8MP_IOMUXC_SAI5_RXFS__GPIO3_IO19 0x12C 0x38C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI5_RXC__AUDIOMIX_SAI5_RX_BCLK 0x130 0x390 0x4F4 0x0 0x0 +#define MX8MP_IOMUXC_SAI5_RXC__AUDIOMIX_SAI1_TX_DATA01 0x130 0x390 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI5_RXC__PWM3_OUT 0x130 0x390 0x000 0x2 0x0 +#define MX8MP_IOMUXC_SAI5_RXC__I2C6_SDA 0x130 0x390 0x5D0 0x3 0x1 +#define MX8MP_IOMUXC_SAI5_RXC__AUDIOMIX_CLK 0x130 0x390 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI5_RXC__GPIO3_IO20 0x130 0x390 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI5_RXD0__AUDIOMIX_SAI5_RX_DATA00 0x134 0x394 0x4F8 0x0 0x0 +#define MX8MP_IOMUXC_SAI5_RXD0__AUDIOMIX_SAI1_TX_DATA02 0x134 0x394 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI5_RXD0__PWM2_OUT 0x134 0x394 0x000 0x2 0x0 +#define MX8MP_IOMUXC_SAI5_RXD0__I2C5_SCL 0x134 0x394 0x5C4 0x3 0x1 +#define MX8MP_IOMUXC_SAI5_RXD0__AUDIOMIX_BIT_STREAM00 0x134 0x394 0x4C0 0x4 0x2 +#define MX8MP_IOMUXC_SAI5_RXD0__GPIO3_IO21 0x134 0x394 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI5_RXD1__AUDIOMIX_SAI5_RX_DATA01 0x138 0x398 0x4FC 0x0 0x0 +#define MX8MP_IOMUXC_SAI5_RXD1__AUDIOMIX_SAI1_TX_DATA03 0x138 0x398 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI5_RXD1__AUDIOMIX_SAI1_TX_SYNC 0x138 0x398 0x4D8 0x2 0x0 +#define MX8MP_IOMUXC_SAI5_RXD1__AUDIOMIX_SAI5_TX_SYNC 0x138 0x398 0x510 0x3 0x0 +#define MX8MP_IOMUXC_SAI5_RXD1__AUDIOMIX_BIT_STREAM01 0x138 0x398 0x4C4 0x4 0x2 +#define MX8MP_IOMUXC_SAI5_RXD1__GPIO3_IO22 0x138 0x398 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI5_RXD1__CAN1_TX 0x138 0x398 0x000 0x6 0x0 +#define MX8MP_IOMUXC_SAI5_RXD2__AUDIOMIX_SAI5_RX_DATA02 0x13C 0x39C 0x500 0x0 0x0 +#define MX8MP_IOMUXC_SAI5_RXD2__AUDIOMIX_SAI1_TX_DATA04 0x13C 0x39C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI5_RXD2__AUDIOMIX_SAI1_TX_SYNC 0x13C 0x39C 0x4D8 0x2 0x1 +#define MX8MP_IOMUXC_SAI5_RXD2__AUDIOMIX_SAI5_TX_BCLK 0x13C 0x39C 0x50C 0x3 0x0 +#define MX8MP_IOMUXC_SAI5_RXD2__AUDIOMIX_BIT_STREAM02 0x13C 0x39C 0x4C8 0x4 0x2 +#define MX8MP_IOMUXC_SAI5_RXD2__GPIO3_IO23 0x13C 0x39C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI5_RXD2__CAN1_RX 0x13C 0x39C 0x54C 0x6 0x0 +#define MX8MP_IOMUXC_SAI5_RXD3__AUDIOMIX_SAI5_RX_DATA03 0x140 0x3A0 0x504 0x0 0x0 +#define MX8MP_IOMUXC_SAI5_RXD3__AUDIOMIX_SAI1_TX_DATA05 0x140 0x3A0 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI5_RXD3__AUDIOMIX_SAI1_TX_SYNC 0x140 0x3A0 0x4D8 0x2 0x2 +#define MX8MP_IOMUXC_SAI5_RXD3__AUDIOMIX_SAI5_TX_DATA00 0x140 0x3A0 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SAI5_RXD3__AUDIOMIX_BIT_STREAM03 0x140 0x3A0 0x4CC 0x4 0x2 +#define MX8MP_IOMUXC_SAI5_RXD3__GPIO3_IO24 0x140 0x3A0 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI5_RXD3__CAN2_TX 0x140 0x3A0 0x000 0x6 0x0 +#define MX8MP_IOMUXC_SAI5_MCLK__AUDIOMIX_SAI5_MCLK 0x144 0x3A4 0x4F0 0x0 0x0 +#define MX8MP_IOMUXC_SAI5_MCLK__AUDIOMIX_SAI1_TX_BCLK 0x144 0x3A4 0x4D4 0x1 0x0 +#define MX8MP_IOMUXC_SAI5_MCLK__PWM1_OUT 0x144 0x3A4 0x000 0x2 0x0 +#define MX8MP_IOMUXC_SAI5_MCLK__I2C5_SDA 0x144 0x3A4 0x5C8 0x3 0x1 +#define MX8MP_IOMUXC_SAI5_MCLK__GPIO3_IO25 0x144 0x3A4 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI5_MCLK__CAN2_RX 0x144 0x3A4 0x550 0x6 0x0 +#define MX8MP_IOMUXC_SAI1_RXFS__AUDIOMIX_SAI1_RX_SYNC 0x148 0x3A8 0x4D0 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_RXFS__AUDIOMIX_SAI5_RX_SYNC 0x148 0x3A8 0x508 0x1 0x1 +#define MX8MP_IOMUXC_SAI1_RXFS__ENET1_1588_EVENT0_IN 0x148 0x3A8 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI1_RXFS__GPIO4_IO00 0x148 0x3A8 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_RXC__AUDIOMIX_SAI1_RX_BCLK 0x14C 0x3AC 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_RXC__AUDIOMIX_SAI5_RX_BCLK 0x14C 0x3AC 0x4F4 0x1 0x1 +#define MX8MP_IOMUXC_SAI1_RXC__AUDIOMIX_CLK 0x14C 0x3AC 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SAI1_RXC__ENET1_1588_EVENT0_OUT 0x14C 0x3AC 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI1_RXC__GPIO4_IO01 0x14C 0x3AC 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_RXD0__AUDIOMIX_SAI1_RX_DATA00 0x150 0x3B0 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_RXD0__AUDIOMIX_SAI5_RX_DATA00 0x150 0x3B0 0x4F8 0x1 0x1 +#define MX8MP_IOMUXC_SAI1_RXD0__AUDIOMIX_SAI1_TX_DATA01 0x150 0x3B0 0x000 0x2 0x0 +#define MX8MP_IOMUXC_SAI1_RXD0__AUDIOMIX_BIT_STREAM00 0x150 0x3B0 0x4C0 0x3 0x3 +#define MX8MP_IOMUXC_SAI1_RXD0__ENET1_1588_EVENT1_IN 0x150 0x3B0 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI1_RXD0__GPIO4_IO02 0x150 0x3B0 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_RXD1__AUDIOMIX_SAI1_RX_DATA01 0x154 0x3B4 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_RXD1__AUDIOMIX_SAI5_RX_DATA01 0x154 0x3B4 0x4FC 0x1 0x1 +#define MX8MP_IOMUXC_SAI1_RXD1__AUDIOMIX_BIT_STREAM01 0x154 0x3B4 0x4C4 0x3 0x3 +#define MX8MP_IOMUXC_SAI1_RXD1__ENET1_1588_EVENT1_OUT 0x154 0x3B4 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI1_RXD1__GPIO4_IO03 0x154 0x3B4 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_RXD2__AUDIOMIX_SAI1_RX_DATA02 0x158 0x3B8 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_RXD2__AUDIOMIX_SAI5_RX_DATA02 0x158 0x3B8 0x500 0x1 0x1 +#define MX8MP_IOMUXC_SAI1_RXD2__AUDIOMIX_BIT_STREAM02 0x158 0x3B8 0x4C8 0x3 0x3 +#define MX8MP_IOMUXC_SAI1_RXD2__ENET1_MDC 0x158 0x3B8 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI1_RXD2__GPIO4_IO04 0x158 0x3B8 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_RXD3__AUDIOMIX_SAI1_RX_DATA03 0x15C 0x3BC 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_RXD3__AUDIOMIX_SAI5_RX_DATA03 0x15C 0x3BC 0x504 0x1 0x1 +#define MX8MP_IOMUXC_SAI1_RXD3__AUDIOMIX_BIT_STREAM03 0x15C 0x3BC 0x4CC 0x3 0x3 +#define MX8MP_IOMUXC_SAI1_RXD3__ENET1_MDIO 0x15C 0x3BC 0x57C 0x4 0x1 +#define MX8MP_IOMUXC_SAI1_RXD3__GPIO4_IO05 0x15C 0x3BC 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_RXD4__AUDIOMIX_SAI1_RX_DATA04 0x160 0x3C0 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_RXD4__AUDIOMIX_SAI6_TX_BCLK 0x160 0x3C0 0x524 0x1 0x1 +#define MX8MP_IOMUXC_SAI1_RXD4__AUDIOMIX_SAI6_RX_BCLK 0x160 0x3C0 0x518 0x2 0x1 +#define MX8MP_IOMUXC_SAI1_RXD4__ENET1_RGMII_RD0 0x160 0x3C0 0x580 0x4 0x1 +#define MX8MP_IOMUXC_SAI1_RXD4__GPIO4_IO06 0x160 0x3C0 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_RXD5__AUDIOMIX_SAI1_RX_DATA05 0x164 0x3C4 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_RXD5__AUDIOMIX_SAI6_TX_DATA00 0x164 0x3C4 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI1_RXD5__AUDIOMIX_SAI6_RX_DATA00 0x164 0x3C4 0x51C 0x2 0x1 +#define MX8MP_IOMUXC_SAI1_RXD5__AUDIOMIX_SAI1_RX_SYNC 0x164 0x3C4 0x4D0 0x3 0x1 +#define MX8MP_IOMUXC_SAI1_RXD5__ENET1_RGMII_RD1 0x164 0x3C4 0x584 0x4 0x1 +#define MX8MP_IOMUXC_SAI1_RXD5__GPIO4_IO07 0x164 0x3C4 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_RXD6__AUDIOMIX_SAI1_RX_DATA06 0x168 0x3C8 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_RXD6__AUDIOMIX_SAI6_TX_SYNC 0x168 0x3C8 0x528 0x1 0x1 +#define MX8MP_IOMUXC_SAI1_RXD6__AUDIOMIX_SAI6_RX_SYNC 0x168 0x3C8 0x520 0x2 0x1 +#define MX8MP_IOMUXC_SAI1_RXD6__ENET1_RGMII_RD2 0x168 0x3C8 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI1_RXD6__GPIO4_IO08 0x168 0x3C8 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_RXD7__AUDIOMIX_SAI1_RX_DATA07 0x16C 0x3CC 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_RXD7__AUDIOMIX_SAI6_MCLK 0x16C 0x3CC 0x514 0x1 0x1 +#define MX8MP_IOMUXC_SAI1_RXD7__AUDIOMIX_SAI1_TX_SYNC 0x16C 0x3CC 0x4D8 0x2 0x3 +#define MX8MP_IOMUXC_SAI1_RXD7__AUDIOMIX_SAI1_TX_DATA04 0x16C 0x3CC 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SAI1_RXD7__ENET1_RGMII_RD3 0x16C 0x3CC 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI1_RXD7__GPIO4_IO09 0x16C 0x3CC 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_TXFS__AUDIOMIX_SAI1_TX_SYNC 0x170 0x3D0 0x4D8 0x0 0x4 +#define MX8MP_IOMUXC_SAI1_TXFS__AUDIOMIX_SAI5_TX_SYNC 0x170 0x3D0 0x510 0x1 0x1 +#define MX8MP_IOMUXC_SAI1_TXFS__ENET1_RGMII_RX_CTL 0x170 0x3D0 0x588 0x4 0x1 +#define MX8MP_IOMUXC_SAI1_TXFS__GPIO4_IO10 0x170 0x3D0 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_TXC__AUDIOMIX_SAI1_TX_BCLK 0x174 0x3D4 0x4D4 0x0 0x1 +#define MX8MP_IOMUXC_SAI1_TXC__AUDIOMIX_SAI5_TX_BCLK 0x174 0x3D4 0x50C 0x1 0x1 +#define MX8MP_IOMUXC_SAI1_TXC__ENET1_RGMII_RXC 0x174 0x3D4 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI1_TXC__GPIO4_IO11 0x174 0x3D4 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_TXD0__AUDIOMIX_SAI1_TX_DATA00 0x178 0x3D8 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_TXD0__AUDIOMIX_SAI5_TX_DATA00 0x178 0x3D8 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI1_TXD0__ENET1_RGMII_TD0 0x178 0x3D8 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI1_TXD0__GPIO4_IO12 0x178 0x3D8 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_TXD1__AUDIOMIX_SAI1_TX_DATA01 0x17C 0x3DC 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_TXD1__AUDIOMIX_SAI5_TX_DATA01 0x17C 0x3DC 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI1_TXD1__ENET1_RGMII_TD1 0x17C 0x3DC 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI1_TXD1__GPIO4_IO13 0x17C 0x3DC 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_TXD2__AUDIOMIX_SAI1_TX_DATA02 0x180 0x3E0 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_TXD2__AUDIOMIX_SAI5_TX_DATA02 0x180 0x3E0 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI1_TXD2__ENET1_RGMII_TD2 0x180 0x3E0 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI1_TXD2__GPIO4_IO14 0x180 0x3E0 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_TXD3__AUDIOMIX_SAI1_TX_DATA03 0x184 0x3E4 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_TXD3__AUDIOMIX_SAI5_TX_DATA03 0x184 0x3E4 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI1_TXD3__ENET1_RGMII_TD3 0x184 0x3E4 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI1_TXD3__GPIO4_IO15 0x184 0x3E4 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_TXD4__AUDIOMIX_SAI1_TX_DATA04 0x188 0x3E8 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_TXD4__AUDIOMIX_SAI6_RX_BCLK 0x188 0x3E8 0x518 0x1 0x2 +#define MX8MP_IOMUXC_SAI1_TXD4__AUDIOMIX_SAI6_TX_BCLK 0x188 0x3E8 0x524 0x2 0x2 +#define MX8MP_IOMUXC_SAI1_TXD4__ENET1_RGMII_TX_CTL 0x188 0x3E8 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI1_TXD4__GPIO4_IO16 0x188 0x3E8 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_TXD5__AUDIOMIX_SAI1_TX_DATA05 0x18C 0x3EC 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_TXD5__AUDIOMIX_SAI6_RX_DATA00 0x18C 0x3EC 0x51C 0x1 0x2 +#define MX8MP_IOMUXC_SAI1_TXD5__AUDIOMIX_SAI6_TX_DATA00 0x18C 0x3EC 0x000 0x2 0x0 +#define MX8MP_IOMUXC_SAI1_TXD5__ENET1_RGMII_TXC 0x18C 0x3EC 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI1_TXD5__GPIO4_IO17 0x18C 0x3EC 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_TXD6__AUDIOMIX_SAI1_TX_DATA06 0x190 0x3F0 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_TXD6__AUDIOMIX_SAI6_RX_SYNC 0x190 0x3F0 0x520 0x1 0x2 +#define MX8MP_IOMUXC_SAI1_TXD6__AUDIOMIX_SAI6_TX_SYNC 0x190 0x3F0 0x528 0x2 0x2 +#define MX8MP_IOMUXC_SAI1_TXD6__ENET1_RX_ER 0x190 0x3F0 0x58C 0x4 0x1 +#define MX8MP_IOMUXC_SAI1_TXD6__GPIO4_IO18 0x190 0x3F0 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_TXD7__AUDIOMIX_SAI1_TX_DATA07 0x194 0x3F4 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_TXD7__AUDIOMIX_SAI6_MCLK 0x194 0x3F4 0x514 0x1 0x2 +#define MX8MP_IOMUXC_SAI1_TXD7__AUDIOMIX_CLK 0x194 0x3F4 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SAI1_TXD7__ENET1_TX_ER 0x194 0x3F4 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI1_TXD7__GPIO4_IO19 0x194 0x3F4 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI1_MCLK__AUDIOMIX_SAI1_MCLK 0x198 0x3F8 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI1_MCLK__AUDIOMIX_SAI5_MCLK 0x198 0x3F8 0x4F0 0x1 0x1 +#define MX8MP_IOMUXC_SAI1_MCLK__AUDIOMIX_SAI1_TX_BCLK 0x198 0x3F8 0x4D4 0x2 0x2 +#define MX8MP_IOMUXC_SAI1_MCLK__ENET1_TX_CLK 0x198 0x3F8 0x578 0x4 0x1 +#define MX8MP_IOMUXC_SAI1_MCLK__GPIO4_IO20 0x198 0x3F8 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI2_RXFS__AUDIOMIX_SAI2_RX_SYNC 0x19C 0x3FC 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI2_RXFS__AUDIOMIX_SAI5_TX_SYNC 0x19C 0x3FC 0x510 0x1 0x2 +#define MX8MP_IOMUXC_SAI2_RXFS__AUDIOMIX_SAI5_TX_DATA01 0x19C 0x3FC 0x000 0x2 0x0 +#define MX8MP_IOMUXC_SAI2_RXFS__AUDIOMIX_SAI2_RX_DATA01 0x19C 0x3FC 0x4DC 0x3 0x0 +#define MX8MP_IOMUXC_SAI2_RXFS__UART1_DCE_TX 0x19C 0x3FC 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI2_RXFS__UART1_DTE_RX 0x19C 0x3FC 0x5E8 0x4 0x2 +#define MX8MP_IOMUXC_SAI2_RXFS__GPIO4_IO21 0x19C 0x3FC 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI2_RXFS__AUDIOMIX_BIT_STREAM02 0x19C 0x3FC 0x4C8 0x6 0x4 +#define MX8MP_IOMUXC_SAI2_RXFS__SIM_M_HSIZE00 0x19C 0x3FC 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SAI2_RXC__AUDIOMIX_SAI2_RX_BCLK 0x1A0 0x400 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI2_RXC__AUDIOMIX_SAI5_TX_BCLK 0x1A0 0x400 0x50C 0x1 0x2 +#define MX8MP_IOMUXC_SAI2_RXC__CAN1_TX 0x1A0 0x400 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SAI2_RXC__UART1_DCE_RX 0x1A0 0x400 0x5E8 0x4 0x3 +#define MX8MP_IOMUXC_SAI2_RXC__UART1_DTE_TX 0x1A0 0x400 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI2_RXC__GPIO4_IO22 0x1A0 0x400 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI2_RXC__AUDIOMIX_BIT_STREAM01 0x1A0 0x400 0x4C4 0x6 0x4 +#define MX8MP_IOMUXC_SAI2_RXC__SIM_M_HSIZE01 0x1A0 0x400 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SAI2_RXD0__AUDIOMIX_SAI2_RX_DATA00 0x1A4 0x404 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI2_RXD0__AUDIOMIX_SAI5_TX_DATA00 0x1A4 0x404 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI2_RXD0__ENET_QOS_1588_EVENT2_OUT 0x1A4 0x404 0x000 0x2 0x0 +#define MX8MP_IOMUXC_SAI2_RXD0__AUDIOMIX_SAI2_TX_DATA01 0x1A4 0x404 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SAI2_RXD0__UART1_DCE_RTS 0x1A4 0x404 0x5E4 0x4 0x2 +#define MX8MP_IOMUXC_SAI2_RXD0__UART1_DTE_CTS 0x1A4 0x404 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI2_RXD0__GPIO4_IO23 0x1A4 0x404 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI2_RXD0__AUDIOMIX_BIT_STREAM03 0x1A4 0x404 0x4CC 0x6 0x4 +#define MX8MP_IOMUXC_SAI2_RXD0__SIM_M_HSIZE02 0x1A4 0x404 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SAI2_TXFS__AUDIOMIX_SAI2_TX_SYNC 0x1A8 0x408 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI2_TXFS__AUDIOMIX_SAI5_TX_DATA01 0x1A8 0x408 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI2_TXFS__ENET_QOS_1588_EVENT3_OUT 0x1A8 0x408 0x000 0x2 0x0 +#define MX8MP_IOMUXC_SAI2_TXFS__AUDIOMIX_SAI2_TX_DATA01 0x1A8 0x408 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SAI2_TXFS__UART1_DCE_CTS 0x1A8 0x408 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI2_TXFS__UART1_DTE_RTS 0x1A8 0x408 0x5E4 0x4 0x3 +#define MX8MP_IOMUXC_SAI2_TXFS__GPIO4_IO24 0x1A8 0x408 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI2_TXFS__AUDIOMIX_BIT_STREAM02 0x1A8 0x408 0x4C8 0x6 0x5 +#define MX8MP_IOMUXC_SAI2_TXFS__SIM_M_HWRITE 0x1A8 0x408 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SAI2_TXC__AUDIOMIX_SAI2_TX_BCLK 0x1AC 0x40C 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI2_TXC__AUDIOMIX_SAI5_TX_DATA02 0x1AC 0x40C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI2_TXC__CAN1_RX 0x1AC 0x40C 0x54C 0x3 0x1 +#define MX8MP_IOMUXC_SAI2_TXC__GPIO4_IO25 0x1AC 0x40C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI2_TXC__AUDIOMIX_BIT_STREAM01 0x1AC 0x40C 0x4C4 0x6 0x5 +#define MX8MP_IOMUXC_SAI2_TXC__SIM_M_HREADYOUT 0x1AC 0x40C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SAI2_TXD0__AUDIOMIX_SAI2_TX_DATA00 0x1B0 0x410 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI2_TXD0__AUDIOMIX_SAI5_TX_DATA03 0x1B0 0x410 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI2_TXD0__ENET_QOS_1588_EVENT2_IN 0x1B0 0x410 0x000 0x2 0x0 +#define MX8MP_IOMUXC_SAI2_TXD0__CAN2_TX 0x1B0 0x410 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SAI2_TXD0__ENET_QOS_1588_EVENT2_AUX_IN 0x1B0 0x410 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI2_TXD0__GPIO4_IO26 0x1B0 0x410 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI2_TXD0__CCMSRCGPCMIX_BOOT_MODE04 0x1B0 0x410 0x000 0x6 0x0 +#define MX8MP_IOMUXC_SAI2_TXD0__TPSMP_CLK 0x1B0 0x410 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SAI2_MCLK__AUDIOMIX_SAI2_MCLK 0x1B4 0x414 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI2_MCLK__AUDIOMIX_SAI5_MCLK 0x1B4 0x414 0x4F0 0x1 0x2 +#define MX8MP_IOMUXC_SAI2_MCLK__ENET_QOS_1588_EVENT3_IN 0x1B4 0x414 0x000 0x2 0x0 +#define MX8MP_IOMUXC_SAI2_MCLK__CAN2_RX 0x1B4 0x414 0x550 0x3 0x1 +#define MX8MP_IOMUXC_SAI2_MCLK__ENET_QOS_1588_EVENT3_AUX_IN 0x1B4 0x414 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI2_MCLK__GPIO4_IO27 0x1B4 0x414 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI2_MCLK__AUDIOMIX_SAI3_MCLK 0x1B4 0x414 0x4E0 0x6 0x1 +#define MX8MP_IOMUXC_SAI2_MCLK__TPSMP_HDATA_DIR 0x1B4 0x414 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SAI3_RXFS__AUDIOMIX_SAI3_RX_SYNC 0x1B8 0x418 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI3_RXFS__AUDIOMIX_SAI2_RX_DATA01 0x1B8 0x418 0x4DC 0x1 0x1 +#define MX8MP_IOMUXC_SAI3_RXFS__AUDIOMIX_SAI5_RX_SYNC 0x1B8 0x418 0x508 0x2 0x2 +#define MX8MP_IOMUXC_SAI3_RXFS__AUDIOMIX_SAI3_RX_DATA01 0x1B8 0x418 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SAI3_RXFS__AUDIOMIX_SPDIF_IN 0x1B8 0x418 0x544 0x4 0x2 +#define MX8MP_IOMUXC_SAI3_RXFS__GPIO4_IO28 0x1B8 0x418 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI3_RXFS__AUDIOMIX_BIT_STREAM00 0x1B8 0x418 0x4C0 0x6 0x4 +#define MX8MP_IOMUXC_SAI3_RXFS__TPSMP_HTRANS00 0x1B8 0x418 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SAI3_RXC__AUDIOMIX_SAI3_RX_BCLK 0x1BC 0x41C 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI3_RXC__AUDIOMIX_SAI2_RX_DATA02 0x1BC 0x41C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI3_RXC__AUDIOMIX_SAI5_RX_BCLK 0x1BC 0x41C 0x4F4 0x2 0x2 +#define MX8MP_IOMUXC_SAI3_RXC__GPT1_CLK 0x1BC 0x41C 0x59C 0x3 0x0 +#define MX8MP_IOMUXC_SAI3_RXC__UART2_DCE_CTS 0x1BC 0x41C 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI3_RXC__UART2_DTE_RTS 0x1BC 0x41C 0x5EC 0x4 0x2 +#define MX8MP_IOMUXC_SAI3_RXC__GPIO4_IO29 0x1BC 0x41C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI3_RXC__AUDIOMIX_CLK 0x1BC 0x41C 0x000 0x6 0x0 +#define MX8MP_IOMUXC_SAI3_RXC__TPSMP_HTRANS01 0x1BC 0x41C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SAI3_RXD__AUDIOMIX_SAI3_RX_DATA00 0x1C0 0x420 0x4E4 0x0 0x1 +#define MX8MP_IOMUXC_SAI3_RXD__AUDIOMIX_SAI2_RX_DATA03 0x1C0 0x420 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI3_RXD__AUDIOMIX_SAI5_RX_DATA00 0x1C0 0x420 0x4F8 0x2 0x2 +#define MX8MP_IOMUXC_SAI3_RXD__UART2_DCE_RTS 0x1C0 0x420 0x5EC 0x4 0x3 +#define MX8MP_IOMUXC_SAI3_RXD__UART2_DTE_CTS 0x1C0 0x420 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI3_RXD__GPIO4_IO30 0x1C0 0x420 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI3_RXD__AUDIOMIX_BIT_STREAM01 0x1C0 0x420 0x4C4 0x6 0x6 +#define MX8MP_IOMUXC_SAI3_RXD__TPSMP_HDATA00 0x1C0 0x420 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SAI3_TXFS__AUDIOMIX_SAI3_TX_SYNC 0x1C4 0x424 0x4EC 0x0 0x1 +#define MX8MP_IOMUXC_SAI3_TXFS__AUDIOMIX_SAI2_TX_DATA01 0x1C4 0x424 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI3_TXFS__AUDIOMIX_SAI5_RX_DATA01 0x1C4 0x424 0x4FC 0x2 0x2 +#define MX8MP_IOMUXC_SAI3_TXFS__AUDIOMIX_SAI3_TX_DATA01 0x1C4 0x424 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SAI3_TXFS__UART2_DCE_RX 0x1C4 0x424 0x5F0 0x4 0x4 +#define MX8MP_IOMUXC_SAI3_TXFS__UART2_DTE_TX 0x1C4 0x424 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI3_TXFS__GPIO4_IO31 0x1C4 0x424 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI3_TXFS__AUDIOMIX_BIT_STREAM03 0x1C4 0x424 0x4CC 0x6 0x5 +#define MX8MP_IOMUXC_SAI3_TXFS__TPSMP_HDATA01 0x1C4 0x424 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SAI3_TXC__AUDIOMIX_SAI3_TX_BCLK 0x1C8 0x428 0x4E8 0x0 0x1 +#define MX8MP_IOMUXC_SAI3_TXC__AUDIOMIX_SAI2_TX_DATA02 0x1C8 0x428 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI3_TXC__AUDIOMIX_SAI5_RX_DATA02 0x1C8 0x428 0x500 0x2 0x2 +#define MX8MP_IOMUXC_SAI3_TXC__GPT1_CAPTURE1 0x1C8 0x428 0x594 0x3 0x0 +#define MX8MP_IOMUXC_SAI3_TXC__UART2_DCE_TX 0x1C8 0x428 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI3_TXC__UART2_DTE_RX 0x1C8 0x428 0x5F0 0x4 0x5 +#define MX8MP_IOMUXC_SAI3_TXC__GPIO5_IO00 0x1C8 0x428 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI3_TXC__AUDIOMIX_BIT_STREAM02 0x1C8 0x428 0x4C8 0x6 0x6 +#define MX8MP_IOMUXC_SAI3_TXC__TPSMP_HDATA02 0x1C8 0x428 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SAI3_TXD__AUDIOMIX_SAI3_TX_DATA00 0x1CC 0x42C 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SAI3_TXD__AUDIOMIX_SAI2_TX_DATA03 0x1CC 0x42C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI3_TXD__AUDIOMIX_SAI5_RX_DATA03 0x1CC 0x42C 0x504 0x2 0x2 +#define MX8MP_IOMUXC_SAI3_TXD__GPT1_CAPTURE2 0x1CC 0x42C 0x598 0x3 0x0 +#define MX8MP_IOMUXC_SAI3_TXD__AUDIOMIX_SPDIF_EXT_CLK 0x1CC 0x42C 0x548 0x4 0x0 +#define MX8MP_IOMUXC_SAI3_TXD__GPIO5_IO01 0x1CC 0x42C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI3_TXD__CCMSRCGPCMIX_BOOT_MODE05 0x1CC 0x42C 0x000 0x6 0x0 +#define MX8MP_IOMUXC_SAI3_TXD__TPSMP_HDATA03 0x1CC 0x42C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SAI3_MCLK__AUDIOMIX_SAI3_MCLK 0x1D0 0x430 0x4E0 0x0 0x2 +#define MX8MP_IOMUXC_SAI3_MCLK__PWM4_OUT 0x1D0 0x430 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SAI3_MCLK__AUDIOMIX_SAI5_MCLK 0x1D0 0x430 0x4F0 0x2 0x3 +#define MX8MP_IOMUXC_SAI3_MCLK__AUDIOMIX_SPDIF_OUT 0x1D0 0x430 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SAI3_MCLK__GPIO5_IO02 0x1D0 0x430 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SAI3_MCLK__AUDIOMIX_SPDIF_IN 0x1D0 0x430 0x544 0x6 0x3 +#define MX8MP_IOMUXC_SAI3_MCLK__TPSMP_HDATA04 0x1D0 0x430 0x000 0x7 0x0 +#define MX8MP_IOMUXC_SPDIF_TX__AUDIOMIX_SPDIF_OUT 0x1D4 0x434 0x000 0x0 0x0 +#define MX8MP_IOMUXC_SPDIF_TX__PWM3_OUT 0x1D4 0x434 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SPDIF_TX__I2C5_SCL 0x1D4 0x434 0x5C4 0x2 0x2 +#define MX8MP_IOMUXC_SPDIF_TX__GPT1_COMPARE1 0x1D4 0x434 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SPDIF_TX__CAN1_TX 0x1D4 0x434 0x000 0x4 0x0 +#define MX8MP_IOMUXC_SPDIF_TX__GPIO5_IO03 0x1D4 0x434 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SPDIF_RX__AUDIOMIX_SPDIF_IN 0x1D8 0x438 0x544 0x0 0x4 +#define MX8MP_IOMUXC_SPDIF_RX__PWM2_OUT 0x1D8 0x438 0x000 0x1 0x0 +#define MX8MP_IOMUXC_SPDIF_RX__I2C5_SDA 0x1D8 0x438 0x5C8 0x2 0x2 +#define MX8MP_IOMUXC_SPDIF_RX__GPT1_COMPARE2 0x1D8 0x438 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SPDIF_RX__CAN1_RX 0x1D8 0x438 0x54C 0x4 0x2 +#define MX8MP_IOMUXC_SPDIF_RX__GPIO5_IO04 0x1D8 0x438 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SPDIF_EXT_CLK__GPT1_COMPARE3 0x1DC 0x43C 0x000 0x3 0x0 +#define MX8MP_IOMUXC_SPDIF_EXT_CLK__GPIO5_IO05 0x1DC 0x43C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_SPDIF_EXT_CLK__AUDIOMIX_SPDIF_EXT_CLK 0x1DC 0x43C 0x548 0x0 0x1 +#define MX8MP_IOMUXC_SPDIF_EXT_CLK__PWM1_OUT 0x1DC 0x43C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_ECSPI1_SCLK__ECSPI1_SCLK 0x1E0 0x440 0x558 0x0 0x0 +#define MX8MP_IOMUXC_ECSPI1_SCLK__UART3_DCE_RX 0x1E0 0x440 0x5F8 0x1 0x4 +#define MX8MP_IOMUXC_ECSPI1_SCLK__UART3_DTE_TX 0x1E0 0x440 0x000 0x1 0x0 +#define MX8MP_IOMUXC_ECSPI1_SCLK__I2C1_SCL 0x1E0 0x440 0x5A4 0x2 0x1 +#define MX8MP_IOMUXC_ECSPI1_SCLK__AUDIOMIX_SAI7_RX_SYNC 0x1E0 0x440 0x538 0x3 0x1 +#define MX8MP_IOMUXC_ECSPI1_SCLK__GPIO5_IO06 0x1E0 0x440 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ECSPI1_SCLK__TPSMP_HDATA08 0x1E0 0x440 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ECSPI1_MOSI__ECSPI1_MOSI 0x1E4 0x444 0x560 0x0 0x0 +#define MX8MP_IOMUXC_ECSPI1_MOSI__UART3_DCE_TX 0x1E4 0x444 0x000 0x1 0x0 +#define MX8MP_IOMUXC_ECSPI1_MOSI__UART3_DTE_RX 0x1E4 0x444 0x5F8 0x1 0x5 +#define MX8MP_IOMUXC_ECSPI1_MOSI__I2C1_SDA 0x1E4 0x444 0x5A8 0x2 0x1 +#define MX8MP_IOMUXC_ECSPI1_MOSI__AUDIOMIX_SAI7_RX_BCLK 0x1E4 0x444 0x530 0x3 0x1 +#define MX8MP_IOMUXC_ECSPI1_MOSI__GPIO5_IO07 0x1E4 0x444 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ECSPI1_MOSI__TPSMP_HDATA09 0x1E4 0x444 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ECSPI1_MISO__ECSPI1_MISO 0x1E8 0x448 0x55C 0x0 0x0 +#define MX8MP_IOMUXC_ECSPI1_MISO__UART3_DCE_CTS 0x1E8 0x448 0x000 0x1 0x0 +#define MX8MP_IOMUXC_ECSPI1_MISO__UART3_DTE_RTS 0x1E8 0x448 0x5F4 0x1 0x2 +#define MX8MP_IOMUXC_ECSPI1_MISO__I2C2_SCL 0x1E8 0x448 0x5AC 0x2 0x1 +#define MX8MP_IOMUXC_ECSPI1_MISO__AUDIOMIX_SAI7_RX_DATA00 0x1E8 0x448 0x534 0x3 0x1 +#define MX8MP_IOMUXC_ECSPI1_MISO__GPIO5_IO08 0x1E8 0x448 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ECSPI1_MISO__TPSMP_HDATA10 0x1E8 0x448 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ECSPI1_SS0__ECSPI1_SS0 0x1EC 0x44C 0x564 0x0 0x0 +#define MX8MP_IOMUXC_ECSPI1_SS0__UART3_DCE_RTS 0x1EC 0x44C 0x5F4 0x1 0x3 +#define MX8MP_IOMUXC_ECSPI1_SS0__UART3_DTE_CTS 0x1EC 0x44C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_ECSPI1_SS0__I2C2_SDA 0x1EC 0x44C 0x5B0 0x2 0x1 +#define MX8MP_IOMUXC_ECSPI1_SS0__AUDIOMIX_SAI7_TX_SYNC 0x1EC 0x44C 0x540 0x3 0x1 +#define MX8MP_IOMUXC_ECSPI1_SS0__GPIO5_IO09 0x1EC 0x44C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ECSPI1_SS0__TPSMP_HDATA11 0x1EC 0x44C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ECSPI2_SCLK__ECSPI2_SCLK 0x1F0 0x450 0x568 0x0 0x1 +#define MX8MP_IOMUXC_ECSPI2_SCLK__UART4_DCE_RX 0x1F0 0x450 0x600 0x1 0x6 +#define MX8MP_IOMUXC_ECSPI2_SCLK__UART4_DTE_TX 0x1F0 0x450 0x000 0x1 0x0 +#define MX8MP_IOMUXC_ECSPI2_SCLK__I2C3_SCL 0x1F0 0x450 0x5B4 0x2 0x3 +#define MX8MP_IOMUXC_ECSPI2_SCLK__AUDIOMIX_SAI7_TX_BCLK 0x1F0 0x450 0x53C 0x3 0x1 +#define MX8MP_IOMUXC_ECSPI2_SCLK__GPIO5_IO10 0x1F0 0x450 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ECSPI2_SCLK__TPSMP_HDATA12 0x1F0 0x450 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ECSPI2_MOSI__ECSPI2_MOSI 0x1F4 0x454 0x570 0x0 0x1 +#define MX8MP_IOMUXC_ECSPI2_MOSI__UART4_DCE_TX 0x1F4 0x454 0x000 0x1 0x0 +#define MX8MP_IOMUXC_ECSPI2_MOSI__UART4_DTE_RX 0x1F4 0x454 0x600 0x1 0x7 +#define MX8MP_IOMUXC_ECSPI2_MOSI__I2C3_SDA 0x1F4 0x454 0x5B8 0x2 0x3 +#define MX8MP_IOMUXC_ECSPI2_MOSI__AUDIOMIX_SAI7_TX_DATA00 0x1F4 0x454 0x000 0x3 0x0 +#define MX8MP_IOMUXC_ECSPI2_MOSI__GPIO5_IO11 0x1F4 0x454 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ECSPI2_MOSI__TPSMP_HDATA13 0x1F4 0x454 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ECSPI2_MISO__GPIO5_IO12 0x1F8 0x458 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ECSPI2_MISO__TPSMP_HDATA14 0x1F8 0x458 0x000 0x7 0x0 +#define MX8MP_IOMUXC_ECSPI2_MISO__ECSPI2_MISO 0x1F8 0x458 0x56C 0x0 0x1 +#define MX8MP_IOMUXC_ECSPI2_MISO__UART4_DCE_CTS 0x1F8 0x458 0x000 0x1 0x0 +#define MX8MP_IOMUXC_ECSPI2_MISO__UART4_DTE_RTS 0x1F8 0x458 0x5FC 0x1 0x2 +#define MX8MP_IOMUXC_ECSPI2_MISO__I2C4_SCL 0x1F8 0x458 0x5BC 0x2 0x4 +#define MX8MP_IOMUXC_ECSPI2_MISO__AUDIOMIX_SAI7_MCLK 0x1F8 0x458 0x52C 0x3 0x1 +#define MX8MP_IOMUXC_ECSPI2_MISO__CCMSRCGPCMIX_CLKO1 0x1F8 0x458 0x000 0x4 0x0 +#define MX8MP_IOMUXC_ECSPI2_SS0__ECSPI2_SS0 0x1FC 0x45C 0x574 0x0 0x1 +#define MX8MP_IOMUXC_ECSPI2_SS0__UART4_DCE_RTS 0x1FC 0x45C 0x5FC 0x1 0x3 +#define MX8MP_IOMUXC_ECSPI2_SS0__UART4_DTE_CTS 0x1FC 0x45C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_ECSPI2_SS0__I2C4_SDA 0x1FC 0x45C 0x5C0 0x2 0x4 +#define MX8MP_IOMUXC_ECSPI2_SS0__CCMSRCGPCMIX_CLKO2 0x1FC 0x45C 0x000 0x4 0x0 +#define MX8MP_IOMUXC_ECSPI2_SS0__GPIO5_IO13 0x1FC 0x45C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_ECSPI2_SS0__TPSMP_HDATA15 0x1FC 0x45C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_I2C1_SCL__I2C1_SCL 0x200 0x460 0x5A4 0x0 0x2 +#define MX8MP_IOMUXC_I2C1_SCL__ENET_QOS_MDC 0x200 0x460 0x000 0x1 0x0 +#define MX8MP_IOMUXC_I2C1_SCL__ECSPI1_SCLK 0x200 0x460 0x558 0x3 0x1 +#define MX8MP_IOMUXC_I2C1_SCL__GPIO5_IO14 0x200 0x460 0x000 0x5 0x0 +#define MX8MP_IOMUXC_I2C1_SCL__TPSMP_HDATA16 0x200 0x460 0x000 0x7 0x0 +#define MX8MP_IOMUXC_I2C1_SDA__I2C1_SDA 0x204 0x464 0x5A8 0x0 0x2 +#define MX8MP_IOMUXC_I2C1_SDA__ENET_QOS_MDIO 0x204 0x464 0x590 0x1 0x2 +#define MX8MP_IOMUXC_I2C1_SDA__ECSPI1_MOSI 0x204 0x464 0x560 0x3 0x1 +#define MX8MP_IOMUXC_I2C1_SDA__GPIO5_IO15 0x204 0x464 0x000 0x5 0x0 +#define MX8MP_IOMUXC_I2C1_SDA__TPSMP_HDATA17 0x204 0x464 0x000 0x7 0x0 +#define MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL 0x208 0x468 0x5AC 0x0 0x2 +#define MX8MP_IOMUXC_I2C2_SCL__ENET_QOS_1588_EVENT1_IN 0x208 0x468 0x000 0x1 0x0 +#define MX8MP_IOMUXC_I2C2_SCL__USDHC3_CD_B 0x208 0x468 0x608 0x2 0x3 +#define MX8MP_IOMUXC_I2C2_SCL__ECSPI1_MISO 0x208 0x468 0x55C 0x3 0x1 +#define MX8MP_IOMUXC_I2C2_SCL__ENET_QOS_1588_EVENT1_AUX_IN 0x208 0x468 0x000 0x4 0x0 +#define MX8MP_IOMUXC_I2C2_SCL__GPIO5_IO16 0x208 0x468 0x000 0x5 0x0 +#define MX8MP_IOMUXC_I2C2_SCL__TPSMP_HDATA18 0x208 0x468 0x000 0x7 0x0 +#define MX8MP_IOMUXC_I2C2_SDA__I2C2_SDA 0x20C 0x46C 0x5B0 0x0 0x2 +#define MX8MP_IOMUXC_I2C2_SDA__ENET_QOS_1588_EVENT1_OUT 0x20C 0x46C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_I2C2_SDA__USDHC3_WP 0x20C 0x46C 0x634 0x2 0x3 +#define MX8MP_IOMUXC_I2C2_SDA__ECSPI1_SS0 0x20C 0x46C 0x564 0x3 0x1 +#define MX8MP_IOMUXC_I2C2_SDA__GPIO5_IO17 0x20C 0x46C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_I2C2_SDA__TPSMP_HDATA19 0x20C 0x46C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_I2C3_SCL__I2C3_SCL 0x210 0x470 0x5B4 0x0 0x4 +#define MX8MP_IOMUXC_I2C3_SCL__PWM4_OUT 0x210 0x470 0x000 0x1 0x0 +#define MX8MP_IOMUXC_I2C3_SCL__GPT2_CLK 0x210 0x470 0x000 0x2 0x0 +#define MX8MP_IOMUXC_I2C3_SCL__ECSPI2_SCLK 0x210 0x470 0x568 0x3 0x2 +#define MX8MP_IOMUXC_I2C3_SCL__GPIO5_IO18 0x210 0x470 0x000 0x5 0x0 +#define MX8MP_IOMUXC_I2C3_SCL__TPSMP_HDATA20 0x210 0x470 0x000 0x7 0x0 +#define MX8MP_IOMUXC_I2C3_SDA__I2C3_SDA 0x214 0x474 0x5B8 0x0 0x4 +#define MX8MP_IOMUXC_I2C3_SDA__PWM3_OUT 0x214 0x474 0x000 0x1 0x0 +#define MX8MP_IOMUXC_I2C3_SDA__GPT3_CLK 0x214 0x474 0x000 0x2 0x0 +#define MX8MP_IOMUXC_I2C3_SDA__ECSPI2_MOSI 0x214 0x474 0x570 0x3 0x2 +#define MX8MP_IOMUXC_I2C3_SDA__GPIO5_IO19 0x214 0x474 0x000 0x5 0x0 +#define MX8MP_IOMUXC_I2C3_SDA__TPSMP_HDATA21 0x214 0x474 0x000 0x7 0x0 +#define MX8MP_IOMUXC_I2C4_SCL__I2C4_SCL 0x218 0x478 0x5BC 0x0 0x5 +#define MX8MP_IOMUXC_I2C4_SCL__PWM2_OUT 0x218 0x478 0x000 0x1 0x0 +#define MX8MP_IOMUXC_I2C4_SCL__HSIOMIX_PCIE_CLKREQ_B 0x218 0x478 0x5A0 0x2 0x0 +#define MX8MP_IOMUXC_I2C4_SCL__ECSPI2_MISO 0x218 0x478 0x56C 0x3 0x2 +#define MX8MP_IOMUXC_I2C4_SCL__GPIO5_IO20 0x218 0x478 0x000 0x5 0x0 +#define MX8MP_IOMUXC_I2C4_SCL__TPSMP_HDATA22 0x218 0x478 0x000 0x7 0x0 +#define MX8MP_IOMUXC_I2C4_SDA__I2C4_SDA 0x21C 0x47C 0x5C0 0x0 0x5 +#define MX8MP_IOMUXC_I2C4_SDA__PWM1_OUT 0x21C 0x47C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_I2C4_SDA__ECSPI2_SS0 0x21C 0x47C 0x574 0x3 0x2 +#define MX8MP_IOMUXC_I2C4_SDA__GPIO5_IO21 0x21C 0x47C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_I2C4_SDA__TPSMP_HDATA23 0x21C 0x47C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_UART1_RXD__UART1_DCE_RX 0x220 0x480 0x5E8 0x0 0x4 +#define MX8MP_IOMUXC_UART1_RXD__UART1_DTE_TX 0x220 0x480 0x000 0x0 0x0 +#define MX8MP_IOMUXC_UART1_RXD__ECSPI3_SCLK 0x220 0x480 0x000 0x1 0x0 +#define MX8MP_IOMUXC_UART1_RXD__GPIO5_IO22 0x220 0x480 0x000 0x5 0x0 +#define MX8MP_IOMUXC_UART1_RXD__TPSMP_HDATA24 0x220 0x480 0x000 0x7 0x0 +#define MX8MP_IOMUXC_UART1_TXD__UART1_DCE_TX 0x224 0x484 0x000 0x0 0x0 +#define MX8MP_IOMUXC_UART1_TXD__UART1_DTE_RX 0x224 0x484 0x5E8 0x0 0x5 +#define MX8MP_IOMUXC_UART1_TXD__ECSPI3_MOSI 0x224 0x484 0x000 0x1 0x0 +#define MX8MP_IOMUXC_UART1_TXD__GPIO5_IO23 0x224 0x484 0x000 0x5 0x0 +#define MX8MP_IOMUXC_UART1_TXD__TPSMP_HDATA25 0x224 0x484 0x000 0x7 0x0 +#define MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX 0x228 0x488 0x5F0 0x0 0x6 +#define MX8MP_IOMUXC_UART2_RXD__UART2_DTE_TX 0x228 0x488 0x000 0x0 0x0 +#define MX8MP_IOMUXC_UART2_RXD__ECSPI3_MISO 0x228 0x488 0x000 0x1 0x0 +#define MX8MP_IOMUXC_UART2_RXD__GPT1_COMPARE3 0x228 0x488 0x000 0x3 0x0 +#define MX8MP_IOMUXC_UART2_RXD__GPIO5_IO24 0x228 0x488 0x000 0x5 0x0 +#define MX8MP_IOMUXC_UART2_RXD__TPSMP_HDATA26 0x228 0x488 0x000 0x7 0x0 +#define MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX 0x22C 0x48C 0x000 0x0 0x0 +#define MX8MP_IOMUXC_UART2_TXD__UART2_DTE_RX 0x22C 0x48C 0x5F0 0x0 0x7 +#define MX8MP_IOMUXC_UART2_TXD__ECSPI3_SS0 0x22C 0x48C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_UART2_TXD__GPT1_COMPARE2 0x22C 0x48C 0x000 0x3 0x0 +#define MX8MP_IOMUXC_UART2_TXD__GPIO5_IO25 0x22C 0x48C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_UART2_TXD__TPSMP_HDATA27 0x22C 0x48C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_UART3_RXD__UART3_DCE_RX 0x230 0x490 0x5F8 0x0 0x6 +#define MX8MP_IOMUXC_UART3_RXD__UART3_DTE_TX 0x230 0x490 0x000 0x0 0x0 +#define MX8MP_IOMUXC_UART3_RXD__UART1_DCE_CTS 0x230 0x490 0x000 0x1 0x0 +#define MX8MP_IOMUXC_UART3_RXD__UART1_DTE_RTS 0x230 0x490 0x5E4 0x1 0x4 +#define MX8MP_IOMUXC_UART3_RXD__USDHC3_RESET_B 0x230 0x490 0x000 0x2 0x0 +#define MX8MP_IOMUXC_UART3_RXD__GPT1_CAPTURE2 0x230 0x490 0x598 0x3 0x1 +#define MX8MP_IOMUXC_UART3_RXD__CAN2_TX 0x230 0x490 0x000 0x4 0x0 +#define MX8MP_IOMUXC_UART3_RXD__GPIO5_IO26 0x230 0x490 0x000 0x5 0x0 +#define MX8MP_IOMUXC_UART3_RXD__TPSMP_HDATA28 0x230 0x490 0x000 0x7 0x0 +#define MX8MP_IOMUXC_UART3_TXD__UART3_DCE_TX 0x234 0x494 0x000 0x0 0x0 +#define MX8MP_IOMUXC_UART3_TXD__UART3_DTE_RX 0x234 0x494 0x5F8 0x0 0x7 +#define MX8MP_IOMUXC_UART3_TXD__UART1_DCE_RTS 0x234 0x494 0x5E4 0x1 0x5 +#define MX8MP_IOMUXC_UART3_TXD__UART1_DTE_CTS 0x234 0x494 0x000 0x1 0x0 +#define MX8MP_IOMUXC_UART3_TXD__USDHC3_VSELECT 0x234 0x494 0x000 0x2 0x0 +#define MX8MP_IOMUXC_UART3_TXD__GPT1_CLK 0x234 0x494 0x59C 0x3 0x1 +#define MX8MP_IOMUXC_UART3_TXD__CAN2_RX 0x234 0x494 0x550 0x4 0x2 +#define MX8MP_IOMUXC_UART3_TXD__GPIO5_IO27 0x234 0x494 0x000 0x5 0x0 +#define MX8MP_IOMUXC_UART3_TXD__TPSMP_HDATA29 0x234 0x494 0x000 0x7 0x0 +#define MX8MP_IOMUXC_UART4_RXD__UART4_DCE_RX 0x238 0x498 0x600 0x0 0x8 +#define MX8MP_IOMUXC_UART4_RXD__UART4_DTE_TX 0x238 0x498 0x000 0x0 0x0 +#define MX8MP_IOMUXC_UART4_RXD__UART2_DCE_CTS 0x238 0x498 0x000 0x1 0x0 +#define MX8MP_IOMUXC_UART4_RXD__UART2_DTE_RTS 0x238 0x498 0x5EC 0x1 0x4 +#define MX8MP_IOMUXC_UART4_RXD__HSIOMIX_PCIE_CLKREQ_B 0x238 0x498 0x5A0 0x2 0x1 +#define MX8MP_IOMUXC_UART4_RXD__GPT1_COMPARE1 0x238 0x498 0x000 0x3 0x0 +#define MX8MP_IOMUXC_UART4_RXD__I2C6_SCL 0x238 0x498 0x5CC 0x4 0x2 +#define MX8MP_IOMUXC_UART4_RXD__GPIO5_IO28 0x238 0x498 0x000 0x5 0x0 +#define MX8MP_IOMUXC_UART4_RXD__TPSMP_HDATA30 0x238 0x498 0x000 0x7 0x0 +#define MX8MP_IOMUXC_UART4_TXD__UART4_DCE_TX 0x23C 0x49C 0x000 0x0 0x0 +#define MX8MP_IOMUXC_UART4_TXD__UART4_DTE_RX 0x23C 0x49C 0x600 0x0 0x9 +#define MX8MP_IOMUXC_UART4_TXD__UART2_DCE_RTS 0x23C 0x49C 0x5EC 0x1 0x5 +#define MX8MP_IOMUXC_UART4_TXD__UART2_DTE_CTS 0x23C 0x49C 0x000 0x1 0x0 +#define MX8MP_IOMUXC_UART4_TXD__GPT1_CAPTURE1 0x23C 0x49C 0x594 0x3 0x1 +#define MX8MP_IOMUXC_UART4_TXD__I2C6_SDA 0x23C 0x49C 0x5D0 0x4 0x2 +#define MX8MP_IOMUXC_UART4_TXD__GPIO5_IO29 0x23C 0x49C 0x000 0x5 0x0 +#define MX8MP_IOMUXC_UART4_TXD__TPSMP_HDATA31 0x23C 0x49C 0x000 0x7 0x0 +#define MX8MP_IOMUXC_HDMI_DDC_SCL__HDMIMIX_EARC_SCL 0x240 0x4A0 0x000 0x0 0x0 +#define MX8MP_IOMUXC_HDMI_DDC_SCL__I2C5_SCL 0x240 0x4A0 0x5C4 0x3 0x3 +#define MX8MP_IOMUXC_HDMI_DDC_SCL__CAN1_TX 0x240 0x4A0 0x000 0x4 0x0 +#define MX8MP_IOMUXC_HDMI_DDC_SCL__GPIO3_IO26 0x240 0x4A0 0x000 0x5 0x0 +#define MX8MP_IOMUXC_HDMI_DDC_SCL__AUDIOMIX_test_out00 0x240 0x4A0 0x000 0x6 0x0 +#define MX8MP_IOMUXC_HDMI_DDC_SDA__HDMIMIX_EARC_SDA 0x244 0x4A4 0x000 0x0 0x0 +#define MX8MP_IOMUXC_HDMI_DDC_SDA__I2C5_SDA 0x244 0x4A4 0x5C8 0x3 0x3 +#define MX8MP_IOMUXC_HDMI_DDC_SDA__CAN1_RX 0x244 0x4A4 0x54C 0x4 0x3 +#define MX8MP_IOMUXC_HDMI_DDC_SDA__GPIO3_IO27 0x244 0x4A4 0x000 0x5 0x0 +#define MX8MP_IOMUXC_HDMI_DDC_SDA__AUDIOMIX_test_out01 0x244 0x4A4 0x000 0x6 0x0 +#define MX8MP_IOMUXC_HDMI_CEC__HDMIMIX_EARC_CEC 0x248 0x4A8 0x000 0x0 0x0 +#define MX8MP_IOMUXC_HDMI_CEC__I2C6_SCL 0x248 0x4A8 0x5CC 0x3 0x3 +#define MX8MP_IOMUXC_HDMI_CEC__CAN2_TX 0x248 0x4A8 0x000 0x4 0x0 +#define MX8MP_IOMUXC_HDMI_CEC__GPIO3_IO28 0x248 0x4A8 0x000 0x5 0x0 +#define MX8MP_IOMUXC_HDMI_HPD__HDMIMIX_EARC_DC_HPD 0x24C 0x4AC 0x000 0x0 0x0 +#define MX8MP_IOMUXC_HDMI_HPD__AUDIOMIX_EARC_HDMI_HPD_O 0x24C 0x4AC 0x000 0x1 0x0 +#define MX8MP_IOMUXC_HDMI_HPD__I2C6_SDA 0x24C 0x4AC 0x5D0 0x3 0x3 +#define MX8MP_IOMUXC_HDMI_HPD__CAN2_RX 0x24C 0x4AC 0x550 0x4 0x3 +#define MX8MP_IOMUXC_HDMI_HPD__GPIO3_IO29 0x24C 0x4AC 0x000 0x5 0x0 + +#endif /* __DTS_IMX8MP_PINFUNC_H */ diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi new file mode 100644 index 000000000000..61cf373ad268 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi @@ -0,0 +1,608 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2019 NXP + */ + +#include +#include +#include +#include + +#include "imx8mp-pinfunc.h" + +/ { + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + ethernet0 = &fec; + gpio0 = &gpio1; + gpio1 = &gpio2; + gpio2 = &gpio3; + gpio3 = &gpio4; + gpio4 = &gpio5; + mmc0 = &usdhc1; + mmc1 = &usdhc2; + mmc2 = &usdhc3; + serial0 = &uart1; + serial1 = &uart2; + serial2 = &uart3; + serial3 = &uart4; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + A53_0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0>; + clock-latency = <61036>; + clocks = <&clk IMX8MP_CLK_ARM>; + enable-method = "psci"; + next-level-cache = <&A53_L2>; + }; + + A53_1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x1>; + clock-latency = <61036>; + clocks = <&clk IMX8MP_CLK_ARM>; + enable-method = "psci"; + next-level-cache = <&A53_L2>; + }; + + A53_2: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x2>; + clock-latency = <61036>; + clocks = <&clk IMX8MP_CLK_ARM>; + enable-method = "psci"; + next-level-cache = <&A53_L2>; + }; + + A53_3: cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x3>; + clock-latency = <61036>; + clocks = <&clk IMX8MP_CLK_ARM>; + enable-method = "psci"; + next-level-cache = <&A53_L2>; + }; + + A53_L2: l2-cache0 { + compatible = "cache"; + }; + }; + + osc_32k: clock-osc-32k { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "osc_32k"; + }; + + osc_24m: clock-osc-24m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "osc_24m"; + }; + + clk_ext1: clock-ext1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <133000000>; + clock-output-names = "clk_ext1"; + }; + + clk_ext2: clock-ext2 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <133000000>; + clock-output-names = "clk_ext2"; + }; + + clk_ext3: clock-ext3 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <133000000>; + clock-output-names = "clk_ext3"; + }; + + clk_ext4: clock-ext4 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency= <133000000>; + clock-output-names = "clk_ext4"; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + clock-frequency = <8000000>; + arm,no-tick-in-suspend; + }; + + soc@0 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x0 0x0 0x3e000000>; + + aips1: bus@30000000 { + compatible = "simple-bus"; + reg = <0x30000000 0x400000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio1: gpio@30200000 { + compatible = "fsl,imx8mp-gpio", "fsl,imx35-gpio"; + reg = <0x30200000 0x10000>; + interrupts = , + ; + clocks = <&clk IMX8MP_CLK_GPIO1_ROOT>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 5 30>; + }; + + gpio2: gpio@30210000 { + compatible = "fsl,imx8mp-gpio", "fsl,imx35-gpio"; + reg = <0x30210000 0x10000>; + interrupts = , + ; + clocks = <&clk IMX8MP_CLK_GPIO2_ROOT>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 35 21>; + }; + + gpio3: gpio@30220000 { + compatible = "fsl,imx8mp-gpio", "fsl,imx35-gpio"; + reg = <0x30220000 0x10000>; + interrupts = , + ; + clocks = <&clk IMX8MP_CLK_GPIO3_ROOT>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 56 26>, <&iomuxc 0 144 4>; + }; + + gpio4: gpio@30230000 { + compatible = "fsl,imx8mp-gpio", "fsl,imx35-gpio"; + reg = <0x30230000 0x10000>; + interrupts = , + ; + clocks = <&clk IMX8MP_CLK_GPIO4_ROOT>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 82 32>; + }; + + gpio5: gpio@30240000 { + compatible = "fsl,imx8mp-gpio", "fsl,imx35-gpio"; + reg = <0x30240000 0x10000>; + interrupts = , + ; + clocks = <&clk IMX8MP_CLK_GPIO5_ROOT>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 114 30>; + }; + + wdog1: watchdog@30280000 { + compatible = "fsl,imx8mp-wdt", "fsl,imx21-wdt"; + reg = <0x30280000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_WDOG1_ROOT>; + status = "disabled"; + }; + + iomuxc: pinctrl@30330000 { + compatible = "fsl,imx8mp-iomuxc"; + reg = <0x30330000 0x10000>; + }; + + gpr: iomuxc-gpr@30340000 { + compatible = "fsl,imx8mp-iomuxc-gpr", "syscon"; + reg = <0x30340000 0x10000>; + }; + + ocotp: ocotp-ctrl@30350000 { + compatible = "fsl,imx8mp-ocotp", "syscon"; + reg = <0x30350000 0x10000>; + clocks = <&clk IMX8MP_CLK_OCOTP_ROOT>; + /* For nvmem subnodes */ + #address-cells = <1>; + #size-cells = <1>; + + cpu_speed_grade: speed-grade@10 { + reg = <0x10 4>; + }; + }; + + anatop: anatop@30360000 { + compatible = "fsl,imx8mp-anatop", "fsl,imx8mm-anatop", + "syscon"; + reg = <0x30360000 0x10000>; + }; + + snvs: snvs@30370000 { + compatible = "fsl,sec-v4.0-mon","syscon", "simple-mfd"; + reg = <0x30370000 0x10000>; + + snvs_rtc: snvs-rtc-lp { + compatible = "fsl,sec-v4.0-mon-rtc-lp"; + regmap =<&snvs>; + offset = <0x34>; + interrupts = , + ; + clocks = <&clk IMX8MP_CLK_SNVS_ROOT>; + clock-names = "snvs-rtc"; + }; + + snvs_pwrkey: snvs-powerkey { + compatible = "fsl,sec-v4.0-pwrkey"; + regmap = <&snvs>; + interrupts = ; + linux,keycode = ; + wakeup-source; + status = "disabled"; + }; + }; + + clk: clock-controller@30380000 { + compatible = "fsl,imx8mp-ccm"; + reg = <0x30380000 0x10000>; + #clock-cells = <1>; + clocks = <&osc_32k>, <&osc_24m>, <&clk_ext1>, <&clk_ext2>, + <&clk_ext3>, <&clk_ext4>; + clock-names = "osc_32k", "osc_24m", "clk_ext1", "clk_ext2", + "clk_ext3", "clk_ext4"; + assigned-clocks = <&clk IMX8MP_CLK_NOC>, + <&clk IMX8MP_CLK_NOC_IO>, + <&clk IMX8MP_CLK_GIC>, + <&clk IMX8MP_CLK_AUDIO_AHB>, + <&clk IMX8MP_CLK_AUDIO_AXI_SRC>, + <&clk IMX8MP_CLK_IPG_AUDIO_ROOT>, + <&clk IMX8MP_AUDIO_PLL1>, + <&clk IMX8MP_AUDIO_PLL2>; + assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>, + <&clk IMX8MP_SYS_PLL1_800M>, + <&clk IMX8MP_SYS_PLL2_500M>, + <&clk IMX8MP_SYS_PLL1_800M>, + <&clk IMX8MP_SYS_PLL1_800M>; + assigned-clock-rates = <1000000000>, + <800000000>, + <500000000>, + <400000000>, + <800000000>, + <400000000>, + <393216000>, + <361267200>; + }; + }; + + aips2: bus@30400000 { + compatible = "simple-bus"; + reg = <0x30400000 0x400000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + pwm1: pwm@30660000 { + compatible = "fsl,imx8mp-pwm", "fsl,imx27-pwm"; + reg = <0x30660000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_PWM1_ROOT>, + <&clk IMX8MP_CLK_PWM1_ROOT>; + clock-names = "ipg", "per"; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm2: pwm@30670000 { + compatible = "fsl,imx8mp-pwm", "fsl,imx27-pwm"; + reg = <0x30670000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_PWM2_ROOT>, + <&clk IMX8MP_CLK_PWM2_ROOT>; + clock-names = "ipg", "per"; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm3: pwm@30680000 { + compatible = "fsl,imx8mp-pwm", "fsl,imx27-pwm"; + reg = <0x30680000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_PWM3_ROOT>, + <&clk IMX8MP_CLK_PWM3_ROOT>; + clock-names = "ipg", "per"; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm4: pwm@30690000 { + compatible = "fsl,imx8mp-pwm", "fsl,imx27-pwm"; + reg = <0x30690000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_PWM4_ROOT>, + <&clk IMX8MP_CLK_PWM4_ROOT>; + clock-names = "ipg", "per"; + #pwm-cells = <2>; + status = "disabled"; + }; + }; + + aips3: bus@30800000 { + compatible = "simple-bus"; + reg = <0x30800000 0x400000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + ecspi1: spi@30820000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx8mp-ecspi", "fsl,imx51-ecspi"; + reg = <0x30820000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_ECSPI1_ROOT>, + <&clk IMX8MP_CLK_ECSPI1_ROOT>; + clock-names = "ipg", "per"; + dmas = <&sdma1 0 7 1>, <&sdma1 1 7 2>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + ecspi2: spi@30830000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx8mp-ecspi", "fsl,imx51-ecspi"; + reg = <0x30830000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_ECSPI2_ROOT>, + <&clk IMX8MP_CLK_ECSPI2_ROOT>; + clock-names = "ipg", "per"; + dmas = <&sdma1 2 7 1>, <&sdma1 3 7 2>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + ecspi3: spi@30840000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx8mp-ecspi", "fsl,imx51-ecspi"; + reg = <0x30840000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_ECSPI3_ROOT>, + <&clk IMX8MP_CLK_ECSPI3_ROOT>; + clock-names = "ipg", "per"; + dmas = <&sdma1 4 7 1>, <&sdma1 5 7 2>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + uart1: serial@30860000 { + compatible = "fsl,imx8mp-uart", "fsl,imx6q-uart"; + reg = <0x30860000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_UART1_ROOT>, + <&clk IMX8MP_CLK_UART1_ROOT>; + clock-names = "ipg", "per"; + dmas = <&sdma1 22 4 0>, <&sdma1 23 4 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + uart3: serial@30880000 { + compatible = "fsl,imx8mp-uart", "fsl,imx6q-uart"; + reg = <0x30880000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_UART3_ROOT>, + <&clk IMX8MP_CLK_UART3_ROOT>; + clock-names = "ipg", "per"; + dmas = <&sdma1 26 4 0>, <&sdma1 27 4 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + uart2: serial@30890000 { + compatible = "fsl,imx8mp-uart", "fsl,imx6q-uart"; + reg = <0x30890000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_UART2_ROOT>, + <&clk IMX8MP_CLK_UART2_ROOT>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + i2c1: i2c@30a20000 { + compatible = "fsl,imx8mp-i2c", "fsl,imx21-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x30a20000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_I2C1_ROOT>; + status = "disabled"; + }; + + i2c2: i2c@30a30000 { + compatible = "fsl,imx8mp-i2c", "fsl,imx21-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x30a30000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_I2C2_ROOT>; + status = "disabled"; + }; + + i2c3: i2c@30a40000 { + compatible = "fsl,imx8mp-i2c", "fsl,imx21-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x30a40000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_I2C3_ROOT>; + status = "disabled"; + }; + + i2c4: i2c@30a50000 { + compatible = "fsl,imx8mp-i2c", "fsl,imx21-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x30a50000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_I2C4_ROOT>; + status = "disabled"; + }; + + uart4: serial@30a60000 { + compatible = "fsl,imx8mp-uart", "fsl,imx6q-uart"; + reg = <0x30a60000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_UART4_ROOT>, + <&clk IMX8MP_CLK_UART4_ROOT>; + clock-names = "ipg", "per"; + dmas = <&sdma1 28 4 0>, <&sdma1 29 4 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + i2c5: i2c@30ad0000 { + compatible = "fsl,imx8mp-i2c", "fsl,imx21-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x30ad0000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_I2C5_ROOT>; + status = "disabled"; + }; + + i2c6: i2c@30ae0000 { + compatible = "fsl,imx8mp-i2c", "fsl,imx21-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x30ae0000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_I2C6_ROOT>; + status = "disabled"; + }; + + usdhc1: mmc@30b40000 { + compatible = "fsl,imx8mp-usdhc", "fsl,imx7d-usdhc"; + reg = <0x30b40000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_DUMMY>, + <&clk IMX8MP_CLK_NAND_USDHC_BUS>, + <&clk IMX8MP_CLK_USDHC1_ROOT>; + clock-names = "ipg", "ahb", "per"; + fsl,tuning-start-tap = <20>; + fsl,tuning-step= <2>; + bus-width = <4>; + status = "disabled"; + }; + + usdhc2: mmc@30b50000 { + compatible = "fsl,imx8mp-usdhc", "fsl,imx7d-usdhc"; + reg = <0x30b50000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_DUMMY>, + <&clk IMX8MP_CLK_NAND_USDHC_BUS>, + <&clk IMX8MP_CLK_USDHC2_ROOT>; + clock-names = "ipg", "ahb", "per"; + fsl,tuning-start-tap = <20>; + fsl,tuning-step= <2>; + bus-width = <4>; + status = "disabled"; + }; + + usdhc3: mmc@30b60000 { + compatible = "fsl,imx8mp-usdhc", "fsl,imx7d-usdhc"; + reg = <0x30b60000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_DUMMY>, + <&clk IMX8MP_CLK_NAND_USDHC_BUS>, + <&clk IMX8MP_CLK_USDHC3_ROOT>; + clock-names = "ipg", "ahb", "per"; + fsl,tuning-start-tap = <20>; + fsl,tuning-step= <2>; + bus-width = <4>; + status = "disabled"; + }; + + sdma1: dma-controller@30bd0000 { + compatible = "fsl,imx8mp-sdma", "fsl,imx8mq-sdma"; + reg = <0x30bd0000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_SDMA1_ROOT>, + <&clk IMX8MP_CLK_SDMA1_ROOT>; + clock-names = "ipg", "ahb"; + #dma-cells = <3>; + fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin"; + }; + + fec: ethernet@30be0000 { + compatible = "fsl,imx8mp-fec", "fsl,imx8mq-fec"; + reg = <0x30be0000 0x10000>; + interrupts = , + , + ; + clocks = <&clk IMX8MP_CLK_ENET1_ROOT>, + <&clk IMX8MP_CLK_SIM_ENET_ROOT>, + <&clk IMX8MP_CLK_ENET_TIMER>, + <&clk IMX8MP_CLK_ENET_REF>, + <&clk IMX8MP_CLK_ENET_PHY_REF>; + clock-names = "ipg", "ahb", "ptp", + "enet_clk_ref", "enet_out"; + assigned-clocks = <&clk IMX8MP_CLK_ENET_AXI>, + <&clk IMX8MP_CLK_ENET_TIMER>, + <&clk IMX8MP_CLK_ENET_REF>, + <&clk IMX8MP_CLK_ENET_TIMER>; + assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_266M>, + <&clk IMX8MP_SYS_PLL2_100M>, + <&clk IMX8MP_SYS_PLL2_125M>; + assigned-clock-rates = <0>, <0>, <125000000>, <100000000>; + fsl,num-tx-queues = <3>; + fsl,num-rx-queues = <3>; + status = "disabled"; + }; + }; + + gic: interrupt-controller@38800000 { + compatible = "arm,gic-v3"; + reg = <0x38800000 0x10000>, + <0x38880000 0xc0000>; + #interrupt-cells = <3>; + interrupt-controller; + interrupts = ; + interrupt-parent = <&gic>; + }; + }; +}; From 9e847693c6f344458d094f2978da98add2ba9d7f Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 11 Feb 2020 20:48:26 +0800 Subject: [PATCH 0374/4444] arm64: dts: freescale: Add i.MX8MP EVK board support Add basic i.MM8MP EVK board support. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/Makefile | 1 + arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 231 +++++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-evk.dts diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 6088e3629151..a6d70b73d69b 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -30,6 +30,7 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-rdb.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mn-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mn-ddr4-evk.dtb +dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-hummingboard-pulse.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mq-librem5-devkit.dtb diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts new file mode 100644 index 000000000000..6df3beb92dc8 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2019 NXP + */ + +/dts-v1/; + +#include "imx8mp.dtsi" + +/ { + model = "NXP i.MX8MPlus EVK board"; + compatible = "fsl,imx8mp-evk", "fsl,imx8mp"; + + chosen { + stdout-path = &uart2; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0x0 0x40000000 0 0xc0000000>, + <0x1 0x00000000 0 0xc0000000>; + }; + + reg_usdhc2_vmmc: regulator-usdhc2 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>; + regulator-name = "VSD_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; + +&fec { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_fec>; + phy-mode = "rgmii-id"; + phy-handle = <ðphy1>; + fsl,magic-packet; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + eee-broken-1000t; + reset-gpios = <&gpio4 2 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&snvs_pwrkey { + status = "okay"; +}; + +&uart2 { + /* console */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + status = "okay"; +}; + +&usdhc2 { + assigned-clocks = <&clk IMX8MP_CLK_USDHC2>; + assigned-clock-rates = <400000000>; + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; + pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>; + pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; + cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; + vmmc-supply = <®_usdhc2_vmmc>; + bus-width = <4>; + status = "okay"; +}; + +&usdhc3 { + assigned-clocks = <&clk IMX8MP_CLK_USDHC3>; + assigned-clock-rates = <400000000>; + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc3>; + pinctrl-1 = <&pinctrl_usdhc3_100mhz>; + pinctrl-2 = <&pinctrl_usdhc3_200mhz>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&wdog1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; + status = "okay"; +}; + +&iomuxc { + pinctrl-names = "default"; + + pinctrl_fec: fecgrp { + fsl,pins = < + MX8MP_IOMUXC_SAI1_RXD2__ENET1_MDC 0x3 + MX8MP_IOMUXC_SAI1_RXD3__ENET1_MDIO 0x3 + MX8MP_IOMUXC_SAI1_RXD4__ENET1_RGMII_RD0 0x91 + MX8MP_IOMUXC_SAI1_RXD5__ENET1_RGMII_RD1 0x91 + MX8MP_IOMUXC_SAI1_RXD6__ENET1_RGMII_RD2 0x91 + MX8MP_IOMUXC_SAI1_RXD7__ENET1_RGMII_RD3 0x91 + MX8MP_IOMUXC_SAI1_TXC__ENET1_RGMII_RXC 0x91 + MX8MP_IOMUXC_SAI1_TXFS__ENET1_RGMII_RX_CTL 0x91 + MX8MP_IOMUXC_SAI1_TXD0__ENET1_RGMII_TD0 0x1f + MX8MP_IOMUXC_SAI1_TXD1__ENET1_RGMII_TD1 0x1f + MX8MP_IOMUXC_SAI1_TXD2__ENET1_RGMII_TD2 0x1f + MX8MP_IOMUXC_SAI1_TXD3__ENET1_RGMII_TD3 0x1f + MX8MP_IOMUXC_SAI1_TXD4__ENET1_RGMII_TX_CTL 0x1f + MX8MP_IOMUXC_SAI1_TXD5__ENET1_RGMII_TXC 0x1f + MX8MP_IOMUXC_SAI1_RXD0__GPIO4_IO02 0x19 + >; + }; + + pinctrl_reg_usdhc2_vmmc: regusdhc2vmmc { + fsl,pins = < + MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19 0x41 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX 0x49 + MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX 0x49 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x190 + MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d0 + MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d0 + MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d0 + MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d0 + MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d0 + MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc1 + >; + }; + + pinctrl_usdhc2_100mhz: usdhc2grp-100mhz { + fsl,pins = < + MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x194 + MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d4 + MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d4 + MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d4 + MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d4 + MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d4 + MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc1 + >; + }; + + pinctrl_usdhc2_200mhz: usdhc2grp-200mhz { + fsl,pins = < + MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x196 + MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d6 + MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d6 + MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d6 + MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d6 + MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d6 + MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc1 + >; + }; + + pinctrl_usdhc2_gpio: usdhc2grp-gpio { + fsl,pins = < + MX8MP_IOMUXC_SD2_CD_B__GPIO2_IO12 0x1c4 + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x190 + MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d0 + MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d0 + MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d0 + MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d0 + MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d0 + MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d0 + MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d0 + MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d0 + MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d0 + MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x190 + >; + }; + + pinctrl_usdhc3_100mhz: usdhc3grp-100mhz { + fsl,pins = < + MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x194 + MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d4 + MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d4 + MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d4 + MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d4 + MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d4 + MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d4 + MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d4 + MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d4 + MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d4 + MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x194 + >; + }; + + pinctrl_usdhc3_200mhz: usdhc3grp-200mhz { + fsl,pins = < + MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x196 + MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d6 + MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d6 + MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d6 + MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d6 + MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d6 + MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d6 + MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d6 + MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d6 + MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d6 + MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x196 + >; + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = < + MX8MP_IOMUXC_GPIO1_IO02__WDOG1_WDOG_B 0xc6 + >; + }; +}; From f34d4bfab3548e8a76eb571efc8e69b60830c268 Mon Sep 17 00:00:00 2001 From: Alifer Moraes Date: Tue, 11 Feb 2020 10:48:28 -0300 Subject: [PATCH 0375/4444] arm64: dts: imx8mq-phanbell: Add support for ethernet Add support for ethernet on Google's i.MX 8MQ Phanbell Signed-off-by: Alifer Moraes Tested-by: Vitor Massaru Iha Signed-off-by: Shawn Guo --- .../boot/dts/freescale/imx8mq-phanbell.dts | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts b/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts index 3f2a489a4ad8..16ed13c44a47 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts @@ -201,6 +201,27 @@ }; }; +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_fec1>; + phy-mode = "rgmii-id"; + phy-reset-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; + phy-reset-duration = <10>; + phy-reset-post-delay = <30>; + phy-handle = <ðphy0>; + fsl,magic-packet; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + ethphy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + }; + }; +}; + &uart1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart1>; @@ -254,6 +275,26 @@ }; &iomuxc { + pinctrl_fec1: fec1grp { + fsl,pins = < + MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC 0x3 + MX8MQ_IOMUXC_ENET_MDIO_ENET1_MDIO 0x23 + MX8MQ_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f + MX8MQ_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f + MX8MQ_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f + MX8MQ_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f + MX8MQ_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91 + MX8MQ_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91 + MX8MQ_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91 + MX8MQ_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91 + MX8MQ_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f + MX8MQ_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91 + MX8MQ_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91 + MX8MQ_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f + MX8MQ_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x19 + >; + }; + pinctrl_i2c1: i2c1grp { fsl,pins = < MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL 0x4000007f From f95d58981f40b546429e1b06e441c70bcc52786e Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 12 Feb 2020 15:02:23 +0800 Subject: [PATCH 0376/4444] clk: imx: Include clk-provider.h instead of clk.h for i.MX8M SoCs clock driver The i.MX8M SoCs clock driver are provider, NOT consumer, so clk-provider.h should be used instead of clk.h. Signed-off-by: Anson Huang Reviewed-by: Stephen Boyd Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mm.c | 2 +- drivers/clk/imx/clk-imx8mn.c | 2 +- drivers/clk/imx/clk-imx8mq.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c index 6dbdc1a1b5eb..0cba5d4bd51e 100644 --- a/drivers/clk/imx/clk-imx8mm.c +++ b/drivers/clk/imx/clk-imx8mm.c @@ -4,7 +4,7 @@ */ #include -#include +#include #include #include #include diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c index 7eea15a81838..6f4547fec368 100644 --- a/drivers/clk/imx/clk-imx8mn.c +++ b/drivers/clk/imx/clk-imx8mn.c @@ -4,7 +4,7 @@ */ #include -#include +#include #include #include #include diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c index ac9452cd9a82..8b4b2fbe4a65 100644 --- a/drivers/clk/imx/clk-imx8mq.c +++ b/drivers/clk/imx/clk-imx8mq.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include #include From 79ccef698ac811b3029fd01cbe2114fed3219c8a Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 12 Feb 2020 17:03:00 +0800 Subject: [PATCH 0377/4444] clk: imx: drop redundant initialization No need to initialize flags as 0, remove the initialization. Signed-off-by: Anson Huang Reviewed-by: Stephen Boyd Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-composite-8m.c | 2 +- drivers/clk/imx/clk-fixup-div.c | 2 +- drivers/clk/imx/clk-fixup-mux.c | 2 +- drivers/clk/imx/clk-gate2.c | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/imx/clk-composite-8m.c b/drivers/clk/imx/clk-composite-8m.c index 4869c16376bf..99773519b5a5 100644 --- a/drivers/clk/imx/clk-composite-8m.c +++ b/drivers/clk/imx/clk-composite-8m.c @@ -92,7 +92,7 @@ static int imx8m_clk_composite_divider_set_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_divider *divider = to_clk_divider(hw); - unsigned long flags = 0; + unsigned long flags; int prediv_value; int div_value; int ret; diff --git a/drivers/clk/imx/clk-fixup-div.c b/drivers/clk/imx/clk-fixup-div.c index 4b17b91504ed..100ca828b052 100644 --- a/drivers/clk/imx/clk-fixup-div.c +++ b/drivers/clk/imx/clk-fixup-div.c @@ -55,7 +55,7 @@ static int clk_fixup_div_set_rate(struct clk_hw *hw, unsigned long rate, struct clk_fixup_div *fixup_div = to_clk_fixup_div(hw); struct clk_divider *div = to_clk_divider(hw); unsigned int divider, value; - unsigned long flags = 0; + unsigned long flags; u32 val; divider = parent_rate / rate; diff --git a/drivers/clk/imx/clk-fixup-mux.c b/drivers/clk/imx/clk-fixup-mux.c index b569d919c645..58a67630bb6a 100644 --- a/drivers/clk/imx/clk-fixup-mux.c +++ b/drivers/clk/imx/clk-fixup-mux.c @@ -42,7 +42,7 @@ static int clk_fixup_mux_set_parent(struct clk_hw *hw, u8 index) { struct clk_fixup_mux *fixup_mux = to_clk_fixup_mux(hw); struct clk_mux *mux = to_clk_mux(hw); - unsigned long flags = 0; + unsigned long flags; u32 val; spin_lock_irqsave(mux->lock, flags); diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c index 7d44ce814806..72a7698be791 100644 --- a/drivers/clk/imx/clk-gate2.c +++ b/drivers/clk/imx/clk-gate2.c @@ -40,7 +40,7 @@ static int clk_gate2_enable(struct clk_hw *hw) { struct clk_gate2 *gate = to_clk_gate2(hw); u32 reg; - unsigned long flags = 0; + unsigned long flags; spin_lock_irqsave(gate->lock, flags); @@ -62,7 +62,7 @@ static void clk_gate2_disable(struct clk_hw *hw) { struct clk_gate2 *gate = to_clk_gate2(hw); u32 reg; - unsigned long flags = 0; + unsigned long flags; spin_lock_irqsave(gate->lock, flags); @@ -101,7 +101,7 @@ static int clk_gate2_is_enabled(struct clk_hw *hw) static void clk_gate2_disable_unused(struct clk_hw *hw) { struct clk_gate2 *gate = to_clk_gate2(hw); - unsigned long flags = 0; + unsigned long flags; u32 reg; spin_lock_irqsave(gate->lock, flags); From 836b2513326ef047e67123ecea389e65addf6c18 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 12 Feb 2020 17:09:43 +0800 Subject: [PATCH 0378/4444] clk: imx7ulp: Include clk-provider.h instead of clk.h The i.MX7ULP clock driver is provider, NOT consumer, so clk-provider.h should be used instead of clk.h. Signed-off-by: Anson Huang Reviewed-by: Stephen Boyd Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx7ulp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-imx7ulp.c b/drivers/clk/imx/clk-imx7ulp.c index 0620d6c8c072..3710aa0dee9b 100644 --- a/drivers/clk/imx/clk-imx7ulp.c +++ b/drivers/clk/imx/clk-imx7ulp.c @@ -8,7 +8,7 @@ */ #include -#include +#include #include #include #include From 8b1a3c0ba9b1cec6dc91904604130a435d90c53c Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 12 Feb 2020 19:57:33 +0800 Subject: [PATCH 0379/4444] clk: imx6sl: Add missing of_node_put() After finishing using device node got from of_find_compatible_node(), of_node_put() needs to be called. Signed-off-by: Anson Huang Reviewed-by: Stephen Boyd Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx6sl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/imx/clk-imx6sl.c b/drivers/clk/imx/clk-imx6sl.c index 4bd44d89eaaa..0f647d148abf 100644 --- a/drivers/clk/imx/clk-imx6sl.c +++ b/drivers/clk/imx/clk-imx6sl.c @@ -208,6 +208,7 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node) np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-anatop"); base = of_iomap(np, 0); WARN_ON(!base); + of_node_put(np); anatop_base = base; hws[IMX6SL_PLL1_BYPASS_SRC] = imx_clk_hw_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); From cb5ae504f2014a66c131920b8eb0ca6b0e6851c6 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 12 Feb 2020 19:57:34 +0800 Subject: [PATCH 0380/4444] clk: imx8mq: Add missing of_node_put() After finishing using device node got from of_find_compatible_node(), of_node_put() needs to be called. Signed-off-by: Anson Huang Reviewed-by: Stephen Boyd Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c index 8b4b2fbe4a65..1f5ea1eaad65 100644 --- a/drivers/clk/imx/clk-imx8mq.c +++ b/drivers/clk/imx/clk-imx8mq.c @@ -305,6 +305,7 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-anatop"); base = of_iomap(np, 0); + of_node_put(np); if (WARN_ON(!base)) return -ENOMEM; From 5062d46e2698e720f866c06563419bff09dcacb4 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 12 Feb 2020 19:57:35 +0800 Subject: [PATCH 0381/4444] clk: imx8mm: Add missing of_node_put() After finishing using device node got from of_find_compatible_node(), of_node_put() needs to be called. Signed-off-by: Anson Huang Reviewed-by: Stephen Boyd Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c index 0cba5d4bd51e..2f2c240a86e2 100644 --- a/drivers/clk/imx/clk-imx8mm.c +++ b/drivers/clk/imx/clk-imx8mm.c @@ -324,6 +324,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev) np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop"); base = of_iomap(np, 0); + of_node_put(np); if (WARN_ON(!base)) return -ENOMEM; From d93171b54cb44e65c1ec5462c17704b51b8afc27 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 12 Feb 2020 19:57:36 +0800 Subject: [PATCH 0382/4444] clk: imx8mn: Add missing of_node_put() After finishing using device node got from of_find_compatible_node(), of_node_put() needs to be called. Signed-off-by: Anson Huang Reviewed-by: Stephen Boyd Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mn.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c index 6f4547fec368..67b826d7184b 100644 --- a/drivers/clk/imx/clk-imx8mn.c +++ b/drivers/clk/imx/clk-imx8mn.c @@ -317,6 +317,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) np = of_find_compatible_node(NULL, NULL, "fsl,imx8mn-anatop"); base = of_iomap(np, 0); + of_node_put(np); if (WARN_ON(!base)) { ret = -ENOMEM; goto unregister_hws; From 680fbce528169eaadf621066a4925794e2addbd7 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 12 Feb 2020 19:57:37 +0800 Subject: [PATCH 0383/4444] clk: imx8mp: Add missing of_node_put() After finishing using device node got from of_find_compatible_node(), of_node_put() needs to be called. Signed-off-by: Anson Huang Reviewed-by: Stephen Boyd Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index ee83aa2162d9..a16af4fce044 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -434,6 +434,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) np = of_find_compatible_node(NULL, NULL, "fsl,imx8mp-anatop"); anatop_base = of_iomap(np, 0); + of_node_put(np); if (WARN_ON(!anatop_base)) return -ENOMEM; From c0157bdcafa16cf0457079ccfba03a9c4034ab66 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 13 Feb 2020 11:17:58 +0800 Subject: [PATCH 0384/4444] ARM: dts: imx: use generic name bus Per devicetree specification, generic names are recommended to be used, such as bus. i.MX AIPS is a AHB - IP bridge bus, so we could use bus as node name. Script: sed -i "s/\ Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx25.dtsi | 4 ++-- arch/arm/boot/dts/imx31.dtsi | 4 ++-- arch/arm/boot/dts/imx35.dtsi | 4 ++-- arch/arm/boot/dts/imx50.dtsi | 4 ++-- arch/arm/boot/dts/imx51.dtsi | 4 ++-- arch/arm/boot/dts/imx53.dtsi | 4 ++-- arch/arm/boot/dts/imx6dl.dtsi | 4 ++-- arch/arm/boot/dts/imx6q.dtsi | 2 +- arch/arm/boot/dts/imx6qdl.dtsi | 4 ++-- arch/arm/boot/dts/imx6qp.dtsi | 2 +- arch/arm/boot/dts/imx6sl.dtsi | 4 ++-- arch/arm/boot/dts/imx6sll.dtsi | 4 ++-- arch/arm/boot/dts/imx6sx.dtsi | 6 +++--- arch/arm/boot/dts/imx6ul.dtsi | 4 ++-- arch/arm/boot/dts/imx6ull.dtsi | 2 +- arch/arm/boot/dts/imx7s.dtsi | 6 +++--- arch/arm/boot/dts/vf500.dtsi | 4 ++-- arch/arm/boot/dts/vfxxx.dtsi | 4 ++-- 18 files changed, 35 insertions(+), 35 deletions(-) diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi index 40b95a290bd6..1123e683025c 100644 --- a/arch/arm/boot/dts/imx25.dtsi +++ b/arch/arm/boot/dts/imx25.dtsi @@ -75,7 +75,7 @@ interrupt-parent = <&asic>; ranges; - aips@43f00000 { /* AIPS1 */ + bus@43f00000 { /* AIPS1 */ compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -332,7 +332,7 @@ }; }; - aips@53f00000 { /* AIPS2 */ + bus@53f00000 { /* AIPS2 */ compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/imx31.dtsi b/arch/arm/boot/dts/imx31.dtsi index 6b62f0745b82..18270ec648fe 100644 --- a/arch/arm/boot/dts/imx31.dtsi +++ b/arch/arm/boot/dts/imx31.dtsi @@ -63,7 +63,7 @@ ranges = <0 0x1fffc000 0x4000>; }; - aips@43f00000 { /* AIPS1 */ + bus@43f00000 { /* AIPS1 */ compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -225,7 +225,7 @@ }; }; - aips@53f00000 { /* AIPS2 */ + bus@53f00000 { /* AIPS2 */ compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/imx35.dtsi b/arch/arm/boot/dts/imx35.dtsi index 9cbdc1a15cda..2ebf2c1fa682 100644 --- a/arch/arm/boot/dts/imx35.dtsi +++ b/arch/arm/boot/dts/imx35.dtsi @@ -66,7 +66,7 @@ cache-level = <2>; }; - aips1: aips@43f00000 { + aips1: bus@43f00000 { compatible = "fsl,aips", "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -199,7 +199,7 @@ }; }; - aips2: aips@53f00000 { + aips2: bus@53f00000 { compatible = "fsl,aips", "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/imx50.dtsi b/arch/arm/boot/dts/imx50.dtsi index 0bfe7c91d0eb..d325658901c5 100644 --- a/arch/arm/boot/dts/imx50.dtsi +++ b/arch/arm/boot/dts/imx50.dtsi @@ -101,7 +101,7 @@ interrupt-parent = <&tzic>; ranges; - aips@50000000 { /* AIPS1 */ + bus@50000000 { /* AIPS1 */ compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -389,7 +389,7 @@ }; }; - aips@60000000 { /* AIPS2 */ + bus@60000000 { /* AIPS2 */ compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi index dea86b98e9c3..6f608d9d9016 100644 --- a/arch/arm/boot/dts/imx51.dtsi +++ b/arch/arm/boot/dts/imx51.dtsi @@ -158,7 +158,7 @@ }; }; - aips@70000000 { /* AIPS1 */ + bus@70000000 { /* AIPS1 */ compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -440,7 +440,7 @@ }; }; - aips@80000000 { /* AIPS2 */ + bus@80000000 { /* AIPS2 */ compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi index ed341cfd9d09..8536f59f59e6 100644 --- a/arch/arm/boot/dts/imx53.dtsi +++ b/arch/arm/boot/dts/imx53.dtsi @@ -222,7 +222,7 @@ clock-names = "core_clk", "mem_iface_clk"; }; - aips@50000000 { /* AIPS1 */ + bus@50000000 { /* AIPS1 */ compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -654,7 +654,7 @@ }; }; - aips@60000000 { /* AIPS2 */ + bus@60000000 { /* AIPS2 */ compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi index 008312ee0c31..4b3a128d9260 100644 --- a/arch/arm/boot/dts/imx6dl.dtsi +++ b/arch/arm/boot/dts/imx6dl.dtsi @@ -85,7 +85,7 @@ clocks = <&clks IMX6QDL_CLK_OCRAM>; }; - aips1: aips-bus@2000000 { + aips1: bus@2000000 { iomuxc: iomuxc@20e0000 { compatible = "fsl,imx6dl-iomuxc"; }; @@ -101,7 +101,7 @@ }; }; - aips2: aips-bus@2100000 { + aips2: bus@2100000 { i2c4: i2c@21f8000 { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index 9d3be1cc6b64..0fad13f9d336 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -164,7 +164,7 @@ clocks = <&clks IMX6QDL_CLK_OCRAM>; }; - aips-bus@2000000 { /* AIPS1 */ + bus@2000000 { /* AIPS1 */ spba-bus@2000000 { ecspi5: spi@2018000 { #address-cells = <1>; diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index e6b4b8525f98..bf9d20f21060 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -294,7 +294,7 @@ status = "disabled"; }; - aips-bus@2000000 { /* AIPS1 */ + bus@2000000 { /* AIPS1 */ compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -935,7 +935,7 @@ }; }; - aips-bus@2100000 { /* AIPS2 */ + bus@2100000 { /* AIPS2 */ compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/imx6qp.dtsi b/arch/arm/boot/dts/imx6qp.dtsi index 5f51f8e5c1fa..93b89dc1f53b 100644 --- a/arch/arm/boot/dts/imx6qp.dtsi +++ b/arch/arm/boot/dts/imx6qp.dtsi @@ -18,7 +18,7 @@ clocks = <&clks IMX6QDL_CLK_OCRAM>; }; - aips-bus@2100000 { + bus@2100000 { pre1: pre@21c8000 { compatible = "fsl,imx6qp-pre"; reg = <0x021c8000 0x1000>; diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi index 59c54e6ad09a..5b26c8d75626 100644 --- a/arch/arm/boot/dts/imx6sl.dtsi +++ b/arch/arm/boot/dts/imx6sl.dtsi @@ -143,7 +143,7 @@ arm,data-latency = <4 2 3>; }; - aips1: aips-bus@2000000 { + aips1: bus@2000000 { compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -786,7 +786,7 @@ }; }; - aips2: aips-bus@2100000 { + aips2: bus@2100000 { compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/imx6sll.dtsi index a1bc5bb31756..797f850492fe 100644 --- a/arch/arm/boot/dts/imx6sll.dtsi +++ b/arch/arm/boot/dts/imx6sll.dtsi @@ -144,7 +144,7 @@ arm,data-latency = <4 2 3>; }; - aips1: aips-bus@2000000 { + aips1: bus@2000000 { compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -663,7 +663,7 @@ }; }; - aips2: aips-bus@2100000 { + aips2: bus@2100000 { compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index 59bad60a47dc..98de781b8082 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -235,7 +235,7 @@ status = "disabled"; }; - aips1: aips-bus@2000000 { + aips1: bus@2000000 { compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -830,7 +830,7 @@ }; }; - aips2: aips-bus@2100000 { + aips2: bus@2100000 { compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -1188,7 +1188,7 @@ }; }; - aips3: aips-bus@2200000 { + aips3: bus@2200000 { compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi index d9fdca12819b..beb82d357f37 100644 --- a/arch/arm/boot/dts/imx6ul.dtsi +++ b/arch/arm/boot/dts/imx6ul.dtsi @@ -204,7 +204,7 @@ status = "disabled"; }; - aips1: aips-bus@2000000 { + aips1: bus@2000000 { compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -771,7 +771,7 @@ }; }; - aips2: aips-bus@2100000 { + aips2: bus@2100000 { compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/imx6ull.dtsi b/arch/arm/boot/dts/imx6ull.dtsi index b7e67d121322..fcde7f77ae42 100644 --- a/arch/arm/boot/dts/imx6ull.dtsi +++ b/arch/arm/boot/dts/imx6ull.dtsi @@ -51,7 +51,7 @@ / { soc { - aips3: aips-bus@2200000 { + aips3: bus@2200000 { compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index 568d7a984aa6..f959f69b0677 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -315,7 +315,7 @@ <0x31006000 0x2000>; }; - aips1: aips-bus@30000000 { + aips1: bus@30000000 { compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -663,7 +663,7 @@ }; }; - aips2: aips-bus@30400000 { + aips2: bus@30400000 { compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -803,7 +803,7 @@ }; }; - aips3: aips-bus@30800000 { + aips3: bus@30800000 { compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/vf500.dtsi b/arch/arm/boot/dts/vf500.dtsi index b0ec475017ad..0c0dd442300a 100644 --- a/arch/arm/boot/dts/vf500.dtsi +++ b/arch/arm/boot/dts/vf500.dtsi @@ -23,7 +23,7 @@ }; soc { - aips-bus@40000000 { + bus@40000000 { intc: interrupt-controller@40003000 { compatible = "arm,cortex-a9-gic"; @@ -43,7 +43,7 @@ }; }; - aips-bus@40080000 { + bus@40080000 { pmu@40089000 { compatible = "arm,cortex-a5-pmu"; interrupts = <7 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi index 028e0ec30e0c..2d547e7b21ad 100644 --- a/arch/arm/boot/dts/vfxxx.dtsi +++ b/arch/arm/boot/dts/vfxxx.dtsi @@ -59,7 +59,7 @@ interrupt-parent = <&mscm_ir>; ranges; - aips0: aips-bus@40000000 { + aips0: bus@40000000 { compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -471,7 +471,7 @@ }; }; - aips1: aips-bus@40080000 { + aips1: bus@40080000 { compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; From 8faa77332fe01a681ef3097581a37b82adc1c14b Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Feb 2020 10:16:09 +0530 Subject: [PATCH 0385/4444] dmaengine: sun4i: set the linear_mode properly Commit 6ebb827f7aad ("dmaengine: sun4i: use 'linear_mode' in sun4i_dma_prep_dma_cyclic") updated the condition but introduced a semi colon this making this statement have no effect, so add the bitwise OR to fix it" Fixes: 6ebb827f7aad ("dmaengine: sun4i: use 'linear_mode' in sun4i_dma_prep_dma_cyclic") Reported-by: Stephen Rothwell Link: https://lore.kernel.org/r/20200214044609.2215861-1-vkoul@kernel.org Signed-off-by: Vinod Koul --- drivers/dma/sun4i-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c index e87fc7c460dd..e7ff09a5031d 100644 --- a/drivers/dma/sun4i-dma.c +++ b/drivers/dma/sun4i-dma.c @@ -697,7 +697,7 @@ sun4i_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf, size_t len, dest = sconfig->dst_addr; endpoints = SUN4I_DMA_CFG_DST_DRQ_TYPE(vchan->endpoint) | SUN4I_DMA_CFG_DST_ADDR_MODE(io_mode) | - SUN4I_DMA_CFG_SRC_DRQ_TYPE(ram_type); + SUN4I_DMA_CFG_SRC_DRQ_TYPE(ram_type) | SUN4I_DMA_CFG_SRC_ADDR_MODE(linear_mode); } else { src = sconfig->src_addr; From 7c48b086965873c0aa93d99773cf64c033b76b2f Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Thu, 13 Feb 2020 10:52:56 +0800 Subject: [PATCH 0386/4444] ARM: dts: imx: make gpt node name generic Node name should be generic, use "timer" instead of "gpt" for gpt node. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl.dtsi | 2 +- arch/arm/boot/dts/imx6sl.dtsi | 2 +- arch/arm/boot/dts/imx6sx.dtsi | 2 +- arch/arm/boot/dts/imx6ul.dtsi | 4 ++-- arch/arm/boot/dts/imx7s.dtsi | 8 ++++---- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index bf9d20f21060..1fc5cc2fffb8 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -574,7 +574,7 @@ status = "disabled"; }; - gpt: gpt@2098000 { + gpt: timer@2098000 { compatible = "fsl,imx6q-gpt", "fsl,imx31-gpt"; reg = <0x02098000 0x4000>; interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi index 5b26c8d75626..75e46e92c182 100644 --- a/arch/arm/boot/dts/imx6sl.dtsi +++ b/arch/arm/boot/dts/imx6sl.dtsi @@ -380,7 +380,7 @@ clock-names = "ipg", "per"; }; - gpt: gpt@2098000 { + gpt: timer@2098000 { compatible = "fsl,imx6sl-gpt"; reg = <0x02098000 0x4000>; interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index 98de781b8082..73423cca9b96 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -466,7 +466,7 @@ status = "disabled"; }; - gpt: gpt@2098000 { + gpt: timer@2098000 { compatible = "fsl,imx6sx-gpt", "fsl,imx6dl-gpt"; reg = <0x02098000 0x4000>; interrupts = ; diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi index beb82d357f37..67b2bab8c155 100644 --- a/arch/arm/boot/dts/imx6ul.dtsi +++ b/arch/arm/boot/dts/imx6ul.dtsi @@ -430,7 +430,7 @@ status = "disabled"; }; - gpt1: gpt@2098000 { + gpt1: timer@2098000 { compatible = "fsl,imx6ul-gpt", "fsl,imx6sx-gpt"; reg = <0x02098000 0x4000>; interrupts = ; @@ -704,7 +704,7 @@ reg = <0x020e4000 0x4000>; }; - gpt2: gpt@20e8000 { + gpt2: timer@20e8000 { compatible = "fsl,imx6ul-gpt", "fsl,imx6sx-gpt"; reg = <0x020e8000 0x4000>; interrupts = ; diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index f959f69b0677..8e59da4f05c9 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -443,7 +443,7 @@ fsl,input-sel = <&iomuxc>; }; - gpt1: gpt@302d0000 { + gpt1: timer@302d0000 { compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt"; reg = <0x302d0000 0x10000>; interrupts = ; @@ -452,7 +452,7 @@ clock-names = "ipg", "per"; }; - gpt2: gpt@302e0000 { + gpt2: timer@302e0000 { compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt"; reg = <0x302e0000 0x10000>; interrupts = ; @@ -462,7 +462,7 @@ status = "disabled"; }; - gpt3: gpt@302f0000 { + gpt3: timer@302f0000 { compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt"; reg = <0x302f0000 0x10000>; interrupts = ; @@ -472,7 +472,7 @@ status = "disabled"; }; - gpt4: gpt@30300000 { + gpt4: timer@30300000 { compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt"; reg = <0x30300000 0x10000>; interrupts = ; From 66d19a4f8d0fa7539f90cad64d793b4dac6f6e5d Mon Sep 17 00:00:00 2001 From: Robert Jones Date: Fri, 14 Feb 2020 13:01:55 -0800 Subject: [PATCH 0387/4444] ARM: dts: imx: ventana: add fxos8700 on gateworks boards Add fxos8700 iio imu entries for Gateworks ventana SBCs. Signed-off-by: Robert Jones Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-gw52xx.dtsi | 5 +++++ arch/arm/boot/dts/imx6qdl-gw53xx.dtsi | 5 +++++ arch/arm/boot/dts/imx6qdl-gw54xx.dtsi | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi index 1a9a9d98f284..60563ff0b7ce 100644 --- a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi +++ b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi @@ -313,6 +313,11 @@ interrupts = <12 2>; wakeup-gpios = <&gpio7 12 GPIO_ACTIVE_LOW>; }; + + accel@1e { + compatible = "nxp,fxos8700"; + reg = <0x1e>; + }; }; &ldb { diff --git a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi index 54b2beadd7a2..8942bec65c5c 100644 --- a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi +++ b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi @@ -304,6 +304,11 @@ interrupts = <11 2>; wakeup-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; }; + + accel@1e { + compatible = "nxp,fxos8700"; + reg = <0x1e>; + }; }; &ldb { diff --git a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi index 1b6c1331c220..c40583dbd96d 100644 --- a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi +++ b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi @@ -361,6 +361,11 @@ interrupts = <12 2>; wakeup-gpios = <&gpio7 12 GPIO_ACTIVE_LOW>; }; + + accel@1e { + compatible = "nxp,fxos8700"; + reg = <0x1e>; + }; }; &ldb { From 62e7f0b553038e3a1a1b2b067dd1fbdacd634e37 Mon Sep 17 00:00:00 2001 From: Robert Jones Date: Fri, 14 Feb 2020 13:02:41 -0800 Subject: [PATCH 0388/4444] ARM: dts: imx6qdl-gw553x: add lsm9ds1 iio imu/magn support Add one node for the accel/gyro i2c device and another for the separate magnetometer device in the lsm9ds1. Signed-off-by: Robert Jones Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-gw553x.dtsi | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/arch/arm/boot/dts/imx6qdl-gw553x.dtsi b/arch/arm/boot/dts/imx6qdl-gw553x.dtsi index a1066897be18..ee85031c3916 100644 --- a/arch/arm/boot/dts/imx6qdl-gw553x.dtsi +++ b/arch/arm/boot/dts/imx6qdl-gw553x.dtsi @@ -173,6 +173,25 @@ pinctrl-0 = <&pinctrl_i2c2>; status = "okay"; + magn@1c { + compatible = "st,lsm9ds1-magn"; + reg = <0x1c>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mag>; + interrupt-parent = <&gpio1>; + interrupts = <2 IRQ_TYPE_EDGE_RISING>; + }; + + imu@6a { + compatible = "st,lsm9ds1-imu"; + reg = <0x6a>; + st,drdy-int-pin = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_imu>; + interrupt-parent = <&gpio7>; + interrupts = <13 IRQ_TYPE_LEVEL_HIGH>; + }; + ltc3676: pmic@3c { compatible = "lltc,ltc3676"; reg = <0x3c>; @@ -426,6 +445,12 @@ >; }; + pinctrl_imu: imugrp { + fsl,pins = < + MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x1b0b0 + >; + }; + pinctrl_ipu1_csi0: ipu1csi0grp { fsl,pins = < MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x1b0b0 @@ -449,6 +474,12 @@ >; }; + pinctrl_mag: maggrp { + fsl,pins = < + MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b0 + >; + }; + pinctrl_pcie: pciegrp { fsl,pins = < MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0 From b0bb4fbad1560b2764477c9c45c5a5b37a90983a Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 14 Feb 2020 10:11:29 +0800 Subject: [PATCH 0389/4444] ARM: dts: imx: make kpp node name generic Node name should be generic, use "keypad" instead of "kpp" for kpp node. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl.dtsi | 2 +- arch/arm/boot/dts/imx6sl.dtsi | 2 +- arch/arm/boot/dts/imx6sx.dtsi | 2 +- arch/arm/boot/dts/imx6ul.dtsi | 2 +- arch/arm/boot/dts/imx7s.dtsi | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index 1fc5cc2fffb8..9691f09b4e5e 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -661,7 +661,7 @@ #interrupt-cells = <2>; }; - kpp: kpp@20b8000 { + kpp: keypad@20b8000 { compatible = "fsl,imx6q-kpp", "fsl,imx21-kpp"; reg = <0x020b8000 0x4000>; interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi index 75e46e92c182..af9af9628a89 100644 --- a/arch/arm/boot/dts/imx6sl.dtsi +++ b/arch/arm/boot/dts/imx6sl.dtsi @@ -491,7 +491,7 @@ <&iomuxc 21 161 1>; }; - kpp: kpp@20b8000 { + kpp: keypad@20b8000 { compatible = "fsl,imx6sl-kpp", "fsl,imx21-kpp"; reg = <0x020b8000 0x4000>; interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index 73423cca9b96..6265e070a899 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -559,7 +559,7 @@ gpio-ranges = <&iomuxc 0 148 10>, <&iomuxc 10 169 2>; }; - kpp: kpp@20b8000 { + kpp: keypad@20b8000 { compatible = "fsl,imx6sx-kpp", "fsl,imx21-kpp"; reg = <0x020b8000 0x4000>; interrupts = ; diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi index 67b2bab8c155..4f197a860782 100644 --- a/arch/arm/boot/dts/imx6ul.dtsi +++ b/arch/arm/boot/dts/imx6ul.dtsi @@ -523,7 +523,7 @@ status = "disabled"; }; - kpp: kpp@20b8000 { + kpp: keypad@20b8000 { compatible = "fsl,imx6ul-kpp", "fsl,imx6q-kpp", "fsl,imx21-kpp"; reg = <0x020b8000 0x4000>; interrupts = ; diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index 8e59da4f05c9..f825e1d8feaa 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -482,7 +482,7 @@ status = "disabled"; }; - kpp: kpp@30320000 { + kpp: keypad@30320000 { compatible = "fsl,imx7d-kpp", "fsl,imx21-kpp"; reg = <0x30320000 0x10000>; interrupts = ; From 993de77eb602d697451fdd240b9fe2e4a0d73e90 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 14 Feb 2020 10:59:36 +0800 Subject: [PATCH 0390/4444] ARM: dts: imx: make clks node name generic Node name should be generic, use "clock-controller" instead of "ccm" for clks node. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl.dtsi | 2 +- arch/arm/boot/dts/imx6sl.dtsi | 2 +- arch/arm/boot/dts/imx6sx.dtsi | 2 +- arch/arm/boot/dts/imx6ul.dtsi | 2 +- arch/arm/boot/dts/imx7s.dtsi | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index 9691f09b4e5e..97c0a8551c87 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -684,7 +684,7 @@ status = "disabled"; }; - clks: ccm@20c4000 { + clks: clock-controller@20c4000 { compatible = "fsl,imx6q-ccm"; reg = <0x020c4000 0x4000>; interrupts = <0 87 IRQ_TYPE_LEVEL_HIGH>, diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi index af9af9628a89..ea889f75e09b 100644 --- a/arch/arm/boot/dts/imx6sl.dtsi +++ b/arch/arm/boot/dts/imx6sl.dtsi @@ -514,7 +514,7 @@ status = "disabled"; }; - clks: ccm@20c4000 { + clks: clock-controller@20c4000 { compatible = "fsl,imx6sl-ccm"; reg = <0x020c4000 0x4000>; interrupts = <0 87 IRQ_TYPE_LEVEL_HIGH>, diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index 6265e070a899..1198117a4728 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -582,7 +582,7 @@ status = "disabled"; }; - clks: ccm@20c4000 { + clks: clock-controller@20c4000 { compatible = "fsl,imx6sx-ccm"; reg = <0x020c4000 0x4000>; interrupts = , diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi index 4f197a860782..30cce35c6b3c 100644 --- a/arch/arm/boot/dts/imx6ul.dtsi +++ b/arch/arm/boot/dts/imx6ul.dtsi @@ -546,7 +546,7 @@ status = "disabled"; }; - clks: ccm@20c4000 { + clks: clock-controller@20c4000 { compatible = "fsl,imx6ul-ccm"; reg = <0x020c4000 0x4000>; interrupts = , diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index f825e1d8feaa..1ac5045812bf 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -612,7 +612,7 @@ }; }; - clks: ccm@30380000 { + clks: clock-controller@30380000 { compatible = "fsl,imx7d-ccm"; reg = <0x30380000 0x10000>; interrupts = , From 6384a04bba158ef927b3abe782b536cca07d11b1 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 14 Feb 2020 11:06:46 +0800 Subject: [PATCH 0391/4444] ARM: imx: Remove unused include of linux/irqchip/arm-gic.h linux/irqchip/arm-gic.h is NOT used at all, no need to include it. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/mach-imx/gpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c index b5b557fe2c49..e96baa493318 100644 --- a/arch/arm/mach-imx/gpc.c +++ b/arch/arm/mach-imx/gpc.c @@ -10,7 +10,7 @@ #include #include #include -#include + #include "common.h" #include "hardware.h" From 709a80c1dbf1cc4e37dbb14dabc4436794e09a6d Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 14 Feb 2020 14:06:46 +0800 Subject: [PATCH 0392/4444] ARM: imx: Remove unused includes on mach-imx6q.c Many includes are NOT used on mach-imx6q.c now, remove them. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/mach-imx/mach-imx6q.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index edd26e0ffeec..284bce1112d2 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -5,29 +5,16 @@ */ #include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #include -#include #include #include -#include #include #include #include #include #include #include -#include #include "common.h" #include "cpuidle.h" From cc56f77e526dd1b7b29b4529367747fc4c789c66 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 14 Feb 2020 14:11:51 +0800 Subject: [PATCH 0393/4444] ARM: imx: Remove unused include of linux/of.h on mach-imx6sl.c linux/of.h is NOT used on mach-imx6sl.c, remove it. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/mach-imx/mach-imx6sl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c index e00818abe54d..e27a6889cc56 100644 --- a/arch/arm/mach-imx/mach-imx6sl.c +++ b/arch/arm/mach-imx/mach-imx6sl.c @@ -4,7 +4,6 @@ */ #include -#include #include #include #include From 6c2d3a14b7aff13f74fb2331d9a54202c66bea4d Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 16 Feb 2020 17:17:48 +0100 Subject: [PATCH 0394/4444] firmware: tegra: Fix a typo in Kconfig A 'n' is mising in 'commuication' Signed-off-by: Christophe JAILLET Signed-off-by: Thierry Reding --- drivers/firmware/tegra/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/tegra/Kconfig b/drivers/firmware/tegra/Kconfig index a887731f50d6..1c8ba1f47c7c 100644 --- a/drivers/firmware/tegra/Kconfig +++ b/drivers/firmware/tegra/Kconfig @@ -7,7 +7,7 @@ config TEGRA_IVC help IVC (Inter-VM Communication) protocol is part of the IPC (Inter Processor Communication) framework on Tegra. It maintains the - data and the different commuication channels in SysRAM or RAM and + data and the different communication channels in SysRAM or RAM and keeps the content is synchronization between host CPU and remote processors. From e5377ab2882eeb10aa32044b1a8ea48b44c9db42 Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Mon, 13 Jan 2020 23:24:06 -0800 Subject: [PATCH 0395/4444] dt-bindings: clock: tegra: Add IDs for OSC clocks Tegra has OSC, OSC_DIV2 and OSC_DIV4 clocks from OSC pads which are the possible parents of Tegra PMC clocks clk_out_1, clk_out_2, and clk_out_3 for Tegra30 through Tegra210. So, this patch adds ids for these clocks. Tested-by: Dmitry Osipenko Reviewed-by: Dmitry Osipenko Acked-by: Rob Herring Signed-off-by: Sowjanya Komatineni Signed-off-by: Thierry Reding --- include/dt-bindings/clock/tegra114-car.h | 4 +++- include/dt-bindings/clock/tegra124-car-common.h | 4 +++- include/dt-bindings/clock/tegra210-car.h | 4 +++- include/dt-bindings/clock/tegra30-car.h | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/dt-bindings/clock/tegra114-car.h b/include/dt-bindings/clock/tegra114-car.h index bb5c2c999c05..df59aaf5bf34 100644 --- a/include/dt-bindings/clock/tegra114-car.h +++ b/include/dt-bindings/clock/tegra114-car.h @@ -228,6 +228,8 @@ #define TEGRA114_CLK_CLK_M 201 #define TEGRA114_CLK_CLK_M_DIV2 202 #define TEGRA114_CLK_CLK_M_DIV4 203 +#define TEGRA114_CLK_OSC_DIV2 202 +#define TEGRA114_CLK_OSC_DIV4 203 #define TEGRA114_CLK_PLL_REF 204 #define TEGRA114_CLK_PLL_C 205 #define TEGRA114_CLK_PLL_C_OUT1 206 @@ -274,7 +276,7 @@ #define TEGRA114_CLK_CLK_OUT_2 246 #define TEGRA114_CLK_CLK_OUT_3 247 #define TEGRA114_CLK_BLINK 248 -/* 249 */ +#define TEGRA114_CLK_OSC 249 /* 250 */ /* 251 */ #define TEGRA114_CLK_XUSB_HOST_SRC 252 diff --git a/include/dt-bindings/clock/tegra124-car-common.h b/include/dt-bindings/clock/tegra124-car-common.h index 0c4f5be0a742..2a9acd592bff 100644 --- a/include/dt-bindings/clock/tegra124-car-common.h +++ b/include/dt-bindings/clock/tegra124-car-common.h @@ -227,6 +227,8 @@ #define TEGRA124_CLK_CLK_M 201 #define TEGRA124_CLK_CLK_M_DIV2 202 #define TEGRA124_CLK_CLK_M_DIV4 203 +#define TEGRA124_CLK_OSC_DIV2 202 +#define TEGRA124_CLK_OSC_DIV4 203 #define TEGRA124_CLK_PLL_REF 204 #define TEGRA124_CLK_PLL_C 205 #define TEGRA124_CLK_PLL_C_OUT1 206 @@ -273,7 +275,7 @@ #define TEGRA124_CLK_CLK_OUT_2 246 #define TEGRA124_CLK_CLK_OUT_3 247 #define TEGRA124_CLK_BLINK 248 -/* 249 */ +#define TEGRA124_CLK_OSC 249 /* 250 */ /* 251 */ #define TEGRA124_CLK_XUSB_HOST_SRC 252 diff --git a/include/dt-bindings/clock/tegra210-car.h b/include/dt-bindings/clock/tegra210-car.h index 44f60623f99b..7a8f10b9a66d 100644 --- a/include/dt-bindings/clock/tegra210-car.h +++ b/include/dt-bindings/clock/tegra210-car.h @@ -262,6 +262,8 @@ #define TEGRA210_CLK_CLK_M 233 #define TEGRA210_CLK_CLK_M_DIV2 234 #define TEGRA210_CLK_CLK_M_DIV4 235 +#define TEGRA210_CLK_OSC_DIV2 234 +#define TEGRA210_CLK_OSC_DIV4 235 #define TEGRA210_CLK_PLL_REF 236 #define TEGRA210_CLK_PLL_C 237 #define TEGRA210_CLK_PLL_C_OUT1 238 @@ -355,7 +357,7 @@ #define TEGRA210_CLK_PLL_A_OUT_ADSP 323 #define TEGRA210_CLK_PLL_A_OUT0_OUT_ADSP 324 /* 325 */ -/* 326 */ +#define TEGRA210_CLK_OSC 326 /* 327 */ /* 328 */ /* 329 */ diff --git a/include/dt-bindings/clock/tegra30-car.h b/include/dt-bindings/clock/tegra30-car.h index 3c90f1535551..7b542c10fc27 100644 --- a/include/dt-bindings/clock/tegra30-car.h +++ b/include/dt-bindings/clock/tegra30-car.h @@ -196,6 +196,8 @@ #define TEGRA30_CLK_CLK_M 171 #define TEGRA30_CLK_CLK_M_DIV2 172 #define TEGRA30_CLK_CLK_M_DIV4 173 +#define TEGRA30_CLK_OSC_DIV2 172 +#define TEGRA30_CLK_OSC_DIV4 173 #define TEGRA30_CLK_PLL_REF 174 #define TEGRA30_CLK_PLL_C 175 #define TEGRA30_CLK_PLL_C_OUT1 176 @@ -243,7 +245,7 @@ #define TEGRA30_CLK_HCLK 217 #define TEGRA30_CLK_PCLK 218 /* 219 */ -/* 220 */ +#define TEGRA30_CLK_OSC 220 /* 221 */ /* 222 */ /* 223 */ From 39faeba7077ef87e1d0d170eda2cfb7b3b79f726 Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Mon, 13 Jan 2020 23:24:11 -0800 Subject: [PATCH 0396/4444] dt-bindings: tegra: Convert Tegra PMC bindings to YAML This patch converts text based Tegra PMC bindings document to YAML schema for performing dt validation. Tested-by: Dmitry Osipenko Reviewed-by: Dmitry Osipenko Reviewed-by: Rob Herring Signed-off-by: Sowjanya Komatineni Signed-off-by: Thierry Reding --- .../bindings/arm/tegra/nvidia,tegra20-pmc.txt | 300 ---------------- .../arm/tegra/nvidia,tegra20-pmc.yaml | 340 ++++++++++++++++++ 2 files changed, 340 insertions(+), 300 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt create mode 100644 Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt deleted file mode 100644 index cb12f33a247f..000000000000 --- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt +++ /dev/null @@ -1,300 +0,0 @@ -NVIDIA Tegra Power Management Controller (PMC) - -== Power Management Controller Node == - -The PMC block interacts with an external Power Management Unit. The PMC -mostly controls the entry and exit of the system from different sleep -modes. It provides power-gating controllers for SoC and CPU power-islands. - -Required properties: -- name : Should be pmc -- compatible : Should contain one of the following: - For Tegra20 must contain "nvidia,tegra20-pmc". - For Tegra30 must contain "nvidia,tegra30-pmc". - For Tegra114 must contain "nvidia,tegra114-pmc" - For Tegra124 must contain "nvidia,tegra124-pmc" - For Tegra132 must contain "nvidia,tegra124-pmc" - For Tegra210 must contain "nvidia,tegra210-pmc" -- reg : Offset and length of the register set for the device -- clocks : Must contain an entry for each entry in clock-names. - See ../clocks/clock-bindings.txt for details. -- clock-names : Must include the following entries: - "pclk" (The Tegra clock of that name), - "clk32k_in" (The 32KHz clock input to Tegra). - -Optional properties: -- nvidia,invert-interrupt : If present, inverts the PMU interrupt signal. - The PMU is an external Power Management Unit, whose interrupt output - signal is fed into the PMC. This signal is optionally inverted, and then - fed into the ARM GIC. The PMC is not involved in the detection or - handling of this interrupt signal, merely its inversion. -- nvidia,suspend-mode : The suspend mode that the platform should use. - Valid values are 0, 1 and 2: - 0 (LP0): CPU + Core voltage off and DRAM in self-refresh - 1 (LP1): CPU voltage off and DRAM in self-refresh - 2 (LP2): CPU voltage off -- nvidia,core-power-req-active-high : Boolean, core power request active-high -- nvidia,sys-clock-req-active-high : Boolean, system clock request active-high -- nvidia,combined-power-req : Boolean, combined power request for CPU & Core -- nvidia,cpu-pwr-good-en : Boolean, CPU power good signal (from PMIC to PMC) - is enabled. - -Required properties when nvidia,suspend-mode is specified: -- nvidia,cpu-pwr-good-time : CPU power good time in uS. -- nvidia,cpu-pwr-off-time : CPU power off time in uS. -- nvidia,core-pwr-good-time : - Core power good time in uS. -- nvidia,core-pwr-off-time : Core power off time in uS. - -Required properties when nvidia,suspend-mode=<0>: -- nvidia,lp0-vec : Starting address and length of LP0 vector - The LP0 vector contains the warm boot code that is executed by AVP when - resuming from the LP0 state. The AVP (Audio-Video Processor) is an ARM7 - processor and always being the first boot processor when chip is power on - or resume from deep sleep mode. When the system is resumed from the deep - sleep mode, the warm boot code will restore some PLLs, clocks and then - bring up CPU0 for resuming the system. - -Hardware-triggered thermal reset: -On Tegra30, Tegra114 and Tegra124, if the 'i2c-thermtrip' subnode exists, -hardware-triggered thermal reset will be enabled. - -Required properties for hardware-triggered thermal reset (inside 'i2c-thermtrip'): -- nvidia,i2c-controller-id : ID of I2C controller to send poweroff command to. Valid values are - described in section 9.2.148 "APBDEV_PMC_SCRATCH53_0" of the - Tegra K1 Technical Reference Manual. -- nvidia,bus-addr : Bus address of the PMU on the I2C bus -- nvidia,reg-addr : I2C register address to write poweroff command to -- nvidia,reg-data : Poweroff command to write to PMU - -Optional properties for hardware-triggered thermal reset (inside 'i2c-thermtrip'): -- nvidia,pinmux-id : Pinmux used by the hardware when issuing poweroff command. - Defaults to 0. Valid values are described in section 12.5.2 - "Pinmux Support" of the Tegra4 Technical Reference Manual. - -Optional nodes: -- powergates : This node contains a hierarchy of power domain nodes, which - should match the powergates on the Tegra SoC. See "Powergate - Nodes" below. - -Example: - -/ SoC dts including file -pmc@7000f400 { - compatible = "nvidia,tegra20-pmc"; - reg = <0x7000e400 0x400>; - clocks = <&tegra_car 110>, <&clk32k_in>; - clock-names = "pclk", "clk32k_in"; - nvidia,invert-interrupt; - nvidia,suspend-mode = <1>; - nvidia,cpu-pwr-good-time = <2000>; - nvidia,cpu-pwr-off-time = <100>; - nvidia,core-pwr-good-time = <3845 3845>; - nvidia,core-pwr-off-time = <458>; - nvidia,core-power-req-active-high; - nvidia,sys-clock-req-active-high; - nvidia,lp0-vec = <0xbdffd000 0x2000>; -}; - -/ Tegra board dts file -{ - ... - pmc@7000f400 { - i2c-thermtrip { - nvidia,i2c-controller-id = <4>; - nvidia,bus-addr = <0x40>; - nvidia,reg-addr = <0x36>; - nvidia,reg-data = <0x2>; - }; - }; - ... - clocks { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - - clk32k_in: clock { - compatible = "fixed-clock"; - reg=<0>; - #clock-cells = <0>; - clock-frequency = <32768>; - }; - }; - ... -}; - - -== Powergate Nodes == - -Each of the powergate nodes represents a power-domain on the Tegra SoC -that can be power-gated by the Tegra PMC. The name of the powergate node -should be one of the below. Note that not every powergate is applicable -to all Tegra devices and the following list shows which powergates are -applicable to which devices. Please refer to the Tegra TRM for more -details on the various powergates. - - Name Description Devices Applicable - 3d 3D Graphics Tegra20/114/124/210 - 3d0 3D Graphics 0 Tegra30 - 3d1 3D Graphics 1 Tegra30 - aud Audio Tegra210 - dfd Debug Tegra210 - dis Display A Tegra114/124/210 - disb Display B Tegra114/124/210 - heg 2D Graphics Tegra30/114/124/210 - iram Internal RAM Tegra124/210 - mpe MPEG Encode All - nvdec NVIDIA Video Decode Engine Tegra210 - nvjpg NVIDIA JPEG Engine Tegra210 - pcie PCIE Tegra20/30/124/210 - sata SATA Tegra30/124/210 - sor Display interfaces Tegra124/210 - ve2 Video Encode Engine 2 Tegra210 - venc Video Encode Engine All - vdec Video Decode Engine Tegra20/30/114/124 - vic Video Imaging Compositor Tegra124/210 - xusba USB Partition A Tegra114/124/210 - xusbb USB Partition B Tegra114/124/210 - xusbc USB Partition C Tegra114/124/210 - -Required properties: - - clocks: Must contain an entry for each clock required by the PMC for - controlling a power-gate. See ../clocks/clock-bindings.txt for details. - - resets: Must contain an entry for each reset required by the PMC for - controlling a power-gate. See ../reset/reset.txt for details. - - #power-domain-cells: Must be 0. - -Example: - - pmc: pmc@7000e400 { - compatible = "nvidia,tegra210-pmc"; - reg = <0x0 0x7000e400 0x0 0x400>; - clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>; - clock-names = "pclk", "clk32k_in"; - - powergates { - pd_audio: aud { - clocks = <&tegra_car TEGRA210_CLK_APE>, - <&tegra_car TEGRA210_CLK_APB2APE>; - resets = <&tegra_car 198>; - #power-domain-cells = <0>; - }; - }; - }; - - -== Powergate Clients == - -Hardware blocks belonging to a power domain should contain a "power-domains" -property that is a phandle pointing to the corresponding powergate node. - -Example: - - adma: adma@702e2000 { - ... - power-domains = <&pd_audio>; - ... - }; - -== Pad Control == - -On Tegra SoCs a pad is a set of pins which are configured as a group. -The pin grouping is a fixed attribute of the hardware. The PMC can be -used to set pad power state and signaling voltage. A pad can be either -in active or power down mode. The support for power state and signaling -voltage configuration varies depending on the pad in question. 3.3 V and -1.8 V signaling voltages are supported on pins where software -controllable signaling voltage switching is available. - -The pad configuration state nodes are placed under the pmc node and they -are referred to by the pinctrl client properties. For more information -see Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt. -The pad name should be used as the value of the pins property in pin -configuration nodes. - -The following pads are present on Tegra124 and Tegra132: -audio bb cam comp -csia csb cse dsi -dsib dsic dsid hdmi -hsic hv lvds mipi-bias -nand pex-bias pex-clk1 pex-clk2 -pex-cntrl sdmmc1 sdmmc3 sdmmc4 -sys_ddc uart usb0 usb1 -usb2 usb_bias - -The following pads are present on Tegra210: -audio audio-hv cam csia -csib csic csid csie -csif dbg debug-nonao dmic -dp dsi dsib dsic -dsid emmc emmc2 gpio -hdmi hsic lvds mipi-bias -pex-bias pex-clk1 pex-clk2 pex-cntrl -sdmmc1 sdmmc3 spi spi-hv -uart usb0 usb1 usb2 -usb3 usb-bias - -Required pin configuration properties: - - pins: Must contain name of the pad(s) to be configured. - -Optional pin configuration properties: - - low-power-enable: Configure the pad into power down mode - - low-power-disable: Configure the pad into active mode - - power-source: Must contain either TEGRA_IO_PAD_VOLTAGE_1V8 - or TEGRA_IO_PAD_VOLTAGE_3V3 to select between signaling voltages. - The values are defined in - include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h. - -Note: The power state can be configured on all of the Tegra124 and - Tegra132 pads. None of the Tegra124 or Tegra132 pads support - signaling voltage switching. - -Note: All of the listed Tegra210 pads except pex-cntrl support power - state configuration. Signaling voltage switching is supported on - following Tegra210 pads: audio, audio-hv, cam, dbg, dmic, gpio, - pex-cntrl, sdmmc1, sdmmc3, spi, spi-hv, and uart. - -Pad configuration state example: - pmc: pmc@7000e400 { - compatible = "nvidia,tegra210-pmc"; - reg = <0x0 0x7000e400 0x0 0x400>; - clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>; - clock-names = "pclk", "clk32k_in"; - - ... - - sdmmc1_3v3: sdmmc1-3v3 { - pins = "sdmmc1"; - power-source = ; - }; - - sdmmc1_1v8: sdmmc1-1v8 { - pins = "sdmmc1"; - power-source = ; - }; - - hdmi_off: hdmi-off { - pins = "hdmi"; - low-power-enable; - } - - hdmi_on: hdmi-on { - pins = "hdmi"; - low-power-disable; - } - }; - -Pinctrl client example: - sdmmc1: sdhci@700b0000 { - ... - pinctrl-names = "sdmmc-3v3", "sdmmc-1v8"; - pinctrl-0 = <&sdmmc1_3v3>; - pinctrl-1 = <&sdmmc1_1v8>; - }; - ... - sor@54540000 { - ... - pinctrl-0 = <&hdmi_off>; - pinctrl-1 = <&hdmi_on>; - pinctrl-names = "hdmi-on", "hdmi-off"; - }; diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml new file mode 100644 index 000000000000..3ff34b348141 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml @@ -0,0 +1,340 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/tegra/nvidia,tegra20-pmc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Tegra Power Management Controller (PMC) + +maintainers: + - Thierry Reding + - Jonathan Hunter + +properties: + compatible: + enum: + - nvidia,tegra20-pmc + - nvidia,tegra20-pmc + - nvidia,tegra30-pmc + - nvidia,tegra114-pmc + - nvidia,tegra124-pmc + - nvidia,tegra210-pmc + + reg: + maxItems: 1 + description: + Offset and length of the register set for the device. + + clock-names: + items: + - const: pclk + - const: clk32k_in + description: + Must includes entries pclk and clk32k_in. + pclk is the Tegra clock of that name and clk32k_in is 32KHz clock + input to Tegra. + + clocks: + maxItems: 2 + description: + Must contain an entry for each entry in clock-names. + See ../clocks/clocks-bindings.txt for details. + + '#interrupt-cells': + const: 2 + description: + Specifies number of cells needed to encode an interrupt source. + The value must be 2. + + interrupt-controller: true + + nvidia,invert-interrupt: + $ref: /schemas/types.yaml#/definitions/flag + description: Inverts the PMU interrupt signal. + The PMU is an external Power Management Unit, whose interrupt output + signal is fed into the PMC. This signal is optionally inverted, and + then fed into the ARM GIC. The PMC is not involved in the detection + or handling of this interrupt signal, merely its inversion. + + nvidia,core-power-req-active-high: + $ref: /schemas/types.yaml#/definitions/flag + description: Core power request active-high. + + nvidia,sys-clock-req-active-high: + $ref: /schemas/types.yaml#/definitions/flag + description: System clock request active-high. + + nvidia,combined-power-req: + $ref: /schemas/types.yaml#/definitions/flag + description: combined power request for CPU and Core. + + nvidia,cpu-pwr-good-en: + $ref: /schemas/types.yaml#/definitions/flag + description: + CPU power good signal from external PMIC to PMC is enabled. + + nvidia,suspend-mode: + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - enum: [0, 1, 2] + description: + The suspend mode that the platform should use. + Mode 0 is for LP0, CPU + Core voltage off and DRAM in self-refresh + Mode 1 is for LP1, CPU voltage off and DRAM in self-refresh + Mode 2 is for LP2, CPU voltage off + + nvidia,cpu-pwr-good-time: + $ref: /schemas/types.yaml#/definitions/uint32 + description: CPU power good time in uSec. + + nvidia,cpu-pwr-off-time: + $ref: /schemas/types.yaml#/definitions/uint32 + description: CPU power off time in uSec. + + nvidia,core-pwr-good-time: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + + Core power good time in uSec. + + nvidia,core-pwr-off-time: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Core power off time in uSec. + + nvidia,lp0-vec: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Starting address and length of LP0 vector. + The LP0 vector contains the warm boot code that is executed + by AVP when resuming from the LP0 state. + The AVP (Audio-Video Processor) is an ARM7 processor and + always being the first boot processor when chip is power on + or resume from deep sleep mode. When the system is resumed + from the deep sleep mode, the warm boot code will restore + some PLLs, clocks and then brings up CPU0 for resuming the + system. + + i2c-thermtrip: + type: object + description: + On Tegra30, Tegra114 and Tegra124 if i2c-thermtrip subnode exists, + hardware-triggered thermal reset will be enabled. + + properties: + nvidia,i2c-controller-id: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + ID of I2C controller to send poweroff command to PMU. + Valid values are described in section 9.2.148 + "APBDEV_PMC_SCRATCH53_0" of the Tegra K1 Technical Reference + Manual. + + nvidia,bus-addr: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Bus address of the PMU on the I2C bus. + + nvidia,reg-addr: + $ref: /schemas/types.yaml#/definitions/uint32 + description: PMU I2C register address to issue poweroff command. + + nvidia,reg-data: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Poweroff command to write to PMU. + + nvidia,pinmux-id: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Pinmux used by the hardware when issuing Poweroff command. + Defaults to 0. Valid values are described in section 12.5.2 + "Pinmux Support" of the Tegra4 Technical Reference Manual. + + required: + - nvidia,i2c-controller-id + - nvidia,bus-addr + - nvidia,reg-addr + - nvidia,reg-data + + additionalProperties: false + + powergates: + type: object + description: | + This node contains a hierarchy of power domain nodes, which should + match the powergates on the Tegra SoC. Each powergate node + represents a power-domain on the Tegra SoC that can be power-gated + by the Tegra PMC. + Hardware blocks belonging to a power domain should contain + "power-domains" property that is a phandle pointing to corresponding + powergate node. + The name of the powergate node should be one of the below. Note that + not every powergate is applicable to all Tegra devices and the following + list shows which powergates are applicable to which devices. + Please refer to Tegra TRM for mode details on the powergate nodes to + use for each power-gate block inside Tegra. + Name Description Devices Applicable + 3d 3D Graphics Tegra20/114/124/210 + 3d0 3D Graphics 0 Tegra30 + 3d1 3D Graphics 1 Tegra30 + aud Audio Tegra210 + dfd Debug Tegra210 + dis Display A Tegra114/124/210 + disb Display B Tegra114/124/210 + heg 2D Graphics Tegra30/114/124/210 + iram Internal RAM Tegra124/210 + mpe MPEG Encode All + nvdec NVIDIA Video Decode Engine Tegra210 + nvjpg NVIDIA JPEG Engine Tegra210 + pcie PCIE Tegra20/30/124/210 + sata SATA Tegra30/124/210 + sor Display interfaces Tegra124/210 + ve2 Video Encode Engine 2 Tegra210 + venc Video Encode Engine All + vdec Video Decode Engine Tegra20/30/114/124 + vic Video Imaging Compositor Tegra124/210 + xusba USB Partition A Tegra114/124/210 + xusbb USB Partition B Tegra114/124/210 + xusbc USB Partition C Tegra114/124/210 + + patternProperties: + "^[a-z0-9]+$": + type: object + + patternProperties: + clocks: + minItems: 1 + maxItems: 8 + description: + Must contain an entry for each clock required by the PMC + for controlling a power-gate. + See ../clocks/clock-bindings.txt document for more details. + + resets: + minItems: 1 + maxItems: 8 + description: + Must contain an entry for each reset required by the PMC + for controlling a power-gate. + See ../reset/reset.txt for more details. + + '#power-domain-cells': + const: 0 + description: Must be 0. + + required: + - clocks + - resets + - '#power-domain-cells' + + additionalProperties: false + +patternProperties: + "^[a-f0-9]+-[a-f0-9]+$": + type: object + description: + This is a Pad configuration node. On Tegra SOCs a pad is a set of + pins which are configured as a group. The pin grouping is a fixed + attribute of the hardware. The PMC can be used to set pad power state + and signaling voltage. A pad can be either in active or power down mode. + The support for power state and signaling voltage configuration varies + depending on the pad in question. 3.3V and 1.8V signaling voltages + are supported on pins where software controllable signaling voltage + switching is available. + + The pad configuration state nodes are placed under the pmc node and they + are referred to by the pinctrl client properties. For more information + see Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt. + The pad name should be used as the value of the pins property in pin + configuration nodes. + + The following pads are present on Tegra124 and Tegra132 + audio, bb, cam, comp, csia, csb, cse, dsi, dsib, dsic, dsid, hdmi, hsic, + hv, lvds, mipi-bias, nand, pex-bias, pex-clk1, pex-clk2, pex-cntrl, + sdmmc1, sdmmc3, sdmmc4, sys_ddc, uart, usb0, usb1, usb2, usb_bias. + + The following pads are present on Tegra210 + audio, audio-hv, cam, csia, csib, csic, csid, csie, csif, dbg, + debug-nonao, dmic, dp, dsi, dsib, dsic, dsid, emmc, emmc2, gpio, hdmi, + hsic, lvds, mipi-bias, pex-bias, pex-clk1, pex-clk2, pex-cntrl, sdmmc1, + sdmmc3, spi, spi-hv, uart, usb0, usb1, usb2, usb3, usb-bias. + + properties: + pins: + $ref: /schemas/types.yaml#/definitions/string + description: Must contain name of the pad(s) to be configured. + + low-power-enable: + $ref: /schemas/types.yaml#/definitions/flag + description: Configure the pad into power down mode. + + low-power-disable: + $ref: /schemas/types.yaml#/definitions/flag + description: Configure the pad into active mode. + + power-source: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Must contain either TEGRA_IO_PAD_VOLTAGE_1V8 or + TEGRA_IO_PAD_VOLTAGE_3V3 to select between signaling voltages. + The values are defined in + include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h. + Power state can be configured on all Tegra124 and Tegra132 + pads. None of the Tegra124 or Tegra132 pads support signaling + voltage switching. + All of the listed Tegra210 pads except pex-cntrl support power + state configuration. Signaling voltage switching is supported + on below Tegra210 pads. + audio, audio-hv, cam, dbg, dmic, gpio, pex-cntrl, sdmmc1, + sdmmc3, spi, spi-hv, and uart. + + required: + - pins + + additionalProperties: false + +required: + - compatible + - reg + - clock-names + - clocks + +dependencies: + "nvidia,suspend-mode": ["nvidia,core-pwr-off-time", "nvidia,cpu-pwr-off-time"] + "nvidia,core-pwr-off-time": ["nvidia,core-pwr-good-time"] + "nvidia,cpu-pwr-off-time": ["nvidia,cpu-pwr-good-time"] + +examples: + - | + + #include + #include + + tegra_pmc: pmc@7000e400 { + compatible = "nvidia,tegra210-pmc"; + reg = <0x0 0x7000e400 0x0 0x400>; + clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>; + clock-names = "pclk", "clk32k_in"; + + nvidia,invert-interrupt; + nvidia,suspend-mode = <0>; + nvidia,cpu-pwr-good-time = <0>; + nvidia,cpu-pwr-off-time = <0>; + nvidia,core-pwr-good-time = <4587 3876>; + nvidia,core-pwr-off-time = <39065>; + nvidia,core-power-req-active-high; + nvidia,sys-clock-req-active-high; + + powergates { + pd_audio: aud { + clocks = <&tegra_car TEGRA210_CLK_APE>, + <&tegra_car TEGRA210_CLK_APB2APE>; + resets = <&tegra_car 198>; + #power-domain-cells = <0>; + }; + + pd_xusbss: xusba { + clocks = <&tegra_car TEGRA210_CLK_XUSB_SS>; + resets = <&tegra_car TEGRA210_CLK_XUSB_SS>; + #power-domain-cells = <0>; + }; + }; + }; From f85fa3198dfc4e359cc6efa58854853b0824bae8 Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Mon, 13 Jan 2020 23:24:12 -0800 Subject: [PATCH 0397/4444] dt-bindings: soc: tegra-pmc: Add Tegra PMC clock bindings Tegra PMC has 3 clocks clk_out_1, clk_out_2, and clk_out_3. This patch documents PMC clock bindings and adds a header defining Tegra PMC clock ids. Tested-by: Dmitry Osipenko Reviewed-by: Dmitry Osipenko Reviewed-by: Rob Herring Signed-off-by: Sowjanya Komatineni Signed-off-by: Thierry Reding --- .../bindings/arm/tegra/nvidia,tegra20-pmc.yaml | 12 ++++++++++++ include/dt-bindings/soc/tegra-pmc.h | 15 +++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 include/dt-bindings/soc/tegra-pmc.h diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml index 3ff34b348141..5b5c42a00264 100644 --- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml @@ -40,6 +40,15 @@ properties: Must contain an entry for each entry in clock-names. See ../clocks/clocks-bindings.txt for details. + '#clock-cells': + const: 1 + description: + Tegra PMC has clk_out_1, clk_out_2, and clk_out_3. + Consumer of PMC clock should specify the desired clock by having + the clock ID in its "clocks" phandle cell with pmc clock provider. + See include/dt-bindings/soc/tegra-pmc.h for the list of Tegra PMC + clock IDs. + '#interrupt-cells': const: 2 description: @@ -296,6 +305,7 @@ required: - reg - clock-names - clocks + - '#clock-cells' dependencies: "nvidia,suspend-mode": ["nvidia,core-pwr-off-time", "nvidia,cpu-pwr-off-time"] @@ -307,12 +317,14 @@ examples: #include #include + #include tegra_pmc: pmc@7000e400 { compatible = "nvidia,tegra210-pmc"; reg = <0x0 0x7000e400 0x0 0x400>; clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>; clock-names = "pclk", "clk32k_in"; + #clock-cells = <1>; nvidia,invert-interrupt; nvidia,suspend-mode = <0>; diff --git a/include/dt-bindings/soc/tegra-pmc.h b/include/dt-bindings/soc/tegra-pmc.h new file mode 100644 index 000000000000..f7c866404456 --- /dev/null +++ b/include/dt-bindings/soc/tegra-pmc.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + */ + +#ifndef _DT_BINDINGS_SOC_TEGRA_PMC_H +#define _DT_BINDINGS_SOC_TEGRA_PMC_H + +#define TEGRA_PMC_CLK_OUT_1 0 +#define TEGRA_PMC_CLK_OUT_2 1 +#define TEGRA_PMC_CLK_OUT_3 2 + +#define TEGRA_PMC_CLK_MAX 3 + +#endif /* _DT_BINDINGS_SOC_TEGRA_PMC_H */ From cd88f16792011a90aa9cda12233f136a528acab3 Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Mon, 13 Jan 2020 23:24:14 -0800 Subject: [PATCH 0398/4444] dt-bindings: soc: tegra-pmc: Add ID for Tegra PMC 32 kHz blink clock Tegra PMC has blink functionality that allows 32 kHz clock out to blink pin of the Tegra. This patch adds id for this blink clock to use for enabling or disabling blink output through device tree. Tested-by: Dmitry Osipenko Reviewed-by: Dmitry Osipenko Acked-by: Rob Herring Signed-off-by: Sowjanya Komatineni Signed-off-by: Thierry Reding --- .../devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml | 2 ++ include/dt-bindings/soc/tegra-pmc.h | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml index 5b5c42a00264..f17bb353f65e 100644 --- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml @@ -44,6 +44,8 @@ properties: const: 1 description: Tegra PMC has clk_out_1, clk_out_2, and clk_out_3. + PMC also has blink control which allows 32Khz clock output to + Tegra blink pad. Consumer of PMC clock should specify the desired clock by having the clock ID in its "clocks" phandle cell with pmc clock provider. See include/dt-bindings/soc/tegra-pmc.h for the list of Tegra PMC diff --git a/include/dt-bindings/soc/tegra-pmc.h b/include/dt-bindings/soc/tegra-pmc.h index f7c866404456..a99a457471ee 100644 --- a/include/dt-bindings/soc/tegra-pmc.h +++ b/include/dt-bindings/soc/tegra-pmc.h @@ -9,7 +9,8 @@ #define TEGRA_PMC_CLK_OUT_1 0 #define TEGRA_PMC_CLK_OUT_2 1 #define TEGRA_PMC_CLK_OUT_3 2 +#define TEGRA_PMC_CLK_BLINK 3 -#define TEGRA_PMC_CLK_MAX 3 +#define TEGRA_PMC_CLK_MAX 4 #endif /* _DT_BINDINGS_SOC_TEGRA_PMC_H */ From a39f842541038e20063fc880652153c0d93a95bf Mon Sep 17 00:00:00 2001 From: "yong.liang" Date: Mon, 17 Feb 2020 16:19:22 +0800 Subject: [PATCH 0399/4444] amr64: dts: mt8183: Add watchdog node Add watchdog device node to MT8183 SoC. Signed-off-by: yong.liang Signed-off-by: Matthias Brugger --- arch/arm64/boot/dts/mediatek/mt8183.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi index 504891d2b97b..f1381e77918b 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi @@ -285,6 +285,13 @@ #interrupt-cells = <2>; }; + watchdog: watchdog@10007000 { + compatible = "mediatek,mt8183-wdt", + "mediatek,mt6589-wdt"; + reg = <0 0x10007000 0 0x100>; + #reset-cells = <1>; + }; + apmixedsys: syscon@1000c000 { compatible = "mediatek,mt8183-apmixedsys", "syscon"; reg = <0 0x1000c000 0 0x1000>; From 305ce1dce9d8046d44a322cb3ef5a6574cf86721 Mon Sep 17 00:00:00 2001 From: Argus Lin Date: Sun, 16 Feb 2020 14:17:21 +0800 Subject: [PATCH 0400/4444] dt-bindings: pwrap: mediatek: add pwrap support for MT6779 Add binding document of pwrap for MT6779 SoCs. Signed-off-by: Argus Lin Acked-by: Rob Herring Signed-off-by: Matthias Brugger --- Documentation/devicetree/bindings/soc/mediatek/pwrap.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt b/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt index 7a32404c6114..ecac2bbeae45 100644 --- a/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt +++ b/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt @@ -20,6 +20,7 @@ Required properties in pwrap device node. - compatible: "mediatek,mt2701-pwrap" for MT2701/7623 SoCs "mediatek,mt6765-pwrap" for MT6765 SoCs + "mediatek,mt6779-pwrap" for MT6779 SoCs "mediatek,mt6797-pwrap" for MT6797 SoCs "mediatek,mt7622-pwrap" for MT7622 SoCs "mediatek,mt8135-pwrap" for MT8135 SoCs From adc4e8fcb23f75538d9a201b2acc56721c5c7559 Mon Sep 17 00:00:00 2001 From: Argus Lin Date: Sun, 16 Feb 2020 14:17:22 +0800 Subject: [PATCH 0401/4444] soc: mediatek: pwrap: add pwrap driver for MT6779 SoCs MT6779 is a highly integrated SoCs, it uses PMIC_MT6359 for power management. This patch adds pwrap master driver to access PMIC_MT6359. Signed-off-by: Argus Lin Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 57 ++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index c725315cf6a8..1f8189afaa21 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -497,6 +497,45 @@ static int mt6765_regs[] = { [PWRAP_DCM_DBC_PRD] = 0x1E0, }; +static int mt6779_regs[] = { + [PWRAP_MUX_SEL] = 0x0, + [PWRAP_WRAP_EN] = 0x4, + [PWRAP_DIO_EN] = 0x8, + [PWRAP_RDDMY] = 0x20, + [PWRAP_CSHEXT_WRITE] = 0x24, + [PWRAP_CSHEXT_READ] = 0x28, + [PWRAP_CSLEXT_WRITE] = 0x2C, + [PWRAP_CSLEXT_READ] = 0x30, + [PWRAP_EXT_CK_WRITE] = 0x34, + [PWRAP_STAUPD_CTRL] = 0x3C, + [PWRAP_STAUPD_GRPEN] = 0x40, + [PWRAP_EINT_STA0_ADR] = 0x44, + [PWRAP_HARB_HPRIO] = 0x68, + [PWRAP_HIPRIO_ARB_EN] = 0x6C, + [PWRAP_MAN_EN] = 0x7C, + [PWRAP_MAN_CMD] = 0x80, + [PWRAP_WACS0_EN] = 0x8C, + [PWRAP_INIT_DONE0] = 0x90, + [PWRAP_WACS1_EN] = 0x94, + [PWRAP_WACS2_EN] = 0x9C, + [PWRAP_INIT_DONE1] = 0x98, + [PWRAP_INIT_DONE2] = 0xA0, + [PWRAP_INT_EN] = 0xBC, + [PWRAP_INT_FLG_RAW] = 0xC0, + [PWRAP_INT_FLG] = 0xC4, + [PWRAP_INT_CLR] = 0xC8, + [PWRAP_INT1_EN] = 0xCC, + [PWRAP_INT1_FLG] = 0xD4, + [PWRAP_INT1_CLR] = 0xD8, + [PWRAP_TIMER_EN] = 0xF0, + [PWRAP_WDT_UNIT] = 0xF8, + [PWRAP_WDT_SRC_EN] = 0xFC, + [PWRAP_WDT_SRC_EN_1] = 0x100, + [PWRAP_WACS2_CMD] = 0xC20, + [PWRAP_WACS2_RDATA] = 0xC24, + [PWRAP_WACS2_VLDCLR] = 0xC28, +}; + static int mt6797_regs[] = { [PWRAP_MUX_SEL] = 0x0, [PWRAP_WRAP_EN] = 0x4, @@ -945,6 +984,7 @@ enum pmic_type { enum pwrap_type { PWRAP_MT2701, PWRAP_MT6765, + PWRAP_MT6779, PWRAP_MT6797, PWRAP_MT7622, PWRAP_MT8135, @@ -1377,6 +1417,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) break; case PWRAP_MT2701: case PWRAP_MT6765: + case PWRAP_MT6779: case PWRAP_MT6797: case PWRAP_MT8173: case PWRAP_MT8516: @@ -1783,6 +1824,19 @@ static const struct pmic_wrapper_type pwrap_mt6765 = { .init_soc_specific = NULL, }; +static const struct pmic_wrapper_type pwrap_mt6779 = { + .regs = mt6779_regs, + .type = PWRAP_MT6779, + .arb_en_all = 0xfbb7f, + .int_en_all = 0xfffffffe, + .int1_en_all = 0, + .spi_w = PWRAP_MAN_CMD_SPI_WRITE, + .wdt_src = PWRAP_WDT_SRC_MASK_ALL, + .caps = 0, + .init_reg_clock = pwrap_common_init_reg_clock, + .init_soc_specific = NULL, +}; + static const struct pmic_wrapper_type pwrap_mt6797 = { .regs = mt6797_regs, .type = PWRAP_MT6797, @@ -1867,6 +1921,9 @@ static const struct of_device_id of_pwrap_match_tbl[] = { }, { .compatible = "mediatek,mt6765-pwrap", .data = &pwrap_mt6765, + }, { + .compatible = "mediatek,mt6779-pwrap", + .data = &pwrap_mt6779, }, { .compatible = "mediatek,mt6797-pwrap", .data = &pwrap_mt6797, From 2faccb56ee6b93bc7dda3c6b5316bc2b025ec27d Mon Sep 17 00:00:00 2001 From: Argus Lin Date: Sun, 16 Feb 2020 14:17:23 +0800 Subject: [PATCH 0402/4444] soc: mediatek: pwrap: add support for MT6359 PMIC MT6359 is a new power management IC and it is used for MT6779 SoCs. To define mt6359_regs for pmic register mapping and pmic_mt6359 for accessing register. Signed-off-by: Argus Lin Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 71 ++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index 1f8189afaa21..5d34e8b9c988 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -111,6 +111,28 @@ enum dew_regs { PWRAP_RG_SPI_CON13, PWRAP_SPISLV_KEY, + /* MT6359 only regs */ + PWRAP_DEW_CRC_SWRST, + PWRAP_DEW_RG_EN_RECORD, + PWRAP_DEW_RECORD_CMD0, + PWRAP_DEW_RECORD_CMD1, + PWRAP_DEW_RECORD_CMD2, + PWRAP_DEW_RECORD_CMD3, + PWRAP_DEW_RECORD_CMD4, + PWRAP_DEW_RECORD_CMD5, + PWRAP_DEW_RECORD_WDATA0, + PWRAP_DEW_RECORD_WDATA1, + PWRAP_DEW_RECORD_WDATA2, + PWRAP_DEW_RECORD_WDATA3, + PWRAP_DEW_RECORD_WDATA4, + PWRAP_DEW_RECORD_WDATA5, + PWRAP_DEW_RG_ADDR_TARGET, + PWRAP_DEW_RG_ADDR_MASK, + PWRAP_DEW_RG_WDATA_TARGET, + PWRAP_DEW_RG_WDATA_MASK, + PWRAP_DEW_RG_SPI_RECORD_CLR, + PWRAP_DEW_RG_CMD_ALERT_CLR, + /* MT6397 only regs */ PWRAP_DEW_EVENT_OUT_EN, PWRAP_DEW_EVENT_SRC_EN, @@ -197,6 +219,42 @@ static const u32 mt6358_regs[] = { [PWRAP_SPISLV_KEY] = 0x044a, }; +static const u32 mt6359_regs[] = { + [PWRAP_DEW_RG_EN_RECORD] = 0x040a, + [PWRAP_DEW_DIO_EN] = 0x040c, + [PWRAP_DEW_READ_TEST] = 0x040e, + [PWRAP_DEW_WRITE_TEST] = 0x0410, + [PWRAP_DEW_CRC_SWRST] = 0x0412, + [PWRAP_DEW_CRC_EN] = 0x0414, + [PWRAP_DEW_CRC_VAL] = 0x0416, + [PWRAP_DEW_CIPHER_KEY_SEL] = 0x0418, + [PWRAP_DEW_CIPHER_IV_SEL] = 0x041a, + [PWRAP_DEW_CIPHER_EN] = 0x041c, + [PWRAP_DEW_CIPHER_RDY] = 0x041e, + [PWRAP_DEW_CIPHER_MODE] = 0x0420, + [PWRAP_DEW_CIPHER_SWRST] = 0x0422, + [PWRAP_DEW_RDDMY_NO] = 0x0424, + [PWRAP_DEW_RECORD_CMD0] = 0x0428, + [PWRAP_DEW_RECORD_CMD1] = 0x042a, + [PWRAP_DEW_RECORD_CMD2] = 0x042c, + [PWRAP_DEW_RECORD_CMD3] = 0x042e, + [PWRAP_DEW_RECORD_CMD4] = 0x0430, + [PWRAP_DEW_RECORD_CMD5] = 0x0432, + [PWRAP_DEW_RECORD_WDATA0] = 0x0434, + [PWRAP_DEW_RECORD_WDATA1] = 0x0436, + [PWRAP_DEW_RECORD_WDATA2] = 0x0438, + [PWRAP_DEW_RECORD_WDATA3] = 0x043a, + [PWRAP_DEW_RECORD_WDATA4] = 0x043c, + [PWRAP_DEW_RECORD_WDATA5] = 0x043e, + [PWRAP_DEW_RG_ADDR_TARGET] = 0x0440, + [PWRAP_DEW_RG_ADDR_MASK] = 0x0442, + [PWRAP_DEW_RG_WDATA_TARGET] = 0x0444, + [PWRAP_DEW_RG_WDATA_MASK] = 0x0446, + [PWRAP_DEW_RG_SPI_RECORD_CLR] = 0x0448, + [PWRAP_DEW_RG_CMD_ALERT_CLR] = 0x0448, + [PWRAP_SPISLV_KEY] = 0x044a, +}; + static const u32 mt6397_regs[] = { [PWRAP_DEW_BASE] = 0xbc00, [PWRAP_DEW_EVENT_OUT_EN] = 0xbc00, @@ -977,6 +1035,7 @@ enum pmic_type { PMIC_MT6351, PMIC_MT6357, PMIC_MT6358, + PMIC_MT6359, PMIC_MT6380, PMIC_MT6397, }; @@ -1752,6 +1811,15 @@ static const struct pwrap_slv_type pmic_mt6358 = { .pwrap_write = pwrap_write16, }; +static const struct pwrap_slv_type pmic_mt6359 = { + .dew_regs = mt6359_regs, + .type = PMIC_MT6359, + .regmap = &pwrap_regmap_config16, + .caps = PWRAP_SLV_CAP_DUALIO, + .pwrap_read = pwrap_read16, + .pwrap_write = pwrap_write16, +}; + static const struct pwrap_slv_type pmic_mt6380 = { .dew_regs = NULL, .type = PMIC_MT6380, @@ -1784,6 +1852,9 @@ static const struct of_device_id of_slave_match_tbl[] = { }, { .compatible = "mediatek,mt6358", .data = &pmic_mt6358, + }, { + .compatible = "mediatek,mt6359", + .data = &pmic_mt6359, }, { /* The MT6380 PMIC only implements a regulator, so we bind it * directly instead of using a MFD. From ed412c12b738bd49225acc14138268dae0330a8c Mon Sep 17 00:00:00 2001 From: Matthias Brugger Date: Wed, 12 Feb 2020 15:41:44 +0100 Subject: [PATCH 0403/4444] ARM: dts: mediatek: rename scpsys nodes to power-controller The nodes with name scpsys actually implement a power-controller. Rename the nodes to match the bindings description. Signed-off-by: Matthias Brugger --- arch/arm/boot/dts/mt2701.dtsi | 2 +- arch/arm/boot/dts/mt7623.dtsi | 2 +- arch/arm/boot/dts/mt7629.dtsi | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi index 51e1305c6471..2093b38d6e6d 100644 --- a/arch/arm/boot/dts/mt2701.dtsi +++ b/arch/arm/boot/dts/mt2701.dtsi @@ -148,7 +148,7 @@ reg = <0 0x10005000 0 0x1000>; }; - scpsys: scpsys@10006000 { + scpsys: power-controller@10006000 { compatible = "mediatek,mt2701-scpsys", "syscon"; #power-domain-cells = <1>; reg = <0 0x10006000 0 0x1000>; diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi index a79f0b6c3429..f76b4a3c34b9 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi @@ -268,7 +268,7 @@ reg = <0 0x10005000 0 0x1000>; }; - scpsys: scpsys@10006000 { + scpsys: power-controller@10006000 { compatible = "mediatek,mt7623-scpsys", "mediatek,mt2701-scpsys", "syscon"; diff --git a/arch/arm/boot/dts/mt7629.dtsi b/arch/arm/boot/dts/mt7629.dtsi index 867b88103b9d..60787632e4a1 100644 --- a/arch/arm/boot/dts/mt7629.dtsi +++ b/arch/arm/boot/dts/mt7629.dtsi @@ -90,7 +90,7 @@ #clock-cells = <1>; }; - scpsys: scpsys@10006000 { + scpsys: power-controller@10006000 { compatible = "mediatek,mt7629-scpsys", "mediatek,mt7622-scpsys"; #power-domain-cells = <1>; From 6fc033b560718444e699c0c5de4960c2235227da Mon Sep 17 00:00:00 2001 From: Matthias Brugger Date: Wed, 12 Feb 2020 15:41:45 +0100 Subject: [PATCH 0404/4444] arm64: dts: mediatek: rename scpsys nodes to power-controller The nodes with name scpsys actually implement a power-controller. Rename the nodes to match the bindings description. Signed-off-by: Matthias Brugger --- arch/arm64/boot/dts/mediatek/mt2712e.dtsi | 2 +- arch/arm64/boot/dts/mediatek/mt6797.dtsi | 2 +- arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2 +- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi index 43307bad3f0d..a00c5caa1915 100644 --- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi @@ -278,7 +278,7 @@ interrupts = ; }; - scpsys: scpsys@10006000 { + scpsys: power-controller@10006000 { compatible = "mediatek,mt2712-scpsys", "syscon"; #power-domain-cells = <1>; reg = <0 0x10006000 0 0x1000>; diff --git a/arch/arm64/boot/dts/mediatek/mt6797.dtsi b/arch/arm64/boot/dts/mediatek/mt6797.dtsi index 2b2a69c7567f..136ef9527a0d 100644 --- a/arch/arm64/boot/dts/mediatek/mt6797.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt6797.dtsi @@ -157,7 +157,7 @@ }; }; - scpsys: scpsys@10006000 { + scpsys: power-controller@10006000 { compatible = "mediatek,mt6797-scpsys"; #power-domain-cells = <1>; reg = <0 0x10006000 0 0x1000>; diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi index dac51e98204c..339dc9f88f43 100644 --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi @@ -230,7 +230,7 @@ #reset-cells = <1>; }; - scpsys: scpsys@10006000 { + scpsys: power-controller@10006000 { compatible = "mediatek,mt7622-scpsys", "syscon"; #power-domain-cells = <1>; diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index 1a9ad90bd7a6..ccb8e88a60c5 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -437,7 +437,7 @@ }; }; - scpsys: scpsys@10006000 { + scpsys: power-controller@10006000 { compatible = "mediatek,mt8173-scpsys"; #power-domain-cells = <1>; reg = <0 0x10006000 0 0x1000>; From 92d8495ce9b79185e5fc512fe28768564eb81722 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 12 Feb 2020 11:08:28 +0100 Subject: [PATCH 0405/4444] ARM: shmobile: Replace by The R-Car Gen2 platform code is not a clock provider, and just needs to call of_clk_init(). Hence it can include instead of . Signed-off-by: Geert Uytterhoeven Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20200212100830.446-6-geert+renesas@glider.be --- arch/arm/mach-shmobile/setup-rcar-gen2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c index 2fd3aa6f3212..1ee5cd2840e0 100644 --- a/arch/arm/mach-shmobile/setup-rcar-gen2.c +++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c @@ -7,7 +7,6 @@ * Copyright (C) 2014 Ulrich Hecht */ -#include #include #include #include @@ -15,6 +14,7 @@ #include #include #include +#include #include #include #include From 107539fb7fe22915fa5bd78db691d21f95fdc3b3 Mon Sep 17 00:00:00 2001 From: Nishad Kamdar Date: Sat, 18 Jan 2020 18:19:00 +0530 Subject: [PATCH 0406/4444] soc: renesas: rcar-sysc: Use the correct style for SPDX License Identifier This patch corrects the SPDX License Identifier style in header file related to Renesas Soc driver support. It assigns explicit block comment to the SPDX License Identifier. Changes made by using a script provided by Joe Perches here: https://lkml.org/lkml/2019/2/7/46. Suggested-by: Joe Perches Signed-off-by: Nishad Kamdar Link: https://lore.kernel.org/r/20200118124856.GA3421@nishad Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/rcar-sysc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h index 8d074489fba9..0fc3b119930a 100644 --- a/drivers/soc/renesas/rcar-sysc.h +++ b/drivers/soc/renesas/rcar-sysc.h @@ -1,5 +1,5 @@ -/* SPDX-License-Identifier: GPL-2.0 - * +/* SPDX-License-Identifier: GPL-2.0 */ +/* * Renesas R-Car System Controller * * Copyright (C) 2016 Glider bvba From 10fa9512769fa3b15ea29f4f331f4604c17b4b2c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 13 Feb 2020 12:20:58 +0100 Subject: [PATCH 0407/4444] usb: audio-v2: Add uac2_effect_unit_descriptor definition The UAC2 Effect Unit Descriptor has a slightly different definition from other similar ones like Processing Unit or Extension Unit. Define it here so that it can be used in USB-audio driver in a later patch. Acked-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20200213112059.18745-2-tiwai@suse.de Signed-off-by: Takashi Iwai --- include/linux/usb/audio-v2.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/linux/usb/audio-v2.h b/include/linux/usb/audio-v2.h index ba4b3e3327ff..cb9900b34b67 100644 --- a/include/linux/usb/audio-v2.h +++ b/include/linux/usb/audio-v2.h @@ -156,6 +156,18 @@ struct uac2_feature_unit_descriptor { __u8 bmaControls[0]; /* variable length */ } __attribute__((packed)); +/* 4.7.2.10 Effect Unit Descriptor */ + +struct uac2_effect_unit_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bUnitID; + __le16 wEffectType; + __u8 bSourceID; + __u8 bmaControls[]; /* variable length */ +} __attribute__((packed)); + /* 4.9.2 Class-Specific AS Interface Descriptor */ struct uac2_as_header_descriptor { From 60081b35c68ba6a466dee08de581be06999c930a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 13 Feb 2020 12:20:59 +0100 Subject: [PATCH 0408/4444] ALSA: usb-audio: Parse source ID of UAC2 effect unit During parsing the input source, we currently cut off at the Effect Unit node without parsing further its source id. It's no big problem, so far, but it should be more consistent to parse it properly. This patch adds the recursive parsing in parse_term_effect_unit(). It doesn't add anything in the audio unit parser itself, and the effect unit itself is still skipped, though. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=206147 Link: https://lore.kernel.org/r/20200213112059.18745-3-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 81b2db0edd5f..56d0878e4999 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -901,6 +901,12 @@ static int parse_term_effect_unit(struct mixer_build *state, struct usb_audio_term *term, void *p1, int id) { + struct uac2_effect_unit_descriptor *d = p1; + int err; + + err = __check_input_term(state, d->bSourceID, term); + if (err < 0) + return err; term->type = UAC3_EFFECT_UNIT << 16; /* virtual type */ term->id = id; return 0; From 2f0b42034bd75a938cdf144149d6db4fa4d51208 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Mon, 17 Feb 2020 10:03:11 +0800 Subject: [PATCH 0409/4444] ASoC: rt1015: fix typo for bypass boost control Fix typo for "Bypass Boost" control. Signed-off-by: Jack Yu Link: https://lore.kernel.org/r/20200217020311.12793-1-jack.yu@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 6d490e2dbc25..d300b417dd50 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -444,7 +444,7 @@ static int rt1015_boost_mode_put(struct snd_kcontrol *kcontrol, return 0; } -static int rt5518_bypass_boost_get(struct snd_kcontrol *kcontrol, +static int rt1015_bypass_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = @@ -457,7 +457,7 @@ static int rt5518_bypass_boost_get(struct snd_kcontrol *kcontrol, return 0; } -static int rt5518_bypass_boost_put(struct snd_kcontrol *kcontrol, +static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = @@ -497,7 +497,7 @@ static const struct snd_kcontrol_new rt1015_snd_controls[] = { rt1015_boost_mode_get, rt1015_boost_mode_put), SOC_ENUM("Mono LR Select", rt1015_mono_lr_sel), SOC_SINGLE_EXT("Bypass Boost", SND_SOC_NOPM, 0, 1, 0, - rt5518_bypass_boost_get, rt5518_bypass_boost_put), + rt1015_bypass_boost_get, rt1015_bypass_boost_put), }; static int rt1015_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, From 0d6f1693f255795d5c747dc444d69c6512586d98 Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Wed, 4 Dec 2019 09:29:20 +0100 Subject: [PATCH 0410/4444] s390/cpum_sf: Rework sampling buffer allocation Adjust sampling buffer allocation depending on frequency and correct comments. Investigation on the interrupt handler revealed that almost always one interupt services one SDB, even when running with the maximum frequency of 100000. Very rarely there have been 2 SBD serviced per interrupt. Therefore reduce the number of SBD per CPU. Each SDB is one page in size. The new formula results in freq:4000 n_sdb:32 new:16 freq:10000 n_sdb:80 new:16 freq:20000 n_sdb:159 new:17 freq:40000 n_sdb:318 new:19 freq:50000 n_sdb:397 new:20 freq:62500 n_sdb:497 new:22 freq:83333 n_sdb:662 new:24 freq:100000 n_sdb:794 new:25 Signed-off-by: Thomas Richter Signed-off-by: Vasily Gorbik --- arch/s390/kernel/perf_cpum_sf.c | 40 +++++++++++++++++---------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c index b095b1c78987..cf2020b8db44 100644 --- a/arch/s390/kernel/perf_cpum_sf.c +++ b/arch/s390/kernel/perf_cpum_sf.c @@ -372,28 +372,33 @@ static void deallocate_buffers(struct cpu_hw_sf *cpuhw) static int allocate_buffers(struct cpu_hw_sf *cpuhw, struct hw_perf_event *hwc) { - unsigned long n_sdb, freq, factor; + unsigned long n_sdb, freq; size_t sample_size; /* Calculate sampling buffers using 4K pages * - * 1. Determine the sample data size which depends on the used - * sampling functions, for example, basic-sampling or - * basic-sampling with diagnostic-sampling. + * 1. The sampling size is 32 bytes for basic sampling. This size + * is the same for all machine types. Diagnostic + * sampling uses auxlilary data buffer setup which provides the + * memory for SDBs using linux common code auxiliary trace + * setup. * - * 2. Use the sampling frequency as input. The sampling buffer is - * designed for almost one second. This can be adjusted through - * the "factor" variable. - * In any case, alloc_sampling_buffer() sets the Alert Request + * 2. Function alloc_sampling_buffer() sets the Alert Request * Control indicator to trigger a measurement-alert to harvest - * sample-data-blocks (sdb). + * sample-data-blocks (SDB). This is done per SDB. This + * measurement alert interrupt fires quick enough to handle + * one SDB, on very high frequency and work loads there might + * be 2 to 3 SBDs available for sample processing. + * Currently there is no need for setup alert request on every + * n-th page. This is counterproductive as one IRQ triggers + * a very high number of samples to be processed at one IRQ. * - * 3. Compute the number of sample-data-blocks and ensure a minimum - * of CPUM_SF_MIN_SDB. Also ensure the upper limit does not - * exceed a "calculated" maximum. The symbolic maximum is - * designed for basic-sampling only and needs to be increased if - * diagnostic-sampling is active. - * See also the remarks for these symbolic constants. + * 3. Use the sampling frequency as input. + * Compute the number of SDBs and ensure a minimum + * of CPUM_SF_MIN_SDB. Depending on frequency add some more + * SDBs to handle a higher sampling rate. + * Use a minimum of CPUM_SF_MIN_SDB and allow for 100 samples + * (one SDB) for every 10000 HZ frequency increment. * * 4. Compute the number of sample-data-block-tables (SDBT) and * ensure a minimum of CPUM_SF_MIN_SDBT (one table can manage up @@ -401,10 +406,7 @@ static int allocate_buffers(struct cpu_hw_sf *cpuhw, struct hw_perf_event *hwc) */ sample_size = sizeof(struct hws_basic_entry); freq = sample_rate_to_freq(&cpuhw->qsi, SAMPL_RATE(hwc)); - factor = 1; - n_sdb = DIV_ROUND_UP(freq, factor * ((PAGE_SIZE-64) / sample_size)); - if (n_sdb < CPUM_SF_MIN_SDB) - n_sdb = CPUM_SF_MIN_SDB; + n_sdb = CPUM_SF_MIN_SDB + DIV_ROUND_UP(freq, 10000); /* If there is already a sampling buffer allocated, it is very likely * that the sampling facility is enabled too. If the event to be From c4f762ff6b7766e0053e39d1d87d599384288048 Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Fri, 7 Feb 2020 09:05:56 +0100 Subject: [PATCH 0411/4444] s390/zcrypt: Support for CCA protected key block version 2 There will come a new CCA keyblock version 2 for protected keys delivered back to the OS. The difference is only the amount of available buffer space to be up to 256 bytes for version 2. Signed-off-by: Harald Freudenberger Signed-off-by: Vasily Gorbik --- drivers/s390/crypto/zcrypt_ccamisc.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c index 110fe9d0cb91..e6899107c586 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.c +++ b/drivers/s390/crypto/zcrypt_ccamisc.c @@ -592,7 +592,7 @@ int cca_sec2protkey(u16 cardnr, u16 domain, u8 pad2[1]; u8 vptype; u8 vp[32]; /* verification pattern */ - } keyblock; + } ckb; } lv3; } __packed * prepparm; @@ -650,15 +650,16 @@ int cca_sec2protkey(u16 cardnr, u16 domain, prepparm = (struct uskrepparm *) prepcblk->rpl_parmb; /* check the returned keyblock */ - if (prepparm->lv3.keyblock.version != 0x01) { - DEBUG_ERR("%s reply param keyblock version mismatch 0x%02x != 0x01\n", - __func__, (int) prepparm->lv3.keyblock.version); + if (prepparm->lv3.ckb.version != 0x01 && + prepparm->lv3.ckb.version != 0x02) { + DEBUG_ERR("%s reply param keyblock version mismatch 0x%02x\n", + __func__, (int) prepparm->lv3.ckb.version); rc = -EIO; goto out; } /* copy the tanslated protected key */ - switch (prepparm->lv3.keyblock.len) { + switch (prepparm->lv3.ckb.len) { case 16+32: /* AES 128 protected key */ if (protkeytype) @@ -676,13 +677,13 @@ int cca_sec2protkey(u16 cardnr, u16 domain, break; default: DEBUG_ERR("%s unknown/unsupported keylen %d\n", - __func__, prepparm->lv3.keyblock.len); + __func__, prepparm->lv3.ckb.len); rc = -EIO; goto out; } - memcpy(protkey, prepparm->lv3.keyblock.key, prepparm->lv3.keyblock.len); + memcpy(protkey, prepparm->lv3.ckb.key, prepparm->lv3.ckb.len); if (protkeylen) - *protkeylen = prepparm->lv3.keyblock.len; + *protkeylen = prepparm->lv3.ckb.len; out: free_cprbmem(mem, PARMBSIZE, 0); @@ -1260,10 +1261,10 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey, prepparm = (struct aurepparm *) prepcblk->rpl_parmb; /* check the returned keyblock */ - if (prepparm->vud.ckb.version != 0x01) { - DEBUG_ERR( - "%s reply param keyblock version mismatch 0x%02x != 0x01\n", - __func__, (int) prepparm->vud.ckb.version); + if (prepparm->vud.ckb.version != 0x01 && + prepparm->vud.ckb.version != 0x02) { + DEBUG_ERR("%s reply param keyblock version mismatch 0x%02x\n", + __func__, (int) prepparm->vud.ckb.version); rc = -EIO; goto out; } From f07980d4ed60fbb35857b655c94b111f4ddf2abf Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Mon, 17 Feb 2020 11:16:53 +0800 Subject: [PATCH 0412/4444] drm/mediatek: fix race condition for HDMI jack status reporting hdmi_conn_detect and mtk_hdmi_audio_hook_plugged_cb would be called by different threads. Imaging the following calling sequence: Thread A Thread B -------------------------------------------------------------------- mtk_hdmi_audio_hook_plugged_cb() mtk_cec_hpd_high() -> disconnected hdmi_conn_detect() mtk_cec_hpd_high() -> connected plugged_cb(connected) plugged_cb(disconnected) The latest disconnected is false reported. Makes mtk_cec_hpd_high and plugged_cb atomic to fix. Also uses the same lock to protect read/write of plugged_cb and codec_dev. Fixes: 5d3c64477392 ("drm/mediatek: support HDMI jack status reporting") Signed-off-by: Tzung-Bi Shih Acked-by: CK Hu Link: https://lore.kernel.org/r/20200217105513.2.I477092c2f104fd589133436c3ae4590e6fc6323b@changeid Signed-off-by: Mark Brown --- drivers/gpu/drm/mediatek/mtk_hdmi.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 03aeb73005ef..d80017e3d84a 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -171,6 +172,7 @@ struct mtk_hdmi { bool enabled; hdmi_codec_plugged_cb plugged_cb; struct device *codec_dev; + struct mutex update_plugged_status_lock; }; static inline struct mtk_hdmi *hdmi_ctx_from_bridge(struct drm_bridge *b) @@ -1199,10 +1201,13 @@ static void mtk_hdmi_clk_disable_audio(struct mtk_hdmi *hdmi) static enum drm_connector_status mtk_hdmi_update_plugged_status(struct mtk_hdmi *hdmi) { - bool connected = mtk_cec_hpd_high(hdmi->cec_dev); + bool connected; + mutex_lock(&hdmi->update_plugged_status_lock); + connected = mtk_cec_hpd_high(hdmi->cec_dev); if (hdmi->plugged_cb && hdmi->codec_dev) hdmi->plugged_cb(hdmi->codec_dev, connected); + mutex_unlock(&hdmi->update_plugged_status_lock); return connected ? connector_status_connected : connector_status_disconnected; @@ -1669,8 +1674,11 @@ static int mtk_hdmi_audio_hook_plugged_cb(struct device *dev, void *data, { struct mtk_hdmi *hdmi = data; + mutex_lock(&hdmi->update_plugged_status_lock); hdmi->plugged_cb = fn; hdmi->codec_dev = codec_dev; + mutex_unlock(&hdmi->update_plugged_status_lock); + mtk_hdmi_update_plugged_status(hdmi); return 0; @@ -1729,6 +1737,7 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev) return ret; } + mutex_init(&hdmi->update_plugged_status_lock); platform_set_drvdata(pdev, hdmi); ret = mtk_hdmi_output_init(hdmi); From 0247142233239dc235f8239aab5c7991250d4e66 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 17 Feb 2020 10:20:19 +0100 Subject: [PATCH 0413/4444] ASoC: meson: aiu: simplify component addition Now that the component name is unique within ASoC, there is no need to hack the debugfs prefix to add more than one ASoC component to a linux device. Remove the unnecessary function and use snd_soc_register_component() directly. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200217092019.433402-1-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/aiu-acodec-ctrl.c | 7 +++---- sound/soc/meson/aiu-codec-ctrl.c | 7 +++---- sound/soc/meson/aiu.c | 20 -------------------- sound/soc/meson/aiu.h | 8 -------- 4 files changed, 6 insertions(+), 36 deletions(-) diff --git a/sound/soc/meson/aiu-acodec-ctrl.c b/sound/soc/meson/aiu-acodec-ctrl.c index b8e88b1a4fc8..7078197e0cc5 100644 --- a/sound/soc/meson/aiu-acodec-ctrl.c +++ b/sound/soc/meson/aiu-acodec-ctrl.c @@ -197,8 +197,7 @@ static const struct snd_soc_component_driver aiu_acodec_ctrl_component = { int aiu_acodec_ctrl_register_component(struct device *dev) { - return aiu_add_component(dev, &aiu_acodec_ctrl_component, - aiu_acodec_ctrl_dai_drv, - ARRAY_SIZE(aiu_acodec_ctrl_dai_drv), - "acodec"); + return snd_soc_register_component(dev, &aiu_acodec_ctrl_component, + aiu_acodec_ctrl_dai_drv, + ARRAY_SIZE(aiu_acodec_ctrl_dai_drv)); } diff --git a/sound/soc/meson/aiu-codec-ctrl.c b/sound/soc/meson/aiu-codec-ctrl.c index 8646a953e3b3..4b773d3e8b07 100644 --- a/sound/soc/meson/aiu-codec-ctrl.c +++ b/sound/soc/meson/aiu-codec-ctrl.c @@ -144,9 +144,8 @@ static const struct snd_soc_component_driver aiu_hdmi_ctrl_component = { int aiu_hdmi_ctrl_register_component(struct device *dev) { - return aiu_add_component(dev, &aiu_hdmi_ctrl_component, - aiu_hdmi_ctrl_dai_drv, - ARRAY_SIZE(aiu_hdmi_ctrl_dai_drv), - "hdmi"); + return snd_soc_register_component(dev, &aiu_hdmi_ctrl_component, + aiu_hdmi_ctrl_dai_drv, + ARRAY_SIZE(aiu_hdmi_ctrl_dai_drv)); } diff --git a/sound/soc/meson/aiu.c b/sound/soc/meson/aiu.c index 34b40b8b8299..d3e2d40e9562 100644 --- a/sound/soc/meson/aiu.c +++ b/sound/soc/meson/aiu.c @@ -71,26 +71,6 @@ int aiu_of_xlate_dai_name(struct snd_soc_component *component, return 0; } -int aiu_add_component(struct device *dev, - const struct snd_soc_component_driver *component_driver, - struct snd_soc_dai_driver *dai_drv, - int num_dai, - const char *debugfs_prefix) -{ - struct snd_soc_component *component; - - component = devm_kzalloc(dev, sizeof(*component), GFP_KERNEL); - if (!component) - return -ENOMEM; - -#ifdef CONFIG_DEBUG_FS - component->debugfs_prefix = debugfs_prefix; -#endif - - return snd_soc_add_component(dev, component, component_driver, - dai_drv, num_dai); -} - static int aiu_cpu_of_xlate_dai_name(struct snd_soc_component *component, struct of_phandle_args *args, const char **dai_name) diff --git a/sound/soc/meson/aiu.h b/sound/soc/meson/aiu.h index 097c26de7b7c..06a968c55728 100644 --- a/sound/soc/meson/aiu.h +++ b/sound/soc/meson/aiu.h @@ -11,9 +11,7 @@ struct clk; struct clk_bulk_data; struct device; struct of_phandle_args; -struct snd_soc_component_driver; struct snd_soc_dai; -struct snd_soc_dai_driver; struct snd_soc_dai_ops; enum aiu_clk_ids { @@ -45,12 +43,6 @@ int aiu_of_xlate_dai_name(struct snd_soc_component *component, const char **dai_name, unsigned int component_id); -int aiu_add_component(struct device *dev, - const struct snd_soc_component_driver *component_driver, - struct snd_soc_dai_driver *dai_drv, - int num_dai, - const char *debugfs_prefix); - int aiu_hdmi_ctrl_register_component(struct device *dev); int aiu_acodec_ctrl_register_component(struct device *dev); From b2ca916ce392a9d4cea3489a3efb2b627b839eaf Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 16 Feb 2020 12:00:48 -0800 Subject: [PATCH 0414/4444] ACPI: NUMA: Up-level "map to online node" functionality The acpi_map_pxm_to_online_node() helper is used to find the closest online node to a given proximity domain. This is used to map devices in a proximity domain with no online memory or cpus to the closest online node and populate a device's 'numa_node' property. The numa_node property allows applications to be migrated "close" to a resource. In preparation for providing a generic facility to optionally map an address range to its closest online node, or the node the range would represent were it to be onlined (target_node), up-level the core of acpi_map_pxm_to_online_node() to a generic mm/numa helper. Cc: Michal Hocko Acked-by: Rafael J. Wysocki Reviewed-by: Ingo Molnar Signed-off-by: Dan Williams Link: https://lore.kernel.org/r/158188324802.894464.13128795207831894206.stgit@dwillia2-desk3.amr.corp.intel.com --- drivers/acpi/numa/srat.c | 41 ---------------------------------------- include/linux/acpi.h | 23 +++++++++++++++++++++- include/linux/numa.h | 9 +++++++++ mm/mempolicy.c | 30 +++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 42 deletions(-) diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c index eadbf90e65d1..47b4969d9b93 100644 --- a/drivers/acpi/numa/srat.c +++ b/drivers/acpi/numa/srat.c @@ -72,47 +72,6 @@ int acpi_map_pxm_to_node(int pxm) } EXPORT_SYMBOL(acpi_map_pxm_to_node); -/** - * acpi_map_pxm_to_online_node - Map proximity ID to online node - * @pxm: ACPI proximity ID - * - * This is similar to acpi_map_pxm_to_node(), but always returns an online - * node. When the mapped node from a given proximity ID is offline, it - * looks up the node distance table and returns the nearest online node. - * - * ACPI device drivers, which are called after the NUMA initialization has - * completed in the kernel, can call this interface to obtain their device - * NUMA topology from ACPI tables. Such drivers do not have to deal with - * offline nodes. A node may be offline when a device proximity ID is - * unique, SRAT memory entry does not exist, or NUMA is disabled, ex. - * "numa=off" on x86. - */ -int acpi_map_pxm_to_online_node(int pxm) -{ - int node, min_node; - - node = acpi_map_pxm_to_node(pxm); - - if (node == NUMA_NO_NODE) - node = 0; - - min_node = node; - if (!node_online(node)) { - int min_dist = INT_MAX, dist, n; - - for_each_online_node(n) { - dist = node_distance(node, n); - if (dist < min_dist) { - min_dist = dist; - min_node = n; - } - } - } - - return min_node; -} -EXPORT_SYMBOL(acpi_map_pxm_to_online_node); - static void __init acpi_table_print_srat_entry(struct acpi_subtable_header *header) { diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 0f24d701fbdc..3839363081f3 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -416,9 +416,30 @@ extern void acpi_osi_setup(char *str); extern bool acpi_osi_is_win8(void); #ifdef CONFIG_ACPI_NUMA -int acpi_map_pxm_to_online_node(int pxm); int acpi_map_pxm_to_node(int pxm); int acpi_get_node(acpi_handle handle); + +/** + * acpi_map_pxm_to_online_node - Map proximity ID to online node + * @pxm: ACPI proximity ID + * + * This is similar to acpi_map_pxm_to_node(), but always returns an online + * node. When the mapped node from a given proximity ID is offline, it + * looks up the node distance table and returns the nearest online node. + * + * ACPI device drivers, which are called after the NUMA initialization has + * completed in the kernel, can call this interface to obtain their device + * NUMA topology from ACPI tables. Such drivers do not have to deal with + * offline nodes. A node may be offline when a device proximity ID is + * unique, SRAT memory entry does not exist, or NUMA is disabled, ex. + * "numa=off" on x86. + */ +static inline int acpi_map_pxm_to_online_node(int pxm) +{ + int node = acpi_map_pxm_to_node(pxm); + + return numa_map_to_online_node(node); +} #else static inline int acpi_map_pxm_to_online_node(int pxm) { diff --git a/include/linux/numa.h b/include/linux/numa.h index 110b0e5d0fb0..20f4e44b186c 100644 --- a/include/linux/numa.h +++ b/include/linux/numa.h @@ -13,4 +13,13 @@ #define NUMA_NO_NODE (-1) +#ifdef CONFIG_NUMA +int numa_map_to_online_node(int node); +#else +static inline int numa_map_to_online_node(int node) +{ + return NUMA_NO_NODE; +} +#endif + #endif /* _LINUX_NUMA_H */ diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 977c641f78cf..756d6e5bb59f 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -127,6 +127,36 @@ static struct mempolicy default_policy = { static struct mempolicy preferred_node_policy[MAX_NUMNODES]; +/** + * numa_map_to_online_node - Find closest online node + * @nid: Node id to start the search + * + * Lookup the next closest node by distance if @nid is not online. + */ +int numa_map_to_online_node(int node) +{ + int min_node; + + if (node == NUMA_NO_NODE) + node = 0; + + min_node = node; + if (!node_online(node)) { + int min_dist = INT_MAX, dist, n; + + for_each_online_node(n) { + dist = node_distance(node, n); + if (dist < min_dist) { + min_dist = dist; + min_node = n; + } + } + } + + return min_node; +} +EXPORT_SYMBOL_GPL(numa_map_to_online_node); + struct mempolicy *get_task_policy(struct task_struct *p) { struct mempolicy *pol = p->mempolicy; From 4fcbe96e4d0bc4abe22ee10573ff663b9ebbcf17 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 16 Feb 2020 12:00:53 -0800 Subject: [PATCH 0415/4444] mm/numa: Skip NUMA_NO_NODE and online nodes in numa_map_to_online_node() Update numa_map_to_online_node() to stop falling back to numa node 0 when the input is NUMA_NO_NODE. Also, skip the lookup if @node is online. This makes the routine compatible with other arch node mapping routines. Reported-by: Aneesh Kumar K.V Reviewed-by: Aneesh Kumar K.V Link: https://lore.kernel.org/r/157401275716.43284.13185549705765009174.stgit@dwillia2-desk3.amr.corp.intel.com Reviewed-by: Ingo Molnar Signed-off-by: Dan Williams Link: https://lore.kernel.org/r/158188325316.894464.15650888748083329531.stgit@dwillia2-desk3.amr.corp.intel.com --- mm/mempolicy.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 756d6e5bb59f..19f7e71945a7 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -135,21 +135,17 @@ static struct mempolicy preferred_node_policy[MAX_NUMNODES]; */ int numa_map_to_online_node(int node) { - int min_node; + int min_dist = INT_MAX, dist, n, min_node; - if (node == NUMA_NO_NODE) - node = 0; + if (node == NUMA_NO_NODE || node_online(node)) + return node; min_node = node; - if (!node_online(node)) { - int min_dist = INT_MAX, dist, n; - - for_each_online_node(n) { - dist = node_distance(node, n); - if (dist < min_dist) { - min_dist = dist; - min_node = n; - } + for_each_online_node(n) { + dist = node_distance(node, n); + if (dist < min_dist) { + min_dist = dist; + min_node = n; } } From 575e23b6e13c5f575a65144579a233b76f5ca86b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 16 Feb 2020 12:00:58 -0800 Subject: [PATCH 0416/4444] powerpc/papr_scm: Switch to numa_map_to_online_node() Now that the core exports numa_map_to_online_node() switch to that instead of the locally coded duplicate. Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: "Oliver O'Halloran" Acked-by: Michael Ellerman Reported-by: "Aneesh Kumar K.V" Reviewed-by: Aneesh Kumar K.V Link: https://lore.kernel.org/r/157401276263.43284.12616818803654229788.stgit@dwillia2-desk3.amr.corp.intel.com Reviewed-by: Ingo Molnar Signed-off-by: Dan Williams Link: https://lore.kernel.org/r/158188325830.894464.9454884523846454529.stgit@dwillia2-desk3.amr.corp.intel.com --- arch/powerpc/platforms/pseries/papr_scm.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c index 0b4467e378e5..3cc66224ec1f 100644 --- a/arch/powerpc/platforms/pseries/papr_scm.c +++ b/arch/powerpc/platforms/pseries/papr_scm.c @@ -285,25 +285,6 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, return 0; } -static inline int papr_scm_node(int node) -{ - int min_dist = INT_MAX, dist; - int nid, min_node; - - if ((node == NUMA_NO_NODE) || node_online(node)) - return node; - - min_node = first_online_node; - for_each_online_node(nid) { - dist = node_distance(node, nid); - if (dist < min_dist) { - min_dist = dist; - min_node = nid; - } - } - return min_node; -} - static int papr_scm_nvdimm_init(struct papr_scm_priv *p) { struct device *dev = &p->pdev->dev; @@ -349,7 +330,7 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p) memset(&ndr_desc, 0, sizeof(ndr_desc)); target_nid = dev_to_node(&p->pdev->dev); - online_nid = papr_scm_node(target_nid); + online_nid = numa_map_to_online_node(target_nid); ndr_desc.numa_node = online_nid; ndr_desc.target_node = target_nid; ndr_desc.res = &p->res; From 1e5d8e1e47afde23e3249aed25d7d124feff5c1c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 16 Feb 2020 12:01:04 -0800 Subject: [PATCH 0417/4444] x86/mm: Introduce CONFIG_NUMA_KEEP_MEMINFO Currently x86 numa_meminfo is marked __initdata in the CONFIG_MEMORY_HOTPLUG=n case. In support of a new facility to allow drivers to map reserved memory to a 'target_node' (phys_to_target_node()), add support for removing the __initdata designation for those users. Both memory hotplug and phys_to_target_node() users select CONFIG_NUMA_KEEP_MEMINFO to tell the arch to maintain its physical address to NUMA mapping infrastructure post init. Cc: Dave Hansen Cc: Andy Lutomirski Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Borislav Petkov Cc: "H. Peter Anvin" Cc: Cc: Andrew Morton Cc: David Hildenbrand Cc: Michal Hocko Reviewed-by: Ingo Molnar Signed-off-by: Dan Williams Reviewed-by: Thomas Gleixner Link: https://lore.kernel.org/r/158188326422.894464.15742054998046628934.stgit@dwillia2-desk3.amr.corp.intel.com --- arch/x86/mm/numa.c | 6 +----- include/linux/numa.h | 7 +++++++ mm/Kconfig | 5 +++++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index 99f7a68738f0..2450b21cc28a 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c @@ -25,11 +25,7 @@ nodemask_t numa_nodes_parsed __initdata; struct pglist_data *node_data[MAX_NUMNODES] __read_mostly; EXPORT_SYMBOL(node_data); -static struct numa_meminfo numa_meminfo -#ifndef CONFIG_MEMORY_HOTPLUG -__initdata -#endif -; +static struct numa_meminfo numa_meminfo __initdata_or_meminfo; static int numa_distance_cnt; static u8 *numa_distance; diff --git a/include/linux/numa.h b/include/linux/numa.h index 20f4e44b186c..5773cd2613fc 100644 --- a/include/linux/numa.h +++ b/include/linux/numa.h @@ -13,6 +13,13 @@ #define NUMA_NO_NODE (-1) +/* optionally keep NUMA memory info available post init */ +#ifdef CONFIG_NUMA_KEEP_MEMINFO +#define __initdata_or_meminfo +#else +#define __initdata_or_meminfo __initdata +#endif + #ifdef CONFIG_NUMA int numa_map_to_online_node(int node); #else diff --git a/mm/Kconfig b/mm/Kconfig index ab80933be65f..328268473fec 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -139,6 +139,10 @@ config HAVE_FAST_GUP config ARCH_KEEP_MEMBLOCK bool +# Keep arch NUMA mapping infrastructure post-init. +config NUMA_KEEP_MEMINFO + bool + config MEMORY_ISOLATION bool @@ -154,6 +158,7 @@ config MEMORY_HOTPLUG bool "Allow for memory hot-add" depends on SPARSEMEM || X86_64_ACPI_NUMA depends on ARCH_ENABLE_MEMORY_HOTPLUG + select NUMA_KEEP_MEMINFO if NUMA config MEMORY_HOTPLUG_SPARSE def_bool y From 0f74226649fb2875a91b68f3750f55220aa73425 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 13 Feb 2020 09:14:09 -0600 Subject: [PATCH 0418/4444] kernel: module: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Jessica Yu --- kernel/module.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/module.c b/kernel/module.c index 33569a01d6e1..b88ec9cd2a7f 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1515,7 +1515,7 @@ struct module_sect_attr { struct module_sect_attrs { struct attribute_group grp; unsigned int nsections; - struct module_sect_attr attrs[0]; + struct module_sect_attr attrs[]; }; static ssize_t module_sect_show(struct module_attribute *mattr, @@ -1608,7 +1608,7 @@ static void remove_sect_attrs(struct module *mod) struct module_notes_attrs { struct kobject *dir; unsigned int notes; - struct bin_attribute attrs[0]; + struct bin_attribute attrs[]; }; static ssize_t module_notes_read(struct file *filp, struct kobject *kobj, From 73ec6d2748dc35db2b32cf3c182a27c4a0837b9b Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 10 Feb 2020 09:31:54 -0800 Subject: [PATCH 0419/4444] scsi: fc: Update Descriptor definition and add RDF and Link Integrity FPINs Update the FC headers for the RDF ELS and populate out the FPIN ELS and the Link integrity FPIN payload. RDF is used to register for diagnostic events. FPIN is how the fabric reports a diagnostic event. Specifically, this patch: - Adds the formal definition of TLV descriptors that are now used in a lot of the FC spec. The simplistic fc_fn_desc structure, basically no more than the tlv definition, is removed. - Small tlv helper functions are added as defines. - The list of known Descriptor tags (identifying the TLV) is expanded and a name initializer introduced. - The LSRI descriptor, returned in many new ELS response payloads is added. - The RDF ELS code is added, and the RDF request response structures added. - The FPIN els definition is corrected. - A full definition of a Link Integrity Notification descriptor is added, [mkp: rolled in kbuild warning fix] Link: https://lore.kernel.org/r/20200210173155.547-2-jsmart2021@gmail.com Reported-by: kbuild test robot Signed-off-by: James Smart Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- include/uapi/scsi/fc/fc_els.h | 213 +++++++++++++++++++++++++++++++--- 1 file changed, 197 insertions(+), 16 deletions(-) diff --git a/include/uapi/scsi/fc/fc_els.h b/include/uapi/scsi/fc/fc_els.h index 76f627f0d13b..66318c44acd7 100644 --- a/include/uapi/scsi/fc/fc_els.h +++ b/include/uapi/scsi/fc/fc_els.h @@ -9,6 +9,7 @@ #define _FC_ELS_H_ #include +#include /* * Fibre Channel Switch - Enhanced Link Services definitions. @@ -40,6 +41,7 @@ enum fc_els_cmd { ELS_REC = 0x13, /* read exchange concise */ ELS_SRR = 0x14, /* sequence retransmission request */ ELS_FPIN = 0x16, /* Fabric Performance Impact Notification */ + ELS_RDF = 0x19, /* Register Diagnostic Functions */ ELS_PRLI = 0x20, /* process login */ ELS_PRLO = 0x21, /* process logout */ ELS_SCN = 0x22, /* state change notification */ @@ -108,6 +110,7 @@ enum fc_els_cmd { [ELS_REC] = "REC", \ [ELS_SRR] = "SRR", \ [ELS_FPIN] = "FPIN", \ + [ELS_RDF] = "RDF", \ [ELS_PRLI] = "PRLI", \ [ELS_PRLO] = "PRLO", \ [ELS_SCN] = "SCN", \ @@ -207,6 +210,99 @@ enum fc_els_rjt_explan { /* TBD - above definitions incomplete */ }; +/* + * Link Service TLV Descriptor Tag Values + */ +enum fc_ls_tlv_dtag { + ELS_DTAG_LS_REQ_INFO = 0x00000001, + /* Link Service Request Information Descriptor */ + ELS_DTAG_LNK_INTEGRITY = 0x00020001, + /* Link Integrity Notification Descriptor */ + ELS_DTAG_DELIVERY = 0x00020002, + /* Delivery Notification Descriptor */ + ELS_DTAG_PEER_CONGEST = 0x00020003, + /* Peer Congestion Notification Descriptor */ + ELS_DTAG_CONGESTION = 0x00020004, + /* Congestion Notification Descriptor */ + ELS_DTAG_FPIN_REGISTER = 0x00030001, + /* FPIN Registration Descriptor */ +}; + +/* + * Initializer useful for decoding table. + * Please keep this in sync with the above definitions. + */ +#define FC_LS_TLV_DTAG_INIT { \ + { ELS_DTAG_LS_REQ_INFO, "Link Service Request Information" }, \ + { ELS_DTAG_LNK_INTEGRITY, "Link Integrity Notification" }, \ + { ELS_DTAG_DELIVERY, "Delivery Notification Present" }, \ + { ELS_DTAG_PEER_CONGEST, "Peer Congestion Notification" }, \ + { ELS_DTAG_CONGESTION, "Congestion Notification" }, \ + { ELS_DTAG_FPIN_REGISTER, "FPIN Registration" }, \ +} + + +/* + * Generic Link Service TLV Descriptor format + * + * This structure, as it defines no payload, will also be referred to + * as the "tlv header" - which contains the tag and len fields. + */ +struct fc_tlv_desc { + __be32 desc_tag; /* Notification Descriptor Tag */ + __be32 desc_len; /* Length of Descriptor (in bytes). + * Size of descriptor excluding + * desc_tag and desc_len fields. + */ + __u8 desc_value[0]; /* Descriptor Value */ +}; + +/* Descriptor tag and len fields are considered the mandatory header + * for a descriptor + */ +#define FC_TLV_DESC_HDR_SZ sizeof(struct fc_tlv_desc) + +/* + * Macro, used when initializing payloads, to return the descriptor length. + * Length is size of descriptor minus the tag and len fields. + */ +#define FC_TLV_DESC_LENGTH_FROM_SZ(desc) \ + (sizeof(desc) - FC_TLV_DESC_HDR_SZ) + +/* Macro, used on received payloads, to return the descriptor length */ +#define FC_TLV_DESC_SZ_FROM_LENGTH(tlv) \ + (__be32_to_cpu((tlv)->desc_len) + FC_TLV_DESC_HDR_SZ) + +/* + * This helper is used to walk descriptors in a descriptor list. + * Given the address of the current descriptor, which minimally contains a + * tag and len field, calculate the address of the next descriptor based + * on the len field. + */ +static inline void *fc_tlv_next_desc(void *desc) +{ + struct fc_tlv_desc *tlv = desc; + + return (desc + FC_TLV_DESC_SZ_FROM_LENGTH(tlv)); +} + + +/* + * Link Service Request Information Descriptor + */ +struct fc_els_lsri_desc { + __be32 desc_tag; /* descriptor tag (0x0000 0001) */ + __be32 desc_len; /* Length of Descriptor (in bytes) (4). + * Size of descriptor excluding + * desc_tag and desc_len fields. + */ + struct { + __u8 cmd; /* ELS cmd byte */ + __u8 bytes[3]; /* bytes 1..3 */ + } rqst_w0; /* Request word 0 */ +}; + + /* * Common service parameters (N ports). */ @@ -819,24 +915,61 @@ enum fc_els_clid_ic { }; -/* - * Fabric Notification Descriptor Tag values - */ -enum fc_fn_dtag { - ELS_FN_DTAG_LNK_INTEGRITY = 0x00020001, /* Link Integrity */ - ELS_FN_DTAG_PEER_CONGEST = 0x00020003, /* Peer Congestion */ - ELS_FN_DTAG_CONGESTION = 0x00020004, /* Congestion */ +enum fc_fpin_li_event_types { + FPIN_LI_UNKNOWN = 0x0, + FPIN_LI_LINK_FAILURE = 0x1, + FPIN_LI_LOSS_OF_SYNC = 0x2, + FPIN_LI_LOSS_OF_SIG = 0x3, + FPIN_LI_PRIM_SEQ_ERR = 0x4, + FPIN_LI_INVALID_TX_WD = 0x5, + FPIN_LI_INVALID_CRC = 0x6, + FPIN_LI_DEVICE_SPEC = 0xF, }; /* - * Fabric Notification Descriptor + * Initializer useful for decoding table. + * Please keep this in sync with the above definitions. */ -struct fc_fn_desc { - __be32 fn_desc_tag; /* Notification Descriptor Tag */ - __be32 fn_desc_value_len; /* Length of Descriptor Value field - * (in bytes) - */ - __u8 fn_desc_value[0]; /* Descriptor Value */ +#define FC_FPIN_LI_EVT_TYPES_INIT { \ + { FPIN_LI_UNKNOWN, "Unknown" }, \ + { FPIN_LI_LINK_FAILURE, "Link Failure" }, \ + { FPIN_LI_LOSS_OF_SYNC, "Loss of Synchronization" }, \ + { FPIN_LI_LOSS_OF_SIG, "Loss of Signal" }, \ + { FPIN_LI_PRIM_SEQ_ERR, "Primitive Sequence Protocol Error" }, \ + { FPIN_LI_INVALID_TX_WD, "Invalid Transmission Word" }, \ + { FPIN_LI_INVALID_CRC, "Invalid CRC" }, \ + { FPIN_LI_DEVICE_SPEC, "Device Specific" }, \ +} + + +/* + * Link Integrity Notification Descriptor + */ +struct fc_fn_li_desc { + __be32 desc_tag; /* Descriptor Tag (0x00020001) */ + __be32 desc_len; /* Length of Descriptor (in bytes). + * Size of descriptor excluding + * desc_tag and desc_len fields. + */ + __be64 detecting_wwpn; /* Port Name that detected event */ + __be64 attached_wwpn; /* Port Name of device attached to + * detecting Port Name + */ + __be16 event_type; /* see enum fc_fpin_li_event_types */ + __be16 event_modifier; /* Implementation specific value + * describing the event type + */ + __be32 event_threshold;/* duration in ms of the link + * integrity detection cycle + */ + __be32 event_count; /* minimum number of event + * occurrences during the event + * threshold to caause the LI event + */ + __be32 pname_count; /* number of portname_list elements */ + __be64 pname_list[0]; /* list of N_Port_Names accessible + * through the attached port + */ }; /* @@ -845,8 +978,56 @@ struct fc_fn_desc { struct fc_els_fpin { __u8 fpin_cmd; /* command (0x16) */ __u8 fpin_zero[3]; /* specified as zero - part of cmd */ - __be32 fpin_desc_cnt; /* count of descriptors */ - struct fc_fn_desc fpin_desc[0]; /* Descriptor list */ + __be32 desc_len; /* Length of Descriptor List (in bytes). + * Size of ELS excluding fpin_cmd, + * fpin_zero and desc_len fields. + */ + struct fc_tlv_desc fpin_desc[0]; /* Descriptor list */ }; +/* Diagnostic Function Descriptor - FPIN Registration */ +struct fc_df_desc_fpin_reg { + __be32 desc_tag; /* FPIN Registration (0x00030001) */ + __be32 desc_len; /* Length of Descriptor (in bytes). + * Size of descriptor excluding + * desc_tag and desc_len fields. + */ + __be32 count; /* Number of desc_tags elements */ + __be32 desc_tags[0]; /* Array of Descriptor Tags. + * Each tag indicates a function + * supported by the N_Port (request) + * or by the N_Port and Fabric + * Controller (reply; may be a subset + * of the request). + * See ELS_FN_DTAG_xxx for tag values. + */ +}; + +/* + * ELS_RDF - Register Diagnostic Functions + */ +struct fc_els_rdf { + __u8 fpin_cmd; /* command (0x19) */ + __u8 fpin_zero[3]; /* specified as zero - part of cmd */ + __be32 desc_len; /* Length of Descriptor List (in bytes). + * Size of ELS excluding fpin_cmd, + * fpin_zero and desc_len fields. + */ + struct fc_tlv_desc desc[0]; /* Descriptor list */ +}; + +/* + * ELS RDF LS_ACC Response. + */ +struct fc_els_rdf_resp { + struct fc_els_ls_acc acc_hdr; + __be32 desc_list_len; /* Length of response (in + * bytes). Excludes acc_hdr + * and desc_list_len fields. + */ + struct fc_els_lsri_desc lsri; + struct fc_tlv_desc desc[0]; /* Supported Descriptor list */ +}; + + #endif /* _FC_ELS_H_ */ From df3fe76658ed47617741819a501e2bd2ae446962 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 10 Feb 2020 09:31:55 -0800 Subject: [PATCH 0420/4444] scsi: lpfc: add RDF registration and Link Integrity FPIN logging This patch modifies lpfc to register for Link Integrity events via the use of an RDF ELS and to perform Link Integrity FPIN logging. Specifically, the driver was modified to: - Format and issue the RDF ELS immediately following SCR registration. This registers the ability of the driver to receive FPIN ELS. - Adds decoding of the FPIN els into the received descriptors, with logging of the Link Integrity event information. After decoding, the ELS is delivered to the scsi fc transport to be delivered to any user-space applications. - To aid in logging, simple helpers were added to create enum to name string lookup functions that utilize the initialization helpers from the fc_els.h header. - Note: base header definitions for the ELS's don't populate the descriptor payloads. As such, lpfc creates it's own version of the structures, using the base definitions (mostly headers) and additionally declaring the descriptors that will complete the population of the ELS. Link: https://lore.kernel.org/r/20200210173155.547-3-jsmart2021@gmail.com Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 29 +++ drivers/scsi/lpfc/lpfc_crtn.h | 3 +- drivers/scsi/lpfc/lpfc_els.c | 326 +++++++++++++++++++++++++++++-- drivers/scsi/lpfc/lpfc_hbadisc.c | 4 +- drivers/scsi/lpfc/lpfc_hw.h | 4 +- drivers/scsi/lpfc/lpfc_hw4.h | 19 ++ drivers/scsi/lpfc/lpfc_sli.c | 1 + 7 files changed, 362 insertions(+), 24 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 6abc837b9a33..357fdec06bae 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -1353,3 +1353,32 @@ lpfc_sli4_mod_hba_eq_delay(struct lpfc_hba *phba, struct lpfc_queue *eq, writel(reg_data.word0, phba->sli4_hba.u.if_type2.EQDregaddr); eq->q_mode = delay; } + + +/* + * Macro that declares tables and a routine to perform enum type to + * ascii string lookup. + * + * Defines a table for an enum. Uses xxx_INIT defines for + * the enum to populate the table. Macro defines a routine (named + * by caller) that will search all elements of the table for the key + * and return the name string if found or "Unrecognized" if not found. + */ +#define DECLARE_ENUM2STR_LOOKUP(routine, enum_name, enum_init) \ +static struct { \ + enum enum_name value; \ + char *name; \ +} fc_##enum_name##_e2str_names[] = enum_init; \ +static const char *routine(enum enum_name table_key) \ +{ \ + int i; \ + char *name = "Unrecognized"; \ + \ + for (i = 0; i < ARRAY_SIZE(fc_##enum_name##_e2str_names); i++) {\ + if (fc_##enum_name##_e2str_names[i].value == table_key) {\ + name = fc_##enum_name##_e2str_names[i].name; \ + break; \ + } \ + } \ + return name; \ +} diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 25d3dd39bc05..a450477a7e00 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -140,9 +140,10 @@ int lpfc_issue_els_prli(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t); int lpfc_issue_els_adisc(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t); int lpfc_issue_els_logo(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t); int lpfc_issue_els_npiv_logo(struct lpfc_vport *, struct lpfc_nodelist *); -int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t); +int lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry); int lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry); int lpfc_issue_fabric_reglogin(struct lpfc_vport *); +int lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry); int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *, diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 8a38e6f7f853..a712f15bc88c 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -3008,10 +3008,9 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, * This routine is a generic completion callback function for ELS commands. * Specifically, it is the callback function which does not need to perform * any command specific operations. It is currently used by the ELS command - * issuing routines for the ELS State Change Request (SCR), - * lpfc_issue_els_scr(), and the ELS Fibre Channel Address Resolution - * Protocol Response (FARPR) routine, lpfc_issue_els_farpr(). Other than - * certain debug loggings, this callback function simply invokes the + * issuing routines for RSCN, lpfc_issue_els_rscn, and the ELS Fibre Channel + * Address Resolution Protocol Response (FARPR) routine, lpfc_issue_els_farpr(). + * Other than certain debug loggings, this callback function simply invokes the * lpfc_els_chk_latt() routine to check whether link went down during the * discovery process. **/ @@ -3025,14 +3024,117 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, irsp = &rspiocb->iocb; lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, - "ELS cmd cmpl: status:x%x/x%x did:x%x", - irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->un.elsreq64.remoteID); + "ELS cmd cmpl: status:x%x/x%x did:x%x", + irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->un.elsreq64.remoteID); + /* ELS cmd tag completes */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n", irsp->ulpIoTag, irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout); + + /* Check to see if link went down during discovery */ + lpfc_els_chk_latt(vport); + lpfc_els_free_iocb(phba, cmdiocb); +} + +/** + * lpfc_cmpl_els_disc_cmd - Completion callback function for Discovery ELS cmd + * @phba: pointer to lpfc hba data structure. + * @cmdiocb: pointer to lpfc command iocb data structure. + * @rspiocb: pointer to lpfc response iocb data structure. + * + * This routine is a generic completion callback function for Discovery ELS cmd. + * Currently used by the ELS command issuing routines for the ELS State Change + * Request (SCR), lpfc_issue_els_scr() and the ELS RDF, lpfc_issue_els_rdf(). + * These commands will be retried once only for ELS timeout errors. + **/ +static void +lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + struct lpfc_iocbq *rspiocb) +{ + struct lpfc_vport *vport = cmdiocb->vport; + IOCB_t *irsp; + struct lpfc_els_rdf_rsp *prdf; + struct lpfc_dmabuf *pcmd, *prsp; + u32 *pdata; + u32 cmd; + + irsp = &rspiocb->iocb; + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, + "ELS cmd cmpl: status:x%x/x%x did:x%x", + irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->un.elsreq64.remoteID); + /* ELS cmd tag completes */ + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0217 ELS cmd tag x%x completes Data: x%x x%x x%x " + "x%x\n", + irsp->ulpIoTag, irsp->ulpStatus, + irsp->un.ulpWord[4], irsp->ulpTimeout, + cmdiocb->retry); + + pcmd = (struct lpfc_dmabuf *)cmdiocb->context2; + if (!pcmd) + goto out; + + pdata = (u32 *)pcmd->virt; + if (!pdata) + goto out; + cmd = *pdata; + + /* Only 1 retry for ELS Timeout only */ + if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT && + ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == + IOERR_SEQUENCE_TIMEOUT)) { + cmdiocb->retry++; + if (cmdiocb->retry <= 1) { + switch (cmd) { + case ELS_CMD_SCR: + lpfc_issue_els_scr(vport, cmdiocb->retry); + break; + case ELS_CMD_RDF: + cmdiocb->context1 = NULL; /* save ndlp refcnt */ + lpfc_issue_els_rdf(vport, cmdiocb->retry); + break; + } + goto out; + } + phba->fc_stat.elsRetryExceeded++; + } + if (irsp->ulpStatus) { + /* ELS discovery cmd completes with error */ + lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS, + "4203 ELS cmd x%x error: x%x x%X\n", cmd, + irsp->ulpStatus, irsp->un.ulpWord[4]); + goto out; + } + + /* The RDF response doesn't have any impact on the running driver + * but the notification descriptors are dumped here for support. + */ + if (cmd == ELS_CMD_RDF) { + int i; + + prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list); + if (!prsp) + goto out; + + prdf = (struct lpfc_els_rdf_rsp *)prsp->virt; + if (!prdf) + goto out; + + for (i = 0; i < ELS_RDF_REG_TAG_CNT && + i < be32_to_cpu(prdf->reg_d1.reg_desc.count); i++) + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "4677 Fabric RDF Notication Grant Data: " + "0x%08x\n", + be32_to_cpu( + prdf->reg_d1.desc_tags[i])); + } + +out: /* Check to see if link went down during discovery */ lpfc_els_chk_latt(vport); lpfc_els_free_iocb(phba, cmdiocb); @@ -3042,11 +3144,10 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /** * lpfc_issue_els_scr - Issue a scr to an node on a vport * @vport: pointer to a host virtual N_Port data structure. - * @nportid: N_Port identifier to the remote node. - * @retry: number of retries to the command IOCB. + * @retry: retry counter for the command IOCB. * * This routine issues a State Change Request (SCR) to a fabric node - * on a @vport. The remote node @nportid is passed into the function. It + * on a @vport. The remote node is Fabric Controller (0xfffffd). It * first search the @vport node list to find the matching ndlp. If no such * ndlp is found, a new ndlp shall be created for this (SCR) purpose. An * IOCB is allocated, payload prepared, and the lpfc_sli_issue_iocb() @@ -3062,7 +3163,7 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * 1 - Failed to issue scr command **/ int -lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) +lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry) { struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *elsiocb; @@ -3072,9 +3173,9 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) cmdsize = (sizeof(uint32_t) + sizeof(SCR)); - ndlp = lpfc_findnode_did(vport, nportid); + ndlp = lpfc_findnode_did(vport, Fabric_Cntl_DID); if (!ndlp) { - ndlp = lpfc_nlp_init(vport, nportid); + ndlp = lpfc_nlp_init(vport, Fabric_Cntl_DID); if (!ndlp) return 1; lpfc_enqueue_node(vport, ndlp); @@ -3109,7 +3210,7 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) ndlp->nlp_DID, 0, 0); phba->fc_stat.elsXmitSCR++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; + elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == IOCB_ERROR) { /* The additional lpfc_nlp_put will cause the following @@ -3339,6 +3440,102 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) /* This will cause the callback-function lpfc_cmpl_els_cmd to * trigger the release of the node. */ + /* Don't release reference count as RDF is likely outstanding */ + return 0; +} + +/** + * lpfc_issue_els_rdf - Register for diagnostic functions from the fabric. + * @vport: pointer to a host virtual N_Port data structure. + * @retry: retry counter for the command IOCB. + * + * This routine issues an ELS RDF to the Fabric Controller to register + * for diagnostic functions. + * + * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp + * will be incremented by 1 for holding the ndlp and the reference to ndlp + * will be stored into the context1 field of the IOCB for the completion + * callback function to the RDF ELS command. + * + * Return code + * 0 - Successfully issued rdf command + * 1 - Failed to issue rdf command + **/ +int +lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry) +{ + struct lpfc_hba *phba = vport->phba; + struct lpfc_iocbq *elsiocb; + struct lpfc_els_rdf_req *prdf; + struct lpfc_nodelist *ndlp; + uint16_t cmdsize; + + cmdsize = sizeof(*prdf); + + ndlp = lpfc_findnode_did(vport, Fabric_Cntl_DID); + if (!ndlp) { + ndlp = lpfc_nlp_init(vport, Fabric_Cntl_DID); + if (!ndlp) + return -ENODEV; + lpfc_enqueue_node(vport, ndlp); + } else if (!NLP_CHK_NODE_ACT(ndlp)) { + ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); + if (!ndlp) + return -ENODEV; + } + + /* RDF ELS is not required on an NPIV VN_Port. */ + if (vport->port_type == LPFC_NPIV_PORT) { + lpfc_nlp_put(ndlp); + return -EACCES; + } + + elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, + ndlp->nlp_DID, ELS_CMD_RDF); + if (!elsiocb) { + /* This will trigger the release of the node just + * allocated + */ + lpfc_nlp_put(ndlp); + return -ENOMEM; + } + + /* Configure the payload for the supported FPIN events. */ + prdf = (struct lpfc_els_rdf_req *) + (((struct lpfc_dmabuf *)elsiocb->context2)->virt); + memset(prdf, 0, cmdsize); + prdf->rdf.fpin_cmd = ELS_RDF; + prdf->rdf.desc_len = cpu_to_be32(sizeof(struct lpfc_els_rdf_req) - + sizeof(struct fc_els_rdf)); + prdf->reg_d1.reg_desc.desc_tag = cpu_to_be32(ELS_DTAG_FPIN_REGISTER); + prdf->reg_d1.reg_desc.desc_len = cpu_to_be32( + FC_TLV_DESC_LENGTH_FROM_SZ(prdf->reg_d1)); + prdf->reg_d1.reg_desc.count = cpu_to_be32(ELS_RDF_REG_TAG_CNT); + prdf->reg_d1.desc_tags[0] = cpu_to_be32(ELS_DTAG_LNK_INTEGRITY); + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, + "Issue RDF: did:x%x", + ndlp->nlp_DID, 0, 0); + + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "6444 Xmit RDF to remote NPORT x%x\n", + ndlp->nlp_DID); + + elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; + if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == + IOCB_ERROR) { + /* The additional lpfc_nlp_put will cause the following + * lpfc_els_free_iocb routine to trigger the rlease of + * the node. + */ + lpfc_nlp_put(ndlp); + lpfc_els_free_iocb(phba, elsiocb); + return -EIO; + } + + /* An RDF was issued - this put ensures the ndlp is cleaned up + * when the RDF completes. + */ lpfc_nlp_put(ndlp); return 0; } @@ -8137,6 +8334,90 @@ lpfc_send_els_event(struct lpfc_vport *vport, } +DECLARE_ENUM2STR_LOOKUP(lpfc_get_tlv_dtag_nm, fc_ls_tlv_dtag, + FC_LS_TLV_DTAG_INIT); + +DECLARE_ENUM2STR_LOOKUP(lpfc_get_fpin_li_event_nm, fc_fpin_li_event_types, + FC_FPIN_LI_EVT_TYPES_INIT); + +/** + * lpfc_els_rcv_fpin_li - Process an FPIN Link Integrity Event. + * @vport: Pointer to vport object. + * @lnk_not: Pointer to the Link Integrity Notification Descriptor. + * + * This function processes a link integrity FPIN event by + * logging a message + **/ +static void +lpfc_els_rcv_fpin_li(struct lpfc_vport *vport, struct fc_tlv_desc *tlv) +{ + struct fc_fn_li_desc *li = (struct fc_fn_li_desc *)tlv; + const char *li_evt_str; + u32 li_evt; + + li_evt = be16_to_cpu(li->event_type); + li_evt_str = lpfc_get_fpin_li_event_nm(li_evt); + + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "4680 FPIN Link Integrity %s (x%x) " + "Detecting PN x%016llx Attached PN x%016llx " + "Duration %d mSecs Count %d Port Cnt %d\n", + li_evt_str, li_evt, + be64_to_cpu(li->detecting_wwpn), + be64_to_cpu(li->attached_wwpn), + be32_to_cpu(li->event_threshold), + be32_to_cpu(li->event_count), + be32_to_cpu(li->pname_count)); +} + +static void +lpfc_els_rcv_fpin(struct lpfc_vport *vport, struct fc_els_fpin *fpin, + u32 fpin_length) +{ + struct fc_tlv_desc *tlv; + const char *dtag_nm; + uint32_t desc_cnt = 0, bytes_remain; + u32 dtag; + + /* FPINs handled only if we are in the right discovery state */ + if (vport->port_state < LPFC_DISC_AUTH) + return; + + /* make sure there is the full fpin header */ + if (fpin_length < sizeof(struct fc_els_fpin)) + return; + + tlv = (struct fc_tlv_desc *)&fpin->fpin_desc[0]; + bytes_remain = fpin_length - offsetof(struct fc_els_fpin, fpin_desc); + bytes_remain = min_t(u32, bytes_remain, be32_to_cpu(fpin->desc_len)); + + /* process each descriptor */ + while (bytes_remain >= FC_TLV_DESC_HDR_SZ && + bytes_remain >= FC_TLV_DESC_SZ_FROM_LENGTH(tlv)) { + + dtag = be32_to_cpu(tlv->desc_tag); + switch (dtag) { + case ELS_DTAG_LNK_INTEGRITY: + lpfc_els_rcv_fpin_li(vport, tlv); + break; + default: + dtag_nm = lpfc_get_tlv_dtag_nm(dtag); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "4678 skipped FPIN descriptor[%d]: " + "tag x%x (%s)\n", + desc_cnt, dtag, dtag_nm); + break; + } + + desc_cnt++; + bytes_remain -= FC_TLV_DESC_SZ_FROM_LENGTH(tlv); + tlv = fc_tlv_next_desc(tlv); + } + + fc_host_fpin_rcv(lpfc_shost_from_vport(vport), fpin_length, + (char *)fpin); +} + /** * lpfc_els_unsol_buffer - Process an unsolicited event data buffer * @phba: pointer to lpfc hba data structure. @@ -8158,7 +8439,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct Scsi_Host *shost; struct lpfc_nodelist *ndlp; struct ls_rjt stat; - uint32_t *payload; + uint32_t *payload, payload_len; uint32_t cmd, did, newnode; uint8_t rjt_exp, rjt_err = 0, init_link = 0; IOCB_t *icmd = &elsiocb->iocb; @@ -8169,6 +8450,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, newnode = 0; payload = ((struct lpfc_dmabuf *)elsiocb->context2)->virt; + payload_len = elsiocb->iocb.unsli3.rcvsli3.acc_len; cmd = *payload; if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0) lpfc_post_buffer(phba, pring, 1); @@ -8514,12 +8796,14 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, rjt_exp = LSEXP_INVALID_OX_RX; break; case ELS_CMD_FPIN: - /* - * Received FPIN from fabric - pass it to the - * transport FPIN handler. - */ - fc_host_fpin_rcv(shost, elsiocb->iocb.unsli3.rcvsli3.acc_len, - (char *)payload); + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, + "RCV FPIN: did:x%x/ste:x%x flg:x%x", + did, vport->port_state, ndlp->nlp_flag); + + lpfc_els_rcv_fpin(vport, (struct fc_els_fpin *)payload, + payload_len); + + /* There are no replies, so no rjt codes */ break; default: lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index e8937071c748..789eecbf32eb 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -4089,7 +4089,9 @@ out: FC_TYPE_NVME); /* Issue SCR just before NameServer GID_FT Query */ - lpfc_issue_els_scr(vport, SCR_DID, 0); + lpfc_issue_els_scr(vport, 0); + + lpfc_issue_els_rdf(vport, 0); } vport->fc_ns_retry = 0; diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 68f62ae6ef4f..ae51c0dbba0a 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -22,7 +22,7 @@ #define FDMI_DID 0xfffffaU #define NameServer_DID 0xfffffcU -#define SCR_DID 0xfffffdU +#define Fabric_Cntl_DID 0xfffffdU #define Fabric_DID 0xfffffeU #define Bcast_DID 0xffffffU #define Mask_DID 0xffffffU @@ -588,6 +588,7 @@ struct fc_vft_header { #define ELS_CMD_RRQ 0x12000000 #define ELS_CMD_REC 0x13000000 #define ELS_CMD_RDP 0x18000000 +#define ELS_CMD_RDF 0x19000000 #define ELS_CMD_PRLI 0x20100014 #define ELS_CMD_NVMEPRLI 0x20140018 #define ELS_CMD_PRLO 0x21100014 @@ -629,6 +630,7 @@ struct fc_vft_header { #define ELS_CMD_RRQ 0x12 #define ELS_CMD_REC 0x13 #define ELS_CMD_RDP 0x18 +#define ELS_CMD_RDF 0x19 #define ELS_CMD_PRLI 0x14001020 #define ELS_CMD_NVMEPRLI 0x18001420 #define ELS_CMD_PRLO 0x14001021 diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 9a064b96e570..10c5d1c3122e 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -20,6 +20,8 @@ * included with this package. * *******************************************************************/ +#include + /* Macros to deal with bit fields. Each bit field must have 3 #defines * associated with it (_SHIFT, _MASK, and _WORD). * EG. For a bit field that is in the 7th bit of the "field4" field of a @@ -4795,6 +4797,23 @@ struct send_frame_wqe { uint32_t fc_hdr_wd5; /* word 15 */ }; +#define ELS_RDF_REG_TAG_CNT 1 +struct lpfc_els_rdf_reg_desc { + struct fc_df_desc_fpin_reg reg_desc; /* descriptor header */ + __be32 desc_tags[ELS_RDF_REG_TAG_CNT]; + /* tags in reg_desc */ +}; + +struct lpfc_els_rdf_req { + struct fc_els_rdf rdf; /* hdr up to descriptors */ + struct lpfc_els_rdf_reg_desc reg_d1; /* 1st descriptor */ +}; + +struct lpfc_els_rdf_rsp { + struct fc_els_rdf_resp rdf_resp; /* hdr up to descriptors */ + struct lpfc_els_rdf_reg_desc reg_d1; /* 1st descriptor */ +}; + union lpfc_wqe { uint32_t words[16]; struct lpfc_wqe_generic generic; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 86ac10ecd65a..0b26b5c0527e 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -9459,6 +9459,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) { if (pcmd && (*pcmd == ELS_CMD_FLOGI || *pcmd == ELS_CMD_SCR || + *pcmd == ELS_CMD_RDF || *pcmd == ELS_CMD_RSCN_XMT || *pcmd == ELS_CMD_FDISC || *pcmd == ELS_CMD_LOGO || From b417107a659e9745f9ff905196ddff70cbe4eaa7 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 12 Feb 2020 18:02:11 -0600 Subject: [PATCH 0421/4444] scsi: advansys: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Link: https://lore.kernel.org/r/20200213000211.GA23171@embeddedor.com Reviewed-by: Hannes Reinecke Signed-off-by: Gustavo A. R. Silva Signed-off-by: Martin K. Petersen --- drivers/scsi/advansys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index a242a62caaa1..c2c7850ff7b4 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -316,7 +316,7 @@ typedef struct asc_sg_head { ushort queue_cnt; ushort entry_to_copy; ushort res; - ASC_SG_LIST sg_list[0]; + ASC_SG_LIST sg_list[]; } ASC_SG_HEAD; typedef struct asc_scsi_q { From 2523486b9860ba6bda6b0ae277d288ef94c0d374 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 14 Feb 2020 19:47:36 -0600 Subject: [PATCH 0422/4444] soundwire: intel: rename res field as link_res There are too many fields called 'res' so add prefix to make it easier to track what the structures are. Pure rename, no functionality change Signed-off-by: Pierre-Louis Bossart Acked-by: Sanyog Kale Link: https://lore.kernel.org/r/20200215014740.27580-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/intel.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index 06ef3a3ac080..78b2ebf0119c 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -103,7 +103,7 @@ enum intel_pdi_type { struct sdw_intel { struct sdw_cdns cdns; int instance; - struct sdw_intel_link_res *res; + struct sdw_intel_link_res *link_res; #ifdef CONFIG_DEBUG_FS struct dentry *debugfs; #endif @@ -193,8 +193,8 @@ static ssize_t intel_sprintf(void __iomem *mem, bool l, static int intel_reg_show(struct seq_file *s_file, void *data) { struct sdw_intel *sdw = s_file->private; - void __iomem *s = sdw->res->shim; - void __iomem *a = sdw->res->alh; + void __iomem *s = sdw->link_res->shim; + void __iomem *a = sdw->link_res->alh; char *buf; ssize_t ret; int i, j; @@ -289,7 +289,7 @@ static void intel_debugfs_exit(struct sdw_intel *sdw) {} static int intel_link_power_up(struct sdw_intel *sdw) { unsigned int link_id = sdw->instance; - void __iomem *shim = sdw->res->shim; + void __iomem *shim = sdw->link_res->shim; int spa_mask, cpa_mask; int link_control, ret; @@ -309,7 +309,7 @@ static int intel_link_power_up(struct sdw_intel *sdw) static int intel_shim_init(struct sdw_intel *sdw) { - void __iomem *shim = sdw->res->shim; + void __iomem *shim = sdw->link_res->shim; unsigned int link_id = sdw->instance; int sync_reg, ret; u16 ioctl = 0, act = 0; @@ -370,7 +370,7 @@ static int intel_shim_init(struct sdw_intel *sdw) static void intel_pdi_init(struct sdw_intel *sdw, struct sdw_cdns_stream_config *config) { - void __iomem *shim = sdw->res->shim; + void __iomem *shim = sdw->link_res->shim; unsigned int link_id = sdw->instance; int pcm_cap, pdm_cap; @@ -404,7 +404,7 @@ static void intel_pdi_init(struct sdw_intel *sdw, static int intel_pdi_get_ch_cap(struct sdw_intel *sdw, unsigned int pdi_num, bool pcm) { - void __iomem *shim = sdw->res->shim; + void __iomem *shim = sdw->link_res->shim; unsigned int link_id = sdw->instance; int count; @@ -476,7 +476,7 @@ static int intel_pdi_ch_update(struct sdw_intel *sdw) static void intel_pdi_shim_configure(struct sdw_intel *sdw, struct sdw_cdns_pdi *pdi) { - void __iomem *shim = sdw->res->shim; + void __iomem *shim = sdw->link_res->shim; unsigned int link_id = sdw->instance; int pdi_conf = 0; @@ -508,7 +508,7 @@ intel_pdi_shim_configure(struct sdw_intel *sdw, struct sdw_cdns_pdi *pdi) static void intel_pdi_alh_configure(struct sdw_intel *sdw, struct sdw_cdns_pdi *pdi) { - void __iomem *alh = sdw->res->alh; + void __iomem *alh = sdw->link_res->alh; unsigned int link_id = sdw->instance; unsigned int conf; @@ -535,7 +535,7 @@ static int intel_params_stream(struct sdw_intel *sdw, struct snd_pcm_hw_params *hw_params, int link_id, int alh_stream_id) { - struct sdw_intel_link_res *res = sdw->res; + struct sdw_intel_link_res *res = sdw->link_res; struct sdw_intel_stream_params_data params_data; params_data.substream = substream; @@ -558,7 +558,7 @@ static int intel_pre_bank_switch(struct sdw_bus *bus) { struct sdw_cdns *cdns = bus_to_cdns(bus); struct sdw_intel *sdw = cdns_to_intel(cdns); - void __iomem *shim = sdw->res->shim; + void __iomem *shim = sdw->link_res->shim; int sync_reg; /* Write to register only for multi-link */ @@ -577,7 +577,7 @@ static int intel_post_bank_switch(struct sdw_bus *bus) { struct sdw_cdns *cdns = bus_to_cdns(bus); struct sdw_intel *sdw = cdns_to_intel(cdns); - void __iomem *shim = sdw->res->shim; + void __iomem *shim = sdw->link_res->shim; int sync_reg, ret; /* Write to register only for multi-link */ @@ -937,9 +937,9 @@ static int intel_probe(struct platform_device *pdev) return -ENOMEM; sdw->instance = pdev->id; - sdw->res = dev_get_platdata(&pdev->dev); + sdw->link_res = dev_get_platdata(&pdev->dev); sdw->cdns.dev = &pdev->dev; - sdw->cdns.registers = sdw->res->registers; + sdw->cdns.registers = sdw->link_res->registers; sdw->cdns.instance = sdw->instance; sdw->cdns.msg_count = 0; sdw->cdns.bus.dev = &pdev->dev; @@ -979,11 +979,12 @@ static int intel_probe(struct platform_device *pdev) intel_pdi_ch_update(sdw); /* Acquire IRQ */ - ret = request_threaded_irq(sdw->res->irq, sdw_cdns_irq, sdw_cdns_thread, + ret = request_threaded_irq(sdw->link_res->irq, + sdw_cdns_irq, sdw_cdns_thread, IRQF_SHARED, KBUILD_MODNAME, &sdw->cdns); if (ret < 0) { dev_err(sdw->cdns.dev, "unable to grab IRQ %d, disabling device\n", - sdw->res->irq); + sdw->link_res->irq); goto err_init; } @@ -1013,7 +1014,7 @@ static int intel_probe(struct platform_device *pdev) err_interrupt: sdw_cdns_enable_interrupt(&sdw->cdns, false); - free_irq(sdw->res->irq, sdw); + free_irq(sdw->link_res->irq, sdw); err_init: sdw_delete_bus_master(&sdw->cdns.bus); return ret; @@ -1028,7 +1029,7 @@ static int intel_remove(struct platform_device *pdev) if (!sdw->cdns.bus.prop.hw_disabled) { intel_debugfs_exit(sdw); sdw_cdns_enable_interrupt(&sdw->cdns, false); - free_irq(sdw->res->irq, sdw); + free_irq(sdw->link_res->irq, sdw); snd_soc_unregister_component(sdw->cdns.dev); } sdw_delete_bus_master(&sdw->cdns.bus); From 27b198f409d876c3445d7c811609801939a04b0b Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Fri, 14 Feb 2020 19:47:37 -0600 Subject: [PATCH 0423/4444] soundwire: intel: add prepare support in sdw dai driver The existing code does not expose a prepare operation, which is very much needed to deal with underflow and resume operations. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Rander Wang Acked-by: Sanyog Kale Link: https://lore.kernel.org/r/20200215014740.27580-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/intel.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index 78b2ebf0119c..bad7c30f1e01 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -699,6 +699,21 @@ error: return ret; } +static int intel_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct sdw_cdns_dma_data *dma; + + dma = snd_soc_dai_get_dma_data(dai, substream); + if (!dma) { + dev_err(dai->dev, "failed to get dma data in %s", + __func__); + return -EIO; + } + + return sdw_prepare_stream(dma->stream); +} + static int intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -745,6 +760,7 @@ static int intel_pdm_set_sdw_stream(struct snd_soc_dai *dai, static const struct snd_soc_dai_ops intel_pcm_dai_ops = { .hw_params = intel_hw_params, + .prepare = intel_prepare, .hw_free = intel_hw_free, .shutdown = intel_shutdown, .set_sdw_stream = intel_pcm_set_sdw_stream, @@ -752,6 +768,7 @@ static const struct snd_soc_dai_ops intel_pcm_dai_ops = { static const struct snd_soc_dai_ops intel_pdm_dai_ops = { .hw_params = intel_hw_params, + .prepare = intel_prepare, .hw_free = intel_hw_free, .shutdown = intel_shutdown, .set_sdw_stream = intel_pdm_set_sdw_stream, From 973a842940bceadcdfe9c77a1fc98ba8526ace0c Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Fri, 14 Feb 2020 19:47:38 -0600 Subject: [PATCH 0424/4444] soundwire: intel: add trigger support in sdw dai driver The existing code does not expose a trigger callback, which is very much required for streaming. The SoundWire stream is enabled and disabled in trigger function. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Rander Wang Acked-by: Sanyog Kale Link: https://lore.kernel.org/r/20200215014740.27580-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/intel.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index bad7c30f1e01..999aa2cd9fea 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -714,6 +714,43 @@ static int intel_prepare(struct snd_pcm_substream *substream, return sdw_prepare_stream(dma->stream); } +static int intel_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct sdw_cdns_dma_data *dma; + int ret; + + dma = snd_soc_dai_get_dma_data(dai, substream); + if (!dma) { + dev_err(dai->dev, "failed to get dma data in %s", __func__); + return -EIO; + } + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_RESUME: + ret = sdw_enable_stream(dma->stream); + break; + + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + ret = sdw_disable_stream(dma->stream); + break; + + default: + ret = -EINVAL; + break; + } + + if (ret) + dev_err(dai->dev, + "%s trigger %d failed: %d", + __func__, cmd, ret); + return ret; +} + static int intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -761,6 +798,7 @@ static int intel_pdm_set_sdw_stream(struct snd_soc_dai *dai, static const struct snd_soc_dai_ops intel_pcm_dai_ops = { .hw_params = intel_hw_params, .prepare = intel_prepare, + .trigger = intel_trigger, .hw_free = intel_hw_free, .shutdown = intel_shutdown, .set_sdw_stream = intel_pcm_set_sdw_stream, @@ -769,6 +807,7 @@ static const struct snd_soc_dai_ops intel_pcm_dai_ops = { static const struct snd_soc_dai_ops intel_pdm_dai_ops = { .hw_params = intel_hw_params, .prepare = intel_prepare, + .trigger = intel_trigger, .hw_free = intel_hw_free, .shutdown = intel_shutdown, .set_sdw_stream = intel_pdm_set_sdw_stream, From 5e7484d01928030ee348cac0b55973781af4c271 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Fri, 14 Feb 2020 19:47:39 -0600 Subject: [PATCH 0425/4444] soundwire: intel: add sdw_stream_setup helper for .startup callback The sdw stream is allocated and stored in dai to share the sdw runtime information. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Rander Wang Acked-by: Sanyog Kale Link: https://lore.kernel.org/r/20200215014740.27580-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/intel.c | 64 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index 999aa2cd9fea..c498812522ab 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -617,6 +617,68 @@ static int intel_post_bank_switch(struct sdw_bus *bus) * DAI routines */ +static int sdw_stream_setup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct sdw_stream_runtime *sdw_stream = NULL; + char *name; + int i, ret; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + name = kasprintf(GFP_KERNEL, "%s-Playback", dai->name); + else + name = kasprintf(GFP_KERNEL, "%s-Capture", dai->name); + + if (!name) + return -ENOMEM; + + sdw_stream = sdw_alloc_stream(name); + if (!sdw_stream) { + dev_err(dai->dev, "alloc stream failed for DAI %s", dai->name); + ret = -ENOMEM; + goto error; + } + + /* Set stream pointer on CPU DAI */ + ret = snd_soc_dai_set_sdw_stream(dai, sdw_stream, substream->stream); + if (ret < 0) { + dev_err(dai->dev, "failed to set stream pointer on cpu dai %s", + dai->name); + goto release_stream; + } + + /* Set stream pointer on all CODEC DAIs */ + for (i = 0; i < rtd->num_codecs; i++) { + ret = snd_soc_dai_set_sdw_stream(rtd->codec_dais[i], sdw_stream, + substream->stream); + if (ret < 0) { + dev_err(dai->dev, "failed to set stream pointer on codec dai %s", + rtd->codec_dais[i]->name); + goto release_stream; + } + } + + return 0; + +release_stream: + sdw_release_stream(sdw_stream); +error: + kfree(name); + return ret; +} + +static int intel_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + /* + * TODO: add pm_runtime support here, the startup callback + * will make sure the IP is 'active' + */ + + return sdw_stream_setup(substream, dai); +} + static int intel_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -796,6 +858,7 @@ static int intel_pdm_set_sdw_stream(struct snd_soc_dai *dai, } static const struct snd_soc_dai_ops intel_pcm_dai_ops = { + .startup = intel_startup, .hw_params = intel_hw_params, .prepare = intel_prepare, .trigger = intel_trigger, @@ -805,6 +868,7 @@ static const struct snd_soc_dai_ops intel_pcm_dai_ops = { }; static const struct snd_soc_dai_ops intel_pdm_dai_ops = { + .startup = intel_startup, .hw_params = intel_hw_params, .prepare = intel_prepare, .trigger = intel_trigger, From eff346f24ba97c3a7c16261d3157adf61ac8960c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 14 Feb 2020 19:47:40 -0600 Subject: [PATCH 0426/4444] soundwire: intel: free all resources on hw_free() Make sure all calls to the SoundWire stream API are done and involve callback. Also kfree the stream name. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Rander Wang Acked-by: Sanyog Kale Link: https://lore.kernel.org/r/20200215014740.27580-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/intel.c | 41 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index c498812522ab..a327669c757b 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -550,6 +550,25 @@ static int intel_params_stream(struct sdw_intel *sdw, return -EIO; } +static int intel_free_stream(struct sdw_intel *sdw, + struct snd_pcm_substream *substream, + struct snd_soc_dai *dai, + int link_id) +{ + struct sdw_intel_link_res *res = sdw->link_res; + struct sdw_intel_stream_free_data free_data; + + free_data.substream = substream; + free_data.dai = dai; + free_data.link_id = link_id; + + if (res->ops && res->ops->free_stream && res->dev) + return res->ops->free_stream(res->dev, + &free_data); + + return 0; +} + /* * bank switch routines */ @@ -817,6 +836,7 @@ static int intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai); + struct sdw_intel *sdw = cdns_to_intel(cdns); struct sdw_cdns_dma_data *dma; int ret; @@ -824,12 +844,29 @@ intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) if (!dma) return -EIO; + ret = sdw_deprepare_stream(dma->stream); + if (ret) { + dev_err(dai->dev, "sdw_deprepare_stream: failed %d", ret); + return ret; + } + ret = sdw_stream_remove_master(&cdns->bus, dma->stream); - if (ret < 0) + if (ret < 0) { dev_err(dai->dev, "remove master from stream %s failed: %d\n", dma->stream->name, ret); + return ret; + } - return ret; + ret = intel_free_stream(sdw, substream, dai, sdw->instance); + if (ret < 0) { + dev_err(dai->dev, "intel_free_stream: failed %d", ret); + return ret; + } + + kfree(dma->stream->name); + sdw_release_stream(dma->stream); + + return 0; } static void intel_shutdown(struct snd_pcm_substream *substream, From 0a7696b319511b0eccb0c92d030d84653b90a975 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 27 Jan 2020 14:27:31 +0000 Subject: [PATCH 0427/4444] firmware: imx: scu-pd: Add missing audio PD ranges imx8qxp_scu_pd_ranges keeps PD ranges for both i.MX8QM and i.MX8QXP. The following PD are missing: audio-clk1/ spdif1 / sai3..7. Add them now. Signed-off-by: Daniel Baluta Signed-off-by: Shawn Guo --- drivers/firmware/imx/scu-pd.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c index b556612207e5..c10f63901c1c 100644 --- a/drivers/firmware/imx/scu-pd.c +++ b/drivers/firmware/imx/scu-pd.c @@ -109,6 +109,7 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { { "audio-pll0", IMX_SC_R_AUDIO_PLL_0, 1, false, 0 }, { "audio-pll1", IMX_SC_R_AUDIO_PLL_1, 1, false, 0 }, { "audio-clk-0", IMX_SC_R_AUDIO_CLK_0, 1, false, 0 }, + { "audio-clk-1", IMX_SC_R_AUDIO_CLK_1, 1, false, 0 }, { "dma0-ch", IMX_SC_R_DMA_0_CH0, 16, true, 0 }, { "dma1-ch", IMX_SC_R_DMA_1_CH0, 16, true, 0 }, { "dma2-ch", IMX_SC_R_DMA_2_CH0, 5, true, 0 }, @@ -116,7 +117,13 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { { "asrc1", IMX_SC_R_ASRC_1, 1, false, 0 }, { "esai0", IMX_SC_R_ESAI_0, 1, false, 0 }, { "spdif0", IMX_SC_R_SPDIF_0, 1, false, 0 }, + { "spdif1", IMX_SC_R_SPDIF_1, 1, false, 0 }, { "sai", IMX_SC_R_SAI_0, 3, true, 0 }, + { "sai3", IMX_SC_R_SAI_3, 1, false, 0 }, + { "sai4", IMX_SC_R_SAI_4, 1, false, 0 }, + { "sai5", IMX_SC_R_SAI_5, 1, false, 0 }, + { "sai6", IMX_SC_R_SAI_6, 1, false, 0 }, + { "sai7", IMX_SC_R_SAI_7, 1, false, 0 }, { "amix", IMX_SC_R_AMIX, 1, false, 0 }, { "mqs0", IMX_SC_R_MQS_0, 1, false, 0 }, { "dsp", IMX_SC_R_DSP, 1, false, 0 }, From e391b24d94915ff870cdca9a1cee01324326bb95 Mon Sep 17 00:00:00 2001 From: Sebastien Fagard Date: Mon, 27 Jan 2020 14:27:32 +0000 Subject: [PATCH 0428/4444] firmware: imx: scu-pd: enlarge PD range for mu_b The range of resources for Messaging Units side B needs to contain all the possible MUB resource available: starting from MU_5B up to MU_13B. This patch is needed to enable MU_8B for the 'imx-shmem-net' driver which allows two OS partitions communicating via MUs without Hypervisor. Signed-off-by: Sebastien Fagard Signed-off-by: Daniel Baluta Signed-off-by: Shawn Guo --- drivers/firmware/imx/scu-pd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c index c10f63901c1c..09cfa268c6bd 100644 --- a/drivers/firmware/imx/scu-pd.c +++ b/drivers/firmware/imx/scu-pd.c @@ -93,7 +93,7 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { { "kpp", IMX_SC_R_KPP, 1, false, 0 }, { "fspi", IMX_SC_R_FSPI_0, 2, true, 0 }, { "mu_a", IMX_SC_R_MU_0A, 14, true, 0 }, - { "mu_b", IMX_SC_R_MU_13B, 1, true, 13 }, + { "mu_b", IMX_SC_R_MU_5B, 9, true, 5 }, /* CONN SS */ { "usb", IMX_SC_R_USB_0, 2, true, 0 }, From 950a0a6eb69a82d50f8bc7252d277a597e9b6efd Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Mon, 17 Feb 2020 19:13:35 +0800 Subject: [PATCH 0429/4444] ARM: dts: imx6sx: Improve UART pins macro defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add DCE/DTE to UART pins macro defines to distinguish the DCE and DTE functions, keep old defines at the end of file for some time to make it backward compatible. Signed-off-by: Anson Huang Reviewed-by: Uwe Kleine-König Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sx-pinfunc.h | 260 +++++++++++++++++++---------- 1 file changed, 174 insertions(+), 86 deletions(-) diff --git a/arch/arm/boot/dts/imx6sx-pinfunc.h b/arch/arm/boot/dts/imx6sx-pinfunc.h index aa194a2fdd53..9814db090487 100644 --- a/arch/arm/boot/dts/imx6sx-pinfunc.h +++ b/arch/arm/boot/dts/imx6sx-pinfunc.h @@ -42,8 +42,8 @@ #define MX6SX_PAD_GPIO1_IO03__GPIO1_IO_3 0x0020 0x0368 0x0000 0x5 0x0 #define MX6SX_PAD_GPIO1_IO03__CCM_PLL3_BYP 0x0020 0x0368 0x0000 0x6 0x0 #define MX6SX_PAD_GPIO1_IO03__PHY_TCK 0x0020 0x0368 0x0000 0x7 0x0 -#define MX6SX_PAD_GPIO1_IO04__UART1_RX 0x0024 0x036C 0x0830 0x0 0x0 -#define MX6SX_PAD_GPIO1_IO04__UART1_TX 0x0024 0x036C 0x0000 0x0 0x0 +#define MX6SX_PAD_GPIO1_IO04__UART1_DCE_TX 0x0024 0x036C 0x0000 0x0 0x0 +#define MX6SX_PAD_GPIO1_IO04__UART1_DTE_RX 0x0024 0x036C 0x0830 0x0 0x0 #define MX6SX_PAD_GPIO1_IO04__USDHC2_RESET_B 0x0024 0x036C 0x0000 0x1 0x0 #define MX6SX_PAD_GPIO1_IO04__ENET1_MDC 0x0024 0x036C 0x0000 0x2 0x0 #define MX6SX_PAD_GPIO1_IO04__OSC32K_32K_OUT 0x0024 0x036C 0x0000 0x3 0x0 @@ -51,8 +51,8 @@ #define MX6SX_PAD_GPIO1_IO04__GPIO1_IO_4 0x0024 0x036C 0x0000 0x5 0x0 #define MX6SX_PAD_GPIO1_IO04__CCM_PLL2_BYP 0x0024 0x036C 0x0000 0x6 0x0 #define MX6SX_PAD_GPIO1_IO04__PHY_TMS 0x0024 0x036C 0x0000 0x7 0x0 -#define MX6SX_PAD_GPIO1_IO05__UART1_RX 0x0028 0x0370 0x0830 0x0 0x1 -#define MX6SX_PAD_GPIO1_IO05__UART1_TX 0x0028 0x0370 0x0000 0x0 0x0 +#define MX6SX_PAD_GPIO1_IO05__UART1_DCE_RX 0x0028 0x0370 0x0830 0x0 0x1 +#define MX6SX_PAD_GPIO1_IO05__UART1_DTE_TX 0x0028 0x0370 0x0000 0x0 0x0 #define MX6SX_PAD_GPIO1_IO05__USDHC2_VSELECT 0x0028 0x0370 0x0000 0x1 0x0 #define MX6SX_PAD_GPIO1_IO05__ENET1_MDIO 0x0028 0x0370 0x0764 0x2 0x0 #define MX6SX_PAD_GPIO1_IO05__ASRC_ASRC_EXT_CLK 0x0028 0x0370 0x0000 0x3 0x0 @@ -60,21 +60,21 @@ #define MX6SX_PAD_GPIO1_IO05__GPIO1_IO_5 0x0028 0x0370 0x0000 0x5 0x0 #define MX6SX_PAD_GPIO1_IO05__SRC_TESTER_ACK 0x0028 0x0370 0x0000 0x6 0x0 #define MX6SX_PAD_GPIO1_IO05__PHY_TDO 0x0028 0x0370 0x0000 0x7 0x0 -#define MX6SX_PAD_GPIO1_IO06__UART2_RX 0x002C 0x0374 0x0838 0x0 0x0 -#define MX6SX_PAD_GPIO1_IO06__UART2_TX 0x002C 0x0374 0x0000 0x0 0x0 +#define MX6SX_PAD_GPIO1_IO06__UART2_DCE_TX 0x002C 0x0374 0x0000 0x0 0x0 +#define MX6SX_PAD_GPIO1_IO06__UART2_DTE_RX 0x002C 0x0374 0x0838 0x0 0x0 #define MX6SX_PAD_GPIO1_IO06__USDHC2_CD_B 0x002C 0x0374 0x086C 0x1 0x1 #define MX6SX_PAD_GPIO1_IO06__ENET2_MDC 0x002C 0x0374 0x0000 0x2 0x0 #define MX6SX_PAD_GPIO1_IO06__CSI1_MCLK 0x002C 0x0374 0x0000 0x3 0x0 -#define MX6SX_PAD_GPIO1_IO06__UART1_RTS_B 0x002C 0x0374 0x082C 0x4 0x0 +#define MX6SX_PAD_GPIO1_IO06__UART1_DCE_RTS 0x002C 0x0374 0x082C 0x4 0x0 #define MX6SX_PAD_GPIO1_IO06__GPIO1_IO_6 0x002C 0x0374 0x0000 0x5 0x0 #define MX6SX_PAD_GPIO1_IO06__SRC_ANY_PU_RESET 0x002C 0x0374 0x0000 0x6 0x0 #define MX6SX_PAD_GPIO1_IO06__OCOTP_CTRL_WRAPPER_FUSE_LATCHED 0x002C 0x0374 0x0000 0x7 0x0 -#define MX6SX_PAD_GPIO1_IO07__UART2_RX 0x0030 0x0378 0x0838 0x0 0x1 -#define MX6SX_PAD_GPIO1_IO07__UART2_TX 0x0030 0x0378 0x0000 0x0 0x0 +#define MX6SX_PAD_GPIO1_IO07__UART2_DCE_RX 0x0030 0x0378 0x0838 0x0 0x1 +#define MX6SX_PAD_GPIO1_IO07__UART2_DTE_TX 0x0030 0x0378 0x0000 0x0 0x0 #define MX6SX_PAD_GPIO1_IO07__USDHC2_WP 0x0030 0x0378 0x0870 0x1 0x1 #define MX6SX_PAD_GPIO1_IO07__ENET2_MDIO 0x0030 0x0378 0x0770 0x2 0x0 #define MX6SX_PAD_GPIO1_IO07__AUDMUX_MCLK 0x0030 0x0378 0x0000 0x3 0x0 -#define MX6SX_PAD_GPIO1_IO07__UART1_CTS_B 0x0030 0x0378 0x0000 0x4 0x0 +#define MX6SX_PAD_GPIO1_IO07__UART1_DCE_CTS 0x0030 0x0378 0x0000 0x4 0x0 #define MX6SX_PAD_GPIO1_IO07__GPIO1_IO_7 0x0030 0x0378 0x0000 0x5 0x0 #define MX6SX_PAD_GPIO1_IO07__SRC_EARLY_RESET 0x0030 0x0378 0x0000 0x6 0x0 #define MX6SX_PAD_GPIO1_IO07__DCIC2_OUT 0x0030 0x0378 0x0000 0x7 0x0 @@ -83,7 +83,7 @@ #define MX6SX_PAD_GPIO1_IO08__WDOG1_WDOG_B 0x0034 0x037C 0x0000 0x1 0x0 #define MX6SX_PAD_GPIO1_IO08__SDMA_EXT_EVENT_0 0x0034 0x037C 0x081C 0x2 0x0 #define MX6SX_PAD_GPIO1_IO08__CCM_PMIC_RDY 0x0034 0x037C 0x069C 0x3 0x1 -#define MX6SX_PAD_GPIO1_IO08__UART2_RTS_B 0x0034 0x037C 0x0834 0x4 0x0 +#define MX6SX_PAD_GPIO1_IO08__UART2_DCE_RTS 0x0034 0x037C 0x0834 0x4 0x0 #define MX6SX_PAD_GPIO1_IO08__GPIO1_IO_8 0x0034 0x037C 0x0000 0x5 0x0 #define MX6SX_PAD_GPIO1_IO08__SRC_SYSTEM_RESET 0x0034 0x037C 0x0000 0x6 0x0 #define MX6SX_PAD_GPIO1_IO08__DCIC1_OUT 0x0034 0x037C 0x0000 0x7 0x0 @@ -92,7 +92,7 @@ #define MX6SX_PAD_GPIO1_IO09__WDOG2_WDOG_B 0x0038 0x0380 0x0000 0x1 0x0 #define MX6SX_PAD_GPIO1_IO09__SDMA_EXT_EVENT_1 0x0038 0x0380 0x0820 0x2 0x0 #define MX6SX_PAD_GPIO1_IO09__CCM_OUT0 0x0038 0x0380 0x0000 0x3 0x0 -#define MX6SX_PAD_GPIO1_IO09__UART2_CTS_B 0x0038 0x0380 0x0000 0x4 0x0 +#define MX6SX_PAD_GPIO1_IO09__UART2_DCE_CTS 0x0038 0x0380 0x0000 0x4 0x0 #define MX6SX_PAD_GPIO1_IO09__GPIO1_IO_9 0x0038 0x0380 0x0000 0x5 0x0 #define MX6SX_PAD_GPIO1_IO09__SRC_INT_BOOT 0x0038 0x0380 0x0000 0x6 0x0 #define MX6SX_PAD_GPIO1_IO09__OBSERVE_MUX_OUT_4 0x0038 0x0380 0x0000 0x7 0x0 @@ -177,8 +177,8 @@ #define MX6SX_PAD_CSI_DATA04__ESAI_TX1 0x005C 0x03A4 0x0794 0x1 0x1 #define MX6SX_PAD_CSI_DATA04__SPDIF_OUT 0x005C 0x03A4 0x0000 0x2 0x0 #define MX6SX_PAD_CSI_DATA04__KPP_COL_6 0x005C 0x03A4 0x07CC 0x3 0x0 -#define MX6SX_PAD_CSI_DATA04__UART6_RX 0x005C 0x03A4 0x0858 0x4 0x0 -#define MX6SX_PAD_CSI_DATA04__UART6_TX 0x005C 0x03A4 0x0000 0x4 0x0 +#define MX6SX_PAD_CSI_DATA04__UART6_DCE_RX 0x005C 0x03A4 0x0858 0x4 0x0 +#define MX6SX_PAD_CSI_DATA04__UART6_DTE_TX 0x005C 0x03A4 0x0000 0x4 0x0 #define MX6SX_PAD_CSI_DATA04__GPIO1_IO_18 0x005C 0x03A4 0x0000 0x5 0x0 #define MX6SX_PAD_CSI_DATA04__WEIM_DATA_19 0x005C 0x03A4 0x0000 0x6 0x0 #define MX6SX_PAD_CSI_DATA04__PWM5_OUT 0x005C 0x03A4 0x0000 0x7 0x0 @@ -188,8 +188,8 @@ #define MX6SX_PAD_CSI_DATA05__ESAI_TX4_RX1 0x0060 0x03A8 0x07A0 0x1 0x1 #define MX6SX_PAD_CSI_DATA05__SPDIF_IN 0x0060 0x03A8 0x0824 0x2 0x1 #define MX6SX_PAD_CSI_DATA05__KPP_ROW_6 0x0060 0x03A8 0x07D8 0x3 0x0 -#define MX6SX_PAD_CSI_DATA05__UART6_RX 0x0060 0x03A8 0x0858 0x4 0x1 -#define MX6SX_PAD_CSI_DATA05__UART6_TX 0x0060 0x03A8 0x0000 0x4 0x0 +#define MX6SX_PAD_CSI_DATA05__UART6_DCE_TX 0x0060 0x03A8 0x0000 0x4 0x0 +#define MX6SX_PAD_CSI_DATA05__UART6_DTE_RX 0x0060 0x03A8 0x0858 0x4 0x1 #define MX6SX_PAD_CSI_DATA05__GPIO1_IO_19 0x0060 0x03A8 0x0000 0x5 0x0 #define MX6SX_PAD_CSI_DATA05__WEIM_DATA_18 0x0060 0x03A8 0x0000 0x6 0x0 #define MX6SX_PAD_CSI_DATA05__PWM6_OUT 0x0060 0x03A8 0x0000 0x7 0x0 @@ -199,7 +199,7 @@ #define MX6SX_PAD_CSI_DATA06__ESAI_TX2_RX3 0x0064 0x03AC 0x0798 0x1 0x1 #define MX6SX_PAD_CSI_DATA06__I2C4_SCL 0x0064 0x03AC 0x07C0 0x2 0x2 #define MX6SX_PAD_CSI_DATA06__KPP_COL_7 0x0064 0x03AC 0x07D0 0x3 0x0 -#define MX6SX_PAD_CSI_DATA06__UART6_RTS_B 0x0064 0x03AC 0x0854 0x4 0x0 +#define MX6SX_PAD_CSI_DATA06__UART6_DCE_RTS 0x0064 0x03AC 0x0854 0x4 0x0 #define MX6SX_PAD_CSI_DATA06__GPIO1_IO_20 0x0064 0x03AC 0x0000 0x5 0x0 #define MX6SX_PAD_CSI_DATA06__WEIM_DATA_17 0x0064 0x03AC 0x0000 0x6 0x0 #define MX6SX_PAD_CSI_DATA06__DCIC2_OUT 0x0064 0x03AC 0x0000 0x7 0x0 @@ -209,7 +209,7 @@ #define MX6SX_PAD_CSI_DATA07__ESAI_TX3_RX2 0x0068 0x03B0 0x079C 0x1 0x1 #define MX6SX_PAD_CSI_DATA07__I2C4_SDA 0x0068 0x03B0 0x07C4 0x2 0x2 #define MX6SX_PAD_CSI_DATA07__KPP_ROW_7 0x0068 0x03B0 0x07DC 0x3 0x0 -#define MX6SX_PAD_CSI_DATA07__UART6_CTS_B 0x0068 0x03B0 0x0000 0x4 0x0 +#define MX6SX_PAD_CSI_DATA07__UART6_DCE_CTS 0x0068 0x03B0 0x0000 0x4 0x0 #define MX6SX_PAD_CSI_DATA07__GPIO1_IO_21 0x0068 0x03B0 0x0000 0x5 0x0 #define MX6SX_PAD_CSI_DATA07__WEIM_DATA_16 0x0068 0x03B0 0x0000 0x6 0x0 #define MX6SX_PAD_CSI_DATA07__DCIC1_OUT 0x0068 0x03B0 0x0000 0x7 0x0 @@ -218,7 +218,7 @@ #define MX6SX_PAD_CSI_HSYNC__CSI1_HSYNC 0x006C 0x03B4 0x0700 0x0 0x0 #define MX6SX_PAD_CSI_HSYNC__ESAI_TX0 0x006C 0x03B4 0x0790 0x1 0x1 #define MX6SX_PAD_CSI_HSYNC__AUDMUX_AUD6_TXD 0x006C 0x03B4 0x0678 0x2 0x1 -#define MX6SX_PAD_CSI_HSYNC__UART4_RTS_B 0x006C 0x03B4 0x0844 0x3 0x2 +#define MX6SX_PAD_CSI_HSYNC__UART4_DCE_RTS 0x006C 0x03B4 0x0844 0x3 0x2 #define MX6SX_PAD_CSI_HSYNC__MQS_LEFT 0x006C 0x03B4 0x0000 0x4 0x0 #define MX6SX_PAD_CSI_HSYNC__GPIO1_IO_22 0x006C 0x03B4 0x0000 0x5 0x0 #define MX6SX_PAD_CSI_HSYNC__WEIM_DATA_25 0x006C 0x03B4 0x0000 0x6 0x0 @@ -228,8 +228,8 @@ #define MX6SX_PAD_CSI_MCLK__CSI1_MCLK 0x0070 0x03B8 0x0000 0x0 0x0 #define MX6SX_PAD_CSI_MCLK__ESAI_TX_HF_CLK 0x0070 0x03B8 0x0784 0x1 0x1 #define MX6SX_PAD_CSI_MCLK__OSC32K_32K_OUT 0x0070 0x03B8 0x0000 0x2 0x0 -#define MX6SX_PAD_CSI_MCLK__UART4_RX 0x0070 0x03B8 0x0848 0x3 0x2 -#define MX6SX_PAD_CSI_MCLK__UART4_TX 0x0070 0x03B8 0x0000 0x3 0x0 +#define MX6SX_PAD_CSI_MCLK__UART4_DCE_RX 0x0070 0x03B8 0x0848 0x3 0x2 +#define MX6SX_PAD_CSI_MCLK__UART4_DTE_TX 0x0070 0x03B8 0x0000 0x3 0x0 #define MX6SX_PAD_CSI_MCLK__ANATOP_32K_OUT 0x0070 0x03B8 0x0000 0x4 0x0 #define MX6SX_PAD_CSI_MCLK__GPIO1_IO_23 0x0070 0x03B8 0x0000 0x5 0x0 #define MX6SX_PAD_CSI_MCLK__WEIM_DATA_26 0x0070 0x03B8 0x0000 0x6 0x0 @@ -239,8 +239,8 @@ #define MX6SX_PAD_CSI_PIXCLK__CSI1_PIXCLK 0x0074 0x03BC 0x0704 0x0 0x0 #define MX6SX_PAD_CSI_PIXCLK__ESAI_RX_HF_CLK 0x0074 0x03BC 0x0780 0x1 0x1 #define MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK 0x0074 0x03BC 0x0000 0x2 0x0 -#define MX6SX_PAD_CSI_PIXCLK__UART4_RX 0x0074 0x03BC 0x0848 0x3 0x3 -#define MX6SX_PAD_CSI_PIXCLK__UART4_TX 0x0074 0x03BC 0x0000 0x3 0x0 +#define MX6SX_PAD_CSI_PIXCLK__UART4_DCE_TX 0x0074 0x03BC 0x0000 0x3 0x0 +#define MX6SX_PAD_CSI_PIXCLK__UART4_DTE_RX 0x0074 0x03BC 0x0848 0x3 0x3 #define MX6SX_PAD_CSI_PIXCLK__ANATOP_24M_OUT 0x0074 0x03BC 0x0000 0x4 0x0 #define MX6SX_PAD_CSI_PIXCLK__GPIO1_IO_24 0x0074 0x03BC 0x0000 0x5 0x0 #define MX6SX_PAD_CSI_PIXCLK__WEIM_DATA_27 0x0074 0x03BC 0x0000 0x6 0x0 @@ -250,7 +250,7 @@ #define MX6SX_PAD_CSI_VSYNC__CSI1_VSYNC 0x0078 0x03C0 0x0708 0x0 0x0 #define MX6SX_PAD_CSI_VSYNC__ESAI_TX5_RX0 0x0078 0x03C0 0x07A4 0x1 0x1 #define MX6SX_PAD_CSI_VSYNC__AUDMUX_AUD6_RXD 0x0078 0x03C0 0x0674 0x2 0x1 -#define MX6SX_PAD_CSI_VSYNC__UART4_CTS_B 0x0078 0x03C0 0x0000 0x3 0x0 +#define MX6SX_PAD_CSI_VSYNC__UART4_DCE_CTS 0x0078 0x03C0 0x0000 0x3 0x0 #define MX6SX_PAD_CSI_VSYNC__MQS_RIGHT 0x0078 0x03C0 0x0000 0x4 0x0 #define MX6SX_PAD_CSI_VSYNC__GPIO1_IO_25 0x0078 0x03C0 0x0000 0x5 0x0 #define MX6SX_PAD_CSI_VSYNC__WEIM_DATA_24 0x0078 0x03C0 0x0000 0x6 0x0 @@ -330,8 +330,8 @@ #define MX6SX_PAD_ENET2_COL__ENET2_COL 0x0094 0x03DC 0x0000 0x0 0x0 #define MX6SX_PAD_ENET2_COL__ENET1_MDC 0x0094 0x03DC 0x0000 0x1 0x0 #define MX6SX_PAD_ENET2_COL__AUDMUX_AUD4_RXC 0x0094 0x03DC 0x064C 0x2 0x1 -#define MX6SX_PAD_ENET2_COL__UART1_RX 0x0094 0x03DC 0x0830 0x3 0x2 -#define MX6SX_PAD_ENET2_COL__UART1_TX 0x0094 0x03DC 0x0000 0x3 0x0 +#define MX6SX_PAD_ENET2_COL__UART1_DCE_RX 0x0094 0x03DC 0x0830 0x3 0x2 +#define MX6SX_PAD_ENET2_COL__UART1_DTE_TX 0x0094 0x03DC 0x0000 0x3 0x0 #define MX6SX_PAD_ENET2_COL__SPDIF_IN 0x0094 0x03DC 0x0824 0x4 0x3 #define MX6SX_PAD_ENET2_COL__GPIO2_IO_6 0x0094 0x03DC 0x0000 0x5 0x0 #define MX6SX_PAD_ENET2_COL__ANATOP_OTG1_ID 0x0094 0x03DC 0x0624 0x6 0x1 @@ -341,8 +341,8 @@ #define MX6SX_PAD_ENET2_CRS__ENET2_CRS 0x0098 0x03E0 0x0000 0x0 0x0 #define MX6SX_PAD_ENET2_CRS__ENET1_MDIO 0x0098 0x03E0 0x0764 0x1 0x2 #define MX6SX_PAD_ENET2_CRS__AUDMUX_AUD4_RXFS 0x0098 0x03E0 0x0650 0x2 0x1 -#define MX6SX_PAD_ENET2_CRS__UART1_RX 0x0098 0x03E0 0x0830 0x3 0x3 -#define MX6SX_PAD_ENET2_CRS__UART1_TX 0x0098 0x03E0 0x0000 0x3 0x0 +#define MX6SX_PAD_ENET2_CRS__UART1_DCE_TX 0x0098 0x03E0 0x0000 0x3 0x0 +#define MX6SX_PAD_ENET2_CRS__UART1_DTE_RX 0x0098 0x03E0 0x0830 0x3 0x3 #define MX6SX_PAD_ENET2_CRS__MLB_SIG 0x0098 0x03E0 0x07F0 0x4 0x1 #define MX6SX_PAD_ENET2_CRS__GPIO2_IO_7 0x0098 0x03E0 0x0000 0x5 0x0 #define MX6SX_PAD_ENET2_CRS__ANATOP_OTG2_ID 0x0098 0x03E0 0x0628 0x6 0x1 @@ -352,7 +352,7 @@ #define MX6SX_PAD_ENET2_RX_CLK__ENET2_RX_CLK 0x009C 0x03E4 0x0774 0x0 0x0 #define MX6SX_PAD_ENET2_RX_CLK__ENET2_REF_CLK_25M 0x009C 0x03E4 0x0000 0x1 0x0 #define MX6SX_PAD_ENET2_RX_CLK__I2C3_SCL 0x009C 0x03E4 0x07B8 0x2 0x1 -#define MX6SX_PAD_ENET2_RX_CLK__UART1_RTS_B 0x009C 0x03E4 0x082C 0x3 0x2 +#define MX6SX_PAD_ENET2_RX_CLK__UART1_DCE_RTS 0x009C 0x03E4 0x082C 0x3 0x2 #define MX6SX_PAD_ENET2_RX_CLK__MLB_DATA 0x009C 0x03E4 0x07EC 0x4 0x1 #define MX6SX_PAD_ENET2_RX_CLK__GPIO2_IO_8 0x009C 0x03E4 0x0000 0x5 0x0 #define MX6SX_PAD_ENET2_RX_CLK__USB_OTG2_OC 0x009C 0x03E4 0x085C 0x6 0x1 @@ -362,7 +362,7 @@ #define MX6SX_PAD_ENET2_TX_CLK__ENET2_TX_CLK 0x00A0 0x03E8 0x0000 0x0 0x0 #define MX6SX_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x00A0 0x03E8 0x076C 0x1 0x1 #define MX6SX_PAD_ENET2_TX_CLK__I2C3_SDA 0x00A0 0x03E8 0x07BC 0x2 0x1 -#define MX6SX_PAD_ENET2_TX_CLK__UART1_CTS_B 0x00A0 0x03E8 0x0000 0x3 0x0 +#define MX6SX_PAD_ENET2_TX_CLK__UART1_DCE_CTS 0x00A0 0x03E8 0x0000 0x3 0x0 #define MX6SX_PAD_ENET2_TX_CLK__MLB_CLK 0x00A0 0x03E8 0x07E8 0x4 0x1 #define MX6SX_PAD_ENET2_TX_CLK__GPIO2_IO_9 0x00A0 0x03E8 0x0000 0x5 0x0 #define MX6SX_PAD_ENET2_TX_CLK__USB_OTG2_PWR 0x00A0 0x03E8 0x0000 0x6 0x0 @@ -371,7 +371,7 @@ #define MX6SX_PAD_ENET2_TX_CLK__PCIE_CTRL_DEBUG_24 0x00A0 0x03E8 0x0000 0x9 0x0 #define MX6SX_PAD_KEY_COL0__KPP_COL_0 0x00A4 0x03EC 0x0000 0x0 0x0 #define MX6SX_PAD_KEY_COL0__USDHC3_CD_B 0x00A4 0x03EC 0x0000 0x1 0x0 -#define MX6SX_PAD_KEY_COL0__UART6_RTS_B 0x00A4 0x03EC 0x0854 0x2 0x2 +#define MX6SX_PAD_KEY_COL0__UART6_DCE_RTS 0x00A4 0x03EC 0x0854 0x2 0x2 #define MX6SX_PAD_KEY_COL0__ECSPI1_SCLK 0x00A4 0x03EC 0x0710 0x3 0x0 #define MX6SX_PAD_KEY_COL0__AUDMUX_AUD5_TXC 0x00A4 0x03EC 0x066C 0x4 0x0 #define MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x00A4 0x03EC 0x0000 0x5 0x0 @@ -380,8 +380,8 @@ #define MX6SX_PAD_KEY_COL0__VADC_DATA_0 0x00A4 0x03EC 0x0000 0x8 0x0 #define MX6SX_PAD_KEY_COL1__KPP_COL_1 0x00A8 0x03F0 0x0000 0x0 0x0 #define MX6SX_PAD_KEY_COL1__USDHC3_RESET_B 0x00A8 0x03F0 0x0000 0x1 0x0 -#define MX6SX_PAD_KEY_COL1__UART6_RX 0x00A8 0x03F0 0x0858 0x2 0x2 -#define MX6SX_PAD_KEY_COL1__UART6_TX 0x00A8 0x03F0 0x0000 0x2 0x0 +#define MX6SX_PAD_KEY_COL1__UART6_DCE_TX 0x00A8 0x03F0 0x0000 0x2 0x0 +#define MX6SX_PAD_KEY_COL1__UART6_DTE_RX 0x00A8 0x03F0 0x0858 0x2 0x2 #define MX6SX_PAD_KEY_COL1__ECSPI1_MISO 0x00A8 0x03F0 0x0714 0x3 0x0 #define MX6SX_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 0x00A8 0x03F0 0x0670 0x4 0x0 #define MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x00A8 0x03F0 0x0000 0x5 0x0 @@ -389,7 +389,7 @@ #define MX6SX_PAD_KEY_COL1__SAI2_TX_SYNC 0x00A8 0x03F0 0x0818 0x7 0x0 #define MX6SX_PAD_KEY_COL2__KPP_COL_2 0x00AC 0x03F4 0x0000 0x0 0x0 #define MX6SX_PAD_KEY_COL2__USDHC4_CD_B 0x00AC 0x03F4 0x0874 0x1 0x1 -#define MX6SX_PAD_KEY_COL2__UART5_RTS_B 0x00AC 0x03F4 0x084C 0x2 0x2 +#define MX6SX_PAD_KEY_COL2__UART5_DCE_RTS 0x00AC 0x03F4 0x084C 0x2 0x2 #define MX6SX_PAD_KEY_COL2__CAN1_TX 0x00AC 0x03F4 0x0000 0x3 0x0 #define MX6SX_PAD_KEY_COL2__CANFD_TX1 0x00AC 0x03F4 0x0000 0x4 0x0 #define MX6SX_PAD_KEY_COL2__GPIO2_IO_12 0x00AC 0x03F4 0x0000 0x5 0x0 @@ -397,8 +397,8 @@ #define MX6SX_PAD_KEY_COL2__ECSPI1_RDY 0x00AC 0x03F4 0x0000 0x7 0x0 #define MX6SX_PAD_KEY_COL3__KPP_COL_3 0x00B0 0x03F8 0x0000 0x0 0x0 #define MX6SX_PAD_KEY_COL3__USDHC4_LCTL 0x00B0 0x03F8 0x0000 0x1 0x0 -#define MX6SX_PAD_KEY_COL3__UART5_RX 0x00B0 0x03F8 0x0850 0x2 0x2 -#define MX6SX_PAD_KEY_COL3__UART5_TX 0x00B0 0x03F8 0x0000 0x2 0x0 +#define MX6SX_PAD_KEY_COL3__UART5_DCE_TX 0x00B0 0x03F8 0x0000 0x2 0x0 +#define MX6SX_PAD_KEY_COL3__UART5_DTE_RX 0x00B0 0x03F8 0x0850 0x2 0x2 #define MX6SX_PAD_KEY_COL3__CAN2_TX 0x00B0 0x03F8 0x0000 0x3 0x0 #define MX6SX_PAD_KEY_COL3__CANFD_TX2 0x00B0 0x03F8 0x0000 0x4 0x0 #define MX6SX_PAD_KEY_COL3__GPIO2_IO_13 0x00B0 0x03F8 0x0000 0x5 0x0 @@ -414,7 +414,7 @@ #define MX6SX_PAD_KEY_COL4__SAI2_RX_BCLK 0x00B4 0x03FC 0x0808 0x7 0x0 #define MX6SX_PAD_KEY_ROW0__KPP_ROW_0 0x00B8 0x0400 0x0000 0x0 0x0 #define MX6SX_PAD_KEY_ROW0__USDHC3_WP 0x00B8 0x0400 0x0000 0x1 0x0 -#define MX6SX_PAD_KEY_ROW0__UART6_CTS_B 0x00B8 0x0400 0x0000 0x2 0x0 +#define MX6SX_PAD_KEY_ROW0__UART6_DCE_CTS 0x00B8 0x0400 0x0000 0x2 0x0 #define MX6SX_PAD_KEY_ROW0__ECSPI1_MOSI 0x00B8 0x0400 0x0718 0x3 0x0 #define MX6SX_PAD_KEY_ROW0__AUDMUX_AUD5_TXD 0x00B8 0x0400 0x0660 0x4 0x0 #define MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x00B8 0x0400 0x0000 0x5 0x0 @@ -423,8 +423,8 @@ #define MX6SX_PAD_KEY_ROW0__GPU_IDLE 0x00B8 0x0400 0x0000 0x8 0x0 #define MX6SX_PAD_KEY_ROW1__KPP_ROW_1 0x00BC 0x0404 0x0000 0x0 0x0 #define MX6SX_PAD_KEY_ROW1__USDHC4_VSELECT 0x00BC 0x0404 0x0000 0x1 0x0 -#define MX6SX_PAD_KEY_ROW1__UART6_RX 0x00BC 0x0404 0x0858 0x2 0x3 -#define MX6SX_PAD_KEY_ROW1__UART6_TX 0x00BC 0x0404 0x0000 0x2 0x0 +#define MX6SX_PAD_KEY_ROW1__UART6_DCE_RX 0x00BC 0x0404 0x0858 0x2 0x3 +#define MX6SX_PAD_KEY_ROW1__UART6_DTE_TX 0x00BC 0x0404 0x0000 0x2 0x0 #define MX6SX_PAD_KEY_ROW1__ECSPI1_SS0 0x00BC 0x0404 0x071C 0x3 0x0 #define MX6SX_PAD_KEY_ROW1__AUDMUX_AUD5_RXD 0x00BC 0x0404 0x065C 0x4 0x0 #define MX6SX_PAD_KEY_ROW1__GPIO2_IO_16 0x00BC 0x0404 0x0000 0x5 0x0 @@ -433,7 +433,7 @@ #define MX6SX_PAD_KEY_ROW1__M4_NMI 0x00BC 0x0404 0x0000 0x8 0x0 #define MX6SX_PAD_KEY_ROW2__KPP_ROW_2 0x00C0 0x0408 0x0000 0x0 0x0 #define MX6SX_PAD_KEY_ROW2__USDHC4_WP 0x00C0 0x0408 0x0878 0x1 0x1 -#define MX6SX_PAD_KEY_ROW2__UART5_CTS_B 0x00C0 0x0408 0x0000 0x2 0x0 +#define MX6SX_PAD_KEY_ROW2__UART5_DCE_CTS 0x00C0 0x0408 0x0000 0x2 0x0 #define MX6SX_PAD_KEY_ROW2__CAN1_RX 0x00C0 0x0408 0x068C 0x3 0x1 #define MX6SX_PAD_KEY_ROW2__CANFD_RX1 0x00C0 0x0408 0x0694 0x4 0x1 #define MX6SX_PAD_KEY_ROW2__GPIO2_IO_17 0x00C0 0x0408 0x0000 0x5 0x0 @@ -441,8 +441,8 @@ #define MX6SX_PAD_KEY_ROW2__ECSPI1_SS3 0x00C0 0x0408 0x0000 0x7 0x0 #define MX6SX_PAD_KEY_ROW3__KPP_ROW_3 0x00C4 0x040C 0x0000 0x0 0x0 #define MX6SX_PAD_KEY_ROW3__USDHC3_LCTL 0x00C4 0x040C 0x0000 0x1 0x0 -#define MX6SX_PAD_KEY_ROW3__UART5_RX 0x00C4 0x040C 0x0850 0x2 0x3 -#define MX6SX_PAD_KEY_ROW3__UART5_TX 0x00C4 0x040C 0x0000 0x2 0x0 +#define MX6SX_PAD_KEY_ROW3__UART5_DCE_RX 0x00C4 0x040C 0x0850 0x2 0x3 +#define MX6SX_PAD_KEY_ROW3__UART5_DTE_TX 0x00C4 0x040C 0x0000 0x2 0x0 #define MX6SX_PAD_KEY_ROW3__CAN2_RX 0x00C4 0x040C 0x0690 0x3 0x1 #define MX6SX_PAD_KEY_ROW3__CANFD_RX2 0x00C4 0x040C 0x0698 0x4 0x1 #define MX6SX_PAD_KEY_ROW3__GPIO2_IO_18 0x00C4 0x040C 0x0000 0x5 0x0 @@ -815,7 +815,7 @@ #define MX6SX_PAD_NAND_DATA04__RAWNAND_DATA04 0x0160 0x04A8 0x0000 0x0 0x0 #define MX6SX_PAD_NAND_DATA04__USDHC2_DATA4 0x0160 0x04A8 0x0000 0x1 0x0 #define MX6SX_PAD_NAND_DATA04__QSPI2_B_SS1_B 0x0160 0x04A8 0x0000 0x2 0x0 -#define MX6SX_PAD_NAND_DATA04__UART3_RTS_B 0x0160 0x04A8 0x083C 0x3 0x0 +#define MX6SX_PAD_NAND_DATA04__UART3_DCE_RTS 0x0160 0x04A8 0x083C 0x3 0x0 #define MX6SX_PAD_NAND_DATA04__AUDMUX_AUD4_RXFS 0x0160 0x04A8 0x0650 0x4 0x0 #define MX6SX_PAD_NAND_DATA04__GPIO4_IO_8 0x0160 0x04A8 0x0000 0x5 0x0 #define MX6SX_PAD_NAND_DATA04__WEIM_AD_4 0x0160 0x04A8 0x0000 0x6 0x0 @@ -825,7 +825,7 @@ #define MX6SX_PAD_NAND_DATA05__RAWNAND_DATA05 0x0164 0x04AC 0x0000 0x0 0x0 #define MX6SX_PAD_NAND_DATA05__USDHC2_DATA5 0x0164 0x04AC 0x0000 0x1 0x0 #define MX6SX_PAD_NAND_DATA05__QSPI2_B_DQS 0x0164 0x04AC 0x0000 0x2 0x0 -#define MX6SX_PAD_NAND_DATA05__UART3_CTS_B 0x0164 0x04AC 0x0000 0x3 0x0 +#define MX6SX_PAD_NAND_DATA05__UART3_DCE_CTS 0x0164 0x04AC 0x0000 0x3 0x0 #define MX6SX_PAD_NAND_DATA05__AUDMUX_AUD4_RXC 0x0164 0x04AC 0x064C 0x4 0x0 #define MX6SX_PAD_NAND_DATA05__GPIO4_IO_9 0x0164 0x04AC 0x0000 0x5 0x0 #define MX6SX_PAD_NAND_DATA05__WEIM_AD_5 0x0164 0x04AC 0x0000 0x6 0x0 @@ -835,8 +835,8 @@ #define MX6SX_PAD_NAND_DATA06__RAWNAND_DATA06 0x0168 0x04B0 0x0000 0x0 0x0 #define MX6SX_PAD_NAND_DATA06__USDHC2_DATA6 0x0168 0x04B0 0x0000 0x1 0x0 #define MX6SX_PAD_NAND_DATA06__QSPI2_A_SS1_B 0x0168 0x04B0 0x0000 0x2 0x0 -#define MX6SX_PAD_NAND_DATA06__UART3_RX 0x0168 0x04B0 0x0840 0x3 0x0 -#define MX6SX_PAD_NAND_DATA06__UART3_TX 0x0168 0x04B0 0x0000 0x3 0x0 +#define MX6SX_PAD_NAND_DATA06__UART3_DCE_RX 0x0168 0x04B0 0x0840 0x3 0x0 +#define MX6SX_PAD_NAND_DATA06__UART3_DTE_TX 0x0168 0x04B0 0x0000 0x3 0x0 #define MX6SX_PAD_NAND_DATA06__PWM3_OUT 0x0168 0x04B0 0x0000 0x4 0x0 #define MX6SX_PAD_NAND_DATA06__GPIO4_IO_10 0x0168 0x04B0 0x0000 0x5 0x0 #define MX6SX_PAD_NAND_DATA06__WEIM_AD_6 0x0168 0x04B0 0x0000 0x6 0x0 @@ -846,8 +846,8 @@ #define MX6SX_PAD_NAND_DATA07__RAWNAND_DATA07 0x016C 0x04B4 0x0000 0x0 0x0 #define MX6SX_PAD_NAND_DATA07__USDHC2_DATA7 0x016C 0x04B4 0x0000 0x1 0x0 #define MX6SX_PAD_NAND_DATA07__QSPI2_A_DQS 0x016C 0x04B4 0x0000 0x2 0x0 -#define MX6SX_PAD_NAND_DATA07__UART3_RX 0x016C 0x04B4 0x0840 0x3 0x1 -#define MX6SX_PAD_NAND_DATA07__UART3_TX 0x016C 0x04B4 0x0000 0x3 0x0 +#define MX6SX_PAD_NAND_DATA07__UART3_DCE_TX 0x016C 0x04B4 0x0000 0x3 0x0 +#define MX6SX_PAD_NAND_DATA07__UART3_DTE_RX 0x016C 0x04B4 0x0840 0x3 0x1 #define MX6SX_PAD_NAND_DATA07__PWM4_OUT 0x016C 0x04B4 0x0000 0x4 0x0 #define MX6SX_PAD_NAND_DATA07__GPIO4_IO_11 0x016C 0x04B4 0x0000 0x5 0x0 #define MX6SX_PAD_NAND_DATA07__WEIM_AD_7 0x016C 0x04B4 0x0000 0x6 0x0 @@ -967,7 +967,7 @@ #define MX6SX_PAD_QSPI1A_SS1_B__SIM_M_HADDR_12 0x019C 0x04E4 0x0000 0x7 0x0 #define MX6SX_PAD_QSPI1A_SS1_B__SDMA_DEBUG_PC_3 0x019C 0x04E4 0x0000 0x9 0x0 #define MX6SX_PAD_QSPI1B_DATA0__QSPI1_B_DATA_0 0x01A0 0x04E8 0x0000 0x0 0x0 -#define MX6SX_PAD_QSPI1B_DATA0__UART3_CTS_B 0x01A0 0x04E8 0x0000 0x1 0x0 +#define MX6SX_PAD_QSPI1B_DATA0__UART3_DCE_CTS 0x01A0 0x04E8 0x0000 0x1 0x0 #define MX6SX_PAD_QSPI1B_DATA0__ECSPI3_MOSI 0x01A0 0x04E8 0x0738 0x2 0x1 #define MX6SX_PAD_QSPI1B_DATA0__ESAI_RX_FS 0x01A0 0x04E8 0x0778 0x3 0x2 #define MX6SX_PAD_QSPI1B_DATA0__CSI1_DATA_22 0x01A0 0x04E8 0x06F4 0x4 0x1 @@ -975,7 +975,7 @@ #define MX6SX_PAD_QSPI1B_DATA0__WEIM_DATA_14 0x01A0 0x04E8 0x0000 0x6 0x0 #define MX6SX_PAD_QSPI1B_DATA0__SIM_M_HADDR_9 0x01A0 0x04E8 0x0000 0x7 0x0 #define MX6SX_PAD_QSPI1B_DATA1__QSPI1_B_DATA_1 0x01A4 0x04EC 0x0000 0x0 0x0 -#define MX6SX_PAD_QSPI1B_DATA1__UART3_RTS_B 0x01A4 0x04EC 0x083C 0x1 0x5 +#define MX6SX_PAD_QSPI1B_DATA1__UART3_DCE_RTS 0x01A4 0x04EC 0x083C 0x1 0x5 #define MX6SX_PAD_QSPI1B_DATA1__ECSPI3_MISO 0x01A4 0x04EC 0x0734 0x2 0x1 #define MX6SX_PAD_QSPI1B_DATA1__ESAI_RX_CLK 0x01A4 0x04EC 0x0788 0x3 0x2 #define MX6SX_PAD_QSPI1B_DATA1__CSI1_DATA_21 0x01A4 0x04EC 0x06F0 0x4 0x1 @@ -1007,8 +1007,8 @@ #define MX6SX_PAD_QSPI1B_DQS__WEIM_DATA_15 0x01B0 0x04F8 0x0000 0x6 0x0 #define MX6SX_PAD_QSPI1B_DQS__SIM_M_HADDR_15 0x01B0 0x04F8 0x0000 0x7 0x0 #define MX6SX_PAD_QSPI1B_SCLK__QSPI1_B_SCLK 0x01B4 0x04FC 0x0000 0x0 0x0 -#define MX6SX_PAD_QSPI1B_SCLK__UART3_RX 0x01B4 0x04FC 0x0840 0x1 0x4 -#define MX6SX_PAD_QSPI1B_SCLK__UART3_TX 0x01B4 0x04FC 0x0000 0x0 0x0 +#define MX6SX_PAD_QSPI1B_SCLK__UART3_DCE_RX 0x01B4 0x04FC 0x0840 0x1 0x4 +#define MX6SX_PAD_QSPI1B_SCLK__UART3_DTE_TX 0x01B4 0x04FC 0x0000 0x0 0x0 #define MX6SX_PAD_QSPI1B_SCLK__ECSPI3_SCLK 0x01B4 0x04FC 0x0730 0x2 0x1 #define MX6SX_PAD_QSPI1B_SCLK__ESAI_RX_HF_CLK 0x01B4 0x04FC 0x0780 0x3 0x2 #define MX6SX_PAD_QSPI1B_SCLK__CSI1_DATA_16 0x01B4 0x04FC 0x06DC 0x4 0x1 @@ -1016,8 +1016,8 @@ #define MX6SX_PAD_QSPI1B_SCLK__WEIM_DATA_8 0x01B4 0x04FC 0x0000 0x6 0x0 #define MX6SX_PAD_QSPI1B_SCLK__SIM_M_HADDR_11 0x01B4 0x04FC 0x0000 0x7 0x0 #define MX6SX_PAD_QSPI1B_SS0_B__QSPI1_B_SS0_B 0x01B8 0x0500 0x0000 0x0 0x0 -#define MX6SX_PAD_QSPI1B_SS0_B__UART3_RX 0x01B8 0x0500 0x0840 0x1 0x5 -#define MX6SX_PAD_QSPI1B_SS0_B__UART3_TX 0x01B8 0x0500 0x0000 0x1 0x0 +#define MX6SX_PAD_QSPI1B_SS0_B__UART3_DCE_TX 0x01B8 0x0500 0x0000 0x1 0x0 +#define MX6SX_PAD_QSPI1B_SS0_B__UART3_DTE_RX 0x01B8 0x0500 0x0840 0x1 0x5 #define MX6SX_PAD_QSPI1B_SS0_B__ECSPI3_SS0 0x01B8 0x0500 0x073C 0x2 0x1 #define MX6SX_PAD_QSPI1B_SS0_B__ESAI_TX_HF_CLK 0x01B8 0x0500 0x0784 0x3 0x3 #define MX6SX_PAD_QSPI1B_SS0_B__CSI1_DATA_17 0x01B8 0x0500 0x06E0 0x4 0x1 @@ -1224,8 +1224,8 @@ #define MX6SX_PAD_SD1_DATA0__AUDMUX_AUD5_RXD 0x0228 0x0570 0x065C 0x1 0x1 #define MX6SX_PAD_SD1_DATA0__CAAM_WRAPPER_RNG_OSC_OBS 0x0228 0x0570 0x0000 0x2 0x0 #define MX6SX_PAD_SD1_DATA0__GPT_CAPTURE1 0x0228 0x0570 0x0000 0x3 0x0 -#define MX6SX_PAD_SD1_DATA0__UART2_RX 0x0228 0x0570 0x0838 0x4 0x2 -#define MX6SX_PAD_SD1_DATA0__UART2_TX 0x0228 0x0570 0x0000 0x4 0x0 +#define MX6SX_PAD_SD1_DATA0__UART2_DCE_RX 0x0228 0x0570 0x0838 0x4 0x2 +#define MX6SX_PAD_SD1_DATA0__UART2_DTE_TX 0x0228 0x0570 0x0000 0x4 0x0 #define MX6SX_PAD_SD1_DATA0__GPIO6_IO_2 0x0228 0x0570 0x0000 0x5 0x0 #define MX6SX_PAD_SD1_DATA0__ENET1_1588_EVENT1_IN 0x0228 0x0570 0x0000 0x6 0x0 #define MX6SX_PAD_SD1_DATA0__CCM_OUT2 0x0228 0x0570 0x0000 0x7 0x0 @@ -1235,8 +1235,8 @@ #define MX6SX_PAD_SD1_DATA1__AUDMUX_AUD5_TXC 0x022C 0x0574 0x066C 0x1 0x1 #define MX6SX_PAD_SD1_DATA1__PWM4_OUT 0x022C 0x0574 0x0000 0x2 0x0 #define MX6SX_PAD_SD1_DATA1__GPT_CAPTURE2 0x022C 0x0574 0x0000 0x3 0x0 -#define MX6SX_PAD_SD1_DATA1__UART2_RX 0x022C 0x0574 0x0838 0x4 0x3 -#define MX6SX_PAD_SD1_DATA1__UART2_TX 0x022C 0x0574 0x0000 0x4 0x0 +#define MX6SX_PAD_SD1_DATA1__UART2_DCE_TX 0x022C 0x0574 0x0000 0x4 0x0 +#define MX6SX_PAD_SD1_DATA1__UART2_DTE_RX 0x022C 0x0574 0x0838 0x4 0x3 #define MX6SX_PAD_SD1_DATA1__GPIO6_IO_3 0x022C 0x0574 0x0000 0x5 0x0 #define MX6SX_PAD_SD1_DATA1__ENET1_1588_EVENT1_OUT 0x022C 0x0574 0x0000 0x6 0x0 #define MX6SX_PAD_SD1_DATA1__CCM_CLKO2 0x022C 0x0574 0x0000 0x7 0x0 @@ -1246,7 +1246,7 @@ #define MX6SX_PAD_SD1_DATA2__AUDMUX_AUD5_TXFS 0x0230 0x0578 0x0670 0x1 0x1 #define MX6SX_PAD_SD1_DATA2__PWM3_OUT 0x0230 0x0578 0x0000 0x2 0x0 #define MX6SX_PAD_SD1_DATA2__GPT_COMPARE2 0x0230 0x0578 0x0000 0x3 0x0 -#define MX6SX_PAD_SD1_DATA2__UART2_CTS_B 0x0230 0x0578 0x0000 0x4 0x0 +#define MX6SX_PAD_SD1_DATA2__UART2_DCE_CTS 0x0230 0x0578 0x0000 0x4 0x0 #define MX6SX_PAD_SD1_DATA2__GPIO6_IO_4 0x0230 0x0578 0x0000 0x5 0x0 #define MX6SX_PAD_SD1_DATA2__ECSPI4_RDY 0x0230 0x0578 0x0000 0x6 0x0 #define MX6SX_PAD_SD1_DATA2__CCM_OUT0 0x0230 0x0578 0x0000 0x7 0x0 @@ -1255,7 +1255,7 @@ #define MX6SX_PAD_SD1_DATA3__AUDMUX_AUD5_TXD 0x0234 0x057C 0x0660 0x1 0x1 #define MX6SX_PAD_SD1_DATA3__AUDMUX_AUD5_RXD 0x0234 0x057C 0x065C 0x2 0x2 #define MX6SX_PAD_SD1_DATA3__GPT_COMPARE3 0x0234 0x057C 0x0000 0x3 0x0 -#define MX6SX_PAD_SD1_DATA3__UART2_RTS_B 0x0234 0x057C 0x0834 0x4 0x3 +#define MX6SX_PAD_SD1_DATA3__UART2_DCE_RTS 0x0234 0x057C 0x0834 0x4 0x3 #define MX6SX_PAD_SD1_DATA3__GPIO6_IO_5 0x0234 0x057C 0x0000 0x5 0x0 #define MX6SX_PAD_SD1_DATA3__ECSPI4_SS1 0x0234 0x057C 0x0000 0x6 0x0 #define MX6SX_PAD_SD1_DATA3__CCM_PMIC_RDY 0x0234 0x057C 0x069C 0x7 0x2 @@ -1287,8 +1287,8 @@ #define MX6SX_PAD_SD2_DATA0__I2C4_SDA 0x0240 0x0588 0x07C4 0x4 0x3 #define MX6SX_PAD_SD2_DATA0__GPIO6_IO_8 0x0240 0x0588 0x0000 0x5 0x0 #define MX6SX_PAD_SD2_DATA0__ECSPI4_SS3 0x0240 0x0588 0x0000 0x6 0x0 -#define MX6SX_PAD_SD2_DATA0__UART4_RX 0x0240 0x0588 0x0848 0x7 0x4 -#define MX6SX_PAD_SD2_DATA0__UART4_TX 0x0240 0x0588 0x0000 0x7 0x0 +#define MX6SX_PAD_SD2_DATA0__UART4_DCE_RX 0x0240 0x0588 0x0848 0x7 0x4 +#define MX6SX_PAD_SD2_DATA0__UART4_DTE_TX 0x0240 0x0588 0x0000 0x7 0x0 #define MX6SX_PAD_SD2_DATA0__VADC_CLAMP_CURRENT_0 0x0240 0x0588 0x0000 0x8 0x0 #define MX6SX_PAD_SD2_DATA0__MMDC_DEBUG_50 0x0240 0x0588 0x0000 0x9 0x0 #define MX6SX_PAD_SD2_DATA1__USDHC2_DATA1 0x0244 0x058C 0x0000 0x0 0x0 @@ -1298,8 +1298,8 @@ #define MX6SX_PAD_SD2_DATA1__I2C4_SCL 0x0244 0x058C 0x07C0 0x4 0x3 #define MX6SX_PAD_SD2_DATA1__GPIO6_IO_9 0x0244 0x058C 0x0000 0x5 0x0 #define MX6SX_PAD_SD2_DATA1__ECSPI4_SS2 0x0244 0x058C 0x0000 0x6 0x0 -#define MX6SX_PAD_SD2_DATA1__UART4_RX 0x0244 0x058C 0x0848 0x7 0x5 -#define MX6SX_PAD_SD2_DATA1__UART4_TX 0x0244 0x058C 0x0000 0x7 0x0 +#define MX6SX_PAD_SD2_DATA1__UART4_DCE_TX 0x0244 0x058C 0x0000 0x7 0x0 +#define MX6SX_PAD_SD2_DATA1__UART4_DTE_RX 0x0244 0x058C 0x0848 0x7 0x5 #define MX6SX_PAD_SD2_DATA1__VADC_CLAMP_CURRENT_1 0x0244 0x058C 0x0000 0x8 0x0 #define MX6SX_PAD_SD2_DATA1__MMDC_DEBUG_49 0x0244 0x058C 0x0000 0x9 0x0 #define MX6SX_PAD_SD2_DATA2__USDHC2_DATA2 0x0248 0x0590 0x0000 0x0 0x0 @@ -1309,8 +1309,8 @@ #define MX6SX_PAD_SD2_DATA2__SDMA_EXT_EVENT_0 0x0248 0x0590 0x081C 0x4 0x2 #define MX6SX_PAD_SD2_DATA2__GPIO6_IO_10 0x0248 0x0590 0x0000 0x5 0x0 #define MX6SX_PAD_SD2_DATA2__SPDIF_OUT 0x0248 0x0590 0x0000 0x6 0x0 -#define MX6SX_PAD_SD2_DATA2__UART6_RX 0x0248 0x0590 0x0858 0x7 0x4 -#define MX6SX_PAD_SD2_DATA2__UART6_TX 0x0248 0x0590 0x0000 0x7 0x0 +#define MX6SX_PAD_SD2_DATA2__UART6_DCE_RX 0x0248 0x0590 0x0858 0x7 0x4 +#define MX6SX_PAD_SD2_DATA2__UART6_DTE_TX 0x0248 0x0590 0x0000 0x7 0x0 #define MX6SX_PAD_SD2_DATA2__VADC_CLAMP_CURRENT_2 0x0248 0x0590 0x0000 0x8 0x0 #define MX6SX_PAD_SD2_DATA2__MMDC_DEBUG_32 0x0248 0x0590 0x0000 0x9 0x0 #define MX6SX_PAD_SD2_DATA3__USDHC2_DATA3 0x024C 0x0594 0x0000 0x0 0x0 @@ -1320,12 +1320,12 @@ #define MX6SX_PAD_SD2_DATA3__MLB_DATA 0x024C 0x0594 0x07EC 0x4 0x2 #define MX6SX_PAD_SD2_DATA3__GPIO6_IO_11 0x024C 0x0594 0x0000 0x5 0x0 #define MX6SX_PAD_SD2_DATA3__SPDIF_IN 0x024C 0x0594 0x0824 0x6 0x4 -#define MX6SX_PAD_SD2_DATA3__UART6_RX 0x024C 0x0594 0x0858 0x7 0x5 -#define MX6SX_PAD_SD2_DATA3__UART6_TX 0x024C 0x0594 0x0000 0x7 0x0 +#define MX6SX_PAD_SD2_DATA3__UART6_DCE_TX 0x024C 0x0594 0x0000 0x7 0x0 +#define MX6SX_PAD_SD2_DATA3__UART6_DTE_RX 0x024C 0x0594 0x0858 0x7 0x5 #define MX6SX_PAD_SD2_DATA3__VADC_CLAMP_CURRENT_3 0x024C 0x0594 0x0000 0x8 0x0 #define MX6SX_PAD_SD2_DATA3__MMDC_DEBUG_31 0x024C 0x0594 0x0000 0x9 0x0 #define MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x0250 0x0598 0x0000 0x0 0x0 -#define MX6SX_PAD_SD3_CLK__UART4_CTS_B 0x0250 0x0598 0x0000 0x1 0x0 +#define MX6SX_PAD_SD3_CLK__UART4_DCE_CTS 0x0250 0x0598 0x0000 0x1 0x0 #define MX6SX_PAD_SD3_CLK__ECSPI4_SCLK 0x0250 0x0598 0x0740 0x2 0x0 #define MX6SX_PAD_SD3_CLK__AUDMUX_AUD6_RXFS 0x0250 0x0598 0x0680 0x3 0x0 #define MX6SX_PAD_SD3_CLK__LCDIF2_VSYNC 0x0250 0x0598 0x0000 0x4 0x0 @@ -1334,8 +1334,8 @@ #define MX6SX_PAD_SD3_CLK__TPSMP_HDATA_29 0x0250 0x0598 0x0000 0x7 0x0 #define MX6SX_PAD_SD3_CLK__SDMA_DEBUG_EVENT_CHANNEL_5 0x0250 0x0598 0x0000 0x9 0x0 #define MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x0254 0x059C 0x0000 0x0 0x0 -#define MX6SX_PAD_SD3_CMD__UART4_RX 0x0254 0x059C 0x0848 0x1 0x0 -#define MX6SX_PAD_SD3_CMD__UART4_TX 0x0254 0x059C 0x0000 0x1 0x0 +#define MX6SX_PAD_SD3_CMD__UART4_DCE_TX 0x0254 0x059C 0x0000 0x1 0x0 +#define MX6SX_PAD_SD3_CMD__UART4_DTE_RX 0x0254 0x059C 0x0848 0x1 0x0 #define MX6SX_PAD_SD3_CMD__ECSPI4_MOSI 0x0254 0x059C 0x0748 0x2 0x0 #define MX6SX_PAD_SD3_CMD__AUDMUX_AUD6_RXC 0x0254 0x059C 0x067C 0x3 0x0 #define MX6SX_PAD_SD3_CMD__LCDIF2_HSYNC 0x0254 0x059C 0x07E4 0x4 0x1 @@ -1364,7 +1364,7 @@ #define MX6SX_PAD_SD3_DATA1__GPU_DEBUG_1 0x025C 0x05A4 0x0000 0x8 0x0 #define MX6SX_PAD_SD3_DATA1__SDMA_DEBUG_EVT_CHN_LINES_1 0x025C 0x05A4 0x0000 0x9 0x0 #define MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x0260 0x05A8 0x0000 0x0 0x0 -#define MX6SX_PAD_SD3_DATA2__UART4_RTS_B 0x0260 0x05A8 0x0844 0x1 0x1 +#define MX6SX_PAD_SD3_DATA2__UART4_DCE_RTS 0x0260 0x05A8 0x0844 0x1 0x1 #define MX6SX_PAD_SD3_DATA2__ECSPI4_SS0 0x0260 0x05A8 0x074C 0x2 0x0 #define MX6SX_PAD_SD3_DATA2__AUDMUX_AUD6_TXFS 0x0260 0x05A8 0x0688 0x3 0x0 #define MX6SX_PAD_SD3_DATA2__LCDIF2_CLK 0x0260 0x05A8 0x0000 0x4 0x0 @@ -1374,8 +1374,8 @@ #define MX6SX_PAD_SD3_DATA2__GPU_DEBUG_2 0x0260 0x05A8 0x0000 0x8 0x0 #define MX6SX_PAD_SD3_DATA2__SDMA_DEBUG_EVENT_CHANNEL_2 0x0260 0x05A8 0x0000 0x9 0x0 #define MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x0264 0x05AC 0x0000 0x0 0x0 -#define MX6SX_PAD_SD3_DATA3__UART4_RX 0x0264 0x05AC 0x0848 0x1 0x1 -#define MX6SX_PAD_SD3_DATA3__UART4_TX 0x0264 0x05AC 0x0000 0x1 0x0 +#define MX6SX_PAD_SD3_DATA3__UART4_DCE_RX 0x0264 0x05AC 0x0848 0x1 0x1 +#define MX6SX_PAD_SD3_DATA3__UART4_DTE_TX 0x0264 0x05AC 0x0000 0x1 0x0 #define MX6SX_PAD_SD3_DATA3__ECSPI4_MISO 0x0264 0x05AC 0x0744 0x2 0x0 #define MX6SX_PAD_SD3_DATA3__AUDMUX_AUD6_TXD 0x0264 0x05AC 0x0678 0x3 0x0 #define MX6SX_PAD_SD3_DATA3__LCDIF2_ENABLE 0x0264 0x05AC 0x0000 0x4 0x0 @@ -1387,8 +1387,8 @@ #define MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x0268 0x05B0 0x0000 0x0 0x0 #define MX6SX_PAD_SD3_DATA4__CAN2_RX 0x0268 0x05B0 0x0690 0x1 0x0 #define MX6SX_PAD_SD3_DATA4__CANFD_RX2 0x0268 0x05B0 0x0698 0x2 0x0 -#define MX6SX_PAD_SD3_DATA4__UART3_RX 0x0268 0x05B0 0x0840 0x3 0x2 -#define MX6SX_PAD_SD3_DATA4__UART3_TX 0x0268 0x05B0 0x0000 0x3 0x0 +#define MX6SX_PAD_SD3_DATA4__UART3_DCE_RX 0x0268 0x05B0 0x0840 0x3 0x2 +#define MX6SX_PAD_SD3_DATA4__UART3_DTE_TX 0x0268 0x05B0 0x0000 0x3 0x0 #define MX6SX_PAD_SD3_DATA4__LCDIF2_DATA_3 0x0268 0x05B0 0x0000 0x4 0x0 #define MX6SX_PAD_SD3_DATA4__GPIO7_IO_6 0x0268 0x05B0 0x0000 0x5 0x0 #define MX6SX_PAD_SD3_DATA4__ENET2_1588_EVENT0_IN 0x0268 0x05B0 0x0000 0x6 0x0 @@ -1398,8 +1398,8 @@ #define MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x026C 0x05B4 0x0000 0x0 0x0 #define MX6SX_PAD_SD3_DATA5__CAN1_TX 0x026C 0x05B4 0x0000 0x1 0x0 #define MX6SX_PAD_SD3_DATA5__CANFD_TX1 0x026C 0x05B4 0x0000 0x2 0x0 -#define MX6SX_PAD_SD3_DATA5__UART3_RX 0x026C 0x05B4 0x0840 0x3 0x3 -#define MX6SX_PAD_SD3_DATA5__UART3_TX 0x026C 0x05B4 0x0000 0x3 0x0 +#define MX6SX_PAD_SD3_DATA5__UART3_DCE_TX 0x026C 0x05B4 0x0000 0x3 0x0 +#define MX6SX_PAD_SD3_DATA5__UART3_DTE_RX 0x026C 0x05B4 0x0840 0x3 0x3 #define MX6SX_PAD_SD3_DATA5__LCDIF2_DATA_2 0x026C 0x05B4 0x0000 0x4 0x0 #define MX6SX_PAD_SD3_DATA5__GPIO7_IO_7 0x026C 0x05B4 0x0000 0x5 0x0 #define MX6SX_PAD_SD3_DATA5__ENET2_1588_EVENT0_OUT 0x026C 0x05B4 0x0000 0x6 0x0 @@ -1409,7 +1409,7 @@ #define MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x0270 0x05B8 0x0000 0x0 0x0 #define MX6SX_PAD_SD3_DATA6__CAN2_TX 0x0270 0x05B8 0x0000 0x1 0x0 #define MX6SX_PAD_SD3_DATA6__CANFD_TX2 0x0270 0x05B8 0x0000 0x2 0x0 -#define MX6SX_PAD_SD3_DATA6__UART3_RTS_B 0x0270 0x05B8 0x083C 0x3 0x2 +#define MX6SX_PAD_SD3_DATA6__UART3_DCE_RTS 0x0270 0x05B8 0x083C 0x3 0x2 #define MX6SX_PAD_SD3_DATA6__LCDIF2_DATA_4 0x0270 0x05B8 0x0000 0x4 0x0 #define MX6SX_PAD_SD3_DATA6__GPIO7_IO_8 0x0270 0x05B8 0x0000 0x5 0x0 #define MX6SX_PAD_SD3_DATA6__ENET1_1588_EVENT0_OUT 0x0270 0x05B8 0x0000 0x6 0x0 @@ -1419,7 +1419,7 @@ #define MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x0274 0x05BC 0x0000 0x0 0x0 #define MX6SX_PAD_SD3_DATA7__CAN1_RX 0x0274 0x05BC 0x068C 0x1 0x0 #define MX6SX_PAD_SD3_DATA7__CANFD_RX1 0x0274 0x05BC 0x0694 0x2 0x0 -#define MX6SX_PAD_SD3_DATA7__UART3_CTS_B 0x0274 0x05BC 0x0000 0x3 0x0 +#define MX6SX_PAD_SD3_DATA7__UART3_DCE_CTS 0x0274 0x05BC 0x0000 0x3 0x0 #define MX6SX_PAD_SD3_DATA7__LCDIF2_DATA_5 0x0274 0x05BC 0x0000 0x4 0x0 #define MX6SX_PAD_SD3_DATA7__GPIO7_IO_9 0x0274 0x05BC 0x0000 0x5 0x0 #define MX6SX_PAD_SD3_DATA7__ENET1_1588_EVENT0_IN 0x0274 0x05BC 0x0000 0x6 0x0 @@ -1488,8 +1488,8 @@ #define MX6SX_PAD_SD4_DATA3__SDMA_DEBUG_MATCHED_DMBUS 0x028C 0x05D4 0x0000 0x9 0x0 #define MX6SX_PAD_SD4_DATA4__USDHC4_DATA4 0x0290 0x05D8 0x0000 0x0 0x0 #define MX6SX_PAD_SD4_DATA4__RAWNAND_DATA09 0x0290 0x05D8 0x0000 0x1 0x0 -#define MX6SX_PAD_SD4_DATA4__UART5_RX 0x0290 0x05D8 0x0850 0x2 0x0 -#define MX6SX_PAD_SD4_DATA4__UART5_TX 0x0290 0x05D8 0x0000 0x2 0x0 +#define MX6SX_PAD_SD4_DATA4__UART5_DCE_RX 0x0290 0x05D8 0x0850 0x2 0x0 +#define MX6SX_PAD_SD4_DATA4__UART5_DTE_TX 0x0290 0x05D8 0x0000 0x2 0x0 #define MX6SX_PAD_SD4_DATA4__ECSPI3_SCLK 0x0290 0x05D8 0x0730 0x3 0x0 #define MX6SX_PAD_SD4_DATA4__LCDIF2_DATA_8 0x0290 0x05D8 0x0000 0x4 0x0 #define MX6SX_PAD_SD4_DATA4__GPIO6_IO_18 0x0290 0x05D8 0x0000 0x5 0x0 @@ -1499,8 +1499,8 @@ #define MX6SX_PAD_SD4_DATA4__SDMA_DEBUG_RTBUFFER_WRITE 0x0290 0x05D8 0x0000 0x9 0x0 #define MX6SX_PAD_SD4_DATA5__USDHC4_DATA5 0x0294 0x05DC 0x0000 0x0 0x0 #define MX6SX_PAD_SD4_DATA5__RAWNAND_CE2_B 0x0294 0x05DC 0x0000 0x1 0x0 -#define MX6SX_PAD_SD4_DATA5__UART5_RX 0x0294 0x05DC 0x0850 0x2 0x1 -#define MX6SX_PAD_SD4_DATA5__UART5_TX 0x0294 0x05DC 0x0000 0x2 0x0 +#define MX6SX_PAD_SD4_DATA5__UART5_DCE_TX 0x0294 0x05DC 0x0000 0x2 0x0 +#define MX6SX_PAD_SD4_DATA5__UART5_DTE_RX 0x0294 0x05DC 0x0850 0x2 0x1 #define MX6SX_PAD_SD4_DATA5__ECSPI3_MOSI 0x0294 0x05DC 0x0738 0x3 0x0 #define MX6SX_PAD_SD4_DATA5__LCDIF2_DATA_7 0x0294 0x05DC 0x0000 0x4 0x0 #define MX6SX_PAD_SD4_DATA5__GPIO6_IO_19 0x0294 0x05DC 0x0000 0x5 0x0 @@ -1510,7 +1510,7 @@ #define MX6SX_PAD_SD4_DATA5__SDMA_DEBUG_EVENT_CHANNEL_0 0x0294 0x05DC 0x0000 0x9 0x0 #define MX6SX_PAD_SD4_DATA6__USDHC4_DATA6 0x0298 0x05E0 0x0000 0x0 0x0 #define MX6SX_PAD_SD4_DATA6__RAWNAND_CE3_B 0x0298 0x05E0 0x0000 0x1 0x0 -#define MX6SX_PAD_SD4_DATA6__UART5_RTS_B 0x0298 0x05E0 0x084C 0x2 0x0 +#define MX6SX_PAD_SD4_DATA6__UART5_DCE_RTS 0x0298 0x05E0 0x084C 0x2 0x0 #define MX6SX_PAD_SD4_DATA6__ECSPI3_MISO 0x0298 0x05E0 0x0734 0x3 0x0 #define MX6SX_PAD_SD4_DATA6__LCDIF2_DATA_6 0x0298 0x05E0 0x0000 0x4 0x0 #define MX6SX_PAD_SD4_DATA6__GPIO6_IO_20 0x0298 0x05E0 0x0000 0x5 0x0 @@ -1520,7 +1520,7 @@ #define MX6SX_PAD_SD4_DATA6__SDMA_DEBUG_EVENT_CHANNEL_1 0x0298 0x05E0 0x0000 0x9 0x0 #define MX6SX_PAD_SD4_DATA7__USDHC4_DATA7 0x029C 0x05E4 0x0000 0x0 0x0 #define MX6SX_PAD_SD4_DATA7__RAWNAND_DATA08 0x029C 0x05E4 0x0000 0x1 0x0 -#define MX6SX_PAD_SD4_DATA7__UART5_CTS_B 0x029C 0x05E4 0x0000 0x2 0x0 +#define MX6SX_PAD_SD4_DATA7__UART5_DCE_CTS 0x029C 0x05E4 0x0000 0x2 0x0 #define MX6SX_PAD_SD4_DATA7__ECSPI3_SS0 0x029C 0x05E4 0x073C 0x3 0x0 #define MX6SX_PAD_SD4_DATA7__LCDIF2_DATA_15 0x029C 0x05E4 0x0000 0x4 0x0 #define MX6SX_PAD_SD4_DATA7__GPIO6_IO_21 0x029C 0x05E4 0x0000 0x5 0x0 @@ -1551,4 +1551,92 @@ #define MX6SX_PAD_USB_H_STROBE__WDOG3_WDOG_RST_B_DEB 0x02A8 0x05F0 0x0000 0x4 0x0 #define MX6SX_PAD_USB_H_STROBE__GPIO7_IO_11 0x02A8 0x05F0 0x0000 0x5 0x0 +/* these are not supposed to be used any more and remove them after some time */ +#define MX6SX_PAD_GPIO1_IO04__UART1_RX MX6SX_PAD_GPIO1_IO04__UART1_DTE_RX +#define MX6SX_PAD_GPIO1_IO04__UART1_TX MX6SX_PAD_GPIO1_IO04__UART1_DCE_TX +#define MX6SX_PAD_GPIO1_IO05__UART1_RX MX6SX_PAD_GPIO1_IO05__UART1_DCE_RX +#define MX6SX_PAD_GPIO1_IO05__UART1_TX MX6SX_PAD_GPIO1_IO05__UART1_DTE_TX +#define MX6SX_PAD_GPIO1_IO06__UART2_RX MX6SX_PAD_GPIO1_IO06__UART2_DTE_RX +#define MX6SX_PAD_GPIO1_IO06__UART2_TX MX6SX_PAD_GPIO1_IO06__UART2_DCE_TX +#define MX6SX_PAD_GPIO1_IO06__UART1_RTS_B MX6SX_PAD_GPIO1_IO06__UART1_DCE_RTS +#define MX6SX_PAD_GPIO1_IO07__UART2_RX MX6SX_PAD_GPIO1_IO07__UART2_DCE_RX +#define MX6SX_PAD_GPIO1_IO07__UART2_TX MX6SX_PAD_GPIO1_IO07__UART2_DTE_TX +#define MX6SX_PAD_GPIO1_IO07__UART1_CTS_B MX6SX_PAD_GPIO1_IO07__UART1_DCE_CTS +#define MX6SX_PAD_GPIO1_IO08__UART2_RTS_B MX6SX_PAD_GPIO1_IO08__UART2_DCE_RTS +#define MX6SX_PAD_GPIO1_IO09__UART2_CTS_B MX6SX_PAD_GPIO1_IO09__UART2_DCE_CTS +#define MX6SX_PAD_CSI_DATA04__UART6_RX MX6SX_PAD_CSI_DATA04__UART6_DCE_RX +#define MX6SX_PAD_CSI_DATA04__UART6_TX MX6SX_PAD_CSI_DATA04__UART6_DTE_TX +#define MX6SX_PAD_CSI_DATA05__UART6_RX MX6SX_PAD_CSI_DATA05__UART6_DTE_RX +#define MX6SX_PAD_CSI_DATA05__UART6_TX MX6SX_PAD_CSI_DATA05__UART6_DCE_TX +#define MX6SX_PAD_CSI_DATA06__UART6_RTS_B MX6SX_PAD_CSI_DATA06__UART6_DCE_RTS +#define MX6SX_PAD_CSI_DATA07__UART6_CTS_B MX6SX_PAD_CSI_DATA07__UART6_DCE_CTS +#define MX6SX_PAD_CSI_HSYNC__UART4_RTS_B MX6SX_PAD_CSI_HSYNC__UART4_DCE_RTS +#define MX6SX_PAD_CSI_MCLK__UART4_RX MX6SX_PAD_CSI_MCLK__UART4_DCE_RX +#define MX6SX_PAD_CSI_MCLK__UART4_TX MX6SX_PAD_CSI_MCLK__UART4_DTE_TX +#define MX6SX_PAD_CSI_PIXCLK__UART4_RX MX6SX_PAD_CSI_PIXCLK__UART4_DTE_RX +#define MX6SX_PAD_CSI_PIXCLK__UART4_TX MX6SX_PAD_CSI_PIXCLK__UART4_DCE_TX +#define MX6SX_PAD_CSI_VSYNC__UART4_CTS_B MX6SX_PAD_CSI_VSYNC__UART4_DCE_CTS +#define MX6SX_PAD_ENET2_COL__UART1_RX MX6SX_PAD_ENET2_COL__UART1_DCE_RX +#define MX6SX_PAD_ENET2_COL__UART1_TX MX6SX_PAD_ENET2_COL__UART1_DTE_TX +#define MX6SX_PAD_ENET2_CRS__UART1_RX MX6SX_PAD_ENET2_CRS__UART1_DTE_RX +#define MX6SX_PAD_ENET2_CRS__UART1_TX MX6SX_PAD_ENET2_CRS__UART1_DCE_TX +#define MX6SX_PAD_ENET2_RX_CLK__UART1_RTS_B MX6SX_PAD_ENET2_RX_CLK__UART1_DCE_RTS +#define MX6SX_PAD_ENET2_TX_CLK__UART1_CTS_B MX6SX_PAD_ENET2_TX_CLK__UART1_DCE_CTS +#define MX6SX_PAD_KEY_COL0__UART6_RTS_B MX6SX_PAD_KEY_COL0__UART6_DCE_RTS +#define MX6SX_PAD_KEY_COL1__UART6_RX MX6SX_PAD_KEY_COL1__UART6_DTE_RX +#define MX6SX_PAD_KEY_COL1__UART6_TX MX6SX_PAD_KEY_COL1__UART6_DCE_TX +#define MX6SX_PAD_KEY_COL2__UART5_RTS_B MX6SX_PAD_KEY_COL2__UART5_DCE_RTS +#define MX6SX_PAD_KEY_COL3__UART5_RX MX6SX_PAD_KEY_COL3__UART5_DTE_RX +#define MX6SX_PAD_KEY_COL3__UART5_TX MX6SX_PAD_KEY_COL3__UART5_DCE_TX +#define MX6SX_PAD_KEY_ROW0__UART6_CTS_B MX6SX_PAD_KEY_ROW0__UART6_DCE_CTS +#define MX6SX_PAD_KEY_ROW1__UART6_RX MX6SX_PAD_KEY_ROW1__UART6_DCE_RX +#define MX6SX_PAD_KEY_ROW1__UART6_TX MX6SX_PAD_KEY_ROW1__UART6_DTE_TX +#define MX6SX_PAD_KEY_ROW2__UART5_CTS_B MX6SX_PAD_KEY_ROW2__UART5_DCE_CTS +#define MX6SX_PAD_KEY_ROW3__UART5_RX MX6SX_PAD_KEY_ROW3__UART5_DCE_RX +#define MX6SX_PAD_KEY_ROW3__UART5_TX MX6SX_PAD_KEY_ROW3__UART5_DTE_TX +#define MX6SX_PAD_NAND_DATA04__UART3_RTS_B MX6SX_PAD_NAND_DATA04__UART3_DCE_RTS +#define MX6SX_PAD_NAND_DATA05__UART3_CTS_B MX6SX_PAD_NAND_DATA05__UART3_DCE_CTS +#define MX6SX_PAD_NAND_DATA06__UART3_RX MX6SX_PAD_NAND_DATA06__UART3_DCE_RX +#define MX6SX_PAD_NAND_DATA06__UART3_TX MX6SX_PAD_NAND_DATA06__UART3_DTE_TX +#define MX6SX_PAD_NAND_DATA07__UART3_RX MX6SX_PAD_NAND_DATA07__UART3_DTE_RX +#define MX6SX_PAD_NAND_DATA07__UART3_TX MX6SX_PAD_NAND_DATA07__UART3_DCE_TX +#define MX6SX_PAD_QSPI1B_DATA0__UART3_CTS_B MX6SX_PAD_QSPI1B_DATA0__UART3_DCE_CTS +#define MX6SX_PAD_QSPI1B_DATA1__UART3_RTS_B MX6SX_PAD_QSPI1B_DATA1__UART3_DCE_RTS +#define MX6SX_PAD_QSPI1B_SCLK__UART3_RX MX6SX_PAD_QSPI1B_SCLK__UART3_DCE_RX +#define MX6SX_PAD_QSPI1B_SCLK__UART3_TX MX6SX_PAD_QSPI1B_SCLK__UART3_DTE_TX +#define MX6SX_PAD_QSPI1B_SS0_B__UART3_RX MX6SX_PAD_QSPI1B_SS0_B__UART3_DTE_RX +#define MX6SX_PAD_QSPI1B_SS0_B__UART3_TX MX6SX_PAD_QSPI1B_SS0_B__UART3_DCE_TX +#define MX6SX_PAD_SD1_DATA0__UART2_RX MX6SX_PAD_SD1_DATA0__UART2_DCE_RX +#define MX6SX_PAD_SD1_DATA0__UART2_TX MX6SX_PAD_SD1_DATA0__UART2_DTE_TX +#define MX6SX_PAD_SD1_DATA1__UART2_RX MX6SX_PAD_SD1_DATA1__UART2_DTE_RX +#define MX6SX_PAD_SD1_DATA1__UART2_TX MX6SX_PAD_SD1_DATA1__UART2_DCE_TX +#define MX6SX_PAD_SD1_DATA2__UART2_CTS_B MX6SX_PAD_SD1_DATA2__UART2_DCE_CTS +#define MX6SX_PAD_SD1_DATA3__UART2_RTS_B MX6SX_PAD_SD1_DATA3__UART2_DCE_RTS +#define MX6SX_PAD_SD2_DATA0__UART4_RX MX6SX_PAD_SD2_DATA0__UART4_DCE_RX +#define MX6SX_PAD_SD2_DATA0__UART4_TX MX6SX_PAD_SD2_DATA0__UART4_DTE_TX +#define MX6SX_PAD_SD2_DATA1__UART4_RX MX6SX_PAD_SD2_DATA1__UART4_DTE_RX +#define MX6SX_PAD_SD2_DATA1__UART4_TX MX6SX_PAD_SD2_DATA1__UART4_DCE_TX +#define MX6SX_PAD_SD2_DATA2__UART6_RX MX6SX_PAD_SD2_DATA2__UART6_DCE_RX +#define MX6SX_PAD_SD2_DATA2__UART6_TX MX6SX_PAD_SD2_DATA2__UART6_DTE_TX +#define MX6SX_PAD_SD2_DATA3__UART6_RX MX6SX_PAD_SD2_DATA3__UART6_DTE_RX +#define MX6SX_PAD_SD2_DATA3__UART6_TX MX6SX_PAD_SD2_DATA3__UART6_DCE_TX +#define MX6SX_PAD_SD3_CLK__UART4_CTS_B MX6SX_PAD_SD3_CLK__UART4_DCE_CTS +#define MX6SX_PAD_SD3_CMD__UART4_RX MX6SX_PAD_SD3_CMD__UART4_DTE_RX +#define MX6SX_PAD_SD3_CMD__UART4_TX MX6SX_PAD_SD3_CMD__UART4_DCE_TX +#define MX6SX_PAD_SD3_DATA2__UART4_RTS_B MX6SX_PAD_SD3_DATA2__UART4_DCE_RTS +#define MX6SX_PAD_SD3_DATA3__UART4_RX MX6SX_PAD_SD3_DATA3__UART4_DCE_RX +#define MX6SX_PAD_SD3_DATA3__UART4_TX MX6SX_PAD_SD3_DATA3__UART4_DTE_TX +#define MX6SX_PAD_SD3_DATA4__UART3_RX MX6SX_PAD_SD3_DATA4__UART3_DCE_RX +#define MX6SX_PAD_SD3_DATA4__UART3_TX MX6SX_PAD_SD3_DATA4__UART3_DTE_TX +#define MX6SX_PAD_SD3_DATA5__UART3_RX MX6SX_PAD_SD3_DATA5__UART3_DTE_RX +#define MX6SX_PAD_SD3_DATA5__UART3_TX MX6SX_PAD_SD3_DATA5__UART3_DCE_TX +#define MX6SX_PAD_SD3_DATA6__UART3_RTS_B MX6SX_PAD_SD3_DATA6__UART3_DCE_RTS +#define MX6SX_PAD_SD3_DATA7__UART3_CTS_B MX6SX_PAD_SD3_DATA7__UART3_DCE_CTS +#define MX6SX_PAD_SD4_DATA4__UART5_RX MX6SX_PAD_SD4_DATA4__UART5_DCE_RX +#define MX6SX_PAD_SD4_DATA4__UART5_TX MX6SX_PAD_SD4_DATA4__UART5_DTE_TX +#define MX6SX_PAD_SD4_DATA5__UART5_RX MX6SX_PAD_SD4_DATA5__UART5_DTE_RX +#define MX6SX_PAD_SD4_DATA5__UART5_TX MX6SX_PAD_SD4_DATA5__UART5_DCE_TX +#define MX6SX_PAD_SD4_DATA6__UART5_RTS_B MX6SX_PAD_SD4_DATA6__UART5_DCE_RTS +#define MX6SX_PAD_SD4_DATA7__UART5_CTS_B MX6SX_PAD_SD4_DATA7__UART5_DCE_CTS + #endif /* __DTS_IMX6SX_PINFUNC_H */ From 02ce1ddcea58f0f0cc535ee0ada7fdafb699fdf2 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Mon, 17 Feb 2020 19:13:36 +0800 Subject: [PATCH 0430/4444] ARM: dts: imx6sx: Add missing UART RTS/CTS pins mux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of UART RTS/CTS pins' DCE/DTE mux function are missing, add them. Signed-off-by: Anson Huang Reviewed-by: Uwe Kleine-König Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sx-pinfunc.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/arm/boot/dts/imx6sx-pinfunc.h b/arch/arm/boot/dts/imx6sx-pinfunc.h index 9814db090487..0b02c7e60c17 100644 --- a/arch/arm/boot/dts/imx6sx-pinfunc.h +++ b/arch/arm/boot/dts/imx6sx-pinfunc.h @@ -66,6 +66,7 @@ #define MX6SX_PAD_GPIO1_IO06__ENET2_MDC 0x002C 0x0374 0x0000 0x2 0x0 #define MX6SX_PAD_GPIO1_IO06__CSI1_MCLK 0x002C 0x0374 0x0000 0x3 0x0 #define MX6SX_PAD_GPIO1_IO06__UART1_DCE_RTS 0x002C 0x0374 0x082C 0x4 0x0 +#define MX6SX_PAD_GPIO1_IO06__UART1_DTE_CTS 0x002C 0x0374 0x0000 0x4 0x0 #define MX6SX_PAD_GPIO1_IO06__GPIO1_IO_6 0x002C 0x0374 0x0000 0x5 0x0 #define MX6SX_PAD_GPIO1_IO06__SRC_ANY_PU_RESET 0x002C 0x0374 0x0000 0x6 0x0 #define MX6SX_PAD_GPIO1_IO06__OCOTP_CTRL_WRAPPER_FUSE_LATCHED 0x002C 0x0374 0x0000 0x7 0x0 @@ -75,6 +76,7 @@ #define MX6SX_PAD_GPIO1_IO07__ENET2_MDIO 0x0030 0x0378 0x0770 0x2 0x0 #define MX6SX_PAD_GPIO1_IO07__AUDMUX_MCLK 0x0030 0x0378 0x0000 0x3 0x0 #define MX6SX_PAD_GPIO1_IO07__UART1_DCE_CTS 0x0030 0x0378 0x0000 0x4 0x0 +#define MX6SX_PAD_GPIO1_IO07__UART1_DTE_RTS 0x0030 0x0378 0x082C 0x4 0x1 #define MX6SX_PAD_GPIO1_IO07__GPIO1_IO_7 0x0030 0x0378 0x0000 0x5 0x0 #define MX6SX_PAD_GPIO1_IO07__SRC_EARLY_RESET 0x0030 0x0378 0x0000 0x6 0x0 #define MX6SX_PAD_GPIO1_IO07__DCIC2_OUT 0x0030 0x0378 0x0000 0x7 0x0 @@ -84,6 +86,7 @@ #define MX6SX_PAD_GPIO1_IO08__SDMA_EXT_EVENT_0 0x0034 0x037C 0x081C 0x2 0x0 #define MX6SX_PAD_GPIO1_IO08__CCM_PMIC_RDY 0x0034 0x037C 0x069C 0x3 0x1 #define MX6SX_PAD_GPIO1_IO08__UART2_DCE_RTS 0x0034 0x037C 0x0834 0x4 0x0 +#define MX6SX_PAD_GPIO1_IO08__UART2_DTE_CTS 0x0034 0x037C 0x0000 0x4 0x0 #define MX6SX_PAD_GPIO1_IO08__GPIO1_IO_8 0x0034 0x037C 0x0000 0x5 0x0 #define MX6SX_PAD_GPIO1_IO08__SRC_SYSTEM_RESET 0x0034 0x037C 0x0000 0x6 0x0 #define MX6SX_PAD_GPIO1_IO08__DCIC1_OUT 0x0034 0x037C 0x0000 0x7 0x0 @@ -93,6 +96,7 @@ #define MX6SX_PAD_GPIO1_IO09__SDMA_EXT_EVENT_1 0x0038 0x0380 0x0820 0x2 0x0 #define MX6SX_PAD_GPIO1_IO09__CCM_OUT0 0x0038 0x0380 0x0000 0x3 0x0 #define MX6SX_PAD_GPIO1_IO09__UART2_DCE_CTS 0x0038 0x0380 0x0000 0x4 0x0 +#define MX6SX_PAD_GPIO1_IO09__UART2_DTE_RTS 0x0038 0x0380 0x0834 0x4 0x1 #define MX6SX_PAD_GPIO1_IO09__GPIO1_IO_9 0x0038 0x0380 0x0000 0x5 0x0 #define MX6SX_PAD_GPIO1_IO09__SRC_INT_BOOT 0x0038 0x0380 0x0000 0x6 0x0 #define MX6SX_PAD_GPIO1_IO09__OBSERVE_MUX_OUT_4 0x0038 0x0380 0x0000 0x7 0x0 @@ -200,6 +204,7 @@ #define MX6SX_PAD_CSI_DATA06__I2C4_SCL 0x0064 0x03AC 0x07C0 0x2 0x2 #define MX6SX_PAD_CSI_DATA06__KPP_COL_7 0x0064 0x03AC 0x07D0 0x3 0x0 #define MX6SX_PAD_CSI_DATA06__UART6_DCE_RTS 0x0064 0x03AC 0x0854 0x4 0x0 +#define MX6SX_PAD_CSI_DATA06__UART6_DTE_CTS 0x0064 0x03AC 0x0000 0x4 0x0 #define MX6SX_PAD_CSI_DATA06__GPIO1_IO_20 0x0064 0x03AC 0x0000 0x5 0x0 #define MX6SX_PAD_CSI_DATA06__WEIM_DATA_17 0x0064 0x03AC 0x0000 0x6 0x0 #define MX6SX_PAD_CSI_DATA06__DCIC2_OUT 0x0064 0x03AC 0x0000 0x7 0x0 @@ -210,6 +215,7 @@ #define MX6SX_PAD_CSI_DATA07__I2C4_SDA 0x0068 0x03B0 0x07C4 0x2 0x2 #define MX6SX_PAD_CSI_DATA07__KPP_ROW_7 0x0068 0x03B0 0x07DC 0x3 0x0 #define MX6SX_PAD_CSI_DATA07__UART6_DCE_CTS 0x0068 0x03B0 0x0000 0x4 0x0 +#define MX6SX_PAD_CSI_DATA07__UART6_DTE_RTS 0x0068 0x03B0 0x0854 0x4 0x1 #define MX6SX_PAD_CSI_DATA07__GPIO1_IO_21 0x0068 0x03B0 0x0000 0x5 0x0 #define MX6SX_PAD_CSI_DATA07__WEIM_DATA_16 0x0068 0x03B0 0x0000 0x6 0x0 #define MX6SX_PAD_CSI_DATA07__DCIC1_OUT 0x0068 0x03B0 0x0000 0x7 0x0 @@ -219,6 +225,7 @@ #define MX6SX_PAD_CSI_HSYNC__ESAI_TX0 0x006C 0x03B4 0x0790 0x1 0x1 #define MX6SX_PAD_CSI_HSYNC__AUDMUX_AUD6_TXD 0x006C 0x03B4 0x0678 0x2 0x1 #define MX6SX_PAD_CSI_HSYNC__UART4_DCE_RTS 0x006C 0x03B4 0x0844 0x3 0x2 +#define MX6SX_PAD_CSI_HSYNC__UART4_DTE_CTS 0x006C 0x03B4 0x0000 0x3 0x0 #define MX6SX_PAD_CSI_HSYNC__MQS_LEFT 0x006C 0x03B4 0x0000 0x4 0x0 #define MX6SX_PAD_CSI_HSYNC__GPIO1_IO_22 0x006C 0x03B4 0x0000 0x5 0x0 #define MX6SX_PAD_CSI_HSYNC__WEIM_DATA_25 0x006C 0x03B4 0x0000 0x6 0x0 @@ -251,6 +258,7 @@ #define MX6SX_PAD_CSI_VSYNC__ESAI_TX5_RX0 0x0078 0x03C0 0x07A4 0x1 0x1 #define MX6SX_PAD_CSI_VSYNC__AUDMUX_AUD6_RXD 0x0078 0x03C0 0x0674 0x2 0x1 #define MX6SX_PAD_CSI_VSYNC__UART4_DCE_CTS 0x0078 0x03C0 0x0000 0x3 0x0 +#define MX6SX_PAD_CSI_VSYNC__UART4_DTE_RTS 0x0078 0x03C0 0x0844 0x3 0x3 #define MX6SX_PAD_CSI_VSYNC__MQS_RIGHT 0x0078 0x03C0 0x0000 0x4 0x0 #define MX6SX_PAD_CSI_VSYNC__GPIO1_IO_25 0x0078 0x03C0 0x0000 0x5 0x0 #define MX6SX_PAD_CSI_VSYNC__WEIM_DATA_24 0x0078 0x03C0 0x0000 0x6 0x0 @@ -353,6 +361,7 @@ #define MX6SX_PAD_ENET2_RX_CLK__ENET2_REF_CLK_25M 0x009C 0x03E4 0x0000 0x1 0x0 #define MX6SX_PAD_ENET2_RX_CLK__I2C3_SCL 0x009C 0x03E4 0x07B8 0x2 0x1 #define MX6SX_PAD_ENET2_RX_CLK__UART1_DCE_RTS 0x009C 0x03E4 0x082C 0x3 0x2 +#define MX6SX_PAD_ENET2_RX_CLK__UART1_DTE_CTS 0x009C 0x03E4 0x0000 0x3 0x0 #define MX6SX_PAD_ENET2_RX_CLK__MLB_DATA 0x009C 0x03E4 0x07EC 0x4 0x1 #define MX6SX_PAD_ENET2_RX_CLK__GPIO2_IO_8 0x009C 0x03E4 0x0000 0x5 0x0 #define MX6SX_PAD_ENET2_RX_CLK__USB_OTG2_OC 0x009C 0x03E4 0x085C 0x6 0x1 @@ -363,6 +372,7 @@ #define MX6SX_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x00A0 0x03E8 0x076C 0x1 0x1 #define MX6SX_PAD_ENET2_TX_CLK__I2C3_SDA 0x00A0 0x03E8 0x07BC 0x2 0x1 #define MX6SX_PAD_ENET2_TX_CLK__UART1_DCE_CTS 0x00A0 0x03E8 0x0000 0x3 0x0 +#define MX6SX_PAD_ENET2_TX_CLK__UART1_DTE_RTS 0x00A0 0x03E8 0x082C 0x3 0x3 #define MX6SX_PAD_ENET2_TX_CLK__MLB_CLK 0x00A0 0x03E8 0x07E8 0x4 0x1 #define MX6SX_PAD_ENET2_TX_CLK__GPIO2_IO_9 0x00A0 0x03E8 0x0000 0x5 0x0 #define MX6SX_PAD_ENET2_TX_CLK__USB_OTG2_PWR 0x00A0 0x03E8 0x0000 0x6 0x0 @@ -372,6 +382,7 @@ #define MX6SX_PAD_KEY_COL0__KPP_COL_0 0x00A4 0x03EC 0x0000 0x0 0x0 #define MX6SX_PAD_KEY_COL0__USDHC3_CD_B 0x00A4 0x03EC 0x0000 0x1 0x0 #define MX6SX_PAD_KEY_COL0__UART6_DCE_RTS 0x00A4 0x03EC 0x0854 0x2 0x2 +#define MX6SX_PAD_KEY_COL0__UART6_DTE_CTS 0x00A4 0x03EC 0x0000 0x2 0x0 #define MX6SX_PAD_KEY_COL0__ECSPI1_SCLK 0x00A4 0x03EC 0x0710 0x3 0x0 #define MX6SX_PAD_KEY_COL0__AUDMUX_AUD5_TXC 0x00A4 0x03EC 0x066C 0x4 0x0 #define MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x00A4 0x03EC 0x0000 0x5 0x0 @@ -390,6 +401,7 @@ #define MX6SX_PAD_KEY_COL2__KPP_COL_2 0x00AC 0x03F4 0x0000 0x0 0x0 #define MX6SX_PAD_KEY_COL2__USDHC4_CD_B 0x00AC 0x03F4 0x0874 0x1 0x1 #define MX6SX_PAD_KEY_COL2__UART5_DCE_RTS 0x00AC 0x03F4 0x084C 0x2 0x2 +#define MX6SX_PAD_KEY_COL2__UART5_DTE_CTS 0x00AC 0x03F4 0x0000 0x2 0x0 #define MX6SX_PAD_KEY_COL2__CAN1_TX 0x00AC 0x03F4 0x0000 0x3 0x0 #define MX6SX_PAD_KEY_COL2__CANFD_TX1 0x00AC 0x03F4 0x0000 0x4 0x0 #define MX6SX_PAD_KEY_COL2__GPIO2_IO_12 0x00AC 0x03F4 0x0000 0x5 0x0 @@ -415,6 +427,7 @@ #define MX6SX_PAD_KEY_ROW0__KPP_ROW_0 0x00B8 0x0400 0x0000 0x0 0x0 #define MX6SX_PAD_KEY_ROW0__USDHC3_WP 0x00B8 0x0400 0x0000 0x1 0x0 #define MX6SX_PAD_KEY_ROW0__UART6_DCE_CTS 0x00B8 0x0400 0x0000 0x2 0x0 +#define MX6SX_PAD_KEY_ROW0__UART6_DTE_RTS 0x00B8 0x0400 0x0854 0x2 0x3 #define MX6SX_PAD_KEY_ROW0__ECSPI1_MOSI 0x00B8 0x0400 0x0718 0x3 0x0 #define MX6SX_PAD_KEY_ROW0__AUDMUX_AUD5_TXD 0x00B8 0x0400 0x0660 0x4 0x0 #define MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x00B8 0x0400 0x0000 0x5 0x0 @@ -434,6 +447,7 @@ #define MX6SX_PAD_KEY_ROW2__KPP_ROW_2 0x00C0 0x0408 0x0000 0x0 0x0 #define MX6SX_PAD_KEY_ROW2__USDHC4_WP 0x00C0 0x0408 0x0878 0x1 0x1 #define MX6SX_PAD_KEY_ROW2__UART5_DCE_CTS 0x00C0 0x0408 0x0000 0x2 0x0 +#define MX6SX_PAD_KEY_ROW2__UART5_DTE_RTS 0x00C0 0x0408 0x084C 0x2 0x3 #define MX6SX_PAD_KEY_ROW2__CAN1_RX 0x00C0 0x0408 0x068C 0x3 0x1 #define MX6SX_PAD_KEY_ROW2__CANFD_RX1 0x00C0 0x0408 0x0694 0x4 0x1 #define MX6SX_PAD_KEY_ROW2__GPIO2_IO_17 0x00C0 0x0408 0x0000 0x5 0x0 @@ -816,6 +830,7 @@ #define MX6SX_PAD_NAND_DATA04__USDHC2_DATA4 0x0160 0x04A8 0x0000 0x1 0x0 #define MX6SX_PAD_NAND_DATA04__QSPI2_B_SS1_B 0x0160 0x04A8 0x0000 0x2 0x0 #define MX6SX_PAD_NAND_DATA04__UART3_DCE_RTS 0x0160 0x04A8 0x083C 0x3 0x0 +#define MX6SX_PAD_NAND_DATA04__UART3_DTE_CTS 0x0160 0x04A8 0x0000 0x3 0x0 #define MX6SX_PAD_NAND_DATA04__AUDMUX_AUD4_RXFS 0x0160 0x04A8 0x0650 0x4 0x0 #define MX6SX_PAD_NAND_DATA04__GPIO4_IO_8 0x0160 0x04A8 0x0000 0x5 0x0 #define MX6SX_PAD_NAND_DATA04__WEIM_AD_4 0x0160 0x04A8 0x0000 0x6 0x0 @@ -826,6 +841,7 @@ #define MX6SX_PAD_NAND_DATA05__USDHC2_DATA5 0x0164 0x04AC 0x0000 0x1 0x0 #define MX6SX_PAD_NAND_DATA05__QSPI2_B_DQS 0x0164 0x04AC 0x0000 0x2 0x0 #define MX6SX_PAD_NAND_DATA05__UART3_DCE_CTS 0x0164 0x04AC 0x0000 0x3 0x0 +#define MX6SX_PAD_NAND_DATA05__UART3_DTE_RTS 0x0164 0x04AC 0x083C 0x3 0x1 #define MX6SX_PAD_NAND_DATA05__AUDMUX_AUD4_RXC 0x0164 0x04AC 0x064C 0x4 0x0 #define MX6SX_PAD_NAND_DATA05__GPIO4_IO_9 0x0164 0x04AC 0x0000 0x5 0x0 #define MX6SX_PAD_NAND_DATA05__WEIM_AD_5 0x0164 0x04AC 0x0000 0x6 0x0 @@ -968,6 +984,7 @@ #define MX6SX_PAD_QSPI1A_SS1_B__SDMA_DEBUG_PC_3 0x019C 0x04E4 0x0000 0x9 0x0 #define MX6SX_PAD_QSPI1B_DATA0__QSPI1_B_DATA_0 0x01A0 0x04E8 0x0000 0x0 0x0 #define MX6SX_PAD_QSPI1B_DATA0__UART3_DCE_CTS 0x01A0 0x04E8 0x0000 0x1 0x0 +#define MX6SX_PAD_QSPI1B_DATA0__UART3_DTE_RTS 0x01A0 0x04E8 0x083C 0x1 0x4 #define MX6SX_PAD_QSPI1B_DATA0__ECSPI3_MOSI 0x01A0 0x04E8 0x0738 0x2 0x1 #define MX6SX_PAD_QSPI1B_DATA0__ESAI_RX_FS 0x01A0 0x04E8 0x0778 0x3 0x2 #define MX6SX_PAD_QSPI1B_DATA0__CSI1_DATA_22 0x01A0 0x04E8 0x06F4 0x4 0x1 @@ -976,6 +993,7 @@ #define MX6SX_PAD_QSPI1B_DATA0__SIM_M_HADDR_9 0x01A0 0x04E8 0x0000 0x7 0x0 #define MX6SX_PAD_QSPI1B_DATA1__QSPI1_B_DATA_1 0x01A4 0x04EC 0x0000 0x0 0x0 #define MX6SX_PAD_QSPI1B_DATA1__UART3_DCE_RTS 0x01A4 0x04EC 0x083C 0x1 0x5 +#define MX6SX_PAD_QSPI1B_DATA1__UART3_DTE_CTS 0x01A4 0x04EC 0x0000 0x1 0x0 #define MX6SX_PAD_QSPI1B_DATA1__ECSPI3_MISO 0x01A4 0x04EC 0x0734 0x2 0x1 #define MX6SX_PAD_QSPI1B_DATA1__ESAI_RX_CLK 0x01A4 0x04EC 0x0788 0x3 0x2 #define MX6SX_PAD_QSPI1B_DATA1__CSI1_DATA_21 0x01A4 0x04EC 0x06F0 0x4 0x1 @@ -1247,6 +1265,7 @@ #define MX6SX_PAD_SD1_DATA2__PWM3_OUT 0x0230 0x0578 0x0000 0x2 0x0 #define MX6SX_PAD_SD1_DATA2__GPT_COMPARE2 0x0230 0x0578 0x0000 0x3 0x0 #define MX6SX_PAD_SD1_DATA2__UART2_DCE_CTS 0x0230 0x0578 0x0000 0x4 0x0 +#define MX6SX_PAD_SD1_DATA2__UART2_DTE_RTS 0x0230 0x0578 0x0834 0x4 0x2 #define MX6SX_PAD_SD1_DATA2__GPIO6_IO_4 0x0230 0x0578 0x0000 0x5 0x0 #define MX6SX_PAD_SD1_DATA2__ECSPI4_RDY 0x0230 0x0578 0x0000 0x6 0x0 #define MX6SX_PAD_SD1_DATA2__CCM_OUT0 0x0230 0x0578 0x0000 0x7 0x0 @@ -1256,6 +1275,7 @@ #define MX6SX_PAD_SD1_DATA3__AUDMUX_AUD5_RXD 0x0234 0x057C 0x065C 0x2 0x2 #define MX6SX_PAD_SD1_DATA3__GPT_COMPARE3 0x0234 0x057C 0x0000 0x3 0x0 #define MX6SX_PAD_SD1_DATA3__UART2_DCE_RTS 0x0234 0x057C 0x0834 0x4 0x3 +#define MX6SX_PAD_SD1_DATA3__UART2_DTE_CTS 0x0234 0x057C 0x0000 0x4 0x0 #define MX6SX_PAD_SD1_DATA3__GPIO6_IO_5 0x0234 0x057C 0x0000 0x5 0x0 #define MX6SX_PAD_SD1_DATA3__ECSPI4_SS1 0x0234 0x057C 0x0000 0x6 0x0 #define MX6SX_PAD_SD1_DATA3__CCM_PMIC_RDY 0x0234 0x057C 0x069C 0x7 0x2 @@ -1326,6 +1346,7 @@ #define MX6SX_PAD_SD2_DATA3__MMDC_DEBUG_31 0x024C 0x0594 0x0000 0x9 0x0 #define MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x0250 0x0598 0x0000 0x0 0x0 #define MX6SX_PAD_SD3_CLK__UART4_DCE_CTS 0x0250 0x0598 0x0000 0x1 0x0 +#define MX6SX_PAD_SD3_CLK__UART4_DTE_RTS 0x0250 0x0598 0x0844 0x1 0x0 #define MX6SX_PAD_SD3_CLK__ECSPI4_SCLK 0x0250 0x0598 0x0740 0x2 0x0 #define MX6SX_PAD_SD3_CLK__AUDMUX_AUD6_RXFS 0x0250 0x0598 0x0680 0x3 0x0 #define MX6SX_PAD_SD3_CLK__LCDIF2_VSYNC 0x0250 0x0598 0x0000 0x4 0x0 @@ -1365,6 +1386,7 @@ #define MX6SX_PAD_SD3_DATA1__SDMA_DEBUG_EVT_CHN_LINES_1 0x025C 0x05A4 0x0000 0x9 0x0 #define MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x0260 0x05A8 0x0000 0x0 0x0 #define MX6SX_PAD_SD3_DATA2__UART4_DCE_RTS 0x0260 0x05A8 0x0844 0x1 0x1 +#define MX6SX_PAD_SD3_DATA2__UART4_DTE_CTS 0x0260 0x05A8 0x0000 0x1 0x0 #define MX6SX_PAD_SD3_DATA2__ECSPI4_SS0 0x0260 0x05A8 0x074C 0x2 0x0 #define MX6SX_PAD_SD3_DATA2__AUDMUX_AUD6_TXFS 0x0260 0x05A8 0x0688 0x3 0x0 #define MX6SX_PAD_SD3_DATA2__LCDIF2_CLK 0x0260 0x05A8 0x0000 0x4 0x0 @@ -1410,6 +1432,7 @@ #define MX6SX_PAD_SD3_DATA6__CAN2_TX 0x0270 0x05B8 0x0000 0x1 0x0 #define MX6SX_PAD_SD3_DATA6__CANFD_TX2 0x0270 0x05B8 0x0000 0x2 0x0 #define MX6SX_PAD_SD3_DATA6__UART3_DCE_RTS 0x0270 0x05B8 0x083C 0x3 0x2 +#define MX6SX_PAD_SD3_DATA6__UART3_DTE_CTS 0x0270 0x05B8 0x0000 0x3 0x0 #define MX6SX_PAD_SD3_DATA6__LCDIF2_DATA_4 0x0270 0x05B8 0x0000 0x4 0x0 #define MX6SX_PAD_SD3_DATA6__GPIO7_IO_8 0x0270 0x05B8 0x0000 0x5 0x0 #define MX6SX_PAD_SD3_DATA6__ENET1_1588_EVENT0_OUT 0x0270 0x05B8 0x0000 0x6 0x0 @@ -1420,6 +1443,7 @@ #define MX6SX_PAD_SD3_DATA7__CAN1_RX 0x0274 0x05BC 0x068C 0x1 0x0 #define MX6SX_PAD_SD3_DATA7__CANFD_RX1 0x0274 0x05BC 0x0694 0x2 0x0 #define MX6SX_PAD_SD3_DATA7__UART3_DCE_CTS 0x0274 0x05BC 0x0000 0x3 0x0 +#define MX6SX_PAD_SD3_DATA7__UART3_DTE_RTS 0x0274 0x05BC 0x083C 0x3 0x3 #define MX6SX_PAD_SD3_DATA7__LCDIF2_DATA_5 0x0274 0x05BC 0x0000 0x4 0x0 #define MX6SX_PAD_SD3_DATA7__GPIO7_IO_9 0x0274 0x05BC 0x0000 0x5 0x0 #define MX6SX_PAD_SD3_DATA7__ENET1_1588_EVENT0_IN 0x0274 0x05BC 0x0000 0x6 0x0 @@ -1511,6 +1535,7 @@ #define MX6SX_PAD_SD4_DATA6__USDHC4_DATA6 0x0298 0x05E0 0x0000 0x0 0x0 #define MX6SX_PAD_SD4_DATA6__RAWNAND_CE3_B 0x0298 0x05E0 0x0000 0x1 0x0 #define MX6SX_PAD_SD4_DATA6__UART5_DCE_RTS 0x0298 0x05E0 0x084C 0x2 0x0 +#define MX6SX_PAD_SD4_DATA6__UART5_DTE_CTS 0x0298 0x05E0 0x0000 0x2 0x0 #define MX6SX_PAD_SD4_DATA6__ECSPI3_MISO 0x0298 0x05E0 0x0734 0x3 0x0 #define MX6SX_PAD_SD4_DATA6__LCDIF2_DATA_6 0x0298 0x05E0 0x0000 0x4 0x0 #define MX6SX_PAD_SD4_DATA6__GPIO6_IO_20 0x0298 0x05E0 0x0000 0x5 0x0 @@ -1521,6 +1546,7 @@ #define MX6SX_PAD_SD4_DATA7__USDHC4_DATA7 0x029C 0x05E4 0x0000 0x0 0x0 #define MX6SX_PAD_SD4_DATA7__RAWNAND_DATA08 0x029C 0x05E4 0x0000 0x1 0x0 #define MX6SX_PAD_SD4_DATA7__UART5_DCE_CTS 0x029C 0x05E4 0x0000 0x2 0x0 +#define MX6SX_PAD_SD4_DATA7__UART5_DTE_RTS 0x029C 0x05E4 0x084C 0x2 0x1 #define MX6SX_PAD_SD4_DATA7__ECSPI3_SS0 0x029C 0x05E4 0x073C 0x3 0x0 #define MX6SX_PAD_SD4_DATA7__LCDIF2_DATA_15 0x029C 0x05E4 0x0000 0x4 0x0 #define MX6SX_PAD_SD4_DATA7__GPIO6_IO_21 0x029C 0x05E4 0x0000 0x5 0x0 From 6f32001feb4049d408eb1cdbaec8111b6eb899f8 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Mon, 17 Feb 2020 19:13:37 +0800 Subject: [PATCH 0431/4444] ARM: dts: imx6sx-nitrogen6sx: Use new pin names with DCE/DTE for UART pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use new pin names containing DCE/DTE for UART RX/TX/RTS/CTS pins, this is to distinguish the DCE/DTE functions. Signed-off-by: Anson Huang Reviewed-by: Uwe Kleine-König Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sx-nitrogen6sx.dts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/imx6sx-nitrogen6sx.dts b/arch/arm/boot/dts/imx6sx-nitrogen6sx.dts index 832b5c5d7441..d84ea6999377 100644 --- a/arch/arm/boot/dts/imx6sx-nitrogen6sx.dts +++ b/arch/arm/boot/dts/imx6sx-nitrogen6sx.dts @@ -484,31 +484,31 @@ pinctrl_uart1: uart1grp { fsl,pins = < - MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1 - MX6SX_PAD_GPIO1_IO05__UART1_RX 0x1b0b1 + MX6SX_PAD_GPIO1_IO04__UART1_DCE_TX 0x1b0b1 + MX6SX_PAD_GPIO1_IO05__UART1_DCE_RX 0x1b0b1 >; }; pinctrl_uart2: uart2grp { fsl,pins = < - MX6SX_PAD_GPIO1_IO06__UART2_TX 0x1b0b1 - MX6SX_PAD_GPIO1_IO07__UART2_RX 0x1b0b1 + MX6SX_PAD_GPIO1_IO06__UART2_DCE_TX 0x1b0b1 + MX6SX_PAD_GPIO1_IO07__UART2_DCE_RX 0x1b0b1 >; }; pinctrl_uart3: uart3grp { fsl,pins = < - MX6SX_PAD_QSPI1B_SS0_B__UART3_TX 0x1b0b1 - MX6SX_PAD_QSPI1B_SCLK__UART3_RX 0x1b0b1 + MX6SX_PAD_QSPI1B_SS0_B__UART3_DCE_TX 0x1b0b1 + MX6SX_PAD_QSPI1B_SCLK__UART3_DCE_RX 0x1b0b1 >; }; pinctrl_uart5: uart5grp { fsl,pins = < - MX6SX_PAD_KEY_COL3__UART5_TX 0x1b0b1 - MX6SX_PAD_KEY_ROW3__UART5_RX 0x1b0b1 - MX6SX_PAD_SD3_DATA6__UART3_RTS_B 0x1b0b1 - MX6SX_PAD_SD3_DATA7__UART3_CTS_B 0x1b0b1 + MX6SX_PAD_KEY_COL3__UART5_DCE_TX 0x1b0b1 + MX6SX_PAD_KEY_ROW3__UART5_DCE_RX 0x1b0b1 + MX6SX_PAD_SD3_DATA6__UART3_DCE_RTS 0x1b0b1 + MX6SX_PAD_SD3_DATA7__UART3_DCE_CTS 0x1b0b1 >; }; From fec9b63833296e414bad3c79ad7041984977c9e4 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Mon, 17 Feb 2020 19:13:38 +0800 Subject: [PATCH 0432/4444] ARM: dts: imx6sx-sabreauto: Use new pin names with DCE/DTE for UART pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use new pin names containing DCE/DTE for UART RX/TX/RTS/CTS pins, this is to distinguish the DCE/DTE functions. Signed-off-by: Anson Huang Reviewed-by: Uwe Kleine-König Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sx-sabreauto.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/imx6sx-sabreauto.dts b/arch/arm/boot/dts/imx6sx-sabreauto.dts index 315044ccd65f..825924448ab4 100644 --- a/arch/arm/boot/dts/imx6sx-sabreauto.dts +++ b/arch/arm/boot/dts/imx6sx-sabreauto.dts @@ -229,8 +229,8 @@ pinctrl_uart1: uart1grp { fsl,pins = < - MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1 - MX6SX_PAD_GPIO1_IO05__UART1_RX 0x1b0b1 + MX6SX_PAD_GPIO1_IO04__UART1_DCE_TX 0x1b0b1 + MX6SX_PAD_GPIO1_IO05__UART1_DCE_RX 0x1b0b1 >; }; From ac7fa7304d8d21916ed22e1dc9457a2da4bbcd4c Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Mon, 17 Feb 2020 19:13:39 +0800 Subject: [PATCH 0433/4444] ARM: dts: imx6sx-sdb: Use new pin names with DCE/DTE for UART pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use new pin names containing DCE/DTE for UART RX/TX/RTS/CTS pins, this is to distinguish the DCE/DTE functions. Signed-off-by: Anson Huang Reviewed-by: Uwe Kleine-König Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sx-sdb.dtsi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/imx6sx-sdb.dtsi b/arch/arm/boot/dts/imx6sx-sdb.dtsi index f6972deb5e39..3e5fb72f21fc 100644 --- a/arch/arm/boot/dts/imx6sx-sdb.dtsi +++ b/arch/arm/boot/dts/imx6sx-sdb.dtsi @@ -564,17 +564,17 @@ pinctrl_uart1: uart1grp { fsl,pins = < - MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1 - MX6SX_PAD_GPIO1_IO05__UART1_RX 0x1b0b1 + MX6SX_PAD_GPIO1_IO04__UART1_DCE_TX 0x1b0b1 + MX6SX_PAD_GPIO1_IO05__UART1_DCE_RX 0x1b0b1 >; }; pinctrl_uart5: uart5grp { fsl,pins = < - MX6SX_PAD_KEY_ROW3__UART5_RX 0x1b0b1 - MX6SX_PAD_KEY_COL3__UART5_TX 0x1b0b1 - MX6SX_PAD_KEY_ROW2__UART5_CTS_B 0x1b0b1 - MX6SX_PAD_KEY_COL2__UART5_RTS_B 0x1b0b1 + MX6SX_PAD_KEY_ROW3__UART5_DCE_RX 0x1b0b1 + MX6SX_PAD_KEY_COL3__UART5_DCE_TX 0x1b0b1 + MX6SX_PAD_KEY_ROW2__UART5_DCE_CTS 0x1b0b1 + MX6SX_PAD_KEY_COL2__UART5_DCE_RTS 0x1b0b1 >; }; From 924d83c7c7da30a28930218e3fcca37fc285944e Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Mon, 17 Feb 2020 19:13:40 +0800 Subject: [PATCH 0434/4444] ARM: dts: imx6sx-softing-vining-2000: Use new pin names with DCE/DTE for UART pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use new pin names containing DCE/DTE for UART RX/TX/RTS/CTS pins, this is to distinguish the DCE/DTE functions. Signed-off-by: Anson Huang Reviewed-by: Uwe Kleine-König Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sx-softing-vining-2000.dts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/imx6sx-softing-vining-2000.dts b/arch/arm/boot/dts/imx6sx-softing-vining-2000.dts index 28563f21024e..61c7e723ad5d 100644 --- a/arch/arm/boot/dts/imx6sx-softing-vining-2000.dts +++ b/arch/arm/boot/dts/imx6sx-softing-vining-2000.dts @@ -384,15 +384,15 @@ pinctrl_uart1: uart1grp { fsl,pins = < - MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1 - MX6SX_PAD_GPIO1_IO05__UART1_RX 0x1b0b1 + MX6SX_PAD_GPIO1_IO04__UART1_DCE_TX 0x1b0b1 + MX6SX_PAD_GPIO1_IO05__UART1_DCE_RX 0x1b0b1 >; }; pinctrl_uart2: uart2grp { fsl,pins = < - MX6SX_PAD_GPIO1_IO06__UART2_TX 0x1b0b1 - MX6SX_PAD_GPIO1_IO07__UART2_RX 0x1b0b1 + MX6SX_PAD_GPIO1_IO06__UART2_DCE_TX 0x1b0b1 + MX6SX_PAD_GPIO1_IO07__UART2_DCE_RX 0x1b0b1 >; }; From 1becc1a317062b840966093615d0e564fa4932a3 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Mon, 17 Feb 2020 19:13:41 +0800 Subject: [PATCH 0435/4444] ARM: dts: imx6sx-udoo-neo: Use new pin names with DCE/DTE for UART pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use new pin names containing DCE/DTE for UART RX/TX/RTS/CTS pins, this is to distinguish the DCE/DTE functions. Signed-off-by: Anson Huang Reviewed-by: Uwe Kleine-König Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sx-udoo-neo.dtsi | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi b/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi index 25d4aa985a69..ee645655090d 100644 --- a/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi +++ b/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi @@ -235,28 +235,28 @@ pinctrl_uart1: uart1grp { fsl,pins = - , - ; + , + ; }; pinctrl_uart2: uart2grp { fsl,pins = - , - ; + , + ; }; pinctrl_uart3: uart3grp { fsl,pins = - , - , - , - ; + , + , + , + ; }; pinctrl_uart5: uart5grp { fsl,pins = - , - ; + , + ; }; pinctrl_uart6: uart6grp { @@ -265,10 +265,10 @@ , , , - , - , - , - ; + , + , + , + ; }; pinctrl_otg1_reg: otg1grp { From 4a4fb66119eb7135e6ce9cf61488c86f9888bb15 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Thu, 13 Feb 2020 16:35:33 +0800 Subject: [PATCH 0436/4444] ARM: imx: Add missing of_node_put() After finishing using device node got from of_find_compatible_node(), of_node_put() needs to be called. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/mach-imx/anatop.c | 6 ++++-- arch/arm/mach-imx/gpc.c | 1 + arch/arm/mach-imx/platsmp.c | 1 + arch/arm/mach-imx/pm-imx6.c | 2 ++ arch/arm/mach-imx/pm-imx7ulp.c | 1 + 5 files changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-imx/anatop.c b/arch/arm/mach-imx/anatop.c index 8fb68c0ec34c..ea4a59648932 100644 --- a/arch/arm/mach-imx/anatop.c +++ b/arch/arm/mach-imx/anatop.c @@ -94,7 +94,7 @@ void imx_anatop_post_resume(void) void __init imx_init_revision_from_anatop(void) { - struct device_node *np; + struct device_node *np, *src_np; void __iomem *anatop_base; unsigned int revision; u32 digprog; @@ -135,9 +135,10 @@ void __init imx_init_revision_from_anatop(void) void __iomem *src_base; u32 sbmr2; - np = of_find_compatible_node(NULL, NULL, + src_np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-src"); src_base = of_iomap(np, 0); + of_node_put(src_np); WARN_ON(!src_base); sbmr2 = readl_relaxed(src_base + SRC_SBMR2); iounmap(src_base); @@ -149,6 +150,7 @@ void __init imx_init_revision_from_anatop(void) } } } + of_node_put(np); mxc_set_cpu_type(digprog >> 16 & 0xff); imx_set_soc_revision(revision); diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c index e96baa493318..fb3cba87940d 100644 --- a/arch/arm/mach-imx/gpc.c +++ b/arch/arm/mach-imx/gpc.c @@ -282,4 +282,5 @@ void __init imx_gpc_check_dt(void) /* map GPC, so that at least CPUidle and WARs keep working */ gpc_base = of_iomap(np, 0); } + of_node_put(np); } diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c index 2aa26928221d..cf4e9335831c 100644 --- a/arch/arm/mach-imx/platsmp.c +++ b/arch/arm/mach-imx/platsmp.c @@ -109,6 +109,7 @@ static void __init ls1021a_smp_prepare_cpus(unsigned int max_cpus) np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcfg"); dcfg_base = of_iomap(np, 0); + of_node_put(np); BUG_ON(!dcfg_base); paddr = __pa_symbol(secondary_startup); diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c index 1c0ecad3620e..dd34dff13762 100644 --- a/arch/arm/mach-imx/pm-imx6.c +++ b/arch/arm/mach-imx/pm-imx6.c @@ -655,6 +655,8 @@ void __init imx6_pm_ccm_init(const char *ccm_compat) if (of_property_read_bool(np, "fsl,pmic-stby-poweroff")) imx6_pm_stby_poweroff_probe(); + + of_node_put(np); } void __init imx6q_pm_init(void) diff --git a/arch/arm/mach-imx/pm-imx7ulp.c b/arch/arm/mach-imx/pm-imx7ulp.c index 7b2f7387e662..2e756d8191fa 100644 --- a/arch/arm/mach-imx/pm-imx7ulp.c +++ b/arch/arm/mach-imx/pm-imx7ulp.c @@ -62,6 +62,7 @@ void __init imx7ulp_pm_init(void) np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-smc1"); smc1_base = of_iomap(np, 0); + of_node_put(np); WARN_ON(!smc1_base); imx7ulp_set_lpm(ULP_PM_RUN); From 5d30f92e7631286b8617777c5400c8eadcae50a1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 16 Feb 2020 12:01:09 -0800 Subject: [PATCH 0437/4444] x86/NUMA: Provide a range-to-target_node lookup facility The DEV_DAX_KMEM facility is a generic mechanism to allow device-dax instances, fronting performance-differentiated-memory like pmem, to be added to the System RAM pool. The NUMA node for that hot-added memory is derived from the device-dax instance's 'target_node' attribute. Recall that the 'target_node' is the ACPI-PXM-to-node translation for memory when it comes online whereas the 'numa_node' attribute of the device represents the closest online cpu node. Presently useful target_node information from the ACPI SRAT is discarded with the expectation that "Reserved" memory will never be onlined. Now, DEV_DAX_KMEM violates that assumption, there is a need to retain the translation. Move, rather than discard, numa_memblk data to a secondary array that memory_add_physaddr_to_target_node() may consider at a later point in time. Cc: Dave Hansen Cc: Andy Lutomirski Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Borislav Petkov Cc: "H. Peter Anvin" Cc: Cc: Andrew Morton Cc: David Hildenbrand Cc: Michal Hocko Reported-by: kbuild test robot Reviewed-by: Ingo Molnar Signed-off-by: Dan Williams Reviewed-by: Thomas Gleixner Link: https://lore.kernel.org/r/158188326978.894464.217282995221175417.stgit@dwillia2-desk3.amr.corp.intel.com --- arch/x86/mm/numa.c | 61 ++++++++++++++++++++++++++++++++++++-------- include/linux/numa.h | 14 +++++++++- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index 2450b21cc28a..59ba008504dc 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c @@ -26,6 +26,7 @@ struct pglist_data *node_data[MAX_NUMNODES] __read_mostly; EXPORT_SYMBOL(node_data); static struct numa_meminfo numa_meminfo __initdata_or_meminfo; +static struct numa_meminfo numa_reserved_meminfo __initdata_or_meminfo; static int numa_distance_cnt; static u8 *numa_distance; @@ -164,6 +165,19 @@ void __init numa_remove_memblk_from(int idx, struct numa_meminfo *mi) (mi->nr_blks - idx) * sizeof(mi->blk[0])); } +/** + * numa_move_tail_memblk - Move a numa_memblk from one numa_meminfo to another + * @dst: numa_meminfo to append block to + * @idx: Index of memblk to remove + * @src: numa_meminfo to remove memblk from + */ +static void __init numa_move_tail_memblk(struct numa_meminfo *dst, int idx, + struct numa_meminfo *src) +{ + dst->blk[dst->nr_blks++] = src->blk[idx]; + numa_remove_memblk_from(idx, src); +} + /** * numa_add_memblk - Add one numa_memblk to numa_meminfo * @nid: NUMA node ID of the new memblk @@ -233,14 +247,19 @@ int __init numa_cleanup_meminfo(struct numa_meminfo *mi) for (i = 0; i < mi->nr_blks; i++) { struct numa_memblk *bi = &mi->blk[i]; - /* make sure all blocks are inside the limits */ + /* move / save reserved memory ranges */ + if (!memblock_overlaps_region(&memblock.memory, + bi->start, bi->end - bi->start)) { + numa_move_tail_memblk(&numa_reserved_meminfo, i--, mi); + continue; + } + + /* make sure all non-reserved blocks are inside the limits */ bi->start = max(bi->start, low); bi->end = min(bi->end, high); - /* and there's no empty or non-exist block */ - if (bi->start >= bi->end || - !memblock_overlaps_region(&memblock.memory, - bi->start, bi->end - bi->start)) + /* and there's no empty block */ + if (bi->start >= bi->end) numa_remove_memblk_from(i--, mi); } @@ -877,16 +896,38 @@ EXPORT_SYMBOL(cpumask_of_node); #endif /* !CONFIG_DEBUG_PER_CPU_MAPS */ -#ifdef CONFIG_MEMORY_HOTPLUG -int memory_add_physaddr_to_nid(u64 start) +#ifdef CONFIG_NUMA_KEEP_MEMINFO +static int meminfo_to_nid(struct numa_meminfo *mi, u64 start) { - struct numa_meminfo *mi = &numa_meminfo; - int nid = mi->blk[0].nid; int i; for (i = 0; i < mi->nr_blks; i++) if (mi->blk[i].start <= start && mi->blk[i].end > start) - nid = mi->blk[i].nid; + return mi->blk[i].nid; + return NUMA_NO_NODE; +} + +int phys_to_target_node(phys_addr_t start) +{ + int nid = meminfo_to_nid(&numa_meminfo, start); + + /* + * Prefer online nodes, but if reserved memory might be + * hot-added continue the search with reserved ranges. + */ + if (nid != NUMA_NO_NODE) + return nid; + + return meminfo_to_nid(&numa_reserved_meminfo, start); +} +EXPORT_SYMBOL_GPL(phys_to_target_node); + +int memory_add_physaddr_to_nid(u64 start) +{ + int nid = meminfo_to_nid(&numa_meminfo, start); + + if (nid == NUMA_NO_NODE) + nid = numa_meminfo.blk[0].nid; return nid; } EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid); diff --git a/include/linux/numa.h b/include/linux/numa.h index 5773cd2613fc..a42df804679e 100644 --- a/include/linux/numa.h +++ b/include/linux/numa.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef _LINUX_NUMA_H #define _LINUX_NUMA_H - +#include #ifdef CONFIG_NODES_SHIFT #define NODES_SHIFT CONFIG_NODES_SHIFT @@ -21,12 +21,24 @@ #endif #ifdef CONFIG_NUMA +/* Generic implementation available */ int numa_map_to_online_node(int node); + +/* + * Optional architecture specific implementation, users need a "depends + * on $ARCH" + */ +int phys_to_target_node(phys_addr_t addr); #else static inline int numa_map_to_online_node(int node) { return NUMA_NO_NODE; } + +static inline int phys_to_target_node(phys_addr_t addr) +{ + return NUMA_NO_NODE; +} #endif #endif /* _LINUX_NUMA_H */ From 7b27a8622f802761d5c6abd6c37b22312a35343c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 16 Feb 2020 12:01:16 -0800 Subject: [PATCH 0438/4444] libnvdimm/e820: Retrieve and populate correct 'target_node' info Use the new phys_to_target_node() and numa_map_to_online_node() helpers to retrieve the correct id for the 'numa_node' ("local" / online initiator node) and 'target_node' (offline target memory node) sysfs attributes. Below is an example from a 4 NUMA node system where all the memory on node2 is pmem / reserved. It should be noted that with the arrival of the ACPI HMAT table and EFI Specific Purpose Memory the kernel will start to see more platforms with reserved / performance differentiated memory in its own NUMA node. Hence all the stakeholders on the Cc for what is ostensibly a libnvdimm local patch. === Before === /* Notice no online memory on node2 at start */ # numactl --hardware available: 3 nodes (0-1,3) node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 node 0 size: 3958 MB node 0 free: 3708 MB node 1 cpus: 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 node 1 size: 4027 MB node 1 free: 3871 MB node 3 cpus: node 3 size: 3994 MB node 3 free: 3971 MB node distances: node 0 1 3 0: 10 21 21 1: 21 10 21 3: 21 21 10 /* * Put the pmem namespace into devdax mode so it can be assigned to the * kmem driver */ # ndctl create-namespace -e namespace0.0 -m devdax -f { "dev":"namespace0.0", "mode":"devdax", "map":"dev", "size":"3.94 GiB (4.23 GB)", "uuid":"1650af9b-9ba3-4704-acd6-10178399d9a3", [..] } /* Online Persistent Memory as System RAM */ # daxctl reconfigure-device --mode=system-ram dax0.0 libdaxctl: memblock_in_dev: dax0.0: memory0: Unable to determine phys_index: Success libdaxctl: memblock_in_dev: dax0.0: memory0: Unable to determine phys_index: Success libdaxctl: memblock_in_dev: dax0.0: memory0: Unable to determine phys_index: Success libdaxctl: memblock_in_dev: dax0.0: memory0: Unable to determine phys_index: Success [ { "chardev":"dax0.0", "size":4225761280, "target_node":0, "mode":"system-ram" } ] reconfigured 1 device /* Note that the memory is onlined by default to the wrong node, node0 */ # numactl --hardware available: 3 nodes (0-1,3) node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 node 0 size: 7926 MB node 0 free: 7655 MB node 1 cpus: 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 node 1 size: 4027 MB node 1 free: 3871 MB node 3 cpus: node 3 size: 3994 MB node 3 free: 3971 MB node distances: node 0 1 3 0: 10 21 21 1: 21 10 21 3: 21 21 10 === After === /* Notice that the "phys_index" error messages are gone */ # daxctl reconfigure-device --mode=system-ram dax0.0 [ { "chardev":"dax0.0", "size":4225761280, "target_node":2, "mode":"system-ram" } ] reconfigured 1 device /* Notice that node2 is now correctly populated */ # numactl --hardware available: 4 nodes (0-3) node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 node 0 size: 3958 MB node 0 free: 3793 MB node 1 cpus: 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 node 1 size: 4027 MB node 1 free: 3851 MB node 2 cpus: node 2 size: 3968 MB node 2 free: 3968 MB node 3 cpus: node 3 size: 3994 MB node 3 free: 3908 MB node distances: node 0 1 2 3 0: 10 21 21 21 1: 21 10 21 21 2: 21 21 10 21 3: 21 21 21 10 Cc: Dave Hansen Cc: Andy Lutomirski Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Andrew Morton Cc: David Hildenbrand Cc: Michal Hocko Cc: Ira Weiny Cc: Vishal Verma Cc: Christoph Hellwig Reviewed-by: Ingo Molnar Signed-off-by: Dan Williams Link: https://lore.kernel.org/r/158188327614.894464.13122730362187722603.stgit@dwillia2-desk3.amr.corp.intel.com --- arch/x86/Kconfig | 1 + drivers/nvdimm/e820.c | 18 ++++-------------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index beea77046f9b..d4e446daf457 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1664,6 +1664,7 @@ config X86_PMEM_LEGACY depends on PHYS_ADDR_T_64BIT depends on BLK_DEV select X86_PMEM_LEGACY_DEVICE + select NUMA_KEEP_MEMINFO if NUMA select LIBNVDIMM help Treat memory marked using the non-standard e820 type of 12 as used diff --git a/drivers/nvdimm/e820.c b/drivers/nvdimm/e820.c index e02f60ad6c99..4cd18be9d0e9 100644 --- a/drivers/nvdimm/e820.c +++ b/drivers/nvdimm/e820.c @@ -7,6 +7,7 @@ #include #include #include +#include static int e820_pmem_remove(struct platform_device *pdev) { @@ -16,27 +17,16 @@ static int e820_pmem_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_MEMORY_HOTPLUG -static int e820_range_to_nid(resource_size_t addr) -{ - return memory_add_physaddr_to_nid(addr); -} -#else -static int e820_range_to_nid(resource_size_t addr) -{ - return NUMA_NO_NODE; -} -#endif - static int e820_register_one(struct resource *res, void *data) { struct nd_region_desc ndr_desc; struct nvdimm_bus *nvdimm_bus = data; + int nid = phys_to_target_node(res->start); memset(&ndr_desc, 0, sizeof(ndr_desc)); ndr_desc.res = res; - ndr_desc.numa_node = e820_range_to_nid(res->start); - ndr_desc.target_node = ndr_desc.numa_node; + ndr_desc.numa_node = numa_map_to_online_node(nid); + ndr_desc.target_node = nid; set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags); if (!nvdimm_pmem_region_create(nvdimm_bus, &ndr_desc)) return -ENXIO; From b9bd80396a42d0335f6cf287d8b561c50b44a2d8 Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Sat, 1 Feb 2020 18:09:33 +0100 Subject: [PATCH 0439/4444] MAINTAINERS: clarify maintenance of nvdimm testing tool The git history shows that the files under ./tools/testing/nvdimm are being developed and maintained by the LIBNVDIMM maintainers. This was identified with a small script that finds all files only belonging to "THE REST" according to the current MAINTAINERS file, and I acted upon its output. Signed-off-by: Lukas Bulwahn Link: https://lore.kernel.org/r/20200201170933.924-1-lukas.bulwahn@gmail.com Signed-off-by: Dan Williams --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index a0d86490c2c6..6e65c79b4c07 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9569,6 +9569,7 @@ F: drivers/acpi/nfit/* F: include/linux/nd.h F: include/linux/libnvdimm.h F: include/uapi/linux/ndctl.h +F: tools/testing/nvdimm/ LICENSES and SPDX stuff M: Thomas Gleixner From c0e71d602053e4e7637e4bc7d0bc9603ea77a33f Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 23 Jan 2020 16:47:20 +0100 Subject: [PATCH 0440/4444] tools/testing/nvdimm: Fix compilation failure without CONFIG_DEV_DAX_PMEM_COMPAT When a kernel is configured without CONFIG_DEV_DAX_PMEM_COMPAT, the compilation of tools/testing/nvdimm fails with: Building modules, stage 2. MODPOST 11 modules ERROR: "dax_pmem_compat_test" [tools/testing/nvdimm/test/nfit_test.ko] undefined! Fix the problem by calling dax_pmem_compat_test() only if the kernel has the required functionality. Signed-off-by: Jan Kara Link: https://lore.kernel.org/r/20200123154720.12097-1-jack@suse.cz Signed-off-by: Dan Williams --- tools/testing/nvdimm/test/nfit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index bf6422a6af7f..a8ee5c4d41eb 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c @@ -3164,7 +3164,9 @@ static __init int nfit_test_init(void) mcsafe_test(); dax_pmem_test(); dax_pmem_core_test(); +#ifdef CONFIG_DEV_DAX_PMEM_COMPAT dax_pmem_compat_test(); +#endif nfit_test_setup(nfit_test_lookup, nfit_test_evaluate_dsm); From 6ec1587b5c172f53ff27e8c00e6ff9927d2650d4 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 20 Jan 2020 14:10:01 +0200 Subject: [PATCH 0441/4444] ARM: at91: pm: use proper master clock register offset SAM9X60's PMC has different master clock register offset than the other SoCs' PMC. Due to this, specify master clock register offset based on PMC compatible and pass it to pm_suspend.S since it is also needed in there. When PM part for SAM9X60 was published the SAM9X60's PMC (commit f6deae46039c ("clk: at91: add sam9x60 pmc driver")) wasn't integrated. Fixes: 01c7031cfa73 ("ARM: at91: pm: initial PM support for SAM9X60") Signed-off-by: Claudiu Beznea Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/1579522208-19523-2-git-send-email-claudiu.beznea@microchip.com --- arch/arm/mach-at91/pm.c | 28 +++++++++++++++++++----- arch/arm/mach-at91/pm.h | 1 + arch/arm/mach-at91/pm_data-offsets.c | 2 ++ arch/arm/mach-at91/pm_suspend.S | 32 +++++++++++++++++----------- 4 files changed, 46 insertions(+), 17 deletions(-) diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 374b9d155558..ae7b148febd9 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -736,13 +736,30 @@ backup_default: struct pmc_info { unsigned long uhp_udp_mask; + unsigned long mckr; }; static const struct pmc_info pmc_infos[] __initconst = { - { .uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP }, - { .uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP }, - { .uhp_udp_mask = AT91SAM926x_PMC_UHP }, - { .uhp_udp_mask = 0 }, + { + .uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP, + .mckr = 0x30, + }, + + { + .uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP, + .mckr = 0x30, + }, + { + .uhp_udp_mask = AT91SAM926x_PMC_UHP, + .mckr = 0x30, + }, + { .uhp_udp_mask = 0, + .mckr = 0x30, + }, + { + .uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP, + .mckr = 0x28, + }, }; static const struct of_device_id atmel_pmc_ids[] __initconst = { @@ -757,7 +774,7 @@ static const struct of_device_id atmel_pmc_ids[] __initconst = { { .compatible = "atmel,sama5d3-pmc", .data = &pmc_infos[1] }, { .compatible = "atmel,sama5d4-pmc", .data = &pmc_infos[1] }, { .compatible = "atmel,sama5d2-pmc", .data = &pmc_infos[1] }, - { .compatible = "microchip,sam9x60-pmc", .data = &pmc_infos[1] }, + { .compatible = "microchip,sam9x60-pmc", .data = &pmc_infos[4] }, { /* sentinel */ }, }; @@ -779,6 +796,7 @@ static void __init at91_pm_init(void (*pm_idle)(void)) pmc = of_id->data; soc_pm.data.uhp_udp_mask = pmc->uhp_udp_mask; + soc_pm.data.pmc_mckr_offset = pmc->mckr; if (pm_idle) arm_pm_idle = pm_idle; diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h index 9fa4f483f2b5..6f7f4236865a 100644 --- a/arch/arm/mach-at91/pm.h +++ b/arch/arm/mach-at91/pm.h @@ -33,6 +33,7 @@ struct at91_pm_data { void __iomem *sfrbu; unsigned int standby_mode; unsigned int suspend_mode; + unsigned int pmc_mckr_offset; }; #endif diff --git a/arch/arm/mach-at91/pm_data-offsets.c b/arch/arm/mach-at91/pm_data-offsets.c index f2d893c03cd9..dfcbe626865c 100644 --- a/arch/arm/mach-at91/pm_data-offsets.c +++ b/arch/arm/mach-at91/pm_data-offsets.c @@ -12,6 +12,8 @@ int main(void) DEFINE(PM_DATA_MODE, offsetof(struct at91_pm_data, mode)); DEFINE(PM_DATA_SHDWC, offsetof(struct at91_pm_data, shdwc)); DEFINE(PM_DATA_SFRBU, offsetof(struct at91_pm_data, sfrbu)); + DEFINE(PM_DATA_PMC_MCKR_OFFSET, offsetof(struct at91_pm_data, + pmc_mckr_offset)); return 0; } diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index ed57c879d4e1..52b262d56cfd 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S @@ -93,6 +93,8 @@ ENTRY(at91_pm_suspend_in_sram) str tmp1, .memtype ldr tmp1, [r0, #PM_DATA_MODE] str tmp1, .pm_mode + ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET] + str tmp1, .mckr_offset /* Both ldrne below are here to preload their address in the TLB */ ldr tmp1, [r0, #PM_DATA_SHDWC] str tmp1, .shdwc @@ -138,9 +140,10 @@ ENDPROC(at91_pm_suspend_in_sram) ENTRY(at91_backup_mode) /* Switch the master clock source to slow clock. */ ldr pmc, .pmc_base - ldr tmp1, [pmc, #AT91_PMC_MCKR] + ldr tmp2, .mckr_offset + ldr tmp1, [pmc, tmp2] bic tmp1, tmp1, #AT91_PMC_CSS - str tmp1, [pmc, #AT91_PMC_MCKR] + str tmp1, [pmc, tmp2] wait_mckrdy @@ -218,6 +221,7 @@ ENDPROC(at91_backup_mode) */ .macro at91_pm_ulp1_mode ldr pmc, .pmc_base + ldr tmp2, .mckr_offset /* Save RC oscillator state and check if it is enabled. */ ldr tmp1, [pmc, #AT91_PMC_SR] @@ -254,10 +258,10 @@ ENDPROC(at91_backup_mode) str tmp1, [pmc, #AT91_CKGR_MOR] /* Switch the master clock source to main clock */ - ldr tmp1, [pmc, #AT91_PMC_MCKR] + ldr tmp1, [pmc, tmp2] bic tmp1, tmp1, #AT91_PMC_CSS orr tmp1, tmp1, #AT91_PMC_CSS_MAIN - str tmp1, [pmc, #AT91_PMC_MCKR] + str tmp1, [pmc, tmp2] wait_mckrdy @@ -280,9 +284,9 @@ ENDPROC(at91_backup_mode) wait_moscrdy /* Switch the master clock source to slow clock */ - ldr tmp1, [pmc, #AT91_PMC_MCKR] + ldr tmp1, [pmc, tmp2] bic tmp1, tmp1, #AT91_PMC_CSS - str tmp1, [pmc, #AT91_PMC_MCKR] + str tmp1, [pmc, tmp2] wait_mckrdy @@ -296,10 +300,10 @@ ENDPROC(at91_backup_mode) wait_moscsels /* Switch the master clock source to main clock */ - ldr tmp1, [pmc, #AT91_PMC_MCKR] + ldr tmp1, [pmc, tmp2] bic tmp1, tmp1, #AT91_PMC_CSS orr tmp1, tmp1, #AT91_PMC_CSS_MAIN - str tmp1, [pmc, #AT91_PMC_MCKR] + str tmp1, [pmc, tmp2] wait_mckrdy @@ -325,16 +329,17 @@ ENDPROC(at91_backup_mode) ENTRY(at91_ulp_mode) ldr pmc, .pmc_base + ldr tmp2, .mckr_offset /* Save Master clock setting */ - ldr tmp1, [pmc, #AT91_PMC_MCKR] + ldr tmp1, [pmc, tmp2] str tmp1, .saved_mckr /* * Set the Master clock source to slow clock */ bic tmp1, tmp1, #AT91_PMC_CSS - str tmp1, [pmc, #AT91_PMC_MCKR] + str tmp1, [pmc, tmp2] wait_mckrdy @@ -355,8 +360,9 @@ ulp_exit: /* * Restore master clock setting */ - ldr tmp1, .saved_mckr - str tmp1, [pmc, #AT91_PMC_MCKR] + ldr tmp1, .mckr_offset + ldr tmp2, .saved_mckr + str tmp2, [pmc, tmp1] wait_mckrdy @@ -502,6 +508,8 @@ ENDPROC(at91_sramc_self_refresh) .word 0 .pm_mode: .word 0 +.mckr_offset: + .word 0 .saved_mckr: .word 0 .saved_sam9_lpr: From c4cae59d80f07f086967b1a67d287832e7fc281e Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 20 Jan 2020 14:10:02 +0200 Subject: [PATCH 0442/4444] ARM: at91: pm: revert do not disable/enable PLLA for ULP modes This reverts commit 2725d70aa5138284ba2cebf0ef51dd23e0c9ea21 ("ARM: at91: pm: do not disable/enable PLLA for ULP modes"). This is because PLLA is the clock source for CPU, PLLA should be disabled/enabled in the final/first phase of suspend/resume so that the power consumption in suspend/resume to be minimal and suspend/resume time to be minimized. Signed-off-by: Claudiu Beznea Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/1579522208-19523-3-git-send-email-claudiu.beznea@microchip.com --- arch/arm/mach-at91/pm_suspend.S | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index 52b262d56cfd..bfb3aab8859e 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S @@ -46,6 +46,15 @@ tmp2 .req r5 beq 1b .endm +/* + * Wait until PLLA has locked. + */ + .macro wait_pllalock +1: ldr tmp1, [pmc, #AT91_PMC_SR] + tst tmp1, #AT91_PMC_LOCKA + beq 1b + .endm + /* * Put the processor to enter the idle state */ @@ -343,6 +352,14 @@ ENTRY(at91_ulp_mode) wait_mckrdy + /* Save PLLA setting and disable it */ + ldr tmp1, [pmc, #AT91_CKGR_PLLAR] + str tmp1, .saved_pllar + + mov tmp1, #AT91_PMC_PLLCOUNT + orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ + str tmp1, [pmc, #AT91_CKGR_PLLAR] + ldr r0, .pm_mode cmp r0, #AT91_PM_ULP1 beq ulp1_mode @@ -357,6 +374,18 @@ ulp1_mode: ulp_exit: ldr pmc, .pmc_base + /* Restore PLLA setting */ + ldr tmp1, .saved_pllar + str tmp1, [pmc, #AT91_CKGR_PLLAR] + + tst tmp1, #(AT91_PMC_MUL & 0xff0000) + bne 3f + tst tmp1, #(AT91_PMC_MUL & ~0xff0000) + beq 4f +3: + wait_pllalock +4: + /* * Restore master clock setting */ @@ -512,6 +541,8 @@ ENDPROC(at91_sramc_self_refresh) .word 0 .saved_mckr: .word 0 +.saved_pllar: + .word 0 .saved_sam9_lpr: .word 0 .saved_sam9_lpr1: From 63d1a6b107d503c7bb6021bcc5ff86568ada91c9 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 20 Jan 2020 14:10:03 +0200 Subject: [PATCH 0443/4444] ARM: at91: pm: add macros for plla disable/enable Add macros for PLLA disable and enable (in disable macro the PLLA state will also be saved). This prepares the field for PLLA disable/enable for suspend/resume on SAM9X60. Signed-off-by: Claudiu Beznea Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/1579522208-19523-4-git-send-email-claudiu.beznea@microchip.com --- arch/arm/mach-at91/pm_suspend.S | 57 +++++++++++++++++---------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index bfb3aab8859e..64460b4e0fc1 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S @@ -46,15 +46,6 @@ tmp2 .req r5 beq 1b .endm -/* - * Wait until PLLA has locked. - */ - .macro wait_pllalock -1: ldr tmp1, [pmc, #AT91_PMC_SR] - tst tmp1, #AT91_PMC_LOCKA - beq 1b - .endm - /* * Put the processor to enter the idle state */ @@ -336,6 +327,34 @@ ENDPROC(at91_backup_mode) 3: .endm +.macro at91_plla_disable + /* Save PLLA setting and disable it */ + ldr tmp1, [pmc, #AT91_CKGR_PLLAR] + str tmp1, .saved_pllar + + /* Disable PLLA. */ + mov tmp1, #AT91_PMC_PLLCOUNT + orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ + str tmp1, [pmc, #AT91_CKGR_PLLAR] +.endm + +.macro at91_plla_enable + /* Restore PLLA setting */ + ldr tmp1, .saved_pllar + str tmp1, [pmc, #AT91_CKGR_PLLAR] + + /* Enable PLLA. */ + tst tmp1, #(AT91_PMC_MUL & 0xff0000) + bne 1f + tst tmp1, #(AT91_PMC_MUL & ~0xff0000) + beq 2f + +1: ldr tmp1, [pmc, #AT91_PMC_SR] + tst tmp1, #AT91_PMC_LOCKA + beq 1b +2: +.endm + ENTRY(at91_ulp_mode) ldr pmc, .pmc_base ldr tmp2, .mckr_offset @@ -352,13 +371,7 @@ ENTRY(at91_ulp_mode) wait_mckrdy - /* Save PLLA setting and disable it */ - ldr tmp1, [pmc, #AT91_CKGR_PLLAR] - str tmp1, .saved_pllar - - mov tmp1, #AT91_PMC_PLLCOUNT - orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ - str tmp1, [pmc, #AT91_CKGR_PLLAR] + at91_plla_disable ldr r0, .pm_mode cmp r0, #AT91_PM_ULP1 @@ -374,17 +387,7 @@ ulp1_mode: ulp_exit: ldr pmc, .pmc_base - /* Restore PLLA setting */ - ldr tmp1, .saved_pllar - str tmp1, [pmc, #AT91_CKGR_PLLAR] - - tst tmp1, #(AT91_PMC_MUL & 0xff0000) - bne 3f - tst tmp1, #(AT91_PMC_MUL & ~0xff0000) - beq 4f -3: - wait_pllalock -4: + at91_plla_enable /* * Restore master clock setting From 0be298a939b748256035f66716fca409dd26d0dc Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 20 Jan 2020 14:10:04 +0200 Subject: [PATCH 0444/4444] ARM: at91: pm: add pmc_version member to at91_pm_data This will be used to differentiate b/w different PLLs settings to be applied in the final/first steps of the suspend/resume process by doing PLL specific configurations. Signed-off-by: Claudiu Beznea Acked-by: Stephen Boyd Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/1579522208-19523-5-git-send-email-claudiu.beznea@microchip.com --- arch/arm/mach-at91/pm.c | 7 +++++++ arch/arm/mach-at91/pm.h | 1 + arch/arm/mach-at91/pm_data-offsets.c | 2 ++ arch/arm/mach-at91/pm_suspend.S | 4 ++++ include/linux/clk/at91_pmc.h | 3 +++ 5 files changed, 17 insertions(+) diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index ae7b148febd9..074bde64064e 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -737,28 +737,34 @@ backup_default: struct pmc_info { unsigned long uhp_udp_mask; unsigned long mckr; + unsigned long version; }; static const struct pmc_info pmc_infos[] __initconst = { { .uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP, .mckr = 0x30, + .version = AT91_PMC_V1, }, { .uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP, .mckr = 0x30, + .version = AT91_PMC_V1, }, { .uhp_udp_mask = AT91SAM926x_PMC_UHP, .mckr = 0x30, + .version = AT91_PMC_V1, }, { .uhp_udp_mask = 0, .mckr = 0x30, + .version = AT91_PMC_V1, }, { .uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP, .mckr = 0x28, + .version = AT91_PMC_V2, }, }; @@ -797,6 +803,7 @@ static void __init at91_pm_init(void (*pm_idle)(void)) pmc = of_id->data; soc_pm.data.uhp_udp_mask = pmc->uhp_udp_mask; soc_pm.data.pmc_mckr_offset = pmc->mckr; + soc_pm.data.pmc_version = pmc->version; if (pm_idle) arm_pm_idle = pm_idle; diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h index 6f7f4236865a..218e8d1a30fb 100644 --- a/arch/arm/mach-at91/pm.h +++ b/arch/arm/mach-at91/pm.h @@ -34,6 +34,7 @@ struct at91_pm_data { unsigned int standby_mode; unsigned int suspend_mode; unsigned int pmc_mckr_offset; + unsigned int pmc_version; }; #endif diff --git a/arch/arm/mach-at91/pm_data-offsets.c b/arch/arm/mach-at91/pm_data-offsets.c index dfcbe626865c..82089ff258c0 100644 --- a/arch/arm/mach-at91/pm_data-offsets.c +++ b/arch/arm/mach-at91/pm_data-offsets.c @@ -14,6 +14,8 @@ int main(void) DEFINE(PM_DATA_SFRBU, offsetof(struct at91_pm_data, sfrbu)); DEFINE(PM_DATA_PMC_MCKR_OFFSET, offsetof(struct at91_pm_data, pmc_mckr_offset)); + DEFINE(PM_DATA_PMC_VERSION, offsetof(struct at91_pm_data, + pmc_version)); return 0; } diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index 64460b4e0fc1..5fa0c2aa10f7 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S @@ -95,6 +95,8 @@ ENTRY(at91_pm_suspend_in_sram) str tmp1, .pm_mode ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET] str tmp1, .mckr_offset + ldr tmp1, [r0, #PM_DATA_PMC_VERSION] + str tmp1, .pmc_version /* Both ldrne below are here to preload their address in the TLB */ ldr tmp1, [r0, #PM_DATA_SHDWC] str tmp1, .shdwc @@ -542,6 +544,8 @@ ENDPROC(at91_sramc_self_refresh) .word 0 .mckr_offset: .word 0 +.pmc_version: + .word 0 .saved_mckr: .word 0 .saved_pllar: diff --git a/include/linux/clk/at91_pmc.h b/include/linux/clk/at91_pmc.h index 390437887b46..f3d691fc5f29 100644 --- a/include/linux/clk/at91_pmc.h +++ b/include/linux/clk/at91_pmc.h @@ -12,6 +12,9 @@ #ifndef AT91_PMC_H #define AT91_PMC_H +#define AT91_PMC_V1 (1) /* PMC version 1 */ +#define AT91_PMC_V2 (2) /* PMC version 2 [SAM9X60] */ + #define AT91_PMC_SCER 0x00 /* System Clock Enable Register */ #define AT91_PMC_SCDR 0x04 /* System Clock Disable Register */ From 4a877560fe047c08b31e698a2668878bbead5f35 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 20 Jan 2020 14:10:05 +0200 Subject: [PATCH 0445/4444] ARM: at91: pm: s/sfr/sfrbu in pm_suspend.S s/sfr/sfrbu in pm_suspend.S. Signed-off-by: Claudiu Beznea Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/1579522208-19523-6-git-send-email-claudiu.beznea@microchip.com --- arch/arm/mach-at91/pm_suspend.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index 5fa0c2aa10f7..c898071e0c0b 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S @@ -103,7 +103,7 @@ ENTRY(at91_pm_suspend_in_sram) cmp tmp1, #0 ldrne tmp2, [tmp1, #0] ldr tmp1, [r0, #PM_DATA_SFRBU] - str tmp1, .sfr + str tmp1, .sfrbu cmp tmp1, #0 ldrne tmp2, [tmp1, #0x10] @@ -150,7 +150,7 @@ ENTRY(at91_backup_mode) wait_mckrdy /*BUMEN*/ - ldr r0, .sfr + ldr r0, .sfrbu mov tmp1, #0x1 str tmp1, [r0, #0x10] @@ -536,7 +536,7 @@ ENDPROC(at91_sramc_self_refresh) .word 0 .shdwc: .word 0 -.sfr: +.sfrbu: .word 0 .memtype: .word 0 From e13208ab5d938e51e46ba44a1dec8073142c3d8c Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 20 Jan 2020 14:10:06 +0200 Subject: [PATCH 0446/4444] clk: at91: move sam9x60's PLL register offsets to PMC header Move SAM9X60's PLL register offsets to PMC header so that the definitions would also be available from arch/arm/mach-at91/pm_suspend.S. This is necessary to disable/enable PLLA for SAM9X60 on suspend/resume. Signed-off-by: Claudiu Beznea Acked-by: Stephen Boyd Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/1579522208-19523-7-git-send-email-claudiu.beznea@microchip.com --- drivers/clk/at91/clk-sam9x60-pll.c | 91 ++++++++++++------------------ include/linux/clk/at91_pmc.h | 20 +++++++ 2 files changed, 57 insertions(+), 54 deletions(-) diff --git a/drivers/clk/at91/clk-sam9x60-pll.c b/drivers/clk/at91/clk-sam9x60-pll.c index dfb354a5ff18..e699803986e5 100644 --- a/drivers/clk/at91/clk-sam9x60-pll.c +++ b/drivers/clk/at91/clk-sam9x60-pll.c @@ -14,27 +14,8 @@ #include "pmc.h" -#define PMC_PLL_CTRL0 0xc -#define PMC_PLL_CTRL0_DIV_MSK GENMASK(7, 0) -#define PMC_PLL_CTRL0_ENPLL BIT(28) -#define PMC_PLL_CTRL0_ENPLLCK BIT(29) -#define PMC_PLL_CTRL0_ENLOCK BIT(31) - -#define PMC_PLL_CTRL1 0x10 -#define PMC_PLL_CTRL1_FRACR_MSK GENMASK(21, 0) -#define PMC_PLL_CTRL1_MUL_MSK GENMASK(30, 24) - -#define PMC_PLL_ACR 0x18 -#define PMC_PLL_ACR_DEFAULT_UPLL 0x12020010UL -#define PMC_PLL_ACR_DEFAULT_PLLA 0x00020010UL -#define PMC_PLL_ACR_UTMIVR BIT(12) -#define PMC_PLL_ACR_UTMIBG BIT(13) -#define PMC_PLL_ACR_LOOP_FILTER_MSK GENMASK(31, 24) - -#define PMC_PLL_UPDT 0x1c -#define PMC_PLL_UPDT_UPDATE BIT(8) - -#define PMC_PLL_ISR0 0xec +#define PMC_PLL_CTRL0_DIV_MSK GENMASK(7, 0) +#define PMC_PLL_CTRL1_MUL_MSK GENMASK(30, 24) #define PLL_DIV_MAX (FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, UINT_MAX) + 1) #define UPLL_DIV 2 @@ -59,7 +40,7 @@ static inline bool sam9x60_pll_ready(struct regmap *regmap, int id) { unsigned int status; - regmap_read(regmap, PMC_PLL_ISR0, &status); + regmap_read(regmap, AT91_PMC_PLL_ISR0, &status); return !!(status & BIT(id)); } @@ -74,12 +55,12 @@ static int sam9x60_pll_prepare(struct clk_hw *hw) u32 val; spin_lock_irqsave(pll->lock, flags); - regmap_write(regmap, PMC_PLL_UPDT, pll->id); + regmap_write(regmap, AT91_PMC_PLL_UPDT, pll->id); - regmap_read(regmap, PMC_PLL_CTRL0, &val); + regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val); div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, val); - regmap_read(regmap, PMC_PLL_CTRL1, &val); + regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val); mul = FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, val); if (sam9x60_pll_ready(regmap, pll->id) && @@ -88,39 +69,39 @@ static int sam9x60_pll_prepare(struct clk_hw *hw) return 0; } - /* Recommended value for PMC_PLL_ACR */ + /* Recommended value for AT91_PMC_PLL_ACR */ if (pll->characteristics->upll) - val = PMC_PLL_ACR_DEFAULT_UPLL; + val = AT91_PMC_PLL_ACR_DEFAULT_UPLL; else - val = PMC_PLL_ACR_DEFAULT_PLLA; - regmap_write(regmap, PMC_PLL_ACR, val); + val = AT91_PMC_PLL_ACR_DEFAULT_PLLA; + regmap_write(regmap, AT91_PMC_PLL_ACR, val); - regmap_write(regmap, PMC_PLL_CTRL1, + regmap_write(regmap, AT91_PMC_PLL_CTRL1, FIELD_PREP(PMC_PLL_CTRL1_MUL_MSK, pll->mul)); if (pll->characteristics->upll) { /* Enable the UTMI internal bandgap */ - val |= PMC_PLL_ACR_UTMIBG; - regmap_write(regmap, PMC_PLL_ACR, val); + val |= AT91_PMC_PLL_ACR_UTMIBG; + regmap_write(regmap, AT91_PMC_PLL_ACR, val); udelay(10); /* Enable the UTMI internal regulator */ - val |= PMC_PLL_ACR_UTMIVR; - regmap_write(regmap, PMC_PLL_ACR, val); + val |= AT91_PMC_PLL_ACR_UTMIVR; + regmap_write(regmap, AT91_PMC_PLL_ACR, val); udelay(10); } - regmap_update_bits(regmap, PMC_PLL_UPDT, - PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE); + regmap_update_bits(regmap, AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_UPDATE, AT91_PMC_PLL_UPDT_UPDATE); - regmap_write(regmap, PMC_PLL_CTRL0, - PMC_PLL_CTRL0_ENLOCK | PMC_PLL_CTRL0_ENPLL | - PMC_PLL_CTRL0_ENPLLCK | pll->div); + regmap_write(regmap, AT91_PMC_PLL_CTRL0, + AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL | + AT91_PMC_PLL_CTRL0_ENPLLCK | pll->div); - regmap_update_bits(regmap, PMC_PLL_UPDT, - PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE); + regmap_update_bits(regmap, AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_UPDATE, AT91_PMC_PLL_UPDT_UPDATE); while (!sam9x60_pll_ready(regmap, pll->id)) cpu_relax(); @@ -144,22 +125,24 @@ static void sam9x60_pll_unprepare(struct clk_hw *hw) spin_lock_irqsave(pll->lock, flags); - regmap_write(pll->regmap, PMC_PLL_UPDT, pll->id); + regmap_write(pll->regmap, AT91_PMC_PLL_UPDT, pll->id); - regmap_update_bits(pll->regmap, PMC_PLL_CTRL0, - PMC_PLL_CTRL0_ENPLLCK, 0); + regmap_update_bits(pll->regmap, AT91_PMC_PLL_CTRL0, + AT91_PMC_PLL_CTRL0_ENPLLCK, 0); - regmap_update_bits(pll->regmap, PMC_PLL_UPDT, - PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE); + regmap_update_bits(pll->regmap, AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_UPDATE, AT91_PMC_PLL_UPDT_UPDATE); - regmap_update_bits(pll->regmap, PMC_PLL_CTRL0, PMC_PLL_CTRL0_ENPLL, 0); + regmap_update_bits(pll->regmap, AT91_PMC_PLL_CTRL0, + AT91_PMC_PLL_CTRL0_ENPLL, 0); if (pll->characteristics->upll) - regmap_update_bits(pll->regmap, PMC_PLL_ACR, - PMC_PLL_ACR_UTMIBG | PMC_PLL_ACR_UTMIVR, 0); + regmap_update_bits(pll->regmap, AT91_PMC_PLL_ACR, + AT91_PMC_PLL_ACR_UTMIBG | + AT91_PMC_PLL_ACR_UTMIVR, 0); - regmap_update_bits(pll->regmap, PMC_PLL_UPDT, - PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE); + regmap_update_bits(pll->regmap, AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_UPDATE, AT91_PMC_PLL_UPDT_UPDATE); spin_unlock_irqrestore(pll->lock, flags); } @@ -316,10 +299,10 @@ sam9x60_clk_register_pll(struct regmap *regmap, spinlock_t *lock, pll->regmap = regmap; pll->lock = lock; - regmap_write(regmap, PMC_PLL_UPDT, id); - regmap_read(regmap, PMC_PLL_CTRL0, &pllr); + regmap_write(regmap, AT91_PMC_PLL_UPDT, id); + regmap_read(regmap, AT91_PMC_PLL_CTRL0, &pllr); pll->div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, pllr); - regmap_read(regmap, PMC_PLL_CTRL1, &pllr); + regmap_read(regmap, AT91_PMC_PLL_CTRL1, &pllr); pll->mul = FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, pllr); hw = &pll->hw; diff --git a/include/linux/clk/at91_pmc.h b/include/linux/clk/at91_pmc.h index f3d691fc5f29..49a53a137610 100644 --- a/include/linux/clk/at91_pmc.h +++ b/include/linux/clk/at91_pmc.h @@ -33,16 +33,34 @@ #define AT91_PMC_HCK0 (1 << 16) /* AHB Clock (USB host) [AT91SAM9261 only] */ #define AT91_PMC_HCK1 (1 << 17) /* AHB Clock (LCD) [AT91SAM9261 only] */ +#define AT91_PMC_PLL_CTRL0 0x0C /* PLL Control Register 0 [for SAM9X60] */ +#define AT91_PMC_PLL_CTRL0_ENPLL (1 << 28) /* Enable PLL */ +#define AT91_PMC_PLL_CTRL0_ENPLLCK (1 << 29) /* Enable PLL clock for PMC */ +#define AT91_PMC_PLL_CTRL0_ENLOCK (1 << 31) /* Enable PLL lock */ + +#define AT91_PMC_PLL_CTRL1 0x10 /* PLL Control Register 1 [for SAM9X60] */ + #define AT91_PMC_PCER 0x10 /* Peripheral Clock Enable Register */ #define AT91_PMC_PCDR 0x14 /* Peripheral Clock Disable Register */ #define AT91_PMC_PCSR 0x18 /* Peripheral Clock Status Register */ +#define AT91_PMC_PLL_ACR 0x18 /* PLL Analog Control Register [for SAM9X60] */ +#define AT91_PMC_PLL_ACR_DEFAULT_UPLL 0x12020010UL /* Default PLL ACR value for UPLL */ +#define AT91_PMC_PLL_ACR_DEFAULT_PLLA 0x00020010UL /* Default PLL ACR value for PLLA */ +#define AT91_PMC_PLL_ACR_UTMIVR (1 << 12) /* UPLL Voltage regulator Control */ +#define AT91_PMC_PLL_ACR_UTMIBG (1 << 13) /* UPLL Bandgap Control */ + #define AT91_CKGR_UCKR 0x1C /* UTMI Clock Register [some SAM9] */ #define AT91_PMC_UPLLEN (1 << 16) /* UTMI PLL Enable */ #define AT91_PMC_UPLLCOUNT (0xf << 20) /* UTMI PLL Start-up Time */ #define AT91_PMC_BIASEN (1 << 24) /* UTMI BIAS Enable */ #define AT91_PMC_BIASCOUNT (0xf << 28) /* UTMI BIAS Start-up Time */ +#define AT91_PMC_PLL_UPDT 0x1C /* PMC PLL update register [for SAM9X60] */ +#define AT91_PMC_PLL_UPDT_UPDATE (1 << 8) /* Update PLL settings */ +#define AT91_PMC_PLL_UPDT_ID (1 << 0) /* PLL ID */ +#define AT91_PMC_PLL_UPDT_STUPTIM (0xff << 16) /* Startup time */ + #define AT91_CKGR_MOR 0x20 /* Main Oscillator Register [not on SAM9RL] */ #define AT91_PMC_MOSCEN (1 << 0) /* Main Oscillator Enable */ #define AT91_PMC_OSCBYPASS (1 << 1) /* Oscillator Bypass */ @@ -183,6 +201,8 @@ #define AT91_PMC_WPVS (0x1 << 0) /* Write Protect Violation Status */ #define AT91_PMC_WPVSRC (0xffff << 8) /* Write Protect Violation Source */ +#define AT91_PMC_PLL_ISR0 0xEC /* PLL Interrupt Status Register 0 [SAM9X60 only] */ + #define AT91_PMC_PCER1 0x100 /* Peripheral Clock Enable Register 1 [SAMA5 only]*/ #define AT91_PMC_PCDR1 0x104 /* Peripheral Clock Enable Register 1 */ #define AT91_PMC_PCSR1 0x108 /* Peripheral Clock Enable Register 1 */ From 4fd36e4583922bf4e5c37a20d5d3fa7bc11d59fe Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 20 Jan 2020 14:10:07 +0200 Subject: [PATCH 0447/4444] ARM: at91: pm: add plla disable/enable support for sam9x60 Add PLLA enable/disable support for SAM9X60. Signed-off-by: Claudiu Beznea Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/1579522208-19523-8-git-send-email-claudiu.beznea@microchip.com --- arch/arm/mach-at91/pm_suspend.S | 117 ++++++++++++++++++++++++++++++-- 1 file changed, 113 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index c898071e0c0b..4e9eb4f57f16 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S @@ -18,6 +18,7 @@ pmc .req r0 tmp1 .req r4 tmp2 .req r5 +tmp3 .req r6 /* * Wait until master clock is ready (after switching master clock source) @@ -331,6 +332,61 @@ ENDPROC(at91_backup_mode) .macro at91_plla_disable /* Save PLLA setting and disable it */ + ldr tmp1, .pmc_version + cmp tmp1, #AT91_PMC_V1 + beq 1f + +#ifdef CONFIG_SOC_SAM9X60 + /* Save PLLA settings. */ + ldr tmp2, [pmc, #AT91_PMC_PLL_UPDT] + bic tmp2, tmp2, #AT91_PMC_PLL_UPDT_ID + str tmp2, [pmc, #AT91_PMC_PLL_UPDT] + + /* save div. */ + mov tmp1, #0 + ldr tmp2, [pmc, #AT91_PMC_PLL_CTRL0] + bic tmp2, tmp2, #0xffffff00 + orr tmp1, tmp1, tmp2 + + /* save mul. */ + ldr tmp2, [pmc, #AT91_PMC_PLL_CTRL1] + bic tmp2, tmp2, #0xffffff + orr tmp1, tmp1, tmp2 + str tmp1, .saved_pllar + + /* step 2. */ + ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] + bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE + bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID + str tmp1, [pmc, #AT91_PMC_PLL_UPDT] + + /* step 3. */ + ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0] + bic tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK + orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL + str tmp1, [pmc, #AT91_PMC_PLL_CTRL0] + + /* step 4. */ + ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] + orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE + bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID + str tmp1, [pmc, #AT91_PMC_PLL_UPDT] + + /* step 5. */ + ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0] + bic tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL + str tmp1, [pmc, #AT91_PMC_PLL_CTRL0] + + /* step 7. */ + ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] + orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE + bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID + str tmp1, [pmc, #AT91_PMC_PLL_UPDT] + + b 2f +#endif + +1: /* Save PLLA setting and disable it */ ldr tmp1, [pmc, #AT91_CKGR_PLLAR] str tmp1, .saved_pllar @@ -338,17 +394,70 @@ ENDPROC(at91_backup_mode) mov tmp1, #AT91_PMC_PLLCOUNT orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ str tmp1, [pmc, #AT91_CKGR_PLLAR] +2: .endm .macro at91_plla_enable + ldr tmp2, .saved_pllar + ldr tmp3, .pmc_version + cmp tmp3, #AT91_PMC_V1 + beq 4f + +#ifdef CONFIG_SOC_SAM9X60 + /* step 1. */ + ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] + bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID + bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE + str tmp1, [pmc, #AT91_PMC_PLL_UPDT] + + /* step 2. */ + ldr tmp1, =#AT91_PMC_PLL_ACR_DEFAULT_PLLA + str tmp1, [pmc, #AT91_PMC_PLL_ACR] + + /* step 3. */ + ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL1] + mov tmp3, tmp2 + bic tmp3, tmp3, #0xffffff + orr tmp1, tmp1, tmp3 + str tmp1, [pmc, #AT91_PMC_PLL_CTRL1] + + /* step 8. */ + ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] + bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID + orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE + str tmp1, [pmc, #AT91_PMC_PLL_UPDT] + + /* step 9. */ + ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0] + orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENLOCK + orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL + orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK + bic tmp1, tmp1, #0xff + mov tmp3, tmp2 + bic tmp3, tmp3, #0xffffff00 + orr tmp1, tmp1, tmp3 + str tmp1, [pmc, #AT91_PMC_PLL_CTRL0] + + /* step 10. */ + ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] + orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE + bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID + str tmp1, [pmc, #AT91_PMC_PLL_UPDT] + + /* step 11. */ +3: ldr tmp1, [pmc, #AT91_PMC_PLL_ISR0] + tst tmp1, #0x1 + beq 3b + b 2f +#endif + /* Restore PLLA setting */ - ldr tmp1, .saved_pllar - str tmp1, [pmc, #AT91_CKGR_PLLAR] +4: str tmp2, [pmc, #AT91_CKGR_PLLAR] /* Enable PLLA. */ - tst tmp1, #(AT91_PMC_MUL & 0xff0000) + tst tmp2, #(AT91_PMC_MUL & 0xff0000) bne 1f - tst tmp1, #(AT91_PMC_MUL & ~0xff0000) + tst tmp2, #(AT91_PMC_MUL & ~0xff0000) beq 2f 1: ldr tmp1, [pmc, #AT91_PMC_SR] From bb1a0e87e1c54cd884e9b92b1cec06b186edc7a0 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 20 Jan 2020 14:10:08 +0200 Subject: [PATCH 0448/4444] ARM: at91: pm: add quirk for sam9x60's ulp1 On SAM9X60 2 nop operations has to be introduced after setting WAITMODE bit in CKGR_MOR. Signed-off-by: Claudiu Beznea Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/1579522208-19523-9-git-send-email-claudiu.beznea@microchip.com --- arch/arm/mach-at91/pm_suspend.S | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index 4e9eb4f57f16..be9764e8d3fa 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S @@ -275,6 +275,10 @@ ENDPROC(at91_backup_mode) orr tmp1, tmp1, #AT91_PMC_KEY str tmp1, [pmc, #AT91_CKGR_MOR] + /* Quirk for SAM9X60's PMC */ + nop + nop + wait_mckrdy /* Enable the crystal oscillator */ From a4877a6fb2bd2e356a5eaacd86d6b6d69ff84e69 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Tue, 18 Feb 2020 11:38:24 +0100 Subject: [PATCH 0449/4444] ASoC: soc-pcm: fix regression in soc_new_pcm() Commit af4bac11531f ("ASoC: soc-pcm: crash in snd_soc_dapm_new_dai") swapped the SNDRV_PCM_STREAM_* parameter in the snd_soc_dai_stream_valid(cpu_dai, ...) checks. But that works only for codec2codec links. For normal links it breaks registration of playback/capture-only PCM devices. E.g. on qcom/apq8016_sbc there is usually one playback-only and one capture-only PCM device, but they disappeared after the commit. The codec2codec case was added in commit a342031cdd08 ("ASoC: create pcm for codec2codec links as well") as an extra check (e.g. `playback = playback && cpu_playback->channels_min`). We should be able to simplify the code by checking directly for the correct stream type in the loop. This also fixes the regression because we check for PLAYBACK for both codec and cpu dai again when codec2codec is not used. Fixes: af4bac11531f ("ASoC: soc-pcm: crash in snd_soc_dapm_new_dai") Signed-off-by: Stephan Gerhold Tested-by: Jerome Brunet Reviewed-by: Jerome Brunet Cc: Jerome Brunet Cc: Sameer Pujar Link: https://lore.kernel.org/r/20200218103824.26708-1-stephan@gerhold.net Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 6630fadd6e09..65a3856be250 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2858,22 +2858,19 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) capture = rtd->dai_link->dpcm_capture; } else { /* Adapt stream for codec2codec links */ - struct snd_soc_pcm_stream *cpu_capture = rtd->dai_link->params ? - &cpu_dai->driver->playback : &cpu_dai->driver->capture; - struct snd_soc_pcm_stream *cpu_playback = rtd->dai_link->params ? - &cpu_dai->driver->capture : &cpu_dai->driver->playback; + int cpu_capture = rtd->dai_link->params ? + SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE; + int cpu_playback = rtd->dai_link->params ? + SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; for_each_rtd_codec_dai(rtd, i, codec_dai) { if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && - snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE)) + snd_soc_dai_stream_valid(cpu_dai, cpu_playback)) playback = 1; if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && - snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK)) + snd_soc_dai_stream_valid(cpu_dai, cpu_capture)) capture = 1; } - - capture = capture && cpu_capture->channels_min; - playback = playback && cpu_playback->channels_min; } if (rtd->dai_link->playback_only) { From a137e9b620bcf3925a8d72dd7ba723910d0bf976 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Sun, 16 Feb 2020 11:27:45 +0800 Subject: [PATCH 0450/4444] rtc: snvs: Remove unused include of of_device.h There is nothing in use from of_device.h, remove it. Signed-off-by: Anson Huang Link: https://lore.kernel.org/r/1581823666-16944-1-git-send-email-Anson.Huang@nxp.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-snvs.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index 757f4daa7181..7630089a113c 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include From 386dd54b3a2eedb91aa6e465e7c3a57db04f3960 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 18 Feb 2020 15:39:16 +0100 Subject: [PATCH 0451/4444] ALSA: core: Expand DMA buffer information Update DMA buffer definition for snd_compr_runtime so it is represented similarly as in snd_pcm_runtime. While at it, modify snd_compr_set_runtime_buffer to account for newly added members. Signed-off-by: Cezary Rojewski Reviewed-by: Takashi Iwai Acked-by: Vinod Koul Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200218143924.10565-2-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- include/sound/compress_driver.h | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index bc88d6f964da..00f633c0c3ba 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -23,7 +23,6 @@ struct snd_compr_ops; * struct snd_compr_runtime: runtime stream description * @state: stream state * @ops: pointer to DSP callbacks - * @dma_buffer_p: runtime dma buffer pointer * @buffer: pointer to kernel buffer, valid only when not in mmap mode or * DSP doesn't implement copy * @buffer_size: size of the above buffer @@ -34,11 +33,14 @@ struct snd_compr_ops; * @total_bytes_transferred: cumulative bytes transferred by offload DSP * @sleep: poll sleep * @private_data: driver private data pointer + * @dma_area: virtual buffer address + * @dma_addr: physical buffer address (not accessible from main CPU) + * @dma_bytes: size of DMA area + * @dma_buffer_p: runtime dma buffer pointer */ struct snd_compr_runtime { snd_pcm_state_t state; struct snd_compr_ops *ops; - struct snd_dma_buffer *dma_buffer_p; void *buffer; u64 buffer_size; u32 fragment_size; @@ -47,6 +49,11 @@ struct snd_compr_runtime { u64 total_bytes_transferred; wait_queue_head_t sleep; void *private_data; + + unsigned char *dma_area; + dma_addr_t dma_addr; + size_t dma_bytes; + struct snd_dma_buffer *dma_buffer_p; }; /** @@ -180,19 +187,29 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream) /** * snd_compr_set_runtime_buffer - Set the Compress runtime buffer - * @substream: compress substream to set + * @stream: compress stream to set * @bufp: the buffer information, NULL to clear * * Copy the buffer information to runtime buffer when @bufp is non-NULL. * Otherwise it clears the current buffer information. */ -static inline void snd_compr_set_runtime_buffer( - struct snd_compr_stream *substream, - struct snd_dma_buffer *bufp) +static inline void +snd_compr_set_runtime_buffer(struct snd_compr_stream *stream, + struct snd_dma_buffer *bufp) { - struct snd_compr_runtime *runtime = substream->runtime; + struct snd_compr_runtime *runtime = stream->runtime; - runtime->dma_buffer_p = bufp; + if (bufp) { + runtime->dma_buffer_p = bufp; + runtime->dma_area = bufp->area; + runtime->dma_addr = bufp->addr; + runtime->dma_bytes = bufp->bytes; + } else { + runtime->dma_buffer_p = NULL; + runtime->dma_area = NULL; + runtime->dma_addr = 0; + runtime->dma_bytes = 0; + } } int snd_compr_stop_error(struct snd_compr_stream *stream, From b9759ef2fd1acb0d3f3dce7991c44a4c5e9e68a3 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 18 Feb 2020 15:39:17 +0100 Subject: [PATCH 0452/4444] ALSA: core: Implement compress page allocation and free routines Add simple malloc and free methods for memory management for compress streams. Based on snd_pcm_lib_malloc_pages and snd_pcm_lib_free_pages implementation. Signed-off-by: Divya Prakash Signed-off-by: Cezary Rojewski Reviewed-by: Takashi Iwai Acked-by: Vinod Koul Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200218143924.10565-3-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- include/sound/compress_driver.h | 5 ++++ sound/core/compress_offload.c | 42 +++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index 00f633c0c3ba..6ce8effa0b12 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -67,6 +67,7 @@ struct snd_compr_runtime { * @metadata_set: metadata set flag, true when set * @next_track: has userspace signal next track transition, true when set * @private_data: pointer to DSP private data + * @dma_buffer: allocated buffer if any */ struct snd_compr_stream { const char *name; @@ -78,6 +79,7 @@ struct snd_compr_stream { bool metadata_set; bool next_track; void *private_data; + struct snd_dma_buffer dma_buffer; }; /** @@ -212,6 +214,9 @@ snd_compr_set_runtime_buffer(struct snd_compr_stream *stream, } } +int snd_compr_malloc_pages(struct snd_compr_stream *stream, size_t size); +int snd_compr_free_pages(struct snd_compr_stream *stream); + int snd_compr_stop_error(struct snd_compr_stream *stream, snd_pcm_state_t state); diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 9de1c9a0173e..509290f2efa8 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -488,6 +488,48 @@ out: } #endif /* !COMPR_CODEC_CAPS_OVERFLOW */ +int snd_compr_malloc_pages(struct snd_compr_stream *stream, size_t size) +{ + struct snd_dma_buffer *dmab; + int ret; + + if (snd_BUG_ON(!(stream) || !(stream)->runtime)) + return -EINVAL; + dmab = kzalloc(sizeof(*dmab), GFP_KERNEL); + if (!dmab) + return -ENOMEM; + dmab->dev = stream->dma_buffer.dev; + ret = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev, size, dmab); + if (ret < 0) { + kfree(dmab); + return ret; + } + + snd_compr_set_runtime_buffer(stream, dmab); + stream->runtime->dma_bytes = size; + return 1; +} +EXPORT_SYMBOL(snd_compr_malloc_pages); + +int snd_compr_free_pages(struct snd_compr_stream *stream) +{ + struct snd_compr_runtime *runtime = stream->runtime; + + if (snd_BUG_ON(!(stream) || !(stream)->runtime)) + return -EINVAL; + if (runtime->dma_area == NULL) + return 0; + if (runtime->dma_buffer_p != &stream->dma_buffer) { + /* It's a newly allocated buffer. Release it now. */ + snd_dma_free_pages(runtime->dma_buffer_p); + kfree(runtime->dma_buffer_p); + } + + snd_compr_set_runtime_buffer(stream, NULL); + return 0; +} +EXPORT_SYMBOL(snd_compr_free_pages); + /* revisit this with snd_pcm_preallocate_xxx */ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream, struct snd_compr_params *params) From 4a9ce6e4d9fb9c4acc44f647a68e59ea50ff1caf Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 18 Feb 2020 15:39:18 +0100 Subject: [PATCH 0453/4444] ASoC: SOF: Intel: Account for compress streams when servicing IRQs Update stream irq handler definition to correctly set hdac_stream current position when servicing stream interrupts for compress streams. Signed-off-by: Cezary Rojewski Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200218143924.10565-4-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- include/sound/hdaudio.h | 2 ++ sound/soc/sof/intel/hda-stream.c | 25 +++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index d4299e146d95..affedc2801c4 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -513,6 +513,7 @@ struct hdac_stream { struct snd_pcm_substream *substream; /* assigned substream, * set in PCM open */ + struct snd_compr_stream *cstream; unsigned int format_val; /* format value to be set in the * controller and the codec */ @@ -527,6 +528,7 @@ struct hdac_stream { bool locked:1; bool stripe:1; /* apply stripe control */ + u64 curr_pos; /* timestamp */ unsigned long start_wallclk; /* start + minimum wallclk */ unsigned long period_wallclk; /* wallclk for period */ diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index c0ab9bb2a797..7daa913dbde0 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -571,6 +571,22 @@ bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev) return ret; } +static void +hda_dsp_set_bytes_transferred(struct hdac_stream *hstream, u64 buffer_size) +{ + u64 prev_pos, pos, num_bytes; + + div64_u64_rem(hstream->curr_pos, buffer_size, &prev_pos); + pos = snd_hdac_stream_get_pos_posbuf(hstream); + + if (pos < prev_pos) + num_bytes = (buffer_size - prev_pos) + pos; + else + num_bytes = pos - prev_pos; + + hstream->curr_pos += num_bytes; +} + static bool hda_dsp_stream_check(struct hdac_bus *bus, u32 status) { struct sof_intel_hda_dev *sof_hda = bus_to_sof_hda(bus); @@ -588,14 +604,19 @@ static bool hda_dsp_stream_check(struct hdac_bus *bus, u32 status) snd_hdac_stream_writeb(s, SD_STS, sd_status); active = true; - if (!s->substream || + if ((!s->substream && !s->cstream) || !s->running || (sd_status & SOF_HDA_CL_DMA_SD_INT_COMPLETE) == 0) continue; /* Inform ALSA only in case not do that with IPC */ - if (sof_hda->no_ipc_position) + if (s->substream && sof_hda->no_ipc_position) { snd_sof_pcm_period_elapsed(s->substream); + } else if (s->cstream) { + hda_dsp_set_bytes_transferred(s, + s->cstream->runtime->buffer_size); + snd_compr_fragment_elapsed(s->cstream); + } } } From f3b433e4699fa358ce5b7bd7688bebe36068c199 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 18 Feb 2020 15:39:19 +0100 Subject: [PATCH 0454/4444] ASoC: SOF: Implement Probe IPC API Add all required types and methods to support each and every request that driver could sent to firmware. Probe is one of SOF firmware features which allows for data extraction and injection directly from or to DMA stream. Exposes eight IPCs: - addition and removal of injection DMAs - addition and removal of probe points - info retrieval of injection DMAs and probe points - probe initialization and cleanup Signed-off-by: Cezary Rojewski Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200218143924.10565-5-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- include/sound/sof/header.h | 11 ++ sound/soc/sof/Kconfig | 8 + sound/soc/sof/Makefile | 1 + sound/soc/sof/intel/hda-ipc.c | 4 +- sound/soc/sof/probe.c | 286 ++++++++++++++++++++++++++++++++++ sound/soc/sof/probe.h | 85 ++++++++++ 6 files changed, 394 insertions(+), 1 deletion(-) create mode 100644 sound/soc/sof/probe.c create mode 100644 sound/soc/sof/probe.h diff --git a/include/sound/sof/header.h b/include/sound/sof/header.h index bf3edd9c08b4..b79479575cc8 100644 --- a/include/sound/sof/header.h +++ b/include/sound/sof/header.h @@ -51,6 +51,7 @@ #define SOF_IPC_GLB_TRACE_MSG SOF_GLB_TYPE(0x9U) #define SOF_IPC_GLB_GDB_DEBUG SOF_GLB_TYPE(0xAU) #define SOF_IPC_GLB_TEST_MSG SOF_GLB_TYPE(0xBU) +#define SOF_IPC_GLB_PROBE SOF_GLB_TYPE(0xCU) /* * DSP Command Message Types @@ -102,6 +103,16 @@ #define SOF_IPC_STREAM_VORBIS_PARAMS SOF_CMD_TYPE(0x010) #define SOF_IPC_STREAM_VORBIS_FREE SOF_CMD_TYPE(0x011) +/* probe */ +#define SOF_IPC_PROBE_INIT SOF_CMD_TYPE(0x001) +#define SOF_IPC_PROBE_DEINIT SOF_CMD_TYPE(0x002) +#define SOF_IPC_PROBE_DMA_ADD SOF_CMD_TYPE(0x003) +#define SOF_IPC_PROBE_DMA_INFO SOF_CMD_TYPE(0x004) +#define SOF_IPC_PROBE_DMA_REMOVE SOF_CMD_TYPE(0x005) +#define SOF_IPC_PROBE_POINT_ADD SOF_CMD_TYPE(0x006) +#define SOF_IPC_PROBE_POINT_INFO SOF_CMD_TYPE(0x007) +#define SOF_IPC_PROBE_POINT_REMOVE SOF_CMD_TYPE(0x008) + /* trace */ #define SOF_IPC_TRACE_DMA_PARAMS SOF_CMD_TYPE(0x001) #define SOF_IPC_TRACE_DMA_POSITION SOF_CMD_TYPE(0x002) diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index 827b0ec92522..65c3cfbcb812 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -41,6 +41,14 @@ config SND_SOC_SOF_OF required to enable i.MX8 devices. Say Y if you need this option. If unsure select "N". +config SND_SOC_SOF_DEBUG_PROBES + bool "SOF enable data probing" + help + This option enables the data probing feature that can be used to + gather data directly from specific points of the audio pipeline. + Say Y if you want to enable probes. + If unsure, select "N". + config SND_SOC_SOF_DEVELOPER_SUPPORT bool "SOF developer options support" depends on EXPERT diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index 0a8bc72c28a5..18d7cab9046e 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -2,6 +2,7 @@ snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\ control.o trace.o utils.o sof-audio.o +snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += probe.o snd-sof-pci-objs := sof-pci-dev.o snd-sof-acpi-objs := sof-acpi-dev.o diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 1837f66e361f..922052883b0a 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -106,7 +106,9 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev) ret = reply.error; } else { /* reply correct size ? */ - if (reply.hdr.size != msg->reply_size) { + if (reply.hdr.size != msg->reply_size && + /* getter payload is never known upfront */ + !(reply.hdr.cmd & SOF_IPC_GLB_PROBE)) { dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n", msg->reply_size, reply.hdr.size); ret = -EINVAL; diff --git a/sound/soc/sof/probe.c b/sound/soc/sof/probe.c new file mode 100644 index 000000000000..2b2f3dcfc7e9 --- /dev/null +++ b/sound/soc/sof/probe.c @@ -0,0 +1,286 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// +// This file is provided under a dual BSD/GPLv2 license. When using or +// redistributing this file, you may do so under either license. +// +// Copyright(c) 2019-2020 Intel Corporation. All rights reserved. +// +// Author: Cezary Rojewski +// + +#include "sof-priv.h" +#include "probe.h" + +/** + * sof_ipc_probe_init - initialize data probing + * @sdev: SOF sound device + * @stream_tag: Extractor stream tag + * @buffer_size: DMA buffer size to set for extractor + * + * Host chooses whether extraction is supported or not by providing + * valid stream tag to DSP. Once specified, stream described by that + * tag will be tied to DSP for extraction for the entire lifetime of + * probe. + * + * Probing is initialized only once and each INIT request must be + * matched by DEINIT call. + */ +int sof_ipc_probe_init(struct snd_sof_dev *sdev, + u32 stream_tag, size_t buffer_size) +{ + struct sof_ipc_probe_dma_add_params *msg; + struct sof_ipc_reply reply; + size_t size = struct_size(msg, dma, 1); + int ret; + + msg = kmalloc(size, GFP_KERNEL); + if (!msg) + return -ENOMEM; + msg->hdr.size = size; + msg->hdr.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_INIT; + msg->num_elems = 1; + msg->dma[0].stream_tag = stream_tag; + msg->dma[0].dma_buffer_size = buffer_size; + + ret = sof_ipc_tx_message(sdev->ipc, msg->hdr.cmd, msg, msg->hdr.size, + &reply, sizeof(reply)); + kfree(msg); + return ret; +} +EXPORT_SYMBOL(sof_ipc_probe_init); + +/** + * sof_ipc_probe_deinit - cleanup after data probing + * @sdev: SOF sound device + * + * Host sends DEINIT request to free previously initialized probe + * on DSP side once it is no longer needed. DEINIT only when there + * are no probes connected and with all injectors detached. + */ +int sof_ipc_probe_deinit(struct snd_sof_dev *sdev) +{ + struct sof_ipc_cmd_hdr msg; + struct sof_ipc_reply reply; + + msg.size = sizeof(msg); + msg.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_DEINIT; + + return sof_ipc_tx_message(sdev->ipc, msg.cmd, &msg, msg.size, + &reply, sizeof(reply)); +} +EXPORT_SYMBOL(sof_ipc_probe_deinit); + +static int sof_ipc_probe_info(struct snd_sof_dev *sdev, unsigned int cmd, + void **params, size_t *num_params) +{ + struct sof_ipc_probe_info_params msg = {{{0}}}; + struct sof_ipc_probe_info_params *reply; + size_t bytes; + int ret; + + *params = NULL; + *num_params = 0; + + reply = kzalloc(SOF_IPC_MSG_MAX_SIZE, GFP_KERNEL); + if (!reply) + return -ENOMEM; + msg.rhdr.hdr.size = sizeof(msg); + msg.rhdr.hdr.cmd = SOF_IPC_GLB_PROBE | cmd; + + ret = sof_ipc_tx_message(sdev->ipc, msg.rhdr.hdr.cmd, &msg, + msg.rhdr.hdr.size, reply, SOF_IPC_MSG_MAX_SIZE); + if (ret < 0 || reply->rhdr.error < 0) + goto exit; + + if (!reply->num_elems) + goto exit; + + bytes = reply->num_elems * sizeof(reply->dma[0]); + *params = kmemdup(&reply->dma[0], bytes, GFP_KERNEL); + if (!*params) { + ret = -ENOMEM; + goto exit; + } + *num_params = msg.num_elems; + +exit: + kfree(reply); + return ret; +} + +/** + * sof_ipc_probe_dma_info - retrieve list of active injection dmas + * @sdev: SOF sound device + * @dma: Returned list of active dmas + * @num_dma: Returned count of active dmas + * + * Host sends DMA_INFO request to obtain list of injection dmas it + * can use to transfer data over with. + * + * Note that list contains only injection dmas as there is only one + * extractor (dma) and it is always assigned on probing init. + * DSP knows exactly where data from extraction probes is going to, + * which is not the case for injection where multiple streams + * could be engaged. + */ +int sof_ipc_probe_dma_info(struct snd_sof_dev *sdev, + struct sof_probe_dma **dma, size_t *num_dma) +{ + return sof_ipc_probe_info(sdev, SOF_IPC_PROBE_DMA_INFO, + (void **)dma, num_dma); +} +EXPORT_SYMBOL(sof_ipc_probe_dma_info); + +/** + * sof_ipc_probe_dma_add - attach to specified dmas + * @sdev: SOF sound device + * @dma: List of streams (dmas) to attach to + * @num_dma: Number of elements in @dma + * + * Contrary to extraction, injection streams are never assigned + * on init. Before attempting any data injection, host is responsible + * for specifying streams which will be later used to transfer data + * to connected probe points. + */ +int sof_ipc_probe_dma_add(struct snd_sof_dev *sdev, + struct sof_probe_dma *dma, size_t num_dma) +{ + struct sof_ipc_probe_dma_add_params *msg; + struct sof_ipc_reply reply; + size_t size = struct_size(msg, dma, num_dma); + int ret; + + msg = kmalloc(size, GFP_KERNEL); + if (!msg) + return -ENOMEM; + msg->hdr.size = size; + msg->num_elems = num_dma; + msg->hdr.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_DMA_ADD; + memcpy(&msg->dma[0], dma, size - sizeof(*msg)); + + ret = sof_ipc_tx_message(sdev->ipc, msg->hdr.cmd, msg, msg->hdr.size, + &reply, sizeof(reply)); + kfree(msg); + return ret; +} +EXPORT_SYMBOL(sof_ipc_probe_dma_add); + +/** + * sof_ipc_probe_dma_remove - detach from specified dmas + * @sdev: SOF sound device + * @stream_tag: List of stream tags to detach from + * @num_stream_tag: Number of elements in @stream_tag + * + * Host sends DMA_REMOVE request to free previously attached stream + * from being occupied for injection. Each detach operation should + * match equivalent DMA_ADD. Detach only when all probes tied to + * given stream have been disconnected. + */ +int sof_ipc_probe_dma_remove(struct snd_sof_dev *sdev, + unsigned int *stream_tag, size_t num_stream_tag) +{ + struct sof_ipc_probe_dma_remove_params *msg; + struct sof_ipc_reply reply; + size_t size = struct_size(msg, stream_tag, num_stream_tag); + int ret; + + msg = kmalloc(size, GFP_KERNEL); + if (!msg) + return -ENOMEM; + msg->hdr.size = size; + msg->num_elems = num_stream_tag; + msg->hdr.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_DMA_REMOVE; + memcpy(&msg->stream_tag[0], stream_tag, size - sizeof(*msg)); + + ret = sof_ipc_tx_message(sdev->ipc, msg->hdr.cmd, msg, msg->hdr.size, + &reply, sizeof(reply)); + kfree(msg); + return ret; +} +EXPORT_SYMBOL(sof_ipc_probe_dma_remove); + +/** + * sof_ipc_probe_points_info - retrieve list of active probe points + * @sdev: SOF sound device + * @desc: Returned list of active probes + * @num_desc: Returned count of active probes + * + * Host sends PROBE_POINT_INFO request to obtain list of active probe + * points, valid for disconnection when given probe is no longer + * required. + */ +int sof_ipc_probe_points_info(struct snd_sof_dev *sdev, + struct sof_probe_point_desc **desc, size_t *num_desc) +{ + return sof_ipc_probe_info(sdev, SOF_IPC_PROBE_POINT_INFO, + (void **)desc, num_desc); +} +EXPORT_SYMBOL(sof_ipc_probe_points_info); + +/** + * sof_ipc_probe_points_add - connect specified probes + * @sdev: SOF sound device + * @desc: List of probe points to connect + * @num_desc: Number of elements in @desc + * + * Dynamically connects to provided set of endpoints. Immediately + * after connection is established, host must be prepared to + * transfer data from or to target stream given the probing purpose. + * + * Each probe point should be removed using PROBE_POINT_REMOVE + * request when no longer needed. + */ +int sof_ipc_probe_points_add(struct snd_sof_dev *sdev, + struct sof_probe_point_desc *desc, size_t num_desc) +{ + struct sof_ipc_probe_point_add_params *msg; + struct sof_ipc_reply reply; + size_t size = struct_size(msg, desc, num_desc); + int ret; + + msg = kmalloc(size, GFP_KERNEL); + if (!msg) + return -ENOMEM; + msg->hdr.size = size; + msg->num_elems = num_desc; + msg->hdr.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_POINT_ADD; + memcpy(&msg->desc[0], desc, size - sizeof(*msg)); + + ret = sof_ipc_tx_message(sdev->ipc, msg->hdr.cmd, msg, msg->hdr.size, + &reply, sizeof(reply)); + kfree(msg); + return ret; +} +EXPORT_SYMBOL(sof_ipc_probe_points_add); + +/** + * sof_ipc_probe_points_remove - disconnect specified probes + * @sdev: SOF sound device + * @buffer_id: List of probe points to disconnect + * @num_buffer_id: Number of elements in @desc + * + * Removes previously connected probes from list of active probe + * points and frees all resources on DSP side. + */ +int sof_ipc_probe_points_remove(struct snd_sof_dev *sdev, + unsigned int *buffer_id, size_t num_buffer_id) +{ + struct sof_ipc_probe_point_remove_params *msg; + struct sof_ipc_reply reply; + size_t size = struct_size(msg, buffer_id, num_buffer_id); + int ret; + + msg = kmalloc(size, GFP_KERNEL); + if (!msg) + return -ENOMEM; + msg->hdr.size = size; + msg->num_elems = num_buffer_id; + msg->hdr.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_POINT_REMOVE; + memcpy(&msg->buffer_id[0], buffer_id, size - sizeof(*msg)); + + ret = sof_ipc_tx_message(sdev->ipc, msg->hdr.cmd, msg, msg->hdr.size, + &reply, sizeof(reply)); + kfree(msg); + return ret; +} +EXPORT_SYMBOL(sof_ipc_probe_points_remove); diff --git a/sound/soc/sof/probe.h b/sound/soc/sof/probe.h new file mode 100644 index 000000000000..45daa5552834 --- /dev/null +++ b/sound/soc/sof/probe.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2019-2020 Intel Corporation. All rights reserved. + * + * Author: Cezary Rojewski + */ + +#ifndef __SOF_PROBE_H +#define __SOF_PROBE_H + +#include + +struct snd_sof_dev; + +#define SOF_PROBE_INVALID_NODE_ID UINT_MAX + +struct sof_probe_dma { + unsigned int stream_tag; + unsigned int dma_buffer_size; +} __packed; + +enum sof_connection_purpose { + SOF_CONNECTION_PURPOSE_EXTRACT = 1, + SOF_CONNECTION_PURPOSE_INJECT, +}; + +struct sof_probe_point_desc { + unsigned int buffer_id; + unsigned int purpose; + unsigned int stream_tag; +} __packed; + +struct sof_ipc_probe_dma_add_params { + struct sof_ipc_cmd_hdr hdr; + unsigned int num_elems; + struct sof_probe_dma dma[0]; +} __packed; + +struct sof_ipc_probe_info_params { + struct sof_ipc_reply rhdr; + unsigned int num_elems; + union { + struct sof_probe_dma dma[0]; + struct sof_probe_point_desc desc[0]; + }; +} __packed; + +struct sof_ipc_probe_dma_remove_params { + struct sof_ipc_cmd_hdr hdr; + unsigned int num_elems; + unsigned int stream_tag[0]; +} __packed; + +struct sof_ipc_probe_point_add_params { + struct sof_ipc_cmd_hdr hdr; + unsigned int num_elems; + struct sof_probe_point_desc desc[0]; +} __packed; + +struct sof_ipc_probe_point_remove_params { + struct sof_ipc_cmd_hdr hdr; + unsigned int num_elems; + unsigned int buffer_id[0]; +} __packed; + +int sof_ipc_probe_init(struct snd_sof_dev *sdev, + u32 stream_tag, size_t buffer_size); +int sof_ipc_probe_deinit(struct snd_sof_dev *sdev); +int sof_ipc_probe_dma_info(struct snd_sof_dev *sdev, + struct sof_probe_dma **dma, size_t *num_dma); +int sof_ipc_probe_dma_add(struct snd_sof_dev *sdev, + struct sof_probe_dma *dma, size_t num_dma); +int sof_ipc_probe_dma_remove(struct snd_sof_dev *sdev, + unsigned int *stream_tag, size_t num_stream_tag); +int sof_ipc_probe_points_info(struct snd_sof_dev *sdev, + struct sof_probe_point_desc **desc, size_t *num_desc); +int sof_ipc_probe_points_add(struct snd_sof_dev *sdev, + struct sof_probe_point_desc *desc, size_t num_desc); +int sof_ipc_probe_points_remove(struct snd_sof_dev *sdev, + unsigned int *buffer_id, size_t num_buffer_id); + +#endif From e145e9af231adff081e0e16e1dacfb6e3c4e968f Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 18 Feb 2020 15:39:20 +0100 Subject: [PATCH 0455/4444] ASoC: SOF: Generic probe compress operations Define system-agnostic probe compress flow which serves as a base for actual, hardware-dependent implementations. As per firmware spec, maximum of one extraction stream is allowed, while for injection, there can be plenty. Apart from probe_pointer, all probe compress operations are mandatory. Copy operation is defined as unified as its flow should be shared across all SOF systems. Signed-off-by: Cezary Rojewski Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200218143924.10565-6-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/sof/Kconfig | 1 + sound/soc/sof/Makefile | 2 +- sound/soc/sof/compress.c | 141 +++++++++++++++++++++++++++++++++++++++ sound/soc/sof/compress.h | 29 ++++++++ sound/soc/sof/core.c | 6 ++ sound/soc/sof/ops.h | 43 ++++++++++++ sound/soc/sof/sof-priv.h | 25 +++++++ 7 files changed, 246 insertions(+), 1 deletion(-) create mode 100644 sound/soc/sof/compress.c create mode 100644 sound/soc/sof/compress.h diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index 65c3cfbcb812..4dda4b62509f 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -43,6 +43,7 @@ config SND_SOC_SOF_OF config SND_SOC_SOF_DEBUG_PROBES bool "SOF enable data probing" + select SND_SOC_COMPRESS help This option enables the data probing feature that can be used to gather data directly from specific points of the audio pipeline. diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index 18d7cab9046e..8eca2f85c90e 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -2,7 +2,7 @@ snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\ control.o trace.o utils.o sof-audio.o -snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += probe.o +snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += probe.o compress.o snd-sof-pci-objs := sof-pci-dev.o snd-sof-acpi-objs := sof-acpi-dev.o diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c new file mode 100644 index 000000000000..e87cc81a0599 --- /dev/null +++ b/sound/soc/sof/compress.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// +// This file is provided under a dual BSD/GPLv2 license. When using or +// redistributing this file, you may do so under either license. +// +// Copyright(c) 2019-2020 Intel Corporation. All rights reserved. +// +// Author: Cezary Rojewski +// + +#include +#include "compress.h" +#include "ops.h" +#include "probe.h" + +int sof_probe_compr_open(struct snd_compr_stream *cstream, + struct snd_soc_dai *dai) +{ + struct snd_sof_dev *sdev = + snd_soc_component_get_drvdata(dai->component); + int ret; + + ret = snd_sof_probe_compr_assign(sdev, cstream, dai); + if (ret < 0) { + dev_err(dai->dev, "Failed to assign probe stream: %d\n", ret); + return ret; + } + + sdev->extractor_stream_tag = ret; + return 0; +} +EXPORT_SYMBOL(sof_probe_compr_open); + +int sof_probe_compr_free(struct snd_compr_stream *cstream, + struct snd_soc_dai *dai) +{ + struct snd_sof_dev *sdev = + snd_soc_component_get_drvdata(dai->component); + struct sof_probe_point_desc *desc; + size_t num_desc; + int i, ret; + + /* disconnect all probe points */ + ret = sof_ipc_probe_points_info(sdev, &desc, &num_desc); + if (ret < 0) { + dev_err(dai->dev, "Failed to get probe points: %d\n", ret); + goto exit; + } + + for (i = 0; i < num_desc; i++) + sof_ipc_probe_points_remove(sdev, &desc[i].buffer_id, 1); + kfree(desc); + +exit: + ret = sof_ipc_probe_deinit(sdev); + if (ret < 0) + dev_err(dai->dev, "Failed to deinit probe: %d\n", ret); + + sdev->extractor_stream_tag = SOF_PROBE_INVALID_NODE_ID; + snd_compr_free_pages(cstream); + + return snd_sof_probe_compr_free(sdev, cstream, dai); +} +EXPORT_SYMBOL(sof_probe_compr_free); + +int sof_probe_compr_set_params(struct snd_compr_stream *cstream, + struct snd_compr_params *params, struct snd_soc_dai *dai) +{ + struct snd_compr_runtime *rtd = cstream->runtime; + struct snd_sof_dev *sdev = + snd_soc_component_get_drvdata(dai->component); + int ret; + + cstream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV_SG; + cstream->dma_buffer.dev.dev = sdev->dev; + ret = snd_compr_malloc_pages(cstream, rtd->buffer_size); + if (ret < 0) + return ret; + + ret = snd_sof_probe_compr_set_params(sdev, cstream, params, dai); + if (ret < 0) + return ret; + + ret = sof_ipc_probe_init(sdev, sdev->extractor_stream_tag, + rtd->dma_bytes); + if (ret < 0) { + dev_err(dai->dev, "Failed to init probe: %d\n", ret); + return ret; + } + + return 0; +} +EXPORT_SYMBOL(sof_probe_compr_set_params); + +int sof_probe_compr_trigger(struct snd_compr_stream *cstream, int cmd, + struct snd_soc_dai *dai) +{ + struct snd_sof_dev *sdev = + snd_soc_component_get_drvdata(dai->component); + + return snd_sof_probe_compr_trigger(sdev, cstream, cmd, dai); +} +EXPORT_SYMBOL(sof_probe_compr_trigger); + +int sof_probe_compr_pointer(struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp, struct snd_soc_dai *dai) +{ + struct snd_sof_dev *sdev = + snd_soc_component_get_drvdata(dai->component); + + return snd_sof_probe_compr_pointer(sdev, cstream, tstamp, dai); +} +EXPORT_SYMBOL(sof_probe_compr_pointer); + +int sof_probe_compr_copy(struct snd_compr_stream *cstream, + char __user *buf, size_t count) +{ + struct snd_compr_runtime *rtd = cstream->runtime; + unsigned int offset, n; + void *ptr; + int ret; + + if (count > rtd->buffer_size) + count = rtd->buffer_size; + + div_u64_rem(rtd->total_bytes_transferred, rtd->buffer_size, &offset); + ptr = rtd->dma_area + offset; + n = rtd->buffer_size - offset; + + if (count < n) { + ret = copy_to_user(buf, ptr, count); + } else { + ret = copy_to_user(buf, ptr, n); + ret += copy_to_user(buf + n, rtd->dma_area, count - n); + } + + if (ret) + return count - ret; + return count; +} +EXPORT_SYMBOL(sof_probe_compr_copy); diff --git a/sound/soc/sof/compress.h b/sound/soc/sof/compress.h new file mode 100644 index 000000000000..dccc9e008f81 --- /dev/null +++ b/sound/soc/sof/compress.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2019-2020 Intel Corporation. All rights reserved. + * + * Author: Cezary Rojewski + */ + +#ifndef __SOF_COMPRESS_H +#define __SOF_COMPRESS_H + +#include + +int sof_probe_compr_open(struct snd_compr_stream *cstream, + struct snd_soc_dai *dai); +int sof_probe_compr_free(struct snd_compr_stream *cstream, + struct snd_soc_dai *dai); +int sof_probe_compr_set_params(struct snd_compr_stream *cstream, + struct snd_compr_params *params, struct snd_soc_dai *dai); +int sof_probe_compr_trigger(struct snd_compr_stream *cstream, int cmd, + struct snd_soc_dai *dai); +int sof_probe_compr_pointer(struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp, struct snd_soc_dai *dai); +int sof_probe_compr_copy(struct snd_compr_stream *cstream, + char __user *buf, size_t count); + +#endif diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 1d07450aff77..91acfae7935c 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -14,6 +14,9 @@ #include #include "sof-priv.h" #include "ops.h" +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) +#include "probe.h" +#endif /* see SOF_DBG_ flags */ int sof_core_debug; @@ -292,6 +295,9 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) sdev->pdata = plat_data; sdev->first_boot = true; sdev->fw_state = SOF_FW_BOOT_NOT_STARTED; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) + sdev->extractor_stream_tag = SOF_PROBE_INVALID_NODE_ID; +#endif dev_set_drvdata(dev, sdev); /* check all mandatory ops */ diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 7f532bcc8e9d..a771500ac442 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -393,6 +393,49 @@ snd_sof_pcm_platform_pointer(struct snd_sof_dev *sdev, return 0; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) +static inline int +snd_sof_probe_compr_assign(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, struct snd_soc_dai *dai) +{ + return sof_ops(sdev)->probe_assign(sdev, cstream, dai); +} + +static inline int +snd_sof_probe_compr_free(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, struct snd_soc_dai *dai) +{ + return sof_ops(sdev)->probe_free(sdev, cstream, dai); +} + +static inline int +snd_sof_probe_compr_set_params(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, + struct snd_compr_params *params, struct snd_soc_dai *dai) +{ + return sof_ops(sdev)->probe_set_params(sdev, cstream, params, dai); +} + +static inline int +snd_sof_probe_compr_trigger(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, int cmd, + struct snd_soc_dai *dai) +{ + return sof_ops(sdev)->probe_trigger(sdev, cstream, cmd, dai); +} + +static inline int +snd_sof_probe_compr_pointer(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp, struct snd_soc_dai *dai) +{ + if (sof_ops(sdev) && sof_ops(sdev)->probe_pointer) + return sof_ops(sdev)->probe_pointer(sdev, cstream, tstamp, dai); + + return 0; +} +#endif + /* machine driver */ static inline int snd_sof_machine_register(struct snd_sof_dev *sdev, void *pdata) diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 00084471d0de..5d16f668d16a 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -170,6 +170,27 @@ struct snd_sof_dsp_ops { snd_pcm_uframes_t (*pcm_pointer)(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream); /* optional */ +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) + /* Except for probe_pointer, all probe ops are mandatory */ + int (*probe_assign)(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, + struct snd_soc_dai *dai); /* mandatory */ + int (*probe_free)(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, + struct snd_soc_dai *dai); /* mandatory */ + int (*probe_set_params)(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, + struct snd_compr_params *params, + struct snd_soc_dai *dai); /* mandatory */ + int (*probe_trigger)(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, int cmd, + struct snd_soc_dai *dai); /* mandatory */ + int (*probe_pointer)(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp, + struct snd_soc_dai *dai); /* optional */ +#endif + /* host read DSP stream data */ void (*ipc_msg_data)(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, @@ -405,6 +426,10 @@ struct snd_sof_dev { wait_queue_head_t waitq; int code_loading; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) + unsigned int extractor_stream_tag; +#endif + /* DMA for Trace */ struct snd_dma_buffer dmatb; struct snd_dma_buffer dmatp; From 49d7948ed174cc170041bf3d22e1f085fd8b87f0 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 18 Feb 2020 15:39:21 +0100 Subject: [PATCH 0456/4444] ASoC: SOF: Intel: Expose SDnFMT helpers Hda stream is setup in similar fashion for compress as it is for pcm operations. To reuse existing code in compress path, expose SDnFMT helper routines. Signed-off-by: Cezary Rojewski Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200218143924.10565-7-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-pcm.c | 8 ++++---- sound/soc/sof/intel/hda.h | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index 23872f6e708d..a46a6baa1c3f 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -27,7 +27,7 @@ #define SDnFMT_BITS(x) ((x) << 4) #define SDnFMT_CHAN(x) ((x) << 0) -static inline u32 get_mult_div(struct snd_sof_dev *sdev, int rate) +u32 hda_dsp_get_mult_div(struct snd_sof_dev *sdev, int rate) { switch (rate) { case 8000: @@ -61,7 +61,7 @@ static inline u32 get_mult_div(struct snd_sof_dev *sdev, int rate) } }; -static inline u32 get_bits(struct snd_sof_dev *sdev, int sample_bits) +u32 hda_dsp_get_bits(struct snd_sof_dev *sdev, int sample_bits) { switch (sample_bits) { case 8: @@ -95,8 +95,8 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev, u32 size, rate, bits; size = params_buffer_bytes(params); - rate = get_mult_div(sdev, params_rate(params)); - bits = get_bits(sdev, params_width(params)); + rate = hda_dsp_get_mult_div(sdev, params_rate(params)); + bits = hda_dsp_get_bits(sdev, params_width(params)); hstream->substream = substream; diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index a46b66437a3d..2b5fde372790 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -502,6 +502,8 @@ void hda_dsp_d0i3_work(struct work_struct *work); /* * DSP PCM Operations. */ +u32 hda_dsp_get_mult_div(struct snd_sof_dev *sdev, int rate); +u32 hda_dsp_get_bits(struct snd_sof_dev *sdev, int sample_bits); int hda_dsp_pcm_open(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream); int hda_dsp_pcm_close(struct snd_sof_dev *sdev, From 4c414da93a4642d02c67fbe82f1834be7bf586b7 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 18 Feb 2020 15:39:22 +0100 Subject: [PATCH 0457/4444] ASoC: SOF: Intel: Probe compress operations Add HDA handlers for soc_compr_ops and snd_compr_ops which cover probe related operations. Implementation supports both connection purposes. These merely define stream setups as core flow is covered by SOF compress core. Signed-off-by: Cezary Rojewski Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200218143924.10565-8-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/Kconfig | 9 +++ sound/soc/sof/intel/Makefile | 1 + sound/soc/sof/intel/apl.c | 9 +++ sound/soc/sof/intel/cnl.c | 9 +++ sound/soc/sof/intel/hda-compress.c | 114 +++++++++++++++++++++++++++++ sound/soc/sof/intel/hda.h | 24 ++++++ 6 files changed, 166 insertions(+) create mode 100644 sound/soc/sof/intel/hda-compress.c diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index 56a837d2cb95..3bc64dee7c39 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -305,6 +305,15 @@ config SND_SOC_SOF_HDA_AUDIO_CODEC Say Y if you want to enable HDAudio codecs with SOF. If unsure select "N". +config SND_SOC_SOF_HDA_PROBES + bool "SOF enable probes over HDA" + depends on SND_SOC_SOF_DEBUG_PROBES + help + This option enables the data probing for Intel(R). + Intel(R) Skylake and newer platforms. + Say Y if you want to enable probes. + If unsure, select "N". + config SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1 bool "SOF enable DMI Link L1" help diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile index b8f58e006e29..cee02a2e00f4 100644 --- a/sound/soc/sof/intel/Makefile +++ b/sound/soc/sof/intel/Makefile @@ -9,6 +9,7 @@ snd-sof-intel-hda-common-objs := hda.o hda-loader.o hda-stream.o hda-trace.o \ hda-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \ hda-dai.o hda-bus.o \ apl.o cnl.o +snd-sof-intel-hda-common-$(CONFIG_SND_SOC_SOF_HDA_PROBES) += hda-compress.o snd-sof-intel-hda-objs := hda-codec.o diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 2483b15699e7..02218d22e51f 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -73,6 +73,15 @@ const struct snd_sof_dsp_ops sof_apl_ops = { .pcm_trigger = hda_dsp_pcm_trigger, .pcm_pointer = hda_dsp_pcm_pointer, +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES) + /* probe callbacks */ + .probe_assign = hda_probe_compr_assign, + .probe_free = hda_probe_compr_free, + .probe_set_params = hda_probe_compr_set_params, + .probe_trigger = hda_probe_compr_trigger, + .probe_pointer = hda_probe_compr_pointer, +#endif + /* firmware loading */ .load_firmware = snd_sof_load_firmware_raw, diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 8a59fec72919..05125cb0be6e 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -284,6 +284,15 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { .pcm_trigger = hda_dsp_pcm_trigger, .pcm_pointer = hda_dsp_pcm_pointer, +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES) + /* probe callbacks */ + .probe_assign = hda_probe_compr_assign, + .probe_free = hda_probe_compr_free, + .probe_set_params = hda_probe_compr_set_params, + .probe_trigger = hda_probe_compr_trigger, + .probe_pointer = hda_probe_compr_pointer, +#endif + /* firmware loading */ .load_firmware = snd_sof_load_firmware_raw, diff --git a/sound/soc/sof/intel/hda-compress.c b/sound/soc/sof/intel/hda-compress.c new file mode 100644 index 000000000000..38a1ebec8478 --- /dev/null +++ b/sound/soc/sof/intel/hda-compress.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// +// This file is provided under a dual BSD/GPLv2 license. When using or +// redistributing this file, you may do so under either license. +// +// Copyright(c) 2019-2020 Intel Corporation. All rights reserved. +// +// Author: Cezary Rojewski +// + +#include +#include +#include "../sof-priv.h" +#include "hda.h" + +static inline struct hdac_ext_stream * +hda_compr_get_stream(struct snd_compr_stream *cstream) +{ + return cstream->runtime->private_data; +} + +int hda_probe_compr_assign(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, + struct snd_soc_dai *dai) +{ + struct hdac_ext_stream *stream; + + stream = hda_dsp_stream_get(sdev, cstream->direction); + if (!stream) + return -EBUSY; + + hdac_stream(stream)->curr_pos = 0; + hdac_stream(stream)->cstream = cstream; + cstream->runtime->private_data = stream; + + return hdac_stream(stream)->stream_tag; +} + +int hda_probe_compr_free(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, + struct snd_soc_dai *dai) +{ + struct hdac_ext_stream *stream = hda_compr_get_stream(cstream); + int ret; + + ret = hda_dsp_stream_put(sdev, cstream->direction, + hdac_stream(stream)->stream_tag); + if (ret < 0) { + dev_dbg(sdev->dev, "stream put failed: %d\n", ret); + return ret; + } + + hdac_stream(stream)->cstream = NULL; + cstream->runtime->private_data = NULL; + + return 0; +} + +int hda_probe_compr_set_params(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, + struct snd_compr_params *params, + struct snd_soc_dai *dai) +{ + struct hdac_ext_stream *stream = hda_compr_get_stream(cstream); + struct hdac_stream *hstream = hdac_stream(stream); + struct snd_dma_buffer *dmab; + u32 bits, rate; + int bps, ret; + + dmab = cstream->runtime->dma_buffer_p; + /* compr params do not store bit depth, default to S32_LE */ + bps = snd_pcm_format_physical_width(SNDRV_PCM_FORMAT_S32_LE); + if (bps < 0) + return bps; + bits = hda_dsp_get_bits(sdev, bps); + rate = hda_dsp_get_mult_div(sdev, params->codec.sample_rate); + + hstream->format_val = rate | bits | (params->codec.ch_out - 1); + hstream->bufsize = cstream->runtime->buffer_size; + hstream->period_bytes = cstream->runtime->fragment_size; + hstream->no_period_wakeup = 0; + + ret = hda_dsp_stream_hw_params(sdev, stream, dmab, NULL); + if (ret < 0) { + dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret); + return ret; + } + + return 0; +} + +int hda_probe_compr_trigger(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, int cmd, + struct snd_soc_dai *dai) +{ + struct hdac_ext_stream *stream = hda_compr_get_stream(cstream); + + return hda_dsp_stream_trigger(sdev, stream, cmd); +} + +int hda_probe_compr_pointer(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp, + struct snd_soc_dai *dai) +{ + struct hdac_ext_stream *stream = hda_compr_get_stream(cstream); + struct snd_soc_pcm_stream *pstream; + + pstream = &dai->driver->capture; + tstamp->copied_total = hdac_stream(stream)->curr_pos; + tstamp->sampling_rate = snd_pcm_rate_bit_to_rate(pstream->rates); + + return 0; +} diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 2b5fde372790..ca44ecb76534 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -11,6 +11,7 @@ #ifndef __SOF_INTEL_HDA_H #define __SOF_INTEL_HDA_H +#include #include #include #include "shim.h" @@ -552,6 +553,29 @@ int hda_ipc_pcm_params(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, const struct sof_ipc_pcm_params_reply *reply); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES) +/* + * Probe Compress Operations. + */ +int hda_probe_compr_assign(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, + struct snd_soc_dai *dai); +int hda_probe_compr_free(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, + struct snd_soc_dai *dai); +int hda_probe_compr_set_params(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, + struct snd_compr_params *params, + struct snd_soc_dai *dai); +int hda_probe_compr_trigger(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, int cmd, + struct snd_soc_dai *dai); +int hda_probe_compr_pointer(struct snd_sof_dev *sdev, + struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp, + struct snd_soc_dai *dai); +#endif + /* * DSP IPC Operations. */ From 394695f410c1cd3208906451ba5420f45c420a51 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 18 Feb 2020 15:39:23 +0100 Subject: [PATCH 0458/4444] ASoC: SOF: Provide probe debugfs support Define debugfs subdirectory delegated for IPC communication with DSP. Input format: uint,uint,(...) which are later translated into DWORDS sequence and further into instances of struct of interest given the IPC type. For Extractor probes, following have been enabled: - PROBE_POINT_ADD (echo <..> probe_points) - PROBE_POINT_REMOVE (echo <..> probe_points_remove) - PROBE_POINT_INFO (cat probe_points) Signed-off-by: Cezary Rojewski Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200218143924.10565-9-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/sof/debug.c | 226 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index d2b3b99d3a20..b5c0d6cf72cc 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -17,6 +17,221 @@ #include "sof-priv.h" #include "ops.h" +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) +#include "probe.h" + +/** + * strsplit_u32 - Split string into sequence of u32 tokens + * @buf: String to split into tokens. + * @delim: String containing delimiter characters. + * @tkns: Returned u32 sequence pointer. + * @num_tkns: Returned number of tokens obtained. + */ +static int +strsplit_u32(char **buf, const char *delim, u32 **tkns, size_t *num_tkns) +{ + char *s; + u32 *data, *tmp; + size_t count = 0; + size_t cap = 32; + int ret = 0; + + *tkns = NULL; + *num_tkns = 0; + data = kcalloc(cap, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + while ((s = strsep(buf, delim)) != NULL) { + ret = kstrtouint(s, 0, data + count); + if (ret) + goto exit; + if (++count >= cap) { + cap *= 2; + tmp = krealloc(data, cap * sizeof(*data), GFP_KERNEL); + if (!tmp) { + ret = -ENOMEM; + goto exit; + } + data = tmp; + } + } + + if (!count) + goto exit; + *tkns = kmemdup(data, count * sizeof(*data), GFP_KERNEL); + if (*tkns == NULL) { + ret = -ENOMEM; + goto exit; + } + *num_tkns = count; + +exit: + kfree(data); + return ret; +} + +static int tokenize_input(const char __user *from, size_t count, + loff_t *ppos, u32 **tkns, size_t *num_tkns) +{ + char *buf; + int ret; + + buf = kmalloc(count + 1, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = simple_write_to_buffer(buf, count, ppos, from, count); + if (ret != count) { + ret = ret >= 0 ? -EIO : ret; + goto exit; + } + + buf[count] = '\0'; + ret = strsplit_u32((char **)&buf, ",", tkns, num_tkns); +exit: + kfree(buf); + return ret; +} + +static ssize_t probe_points_read(struct file *file, + char __user *to, size_t count, loff_t *ppos) +{ + struct snd_sof_dfsentry *dfse = file->private_data; + struct snd_sof_dev *sdev = dfse->sdev; + struct sof_probe_point_desc *desc; + size_t num_desc, len = 0; + char *buf; + int i, ret; + + if (sdev->extractor_stream_tag == SOF_PROBE_INVALID_NODE_ID) { + dev_warn(sdev->dev, "no extractor stream running\n"); + return -ENOENT; + } + + buf = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = sof_ipc_probe_points_info(sdev, &desc, &num_desc); + if (ret < 0) + goto exit; + + for (i = 0; i < num_desc; i++) { + ret = snprintf(buf + len, PAGE_SIZE - len, + "Id: %#010x Purpose: %d Node id: %#x\n", + desc[i].buffer_id, desc[i].purpose, desc[i].stream_tag); + if (ret < 0) + goto free_desc; + len += ret; + } + + ret = simple_read_from_buffer(to, count, ppos, buf, len); +free_desc: + kfree(desc); +exit: + kfree(buf); + return ret; +} + +static ssize_t probe_points_write(struct file *file, + const char __user *from, size_t count, loff_t *ppos) +{ + struct snd_sof_dfsentry *dfse = file->private_data; + struct snd_sof_dev *sdev = dfse->sdev; + struct sof_probe_point_desc *desc; + size_t num_tkns, bytes; + u32 *tkns; + int ret; + + if (sdev->extractor_stream_tag == SOF_PROBE_INVALID_NODE_ID) { + dev_warn(sdev->dev, "no extractor stream running\n"); + return -ENOENT; + } + + ret = tokenize_input(from, count, ppos, &tkns, &num_tkns); + if (ret < 0) + return ret; + bytes = sizeof(*tkns) * num_tkns; + if (!num_tkns || (bytes % sizeof(*desc))) { + ret = -EINVAL; + goto exit; + } + + desc = (struct sof_probe_point_desc *)tkns; + ret = sof_ipc_probe_points_add(sdev, + desc, bytes / sizeof(*desc)); + if (!ret) + ret = count; +exit: + kfree(tkns); + return ret; +} + +static const struct file_operations probe_points_fops = { + .open = simple_open, + .read = probe_points_read, + .write = probe_points_write, + .llseek = default_llseek, +}; + +static ssize_t probe_points_remove_write(struct file *file, + const char __user *from, size_t count, loff_t *ppos) +{ + struct snd_sof_dfsentry *dfse = file->private_data; + struct snd_sof_dev *sdev = dfse->sdev; + size_t num_tkns; + u32 *tkns; + int ret; + + if (sdev->extractor_stream_tag == SOF_PROBE_INVALID_NODE_ID) { + dev_warn(sdev->dev, "no extractor stream running\n"); + return -ENOENT; + } + + ret = tokenize_input(from, count, ppos, &tkns, &num_tkns); + if (ret < 0) + return ret; + if (!num_tkns) { + ret = -EINVAL; + goto exit; + } + + ret = sof_ipc_probe_points_remove(sdev, tkns, num_tkns); + if (!ret) + ret = count; +exit: + kfree(tkns); + return ret; +} + +static const struct file_operations probe_points_remove_fops = { + .open = simple_open, + .write = probe_points_remove_write, + .llseek = default_llseek, +}; + +static int snd_sof_debugfs_probe_item(struct snd_sof_dev *sdev, + const char *name, mode_t mode, + const struct file_operations *fops) +{ + struct snd_sof_dfsentry *dfse; + + dfse = devm_kzalloc(sdev->dev, sizeof(*dfse), GFP_KERNEL); + if (!dfse) + return -ENOMEM; + + dfse->type = SOF_DFSENTRY_TYPE_BUF; + dfse->sdev = sdev; + + debugfs_create_file(name, mode, sdev->debugfs_root, dfse, fops); + /* add to dfsentry list */ + list_add(&dfse->list, &sdev->dfsentry_list); + + return 0; +} +#endif + #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) #define MAX_IPC_FLOOD_DURATION_MS 1000 #define MAX_IPC_FLOOD_COUNT 10000 @@ -436,6 +651,17 @@ int snd_sof_dbg_init(struct snd_sof_dev *sdev) return err; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) + err = snd_sof_debugfs_probe_item(sdev, "probe_points", + 0644, &probe_points_fops); + if (err < 0) + return err; + err = snd_sof_debugfs_probe_item(sdev, "probe_points_remove", + 0200, &probe_points_remove_fops); + if (err < 0) + return err; +#endif + #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) /* create read-write ipc_flood_count debugfs entry */ err = snd_sof_debugfs_buf_item(sdev, NULL, 0, From 70368106467cd8c420176bf3ab0acc797f6584bf Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 18 Feb 2020 15:39:24 +0100 Subject: [PATCH 0459/4444] ASoC: SOF: Intel: Add Probe compress CPU DAIs Declare extraction CPU DAI as well as sof_probe_compr_ops. FE DAIs can link against these new CPU DAI to create new compress devices. Signed-off-by: Cezary Rojewski Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200218143924.10565-10-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/sof/compress.c | 5 +++++ sound/soc/sof/compress.h | 2 ++ sound/soc/sof/intel/hda-dai.c | 28 ++++++++++++++++++++++++++++ sound/soc/sof/intel/hda.h | 6 ++++++ sound/soc/sof/pcm.c | 7 +++++++ 5 files changed, 48 insertions(+) diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c index e87cc81a0599..7354dc6a49cf 100644 --- a/sound/soc/sof/compress.c +++ b/sound/soc/sof/compress.c @@ -13,6 +13,11 @@ #include "ops.h" #include "probe.h" +struct snd_compr_ops sof_probe_compressed_ops = { + .copy = sof_probe_compr_copy, +}; +EXPORT_SYMBOL(sof_probe_compressed_ops); + int sof_probe_compr_open(struct snd_compr_stream *cstream, struct snd_soc_dai *dai) { diff --git a/sound/soc/sof/compress.h b/sound/soc/sof/compress.h index dccc9e008f81..800f163603e1 100644 --- a/sound/soc/sof/compress.h +++ b/sound/soc/sof/compress.h @@ -13,6 +13,8 @@ #include +extern struct snd_compr_ops sof_probe_compressed_ops; + int sof_probe_compr_open(struct snd_compr_stream *cstream, struct snd_soc_dai *dai); int sof_probe_compr_free(struct snd_compr_stream *cstream, diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 9c6e3f990ee3..ed5e7d2c0d43 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -399,6 +399,19 @@ static const struct snd_soc_dai_ops hda_link_dai_ops = { .trigger = hda_link_pcm_trigger, .prepare = hda_link_pcm_prepare, }; + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES) +#include "../compress.h" + +static struct snd_soc_cdai_ops sof_probe_compr_ops = { + .startup = sof_probe_compr_open, + .shutdown = sof_probe_compr_free, + .set_params = sof_probe_compr_set_params, + .trigger = sof_probe_compr_trigger, + .pointer = sof_probe_compr_pointer, +}; + +#endif #endif /* @@ -460,5 +473,20 @@ struct snd_soc_dai_driver skl_dai[] = { .name = "Alt Analog CPU DAI", .ops = &hda_link_dai_ops, }, +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES) +{ + .name = "Probe Extraction CPU DAI", + .compress_new = snd_soc_new_compress, + .cops = &sof_probe_compr_ops, + .capture = { + .stream_name = "Probe Extraction", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + }, +}, +#endif #endif }; diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index ca44ecb76534..537c0a930a15 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -349,7 +349,13 @@ /* Number of DAIs */ #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES) +#define SOF_SKL_NUM_DAIS 16 +#else #define SOF_SKL_NUM_DAIS 15 +#endif + #else #define SOF_SKL_NUM_DAIS 8 #endif diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index db3df02c7398..b239bbff4b5c 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -16,6 +16,9 @@ #include "sof-priv.h" #include "sof-audio.h" #include "ops.h" +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) +#include "compress.h" +#endif /* Create DMA buffer page table for DSP */ static int create_page_table(struct snd_soc_component *component, @@ -787,6 +790,10 @@ void snd_sof_new_platform_drv(struct snd_sof_dev *sdev) #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS) pd->compr_ops = &sof_compressed_ops; +#endif +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) + /* override cops when probe support is enabled */ + pd->compr_ops = &sof_probe_compressed_ops; #endif pd->pcm_construct = sof_pcm_new; pd->ignore_machine = drv_name; From ebbfabc16d23dfd20eecd4b6e68212fec37ae7c6 Mon Sep 17 00:00:00 2001 From: Derek Fang Date: Tue, 18 Feb 2020 21:51:51 +0800 Subject: [PATCH 0460/4444] ASoC: rt5682: Add CCF usage for providing I2S clks There is a need to use RT5682 as DAI clock master for other codecs within a platform, which means that the DAI clocks are required to remain, regardless of whether the RT5682 is actually running playback/capture. The RT5682 CCF basic functions are implemented almost by the existing internal functions and asoc apis. It needs a clk provider (rt5682 mclk) to generate the bclk and wclk outputs. The RT5682 CCF supports and restricts as below: 1. Fmt of DAI-AIF1 must be configured to master before using CCF. 2. Only accept a 48MHz clk as the clk provider. 3. Only provide a 48kHz wclk and a set of multiples of wclk as bclk. There are some temporary limitations in this patch until a better implementation. Signed-off-by: Derek Fang Link: https://lore.kernel.org/r/1582033912-6841-1-git-send-email-derek.fang@realtek.com Signed-off-by: Mark Brown --- include/sound/rt5682.h | 8 + sound/soc/codecs/rt5682.c | 407 +++++++++++++++++++++++++++++++++++++- sound/soc/codecs/rt5682.h | 4 +- 3 files changed, 415 insertions(+), 4 deletions(-) diff --git a/include/sound/rt5682.h b/include/sound/rt5682.h index bc2c31734df1..6bf0e3581056 100644 --- a/include/sound/rt5682.h +++ b/include/sound/rt5682.h @@ -24,6 +24,12 @@ enum rt5682_jd_src { RT5682_JD1, }; +enum rt5682_dai_clks { + RT5682_DAI_WCLK_IDX, + RT5682_DAI_BCLK_IDX, + RT5682_DAI_NUM_CLKS, +}; + struct rt5682_platform_data { int ldo1_en; /* GPIO for LDO1_EN */ @@ -32,6 +38,8 @@ struct rt5682_platform_data { enum rt5682_dmic1_clk_pin dmic1_clk_pin; enum rt5682_jd_src jd_src; unsigned int btndet_delay; + + const char *dai_clk_names[RT5682_DAI_NUM_CLKS]; }; #endif diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 9fbb3862f8d7..6774813e0eea 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include #include #include "rl6231.h" @@ -45,6 +48,8 @@ static const struct rt5682_platform_data i2s_default_platform_data = { .dmic1_clk_pin = RT5682_DMIC1_CLK_GPIO3, .jd_src = RT5682_JD1, .btndet_delay = 16, + .dai_clk_names[RT5682_DAI_WCLK_IDX] = "rt5682-dai-wclk", + .dai_clk_names[RT5682_DAI_BCLK_IDX] = "rt5682-dai-bclk", }; struct rt5682_priv { @@ -58,6 +63,13 @@ struct rt5682_priv { struct mutex calibrate_mutex; bool is_sdw; +#ifdef CONFIG_COMMON_CLK + struct clk_hw dai_clks_hw[RT5682_DAI_NUM_CLKS]; + struct clk_lookup *dai_clks_lookup[RT5682_DAI_NUM_CLKS]; + struct clk *dai_clks[RT5682_DAI_NUM_CLKS]; + struct clk *mclk; +#endif + int sysclk; int sysclk_src; int lrck[RT5682_AIFS]; @@ -921,6 +933,7 @@ static int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + struct snd_soc_dapm_context *dapm = &component->dapm; unsigned int val, count; if (jack_insert) { @@ -963,8 +976,13 @@ static int rt5682_headset_detect(struct snd_soc_component *component, rt5682_enable_push_button_irq(component, false); snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, RT5682_TRIG_JD_MASK, RT5682_TRIG_JD_LOW); - snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1, - RT5682_PWR_VREF2 | RT5682_PWR_MB, 0); + if (snd_soc_dapm_get_pin_status(dapm, "MICBIAS")) + snd_soc_component_update_bits(component, + RT5682_PWR_ANLG_1, RT5682_PWR_VREF2, 0); + else + snd_soc_component_update_bits(component, + RT5682_PWR_ANLG_1, + RT5682_PWR_VREF2 | RT5682_PWR_MB, 0); snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3, RT5682_PWR_CBJ, 0); @@ -1633,6 +1651,7 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = { rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_SUPPLY("Vref2", RT5682_PWR_ANLG_1, RT5682_PWR_VREF2_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, NULL, 0), /* ASRC */ SND_SOC_DAPM_SUPPLY_S("DAC STO1 ASRC", 1, RT5682_PLL_TRACK_1, @@ -2459,12 +2478,380 @@ static int rt5682_set_bias_level(struct snd_soc_component *component, return 0; } +#ifdef CONFIG_COMMON_CLK +#define CLK_PLL2_FIN 48000000 +#define CLK_PLL2_FOUT 24576000 +#define CLK_48 48000 + +static bool rt5682_clk_check(struct rt5682_priv *rt5682) +{ + if (!rt5682->master[RT5682_AIF1]) { + dev_err(rt5682->component->dev, "sysclk/dai not set correctly\n"); + return false; + } + return true; +} + +static int rt5682_wclk_prepare(struct clk_hw *hw) +{ + struct rt5682_priv *rt5682 = + container_of(hw, struct rt5682_priv, + dai_clks_hw[RT5682_DAI_WCLK_IDX]); + struct snd_soc_component *component = rt5682->component; + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + + if (!rt5682_clk_check(rt5682)) + return -EINVAL; + + snd_soc_dapm_mutex_lock(dapm); + + snd_soc_dapm_force_enable_pin_unlocked(dapm, "MICBIAS"); + snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1, + RT5682_PWR_MB, RT5682_PWR_MB); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "I2S1"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2F"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2B"); + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); + + return 0; +} + +static void rt5682_wclk_unprepare(struct clk_hw *hw) +{ + struct rt5682_priv *rt5682 = + container_of(hw, struct rt5682_priv, + dai_clks_hw[RT5682_DAI_WCLK_IDX]); + struct snd_soc_component *component = rt5682->component; + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + + if (!rt5682_clk_check(rt5682)) + return; + + snd_soc_dapm_mutex_lock(dapm); + + snd_soc_dapm_disable_pin_unlocked(dapm, "MICBIAS"); + if (!rt5682->jack_type) + snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1, + RT5682_PWR_MB, 0); + snd_soc_dapm_disable_pin_unlocked(dapm, "I2S1"); + snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2F"); + snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2B"); + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); +} + +static unsigned long rt5682_wclk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct rt5682_priv *rt5682 = + container_of(hw, struct rt5682_priv, + dai_clks_hw[RT5682_DAI_WCLK_IDX]); + + if (!rt5682_clk_check(rt5682)) + return 0; + /* + * Only accept to set wclk rate to 48kHz temporarily. + */ + return CLK_48; +} + +static long rt5682_wclk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct rt5682_priv *rt5682 = + container_of(hw, struct rt5682_priv, + dai_clks_hw[RT5682_DAI_WCLK_IDX]); + + if (!rt5682_clk_check(rt5682)) + return -EINVAL; + /* + * Only accept to set wclk rate to 48kHz temporarily. + */ + return CLK_48; +} + +static int rt5682_wclk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct rt5682_priv *rt5682 = + container_of(hw, struct rt5682_priv, + dai_clks_hw[RT5682_DAI_WCLK_IDX]); + struct snd_soc_component *component = rt5682->component; + struct clk *parent_clk; + const char * const clk_name = __clk_get_name(hw->clk); + int pre_div; + + if (!rt5682_clk_check(rt5682)) + return -EINVAL; + + /* + * Whether the wclk's parent clk (mclk) exists or not, please ensure + * it is fixed or set to 48MHz before setting wclk rate. It's a + * temporary limitation. Only accept 48MHz clk as the clk provider. + * + * It will set the codec anyway by assuming mclk is 48MHz. + */ + parent_clk = clk_get_parent(hw->clk); + if (!parent_clk) + dev_warn(component->dev, + "Parent mclk of wclk not acquired in driver. Please ensure mclk was provided as %d Hz.\n", + CLK_PLL2_FIN); + + if (parent_rate != CLK_PLL2_FIN) + dev_warn(component->dev, "clk %s only support %d Hz input\n", + clk_name, CLK_PLL2_FIN); + + /* + * It's a temporary limitation. Only accept to set wclk rate to 48kHz. + * It will force wclk to 48kHz even it's not. + */ + if (rate != CLK_48) { + dev_warn(component->dev, "clk %s only support %d Hz output\n", + clk_name, CLK_48); + rate = CLK_48; + } + + /* + * To achieve the rate conversion from 48MHz to 48kHz, PLL2 is needed. + */ + rt5682_set_component_pll(component, RT5682_PLL2, RT5682_PLL2_S_MCLK, + CLK_PLL2_FIN, CLK_PLL2_FOUT); + + rt5682_set_component_sysclk(component, RT5682_SCLK_S_PLL2, 0, + CLK_PLL2_FOUT, SND_SOC_CLOCK_IN); + + pre_div = rl6231_get_clk_info(rt5682->sysclk, rate); + + snd_soc_component_update_bits(component, RT5682_ADDA_CLK_1, + RT5682_I2S_M_DIV_MASK | RT5682_I2S_CLK_SRC_MASK, + pre_div << RT5682_I2S_M_DIV_SFT | + (rt5682->sysclk_src) << RT5682_I2S_CLK_SRC_SFT); + + return 0; +} + +static unsigned long rt5682_bclk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct rt5682_priv *rt5682 = + container_of(hw, struct rt5682_priv, + dai_clks_hw[RT5682_DAI_BCLK_IDX]); + struct snd_soc_component *component = rt5682->component; + unsigned int bclks_per_wclk; + + snd_soc_component_read(component, RT5682_TDM_TCON_CTRL, + &bclks_per_wclk); + + switch (bclks_per_wclk & RT5682_TDM_BCLK_MS1_MASK) { + case RT5682_TDM_BCLK_MS1_256: + return parent_rate * 256; + case RT5682_TDM_BCLK_MS1_128: + return parent_rate * 128; + case RT5682_TDM_BCLK_MS1_64: + return parent_rate * 64; + case RT5682_TDM_BCLK_MS1_32: + return parent_rate * 32; + default: + return 0; + } +} + +static unsigned long rt5682_bclk_get_factor(unsigned long rate, + unsigned long parent_rate) +{ + unsigned long factor; + + factor = rate / parent_rate; + if (factor < 64) + return 32; + else if (factor < 128) + return 64; + else if (factor < 256) + return 128; + else + return 256; +} + +static long rt5682_bclk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct rt5682_priv *rt5682 = + container_of(hw, struct rt5682_priv, + dai_clks_hw[RT5682_DAI_BCLK_IDX]); + unsigned long factor; + + if (!*parent_rate || !rt5682_clk_check(rt5682)) + return -EINVAL; + + /* + * BCLK rates are set as a multiplier of WCLK in HW. + * We don't allow changing the parent WCLK. We just do + * some rounding down based on the parent WCLK rate + * and find the appropriate multiplier of BCLK to + * get the rounded down BCLK value. + */ + factor = rt5682_bclk_get_factor(rate, *parent_rate); + + return *parent_rate * factor; +} + +static int rt5682_bclk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct rt5682_priv *rt5682 = + container_of(hw, struct rt5682_priv, + dai_clks_hw[RT5682_DAI_BCLK_IDX]); + struct snd_soc_component *component = rt5682->component; + struct snd_soc_dai *dai = NULL; + unsigned long factor; + + if (!rt5682_clk_check(rt5682)) + return -EINVAL; + + factor = rt5682_bclk_get_factor(rate, parent_rate); + + for_each_component_dais(component, dai) + if (dai->id == RT5682_AIF1) + break; + if (!dai) { + dev_err(component->dev, "dai %d not found in component\n", + RT5682_AIF1); + return -ENODEV; + } + + return rt5682_set_bclk1_ratio(dai, factor); +} + +static const struct clk_ops rt5682_dai_clk_ops[RT5682_DAI_NUM_CLKS] = { + [RT5682_DAI_WCLK_IDX] = { + .prepare = rt5682_wclk_prepare, + .unprepare = rt5682_wclk_unprepare, + .recalc_rate = rt5682_wclk_recalc_rate, + .round_rate = rt5682_wclk_round_rate, + .set_rate = rt5682_wclk_set_rate, + }, + [RT5682_DAI_BCLK_IDX] = { + .recalc_rate = rt5682_bclk_recalc_rate, + .round_rate = rt5682_bclk_round_rate, + .set_rate = rt5682_bclk_set_rate, + }, +}; + +static int rt5682_register_dai_clks(struct snd_soc_component *component) +{ + struct device *dev = component->dev; + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + struct rt5682_platform_data *pdata = &rt5682->pdata; + struct clk_init_data init; + struct clk *dai_clk; + struct clk_lookup *dai_clk_lookup; + struct clk_hw *dai_clk_hw; + const char *parent_name; + int i, ret; + + for (i = 0; i < RT5682_DAI_NUM_CLKS; ++i) { + dai_clk_hw = &rt5682->dai_clks_hw[i]; + + switch (i) { + case RT5682_DAI_WCLK_IDX: + /* Make MCLK the parent of WCLK */ + if (rt5682->mclk) { + parent_name = __clk_get_name(rt5682->mclk); + init.parent_names = &parent_name; + init.num_parents = 1; + } else { + init.parent_names = NULL; + init.num_parents = 0; + } + break; + case RT5682_DAI_BCLK_IDX: + /* Make WCLK the parent of BCLK */ + parent_name = __clk_get_name( + rt5682->dai_clks[RT5682_DAI_WCLK_IDX]); + init.parent_names = &parent_name; + init.num_parents = 1; + break; + default: + dev_err(dev, "Invalid clock index\n"); + ret = -EINVAL; + goto err; + } + + init.name = pdata->dai_clk_names[i]; + init.ops = &rt5682_dai_clk_ops[i]; + init.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_GATE; + dai_clk_hw->init = &init; + + dai_clk = devm_clk_register(dev, dai_clk_hw); + if (IS_ERR(dai_clk)) { + dev_warn(dev, "Failed to register %s: %ld\n", + init.name, PTR_ERR(dai_clk)); + ret = PTR_ERR(dai_clk); + goto err; + } + rt5682->dai_clks[i] = dai_clk; + + if (dev->of_node) { + devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, + dai_clk_hw); + } else { + dai_clk_lookup = clkdev_create(dai_clk, init.name, + "%s", dev_name(dev)); + if (!dai_clk_lookup) { + ret = -ENOMEM; + goto err; + } else { + rt5682->dai_clks_lookup[i] = dai_clk_lookup; + } + } + } + + return 0; + +err: + do { + if (rt5682->dai_clks_lookup[i]) + clkdev_drop(rt5682->dai_clks_lookup[i]); + } while (i-- > 0); + + return ret; +} +#endif /* CONFIG_COMMON_CLK */ + static int rt5682_probe(struct snd_soc_component *component) { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); +#ifdef CONFIG_COMMON_CLK + int ret; +#endif rt5682->component = component; +#ifdef CONFIG_COMMON_CLK + /* Check if MCLK provided */ + rt5682->mclk = devm_clk_get(component->dev, "mclk"); + if (IS_ERR(rt5682->mclk)) { + if (PTR_ERR(rt5682->mclk) != -ENOENT) { + ret = PTR_ERR(rt5682->mclk); + return ret; + } + rt5682->mclk = NULL; + } + + /* Register CCF DAI clock control */ + ret = rt5682_register_dai_clks(component); + if (ret) + return ret; + + /* Initial setup for CCF */ + rt5682->lrck[RT5682_AIF1] = CLK_48; +#endif + return 0; } @@ -2472,6 +2859,15 @@ static void rt5682_remove(struct snd_soc_component *component) { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); +#ifdef CONFIG_COMMON_CLK + int i; + + for (i = RT5682_DAI_NUM_CLKS - 1; i >= 0; --i) { + if (rt5682->dai_clks_lookup[i]) + clkdev_drop(rt5682->dai_clks_lookup[i]); + } +#endif + rt5682_reset(rt5682); } @@ -2606,6 +3002,13 @@ static int rt5682_parse_dt(struct rt5682_priv *rt5682, struct device *dev) rt5682->pdata.ldo1_en = of_get_named_gpio(dev->of_node, "realtek,ldo1-en-gpios", 0); + if (device_property_read_string_array(dev, "clock-output-names", + rt5682->pdata.dai_clk_names, + RT5682_DAI_NUM_CLKS) < 0) + dev_warn(dev, "Using default DAI clk names: %s, %s\n", + rt5682->pdata.dai_clk_names[RT5682_DAI_WCLK_IDX], + rt5682->pdata.dai_clk_names[RT5682_DAI_BCLK_IDX]); + return 0; } diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h index 465c99b7f906..f82126a6f211 100644 --- a/sound/soc/codecs/rt5682.h +++ b/sound/soc/codecs/rt5682.h @@ -841,8 +841,8 @@ #define RT5682_TDM_M_LP_INV (0x1 << 1) #define RT5682_TDM_MS_MASK (0x1 << 0) #define RT5682_TDM_MS_SFT 0 -#define RT5682_TDM_MS_M (0x0 << 0) -#define RT5682_TDM_MS_S (0x1 << 0) +#define RT5682_TDM_MS_S (0x0 << 0) +#define RT5682_TDM_MS_M (0x1 << 0) /* Global Clock Control (0x0080) */ #define RT5682_SCLK_SRC_MASK (0x7 << 13) From 8b59e642d05f0ae9800b057350c063fe7debd6bc Mon Sep 17 00:00:00 2001 From: Derek Fang Date: Tue, 18 Feb 2020 21:51:52 +0800 Subject: [PATCH 0461/4444] ASoC: rt5682: Add DAI clock binding info for WCLK/BCLK CCF usage This patch describes that rt5682 can expose WCLK and BCLK clocks and how to use. Signed-off-by: Derek Fang Link: https://lore.kernel.org/r/1582033912-6841-2-git-send-email-derek.fang@realtek.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/rt5682.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/rt5682.txt b/Documentation/devicetree/bindings/sound/rt5682.txt index 30e927a28369..ac98151d29e4 100644 --- a/Documentation/devicetree/bindings/sound/rt5682.txt +++ b/Documentation/devicetree/bindings/sound/rt5682.txt @@ -32,6 +32,12 @@ Optional properties: The delay time is realtek,btndet-delay value multiple of 8.192 ms. If absent, the default is 16. +- #clock-cells : Should be set to '<1>', wclk and bclk sources provided. +- clock-output-names : Name given for DAI clocks output. + +- clocks : phandle and clock specifier for codec MCLK. +- clock-names : Clock name string for 'clocks' attribute, should be "mclk". + Pins on the device (for linking into audio routes) for RT5682: * DMIC L1 @@ -53,4 +59,10 @@ rt5682 { realtek,dmic1-clk-pin = <1>; realtek,jd-src = <1>; realtek,btndet-delay = <16>; + + #clock-cells = <1>; + clock-output-names = "rt5682-dai-wclk", "rt5682-dai-bclk"; + + clocks = <&osc>; + clock-names = "mclk"; }; From d9303690f753dfdae51304fc89f4b04c0549a9f7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:27:39 +0900 Subject: [PATCH 0462/4444] ASoC: soc-pcm: move dai_get_widget() This patch moves dai_get_widget() to top side. This is prepare for cleanup soc-pcm.c Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87h7zpbouu.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 65a3856be250..23e36f4f965c 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -82,6 +82,15 @@ static int soc_rtd_trigger(struct snd_soc_pcm_runtime *rtd, return 0; } +static inline +struct snd_soc_dapm_widget *dai_get_widget(struct snd_soc_dai *dai, int stream) +{ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + return dai->playback_widget; + else + return dai->capture_widget; +} + static void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, int stream, int action) { @@ -1287,15 +1296,6 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, return NULL; } -static inline struct snd_soc_dapm_widget * - dai_get_widget(struct snd_soc_dai *dai, int stream) -{ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - return dai->playback_widget; - else - return dai->capture_widget; -} - static int widget_in_list(struct snd_soc_dapm_widget_list *list, struct snd_soc_dapm_widget *widget) { From 93597fae552a35d27cd1f399ffab6a6862cf9dc3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:27:43 +0900 Subject: [PATCH 0463/4444] ASoC: soc-pcm: use dai_get_widget() at dpcm_get_be() dpcm_get_be() has very duplicate code. dpcm_get_be() { ... if (stream == SNDRV_PCM_STREAM_PLAYBACK) { (1) /* code for Playback */ } else { (2) /* code for Capture */ } } The difference between Playback (1) and Capture (2) code is pointer only (= "playback_widget" or "caputre_widget"). OTOH, now we already has dai_get_widget() for it. This means we can merge (1) and (2). This patch do it and remove duplicated code. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87ftf9bouq.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 47 +++++++++++++++------------------------------ 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 23e36f4f965c..b708db972310 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1246,47 +1246,30 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, struct snd_soc_dapm_widget *widget, int stream) { struct snd_soc_pcm_runtime *be; + struct snd_soc_dapm_widget *w; struct snd_soc_dai *dai; int i; dev_dbg(card->dev, "ASoC: find BE for widget %s\n", widget->name); - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - for_each_card_rtds(card, be) { + for_each_card_rtds(card, be) { - if (!be->dai_link->no_pcm) - continue; + if (!be->dai_link->no_pcm) + continue; - dev_dbg(card->dev, "ASoC: try BE : %s\n", - be->cpu_dai->playback_widget ? - be->cpu_dai->playback_widget->name : "(not set)"); + w = dai_get_widget(be->cpu_dai, stream); - if (be->cpu_dai->playback_widget == widget) + dev_dbg(card->dev, "ASoC: try BE : %s\n", + w ? w->name : "(not set)"); + + if (w == widget) + return be; + + for_each_rtd_codec_dai(be, i, dai) { + w = dai_get_widget(dai, stream); + + if (w == widget) return be; - - for_each_rtd_codec_dai(be, i, dai) { - if (dai->playback_widget == widget) - return be; - } - } - } else { - - for_each_card_rtds(card, be) { - - if (!be->dai_link->no_pcm) - continue; - - dev_dbg(card->dev, "ASoC: try BE %s\n", - be->cpu_dai->capture_widget ? - be->cpu_dai->capture_widget->name : "(not set)"); - - if (be->cpu_dai->capture_widget == widget) - return be; - - for_each_rtd_codec_dai(be, i, dai) { - if (dai->capture_widget == widget) - return be; - } } } From c2cd821603c216a6a7242b2b4c1a093051e26aaf Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:27:48 +0900 Subject: [PATCH 0464/4444] ASoC: soc-pcm: use dai_get_widget() at dpcm_end_walk_at_be() dpcm_end_walk_at_be() has very duplicate code. dpcm_end_walk_at_be() { ... if (stream == SNDRV_PCM_STREAM_PLAYBACK) { (1) /* code for Playback */ } else { (2) /* code for Capture */ } } The difference between Playback (1) and Capture (2) code is pointer only (= "playback_widget" or "caputre_widget"). OTOH, now we already has dai_get_widget() for it. This means we can merge (1) and (2). This patch do it and remove duplicated code. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87eeutboul.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b708db972310..7d4419ae63f6 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1297,34 +1297,29 @@ static bool dpcm_end_walk_at_be(struct snd_soc_dapm_widget *widget, { struct snd_soc_card *card = widget->dapm->card; struct snd_soc_pcm_runtime *rtd; + struct snd_soc_dapm_widget *w; struct snd_soc_dai *dai; + int stream; int i; - if (dir == SND_SOC_DAPM_DIR_OUT) { - for_each_card_rtds(card, rtd) { - if (!rtd->dai_link->no_pcm) - continue; + /* adjust dir to stream */ + if (dir == SND_SOC_DAPM_DIR_OUT) + stream = SNDRV_PCM_STREAM_PLAYBACK; + else + stream = SNDRV_PCM_STREAM_CAPTURE; - if (rtd->cpu_dai->playback_widget == widget) + for_each_card_rtds(card, rtd) { + if (!rtd->dai_link->no_pcm) + continue; + + w = dai_get_widget(rtd->cpu_dai, stream); + if (w == widget) + return true; + + for_each_rtd_codec_dai(rtd, i, dai) { + w = dai_get_widget(dai, stream); + if (w == widget) return true; - - for_each_rtd_codec_dai(rtd, i, dai) { - if (dai->playback_widget == widget) - return true; - } - } - } else { /* SND_SOC_DAPM_DIR_IN */ - for_each_card_rtds(card, rtd) { - if (!rtd->dai_link->no_pcm) - continue; - - if (rtd->cpu_dai->capture_widget == widget) - return true; - - for_each_rtd_codec_dai(rtd, i, dai) { - if (dai->capture_widget == widget) - return true; - } } } From 027a483871832044fa0cb8e9df208cca5230ae91 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:27:53 +0900 Subject: [PATCH 0465/4444] ASoC: soc-pcm: use dpcm_get_be() at dpcm_end_walk_at_be() dpcm_end_walk_at_be() and dpcm_get_be() are almost same code. This patch uses dpcm_get_be() from dpcm_end_walk_at_be(). Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87d0adbouh.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 7d4419ae63f6..1d48be24bfaa 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1297,10 +1297,7 @@ static bool dpcm_end_walk_at_be(struct snd_soc_dapm_widget *widget, { struct snd_soc_card *card = widget->dapm->card; struct snd_soc_pcm_runtime *rtd; - struct snd_soc_dapm_widget *w; - struct snd_soc_dai *dai; int stream; - int i; /* adjust dir to stream */ if (dir == SND_SOC_DAPM_DIR_OUT) @@ -1308,20 +1305,9 @@ static bool dpcm_end_walk_at_be(struct snd_soc_dapm_widget *widget, else stream = SNDRV_PCM_STREAM_CAPTURE; - for_each_card_rtds(card, rtd) { - if (!rtd->dai_link->no_pcm) - continue; - - w = dai_get_widget(rtd->cpu_dai, stream); - if (w == widget) - return true; - - for_each_rtd_codec_dai(rtd, i, dai) { - w = dai_get_widget(dai, stream); - if (w == widget) - return true; - } - } + rtd = dpcm_get_be(card, widget, stream); + if (rtd) + return true; return false; } From c9645d2a952b7925b6708b24242cd5ed04975648 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:27:57 +0900 Subject: [PATCH 0466/4444] ASoC: soc-pcm: remove soc_dpcm_be_digital_mute() No one is using soc_dpcm_be_digital_mute(). If it exists only by assumption that "it may be necessary someday", let's remove it now. Otherwise code maintenance will be difficult. We can revive it when we really needed it. Let's remove it, so far. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87blpxbouc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dpcm.h | 1 - sound/soc/soc-pcm.c | 27 --------------------------- 2 files changed, 28 deletions(-) diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index b654ebfc8766..665516387671 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -141,7 +141,6 @@ void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream, enum snd_soc_dpcm_state state); /* internal use only */ -int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute); int soc_dpcm_runtime_update(struct snd_soc_card *); #ifdef CONFIG_DEBUG_FS diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 1d48be24bfaa..b8ea4d892031 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2719,33 +2719,6 @@ out: mutex_unlock(&card->mutex); return ret; } -int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute) -{ - struct snd_soc_dpcm *dpcm; - struct snd_soc_dai *dai; - - for_each_dpcm_be(fe, SNDRV_PCM_STREAM_PLAYBACK, dpcm) { - - struct snd_soc_pcm_runtime *be = dpcm->be; - int i; - - if (be->dai_link->ignore_suspend) - continue; - - for_each_rtd_codec_dai(be, i, dai) { - struct snd_soc_dai_driver *drv = dai->driver; - - dev_dbg(be->dev, "ASoC: BE digital mute %s\n", - be->dai_link->name); - - if (drv->ops && drv->ops->digital_mute && - dai->playback_active) - drv->ops->digital_mute(dai, mute); - } - } - - return 0; -} static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) { From 289a7e64f8583aaa45847c7fa3b7fabf8d48fd6b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:28:04 +0900 Subject: [PATCH 0467/4444] ASoC: soc-pcm: remove snd_soc_dpcm_be_get/set_state() No one is using snd_soc_dpcm_be_get/set_state(). If it exists only by assumption that "it may be necessary someday", let's remove it now. Otherwise code maintenance will be difficult. We can revive it when we really needed it. Let's remove it, so far. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87a75hbou7.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dpcm.h | 8 -------- sound/soc/soc-pcm.c | 16 ---------------- 2 files changed, 24 deletions(-) diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index 665516387671..3e7819d2a6aa 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -132,14 +132,6 @@ int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe, struct snd_pcm_substream * snd_soc_dpcm_get_substream(struct snd_soc_pcm_runtime *be, int stream); -/* get the BE runtime state */ -enum snd_soc_dpcm_state - snd_soc_dpcm_be_get_state(struct snd_soc_pcm_runtime *be, int stream); - -/* set the BE runtime state */ -void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream, - enum snd_soc_dpcm_state state); - /* internal use only */ int soc_dpcm_runtime_update(struct snd_soc_card *); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b8ea4d892031..bd4e4f86f5b2 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2954,22 +2954,6 @@ struct snd_pcm_substream * } EXPORT_SYMBOL_GPL(snd_soc_dpcm_get_substream); -/* get the BE runtime state */ -enum snd_soc_dpcm_state - snd_soc_dpcm_be_get_state(struct snd_soc_pcm_runtime *be, int stream) -{ - return be->dpcm[stream].state; -} -EXPORT_SYMBOL_GPL(snd_soc_dpcm_be_get_state); - -/* set the BE runtime state */ -void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, - int stream, enum snd_soc_dpcm_state state) -{ - be->dpcm[stream].state = state; -} -EXPORT_SYMBOL_GPL(snd_soc_dpcm_be_set_state); - /* * We can only hw_free, stop, pause or suspend a BE DAI if any of it's FE * are not running, paused or suspended for the specified stream direction. From 085d22be035db245c44714cf879a73eae06c9f6b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:28:07 +0900 Subject: [PATCH 0468/4444] ASoC: soc-pcm: add snd_soc_dpcm_can_be() and remove duplicate code Below functions are doing very similar things, the difference is used state only. snd_soc_dpcm_can_be_free_stop() snd_soc_dpcm_can_be_params() This patch adds common snd_soc_dpcm_check_state(), and use it from snd_soc_dpcm_can_be_free_stop() / snd_soc_dpcm_can_be_params(). It can reduce duplicate code. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/878sl1bou2.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 70 ++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index bd4e4f86f5b2..d77a2c22a04f 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2954,17 +2954,17 @@ struct snd_pcm_substream * } EXPORT_SYMBOL_GPL(snd_soc_dpcm_get_substream); -/* - * We can only hw_free, stop, pause or suspend a BE DAI if any of it's FE - * are not running, paused or suspended for the specified stream direction. - */ -int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe, - struct snd_soc_pcm_runtime *be, int stream) +static int snd_soc_dpcm_check_state(struct snd_soc_pcm_runtime *fe, + struct snd_soc_pcm_runtime *be, + int stream, + const enum snd_soc_dpcm_state *states, + int num_states) { struct snd_soc_dpcm *dpcm; int state; int ret = 1; unsigned long flags; + int i; spin_lock_irqsave(&fe->card->dpcm_lock, flags); for_each_dpcm_fe(be, stream, dpcm) { @@ -2973,18 +2973,34 @@ int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe, continue; state = dpcm->fe->dpcm[stream].state; - if (state == SND_SOC_DPCM_STATE_START || - state == SND_SOC_DPCM_STATE_PAUSED || - state == SND_SOC_DPCM_STATE_SUSPEND) { - ret = 0; - break; + for (i = 0; i < num_states; i++) { + if (state == states[i]) { + ret = 0; + break; + } } } spin_unlock_irqrestore(&fe->card->dpcm_lock, flags); - /* it's safe to free/stop this BE DAI */ + /* it's safe to do this BE DAI */ return ret; } + +/* + * We can only hw_free, stop, pause or suspend a BE DAI if any of it's FE + * are not running, paused or suspended for the specified stream direction. + */ +int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe, + struct snd_soc_pcm_runtime *be, int stream) +{ + const enum snd_soc_dpcm_state state[] = { + SND_SOC_DPCM_STATE_START, + SND_SOC_DPCM_STATE_PAUSED, + SND_SOC_DPCM_STATE_SUSPEND, + }; + + return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state)); +} EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_free_stop); /* @@ -2994,30 +3010,14 @@ EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_free_stop); int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe, struct snd_soc_pcm_runtime *be, int stream) { - struct snd_soc_dpcm *dpcm; - int state; - int ret = 1; - unsigned long flags; + const enum snd_soc_dpcm_state state[] = { + SND_SOC_DPCM_STATE_START, + SND_SOC_DPCM_STATE_PAUSED, + SND_SOC_DPCM_STATE_SUSPEND, + SND_SOC_DPCM_STATE_PREPARE, + }; - spin_lock_irqsave(&fe->card->dpcm_lock, flags); - for_each_dpcm_fe(be, stream, dpcm) { - - if (dpcm->fe == fe) - continue; - - state = dpcm->fe->dpcm[stream].state; - if (state == SND_SOC_DPCM_STATE_START || - state == SND_SOC_DPCM_STATE_PAUSED || - state == SND_SOC_DPCM_STATE_SUSPEND || - state == SND_SOC_DPCM_STATE_PREPARE) { - ret = 0; - break; - } - } - spin_unlock_irqrestore(&fe->card->dpcm_lock, flags); - - /* it's safe to change hw_params */ - return ret; + return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state)); } EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params); From cae06eb92557f0a073835380e57abee5f8173d73 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:28:11 +0900 Subject: [PATCH 0469/4444] ASoC: soc-pcm: use goto and remove multi return When we use some kind of lock, we need to do unlock. In that time, multi unlock/return is not good implementation. This patch add label and use goto at dpcm_fe_dai_open() to reduce such code. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/877e0lboty.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index d77a2c22a04f..5a79a830ee18 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2733,8 +2733,7 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) ret = dpcm_path_get(fe, stream, &list); if (ret < 0) { - mutex_unlock(&fe->card->mutex); - return ret; + goto open_end; } else if (ret == 0) { dev_dbg(fe->dev, "ASoC: %s no valid %s route\n", fe->dai_link->name, stream ? "capture" : "playback"); @@ -2755,6 +2754,7 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) dpcm_clear_pending_state(fe, stream); dpcm_path_put(&list); +open_end: mutex_unlock(&fe->card->mutex); return ret; } From 0f6011fd79a2fb92cb80177fd6bdc8aac3a3cd93 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:28:15 +0900 Subject: [PATCH 0470/4444] ASoC: soc-pcm: merge playback/cature_active into stream_active DAI has playback_active and capture_active to care usage count. OTOH, we have SNDRV_PCM_STREAM_PLAYBACK/CAPTURE. But because of this kind of implementation mismatch, ALSA SoC has many verbose code. To solve this issue, this patch merge playback_active/capture_active into stream_active[2]; Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/875zg5botu.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +-- sound/soc/codecs/cs4271.c | 4 ++-- sound/soc/dwc/dwc-i2s.c | 4 ++-- sound/soc/soc-core.c | 17 +++++++++-------- sound/soc/soc-pcm.c | 25 ++++++++++++------------- 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 04c23ac0dfff..7481e468be39 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -322,8 +322,7 @@ struct snd_soc_dai { struct snd_soc_dai_driver *driver; /* DAI runtime info */ - unsigned int capture_active; /* stream usage count */ - unsigned int playback_active; /* stream usage count */ + unsigned int stream_active[SNDRV_PCM_STREAM_LAST + 1]; /* usage count */ unsigned int active; diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 04b86a51e055..62f412d6f9f2 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -356,9 +356,9 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream, */ if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK && - !dai->capture_active) || + !dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]) || (substream->stream == SNDRV_PCM_STREAM_CAPTURE && - !dai->playback_active)) { + !dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK])) { ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, CS4271_MODE2_PDN, CS4271_MODE2_PDN); diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c index 7eeca2150b2d..a8bff6f08a69 100644 --- a/sound/soc/dwc/dwc-i2s.c +++ b/sound/soc/dwc/dwc-i2s.c @@ -427,9 +427,9 @@ static int dw_i2s_resume(struct snd_soc_component *component) clk_enable(dev->clk); for_each_component_dais(component, dai) { - if (dai->playback_active) + if (dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK]) dw_i2s_config(dev, SNDRV_PCM_STREAM_PLAYBACK); - if (dai->capture_active) + if (dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]) dw_i2s_config(dev, SNDRV_PCM_STREAM_CAPTURE); } diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6a58a8f6e3c4..f0ae1a7d7e09 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -365,19 +365,20 @@ EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime); void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *codec_dai = rtd->codec_dai; + int playback = SNDRV_PCM_STREAM_PLAYBACK; mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n", codec_dai->driver->playback.stream_name, - codec_dai->playback_active ? "active" : "inactive", + codec_dai->stream_active[playback] ? "active" : "inactive", rtd->pop_wait ? "yes" : "no"); /* are we waiting on this codec DAI stream */ if (rtd->pop_wait == 1) { rtd->pop_wait = 0; - snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, + snd_soc_dapm_stream_event(rtd, playback, SND_SOC_DAPM_STREAM_STOP); } @@ -514,6 +515,7 @@ int snd_soc_suspend(struct device *dev) struct snd_soc_card *card = dev_get_drvdata(dev); struct snd_soc_component *component; struct snd_soc_pcm_runtime *rtd; + int playback = SNDRV_PCM_STREAM_PLAYBACK; int i; /* If the card is not initialized yet there is nothing to do */ @@ -537,9 +539,8 @@ int snd_soc_suspend(struct device *dev) continue; for_each_rtd_codec_dai(rtd, i, dai) { - if (dai->playback_active) - snd_soc_dai_digital_mute(dai, 1, - SNDRV_PCM_STREAM_PLAYBACK); + if (dai->stream_active[playback]) + snd_soc_dai_digital_mute(dai, 1, playback); } } @@ -680,14 +681,14 @@ static void soc_resume_deferred(struct work_struct *work) /* unmute any active DACs */ for_each_card_rtds(card, rtd) { struct snd_soc_dai *dai; + int playback = SNDRV_PCM_STREAM_PLAYBACK; if (rtd->dai_link->ignore_suspend) continue; for_each_rtd_codec_dai(rtd, i, dai) { - if (dai->playback_active) - snd_soc_dai_digital_mute(dai, 0, - SNDRV_PCM_STREAM_PLAYBACK); + if (dai->stream_active[playback]) + snd_soc_dai_digital_mute(dai, 0, playback); } } diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 5a79a830ee18..6fd69574ca31 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -100,15 +100,9 @@ static void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, lockdep_assert_held(&rtd->card->pcm_mutex); - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - cpu_dai->playback_active += action; - for_each_rtd_codec_dai(rtd, i, codec_dai) - codec_dai->playback_active += action; - } else { - cpu_dai->capture_active += action; - for_each_rtd_codec_dai(rtd, i, codec_dai) - codec_dai->capture_active += action; - } + cpu_dai->stream_active[stream] += action; + for_each_rtd_codec_dai(rtd, i, codec_dai) + codec_dai->stream_active[stream] += action; cpu_dai->active += action; cpu_dai->component->active += action; @@ -967,8 +961,11 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) /* apply codec digital mute */ for_each_rtd_codec_dai(rtd, i, codec_dai) { - if ((playback && codec_dai->playback_active == 1) || - (!playback && codec_dai->capture_active == 1)) + int playback_active = codec_dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK]; + int capture_active = codec_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]; + + if ((playback && playback_active == 1) || + (!playback && capture_active == 1)) snd_soc_dai_digital_mute(codec_dai, 1, substream->stream); } @@ -2634,7 +2631,8 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) goto capture; /* skip if FE isn't currently playing */ - if (!fe->cpu_dai->playback_active || !fe->codec_dai->playback_active) + if (!fe->cpu_dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK] || + !fe->codec_dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK]) goto capture; paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list); @@ -2665,7 +2663,8 @@ capture: return 0; /* skip if FE isn't currently capturing */ - if (!fe->cpu_dai->capture_active || !fe->codec_dai->capture_active) + if (!fe->cpu_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE] || + !fe->codec_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]) return 0; paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list); From 3193abd26b515ccac65e1c323533cb7f53d06176 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:28:19 +0900 Subject: [PATCH 0471/4444] ALSA: pcm.h: add for_each_pcm_streams() ALSA code has SNDRV_PCM_STREAM_PLAYBACK/CAPTURE everywhere. Having for_each_xxxx macro is useful. This patch adds for_each_pcm_streams() for it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Acked-by: Takashi Iwai Link: https://lore.kernel.org/r/874kvpbotq.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/pcm.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index f657ff08f317..2628246b76fa 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -644,6 +644,11 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, #define snd_pcm_group_for_each_entry(s, substream) \ list_for_each_entry(s, &substream->group->substreams, link_list) +#define for_each_pcm_streams(stream) \ + for (stream = SNDRV_PCM_STREAM_PLAYBACK; \ + stream <= SNDRV_PCM_STREAM_LAST; \ + stream++) + /** * snd_pcm_running - Check whether the substream is in a running state * @substream: substream to check From d74c2a156b710e9ad81193a60e037430f8894c0c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:28:25 +0900 Subject: [PATCH 0472/4444] ASoC: soc-core: use for_each_pcm_streams() macro Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/8736b9botk.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f0ae1a7d7e09..30c17fde14ca 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -432,6 +432,7 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( struct snd_soc_component *component; struct device *dev; int ret; + int stream; /* * for rtd->dev @@ -466,10 +467,10 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( rtd->dev = dev; INIT_LIST_HEAD(&rtd->list); - INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients); - INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients); - INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].fe_clients); - INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].fe_clients); + for_each_pcm_streams(stream) { + INIT_LIST_HEAD(&rtd->dpcm[stream].be_clients); + INIT_LIST_HEAD(&rtd->dpcm[stream].fe_clients); + } dev_set_drvdata(dev, rtd); INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); @@ -559,17 +560,14 @@ int snd_soc_suspend(struct device *dev) snd_soc_flush_all_delayed_work(card); for_each_card_rtds(card, rtd) { + int stream; if (rtd->dai_link->ignore_suspend) continue; - snd_soc_dapm_stream_event(rtd, - SNDRV_PCM_STREAM_PLAYBACK, - SND_SOC_DAPM_STREAM_SUSPEND); - - snd_soc_dapm_stream_event(rtd, - SNDRV_PCM_STREAM_CAPTURE, - SND_SOC_DAPM_STREAM_SUSPEND); + for_each_pcm_streams(stream) + snd_soc_dapm_stream_event(rtd, stream, + SND_SOC_DAPM_STREAM_SUSPEND); } /* Recheck all endpoints too, their state is affected by suspend */ @@ -665,17 +663,14 @@ static void soc_resume_deferred(struct work_struct *work) } for_each_card_rtds(card, rtd) { + int stream; if (rtd->dai_link->ignore_suspend) continue; - snd_soc_dapm_stream_event(rtd, - SNDRV_PCM_STREAM_PLAYBACK, - SND_SOC_DAPM_STREAM_RESUME); - - snd_soc_dapm_stream_event(rtd, - SNDRV_PCM_STREAM_CAPTURE, - SND_SOC_DAPM_STREAM_RESUME); + for_each_pcm_streams(stream) + snd_soc_dapm_stream_event(rtd, stream, + SND_SOC_DAPM_STREAM_RESUME); } /* unmute any active DACs */ From 7083f877ea66e106f90e9a1a0dabb19ebbacc4e6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:28:28 +0900 Subject: [PATCH 0473/4444] ASoC: soc-pcm: use for_each_pcm_streams() macro Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/871rqtboth.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 105 ++++++++++++++++---------------------------- 1 file changed, 39 insertions(+), 66 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 6fd69574ca31..63f67eb7c077 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2612,6 +2612,7 @@ static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream) static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) { struct snd_soc_dapm_widget_list *list; + int stream; int count, paths; if (!fe->dai_link->dynamic) @@ -2625,69 +2626,42 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) dev_dbg(fe->dev, "ASoC: DPCM %s runtime update for FE %s\n", new ? "new" : "old", fe->dai_link->name); - /* skip if FE doesn't have playback capability */ - if (!snd_soc_dai_stream_valid(fe->cpu_dai, SNDRV_PCM_STREAM_PLAYBACK) || - !snd_soc_dai_stream_valid(fe->codec_dai, SNDRV_PCM_STREAM_PLAYBACK)) - goto capture; + for_each_pcm_streams(stream) { - /* skip if FE isn't currently playing */ - if (!fe->cpu_dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK] || - !fe->codec_dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK]) - goto capture; + /* skip if FE doesn't have playback/capture capability */ + if (!snd_soc_dai_stream_valid(fe->cpu_dai, stream) || + !snd_soc_dai_stream_valid(fe->codec_dai, stream)) + continue; - paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list); - if (paths < 0) { - dev_warn(fe->dev, "ASoC: %s no valid %s path\n", - fe->dai_link->name, "playback"); - return paths; + /* skip if FE isn't currently playing/capturing */ + if (!fe->cpu_dai->stream_active[stream] || + !fe->codec_dai->stream_active[stream]) + continue; + + paths = dpcm_path_get(fe, stream, &list); + if (paths < 0) { + dev_warn(fe->dev, "ASoC: %s no valid %s path\n", + fe->dai_link->name, + stream == SNDRV_PCM_STREAM_PLAYBACK ? + "playback" : "capture"); + return paths; + } + + /* update any playback/capture paths */ + count = dpcm_process_paths(fe, stream, &list, new); + if (count) { + if (new) + dpcm_run_new_update(fe, stream); + else + dpcm_run_old_update(fe, stream); + + dpcm_clear_pending_state(fe, stream); + dpcm_be_disconnect(fe, stream); + } + + dpcm_path_put(&list); } - /* update any playback paths */ - count = dpcm_process_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, &list, new); - if (count) { - if (new) - dpcm_run_new_update(fe, SNDRV_PCM_STREAM_PLAYBACK); - else - dpcm_run_old_update(fe, SNDRV_PCM_STREAM_PLAYBACK); - - dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_PLAYBACK); - dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK); - } - - dpcm_path_put(&list); - -capture: - /* skip if FE doesn't have capture capability */ - if (!snd_soc_dai_stream_valid(fe->cpu_dai, SNDRV_PCM_STREAM_CAPTURE) || - !snd_soc_dai_stream_valid(fe->codec_dai, SNDRV_PCM_STREAM_CAPTURE)) - return 0; - - /* skip if FE isn't currently capturing */ - if (!fe->cpu_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE] || - !fe->codec_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]) - return 0; - - paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list); - if (paths < 0) { - dev_warn(fe->dev, "ASoC: %s no valid %s path\n", - fe->dai_link->name, "capture"); - return paths; - } - - /* update any old capture paths */ - count = dpcm_process_paths(fe, SNDRV_PCM_STREAM_CAPTURE, &list, new); - if (count) { - if (new) - dpcm_run_new_update(fe, SNDRV_PCM_STREAM_CAPTURE); - else - dpcm_run_old_update(fe, SNDRV_PCM_STREAM_CAPTURE); - - dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_CAPTURE); - dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE); - } - - dpcm_path_put(&list); - return 0; } @@ -3114,19 +3088,18 @@ static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf, { struct snd_soc_pcm_runtime *fe = file->private_data; ssize_t out_count = PAGE_SIZE, offset = 0, ret = 0; + int stream; char *buf; buf = kmalloc(out_count, GFP_KERNEL); if (!buf) return -ENOMEM; - if (snd_soc_dai_stream_valid(fe->cpu_dai, SNDRV_PCM_STREAM_PLAYBACK)) - offset += dpcm_show_state(fe, SNDRV_PCM_STREAM_PLAYBACK, - buf + offset, out_count - offset); - - if (snd_soc_dai_stream_valid(fe->cpu_dai, SNDRV_PCM_STREAM_CAPTURE)) - offset += dpcm_show_state(fe, SNDRV_PCM_STREAM_CAPTURE, - buf + offset, out_count - offset); + for_each_pcm_streams(stream) + if (snd_soc_dai_stream_valid(fe->cpu_dai, stream)) + offset += dpcm_show_state(fe, stream, + buf + offset, + out_count - offset); ret = simple_read_from_buffer(user_buf, count, ppos, buf, offset); From ee10fbe1cdf7cb4ae62f5e23ccd771e696b8f404 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:28:32 +0900 Subject: [PATCH 0474/4444] ASoC: soc-generic-dmaengine-pcm: use for_each_pcm_streams() macro Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87zhdhaa8x.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-generic-dmaengine-pcm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 2cc25651661c..d6b4831e8aec 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -237,7 +237,7 @@ static int dmaengine_pcm_new(struct snd_soc_component *component, max_buffer_size = SIZE_MAX; } - for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) { + for_each_pcm_streams(i) { substream = rtd->pcm->streams[i].substream; if (!substream) continue; @@ -371,8 +371,7 @@ static int dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm, dev = config->dma_dev; } - for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; - i++) { + for_each_pcm_streams(i) { if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) name = "rx-tx"; else @@ -401,8 +400,7 @@ static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm) { unsigned int i; - for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; - i++) { + for_each_pcm_streams(i) { if (!pcm->chan[i]) continue; dma_release_channel(pcm->chan[i]); From 0a170be9631ea8335e494f3c5f7ab720287023a2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:28:36 +0900 Subject: [PATCH 0475/4444] ASoC: dwc: dwc-i2s: use for_each_pcm_streams() macro Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87y2t1aa8t.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/dwc/dwc-i2s.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c index a8bff6f08a69..515f88456dbd 100644 --- a/sound/soc/dwc/dwc-i2s.c +++ b/sound/soc/dwc/dwc-i2s.c @@ -422,15 +422,15 @@ static int dw_i2s_resume(struct snd_soc_component *component) { struct dw_i2s_dev *dev = snd_soc_component_get_drvdata(component); struct snd_soc_dai *dai; + int stream; if (dev->capability & DW_I2S_MASTER) clk_enable(dev->clk); for_each_component_dais(component, dai) { - if (dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK]) - dw_i2s_config(dev, SNDRV_PCM_STREAM_PLAYBACK); - if (dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]) - dw_i2s_config(dev, SNDRV_PCM_STREAM_CAPTURE); + for_each_pcm_streams(stream) + if (dai->stream_active[stream]) + dw_i2s_config(dev, stream); } return 0; From fa7b2a1fcb92906a284b0824b45866a7b8afb599 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:28:40 +0900 Subject: [PATCH 0476/4444] ASoC: fsl: fsl_asrc_dma: use for_each_pcm_streams() macro Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87wo8laa8p.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc_dma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c index ece130f59d15..44e5924be870 100644 --- a/sound/soc/fsl/fsl_asrc_dma.c +++ b/sound/soc/fsl/fsl_asrc_dma.c @@ -400,7 +400,7 @@ static int fsl_asrc_dma_pcm_new(struct snd_soc_component *component, return ret; } - for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_LAST; i++) { + for_each_pcm_streams(i) { substream = pcm->streams[i].substream; if (!substream) continue; @@ -428,7 +428,7 @@ static void fsl_asrc_dma_pcm_free(struct snd_soc_component *component, struct snd_pcm_substream *substream; int i; - for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_LAST; i++) { + for_each_pcm_streams(i) { substream = pcm->streams[i].substream; if (!substream) continue; From 4c260c3f19bd16e6b11841aad1162f5a105ed24e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:28:44 +0900 Subject: [PATCH 0477/4444] ASoC: qcom: lpass-platform: use for_each_pcm_streams() macro Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87v9o5aa8m.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index b05091c283b7..5d1bc5757169 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -529,7 +529,7 @@ static void lpass_platform_pcm_free(struct snd_soc_component *component, struct snd_pcm_substream *substream; int i; - for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) { + for_each_pcm_streams(i) { substream = pcm->streams[i].substream; if (substream) { snd_dma_free_pages(&substream->dma_buffer); From 525c4107da8c0a86aa3548dc6e1d0014749e95f7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:28:47 +0900 Subject: [PATCH 0478/4444] ASoC: sof: sof-audio: use for_each_pcm_streams() macro Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87tv3paa8i.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-audio.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 75f2ef2bd94b..fc4ed2a8a914 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -23,7 +23,7 @@ bool snd_sof_dsp_only_d0i3_compatible_stream_active(struct snd_sof_dev *sdev) int dir; list_for_each_entry(spcm, &sdev->pcm_list, list) { - for (dir = 0; dir <= SNDRV_PCM_STREAM_CAPTURE; dir++) { + for_each_pcm_streams(dir) { substream = spcm->stream[dir].substream; if (!substream || !substream->runtime) continue; @@ -71,7 +71,7 @@ int sof_set_hw_params_upon_resume(struct device *dev) * have been suspended. */ list_for_each_entry(spcm, &sdev->pcm_list, list) { - for (dir = 0; dir <= SNDRV_PCM_STREAM_CAPTURE; dir++) { + for_each_pcm_streams(dir) { /* * do not reset hw_params upon resume for streams that * were kept running during suspend @@ -319,16 +319,11 @@ struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_soc_component *scomp, int dir; list_for_each_entry(spcm, &sdev->pcm_list, list) { - dir = SNDRV_PCM_STREAM_PLAYBACK; - if (spcm->stream[dir].comp_id == comp_id) { - *direction = dir; - return spcm; - } - - dir = SNDRV_PCM_STREAM_CAPTURE; - if (spcm->stream[dir].comp_id == comp_id) { - *direction = dir; - return spcm; + for_each_pcm_streams(dir) { + if (spcm->stream[dir].comp_id == comp_id) { + *direction = dir; + return spcm; + } } } From ffd11d1e7ad4602d5d1c2b4517ad316f7587d4d9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Feb 2020 17:28:51 +0900 Subject: [PATCH 0479/4444] ALSA: usx2y: use for_each_pcm_streams() macro Signed-off-by: Kuninori Morimoto Reviewed-by: Takashi Iwai Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87sgj9aa8e.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/usb/usx2y/usbusx2yaudio.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index 772f6f3ccbb1..37d290fe9d43 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -906,11 +906,12 @@ static const struct snd_pcm_ops snd_usX2Y_pcm_ops = */ static void usX2Y_audio_stream_free(struct snd_usX2Y_substream **usX2Y_substream) { - kfree(usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]); - usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK] = NULL; + int stream; - kfree(usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]); - usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE] = NULL; + for_each_pcm_streams(stream) { + kfree(usX2Y_substream[stream]); + usX2Y_substream[stream] = NULL; + } } static void snd_usX2Y_pcm_private_free(struct snd_pcm *pcm) From c2d35ada106ed51bb4080cc235a6c421b883cbec Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Tue, 18 Feb 2020 18:14:18 +0100 Subject: [PATCH 0480/4444] arm64: dts: ls1028a: add missing SPI nodes The LS1028A has three (dual) SPI controller. These are compatible with the ones from the LS1021A. Add the nodes. The third controller was tested on a custom board. Signed-off-by: Michael Walle Signed-off-by: Shawn Guo --- .../arm64/boot/dts/freescale/fsl-ls1028a.dtsi | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi index da3906858430..8694098aa94b 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi @@ -290,6 +290,45 @@ status = "disabled"; }; + dspi0: spi@2100000 { + compatible = "fsl,ls1028a-dspi", "fsl,ls1021a-v1.0-dspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2100000 0x0 0x10000>; + interrupts = ; + clock-names = "dspi"; + clocks = <&clockgen 4 1>; + spi-num-chipselects = <4>; + little-endian; + status = "disabled"; + }; + + dspi1: spi@2110000 { + compatible = "fsl,ls1028a-dspi", "fsl,ls1021a-v1.0-dspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2110000 0x0 0x10000>; + interrupts = ; + clock-names = "dspi"; + clocks = <&clockgen 4 1>; + spi-num-chipselects = <4>; + little-endian; + status = "disabled"; + }; + + dspi2: spi@2120000 { + compatible = "fsl,ls1028a-dspi", "fsl,ls1021a-v1.0-dspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2120000 0x0 0x10000>; + interrupts = ; + clock-names = "dspi"; + clocks = <&clockgen 4 1>; + spi-num-chipselects = <3>; + little-endian; + status = "disabled"; + }; + esdhc: mmc@2140000 { compatible = "fsl,ls1028a-esdhc", "fsl,esdhc"; reg = <0x0 0x2140000 0x0 0x10000>; From 64bee9c6cd48179010149313f74f9557345fd0da Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 18 Feb 2020 19:03:24 +0800 Subject: [PATCH 0481/4444] clk: imx8mp: Include slab.h instead of clkdev.h slab.h is necessary and included indirectly by clkdev.h, actually, there is nothing in use from clkdev.h, so just include slab.h instead of clkdev.h. Signed-off-by: Anson Huang Reviewed-by: Stephen Boyd Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index a16af4fce044..3adc8aa46200 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -4,13 +4,13 @@ */ #include -#include #include #include #include #include #include #include +#include #include #include "clk.h" From 2b507025e4b728bb1612855caa6a4abaf5fb0030 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 18 Feb 2020 19:03:25 +0800 Subject: [PATCH 0482/4444] clk: imx8mm: Remove unused includes There is nothing in use from init.h/of.h, remove them. Signed-off-by: Anson Huang Reviewed-by: Stephen Boyd Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c index 2f2c240a86e2..481d20ae4e0b 100644 --- a/drivers/clk/imx/clk-imx8mm.c +++ b/drivers/clk/imx/clk-imx8mm.c @@ -6,10 +6,8 @@ #include #include #include -#include #include #include -#include #include #include #include From 6b2d0cffee52260bbf20414ce408af3f6f718d52 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 18 Feb 2020 19:03:26 +0800 Subject: [PATCH 0483/4444] clk: imx8mn: Remove unused includes There is nothing in use from init.h/of.h, remove them. Signed-off-by: Anson Huang Reviewed-by: Stephen Boyd Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mn.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c index 67b826d7184b..fb47f86e35e8 100644 --- a/drivers/clk/imx/clk-imx8mn.c +++ b/drivers/clk/imx/clk-imx8mn.c @@ -6,10 +6,8 @@ #include #include #include -#include #include #include -#include #include #include #include From b7ad6be2ee67b12cba31d30deb34beab19acac57 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 19 Feb 2020 00:21:00 +0300 Subject: [PATCH 0484/4444] mtd: spi-nor: split spi_nor_spimem_xfer_data() spi_nor_spimem_xfer_data() being a helper function for the data reads/ writes contains 3 fragments that depend on the data direction; and I'm going to add another one to call the SPI dirmap API... I think this function should be split so that the common fragments are put into 2 functions, spi_nor_spimem_bounce() and spi_nor_spimem_exec_op() called from spi_nor_spimem_{read|write}_data(), and the data direction dependent bits moved back into those read/write functions -- that way we would be able to avoid *goto*s otherwise needed in the next patch adding the SPI dirmap support... Signed-off-by: Sergei Shtylyov Signed-off-by: Tudor Ambarus --- drivers/mtd/spi-nor/spi-nor.c | 87 +++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index b5ef17b2897a..1ce9784d86e8 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -246,55 +246,45 @@ struct flash_info { #define JEDEC_MFR(info) ((info)->id[0]) /** - * spi_nor_spimem_xfer_data() - helper function to read/write data to - * flash's memory region + * spi_nor_spimem_bounce() - check if a bounce buffer is needed for the data + * transfer * @nor: pointer to 'struct spi_nor' * @op: pointer to 'struct spi_mem_op' template for transfer * - * Return: number of bytes transferred on success, -errno otherwise + * If we have to use the bounce buffer, the data field in @op will be updated. + * + * Return: true if the bounce buffer is needed, false if not */ -static ssize_t spi_nor_spimem_xfer_data(struct spi_nor *nor, - struct spi_mem_op *op) +static bool spi_nor_spimem_bounce(struct spi_nor *nor, struct spi_mem_op *op) { - bool usebouncebuf = false; - void *rdbuf = NULL; - const void *buf; - int ret; - - if (op->data.dir == SPI_MEM_DATA_IN) - buf = op->data.buf.in; - else - buf = op->data.buf.out; - - if (object_is_on_stack(buf) || !virt_addr_valid(buf)) - usebouncebuf = true; - - if (usebouncebuf) { + /* op->data.buf.in occupies the same memory as op->data.buf.out */ + if (object_is_on_stack(op->data.buf.in) || + !virt_addr_valid(op->data.buf.in)) { if (op->data.nbytes > nor->bouncebuf_size) op->data.nbytes = nor->bouncebuf_size; - - if (op->data.dir == SPI_MEM_DATA_IN) { - rdbuf = op->data.buf.in; - op->data.buf.in = nor->bouncebuf; - } else { - op->data.buf.out = nor->bouncebuf; - memcpy(nor->bouncebuf, buf, - op->data.nbytes); - } + op->data.buf.in = nor->bouncebuf; + return true; } - ret = spi_mem_adjust_op_size(nor->spimem, op); - if (ret) - return ret; + return false; +} - ret = spi_mem_exec_op(nor->spimem, op); - if (ret) - return ret; +/** + * spi_nor_spimem_exec_op() - execute a memory operation + * @nor: pointer to 'struct spi_nor' + * @op: pointer to 'struct spi_mem_op' template for transfer + * + * Return: 0 on success, -error otherwise. + */ +static int spi_nor_spimem_exec_op(struct spi_nor *nor, struct spi_mem_op *op) +{ + int error; - if (usebouncebuf && op->data.dir == SPI_MEM_DATA_IN) - memcpy(rdbuf, nor->bouncebuf, op->data.nbytes); + error = spi_mem_adjust_op_size(nor->spimem, op); + if (error) + return error; - return op->data.nbytes; + return spi_mem_exec_op(nor->spimem, op); } /** @@ -315,6 +305,8 @@ static ssize_t spi_nor_spimem_read_data(struct spi_nor *nor, loff_t from, SPI_MEM_OP_ADDR(nor->addr_width, from, 1), SPI_MEM_OP_DUMMY(nor->read_dummy, 1), SPI_MEM_OP_DATA_IN(len, buf, 1)); + bool usebouncebuf; + int error; /* get transfer protocols. */ op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto); @@ -325,7 +317,16 @@ static ssize_t spi_nor_spimem_read_data(struct spi_nor *nor, loff_t from, /* convert the dummy cycles to the number of bytes */ op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8; - return spi_nor_spimem_xfer_data(nor, &op); + usebouncebuf = spi_nor_spimem_bounce(nor, &op); + + error = spi_nor_spimem_exec_op(nor, &op); + if (error) + return error; + + if (usebouncebuf) + memcpy(buf, op.data.buf.in, op.data.nbytes); + + return op.data.nbytes; } /** @@ -364,6 +365,7 @@ static ssize_t spi_nor_spimem_write_data(struct spi_nor *nor, loff_t to, SPI_MEM_OP_ADDR(nor->addr_width, to, 1), SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_OUT(len, buf, 1)); + int error; op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto); op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto); @@ -372,7 +374,14 @@ static ssize_t spi_nor_spimem_write_data(struct spi_nor *nor, loff_t to, if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second) op.addr.nbytes = 0; - return spi_nor_spimem_xfer_data(nor, &op); + if (spi_nor_spimem_bounce(nor, &op)) + memcpy(nor->bouncebuf, buf, op.data.nbytes); + + error = spi_nor_spimem_exec_op(nor, &op); + if (error) + return error; + + return op.data.nbytes; } /** From df5c21002cf4bb9c755c6330d101487c5d530c10 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 19 Feb 2020 00:24:10 +0300 Subject: [PATCH 0485/4444] mtd: spi-nor: use spi-mem dirmap API Make use of the spi-mem direct mapping API to let advanced controllers optimize read/write operations when they support direct mapping. Based on the original patch by Boris Brezillon . Signed-off-by: Sergei Shtylyov Reviewed-by: Boris Brezillon Signed-off-by: Tudor Ambarus --- drivers/mtd/spi-nor/spi-nor.c | 94 +++++++++++++++++++++++++++++++---- include/linux/mtd/spi-nor.h | 6 +++ 2 files changed, 90 insertions(+), 10 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 1ce9784d86e8..1224247b26cc 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -306,6 +306,7 @@ static ssize_t spi_nor_spimem_read_data(struct spi_nor *nor, loff_t from, SPI_MEM_OP_DUMMY(nor->read_dummy, 1), SPI_MEM_OP_DATA_IN(len, buf, 1)); bool usebouncebuf; + ssize_t nbytes; int error; /* get transfer protocols. */ @@ -319,14 +320,20 @@ static ssize_t spi_nor_spimem_read_data(struct spi_nor *nor, loff_t from, usebouncebuf = spi_nor_spimem_bounce(nor, &op); - error = spi_nor_spimem_exec_op(nor, &op); - if (error) - return error; + if (nor->dirmap.rdesc) { + nbytes = spi_mem_dirmap_read(nor->dirmap.rdesc, op.addr.val, + op.data.nbytes, op.data.buf.in); + } else { + error = spi_nor_spimem_exec_op(nor, &op); + if (error) + return error; + nbytes = op.data.nbytes; + } - if (usebouncebuf) - memcpy(buf, op.data.buf.in, op.data.nbytes); + if (usebouncebuf && nbytes > 0) + memcpy(buf, op.data.buf.in, nbytes); - return op.data.nbytes; + return nbytes; } /** @@ -365,6 +372,7 @@ static ssize_t spi_nor_spimem_write_data(struct spi_nor *nor, loff_t to, SPI_MEM_OP_ADDR(nor->addr_width, to, 1), SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_OUT(len, buf, 1)); + ssize_t nbytes; int error; op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto); @@ -377,11 +385,17 @@ static ssize_t spi_nor_spimem_write_data(struct spi_nor *nor, loff_t to, if (spi_nor_spimem_bounce(nor, &op)) memcpy(nor->bouncebuf, buf, op.data.nbytes); - error = spi_nor_spimem_exec_op(nor, &op); - if (error) - return error; + if (nor->dirmap.wdesc) { + nbytes = spi_mem_dirmap_write(nor->dirmap.wdesc, op.addr.val, + op.data.nbytes, op.data.buf.out); + } else { + error = spi_nor_spimem_exec_op(nor, &op); + if (error) + return error; + nbytes = op.data.nbytes; + } - return op.data.nbytes; + return nbytes; } /** @@ -5265,6 +5279,58 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, } EXPORT_SYMBOL_GPL(spi_nor_scan); +static int spi_nor_create_read_dirmap(struct spi_nor *nor) +{ + struct spi_mem_dirmap_info info = { + .op_tmpl = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 1), + SPI_MEM_OP_ADDR(nor->addr_width, 0, 1), + SPI_MEM_OP_DUMMY(nor->read_dummy, 1), + SPI_MEM_OP_DATA_IN(0, NULL, 1)), + .offset = 0, + .length = nor->mtd.size, + }; + struct spi_mem_op *op = &info.op_tmpl; + + /* get transfer protocols. */ + op->cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto); + op->addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->read_proto); + op->dummy.buswidth = op->addr.buswidth; + op->data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto); + + /* convert the dummy cycles to the number of bytes */ + op->dummy.nbytes = (nor->read_dummy * op->dummy.buswidth) / 8; + + nor->dirmap.rdesc = devm_spi_mem_dirmap_create(nor->dev, nor->spimem, + &info); + return PTR_ERR_OR_ZERO(nor->dirmap.rdesc); +} + +static int spi_nor_create_write_dirmap(struct spi_nor *nor) +{ + struct spi_mem_dirmap_info info = { + .op_tmpl = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 1), + SPI_MEM_OP_ADDR(nor->addr_width, 0, 1), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(0, NULL, 1)), + .offset = 0, + .length = nor->mtd.size, + }; + struct spi_mem_op *op = &info.op_tmpl; + + /* get transfer protocols. */ + op->cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto); + op->addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto); + op->dummy.buswidth = op->addr.buswidth; + op->data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto); + + if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second) + op->addr.nbytes = 0; + + nor->dirmap.wdesc = devm_spi_mem_dirmap_create(nor->dev, nor->spimem, + &info); + return PTR_ERR_OR_ZERO(nor->dirmap.wdesc); +} + static int spi_nor_probe(struct spi_mem *spimem) { struct spi_device *spi = spimem->spi; @@ -5326,6 +5392,14 @@ static int spi_nor_probe(struct spi_mem *spimem) return -ENOMEM; } + ret = spi_nor_create_read_dirmap(nor); + if (ret) + return ret; + + ret = spi_nor_create_write_dirmap(nor); + if (ret) + return ret; + return mtd_device_register(&nor->mtd, data ? data->parts : NULL, data ? data->nr_parts : 0); } diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 61be6ed33097..de90724f62f1 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -580,6 +580,7 @@ struct flash_info; * The structure includes legacy flash parameters and * settings that can be overwritten by the spi_nor_fixups * hooks, or dynamically when parsing the SFDP tables. + * @dirmap: pointers to struct spi_mem_dirmap_desc for reads/writes. * @priv: the private data */ struct spi_nor { @@ -606,6 +607,11 @@ struct spi_nor { struct spi_nor_flash_parameter params; + struct { + struct spi_mem_dirmap_desc *rdesc; + struct spi_mem_dirmap_desc *wdesc; + } dirmap; + void *priv; }; From f98df5ed0a670f2c4c1a50d7901acbb862a247c7 Mon Sep 17 00:00:00 2001 From: Oliver O'Halloran Date: Thu, 30 Jan 2020 17:31:52 +1100 Subject: [PATCH 0486/4444] powerpc/pseries/vio: Remove stray #ifdef CONFIG_PPC_PSERIES vio.c is in platforms/pseries, which is only built if PPC_PSERIES=y. In other words, this ifdef is pointless. Signed-off-by: Oliver O'Halloran Reviewed-by: Tyrel Datwyler Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200130063153.19915-1-oohall@gmail.com --- arch/powerpc/platforms/pseries/vio.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c index f682b7babc09..37f1f25ba804 100644 --- a/arch/powerpc/platforms/pseries/vio.c +++ b/arch/powerpc/platforms/pseries/vio.c @@ -1628,7 +1628,6 @@ const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length) } EXPORT_SYMBOL(vio_get_attribute); -#ifdef CONFIG_PPC_PSERIES /* vio_find_name() - internal because only vio.c knows how we formatted the * kobject name */ @@ -1698,7 +1697,6 @@ int vio_disable_interrupts(struct vio_dev *dev) return rc; } EXPORT_SYMBOL(vio_disable_interrupts); -#endif /* CONFIG_PPC_PSERIES */ static int __init vio_init(void) { From 8cbb00a901037986f4066e2fc0d36a4882475662 Mon Sep 17 00:00:00 2001 From: Oliver O'Halloran Date: Thu, 30 Jan 2020 17:31:53 +1100 Subject: [PATCH 0487/4444] powerpc/pseries/Makefile: Remove CONFIG_PPC_PSERIES check The pseries Makefile (arch/powerpc/platforms/pseries/Makefile) is only included by the platform Makefile (arch/powerpc/platform/Makefile) when CONFIG_PPC_PSERIES is selected, so checking for CONFIG_PPC_PSERIES in the pseries Makefile is pointless. Signed-off-by: Oliver O'Halloran Reviewed-by: Tyrel Datwyler Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200130063153.19915-2-oohall@gmail.com --- arch/powerpc/platforms/pseries/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index a3c74a5cf20d..c8a2b0b05ac0 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -29,6 +29,4 @@ obj-$(CONFIG_PPC_SPLPAR) += vphn.o obj-$(CONFIG_PPC_SVM) += svm.o obj-$(CONFIG_FA_DUMP) += rtas-fadump.o -ifdef CONFIG_PPC_PSERIES obj-$(CONFIG_SUSPEND) += suspend.o -endif From 72c4ebbac476b8375e69fd09390e6b64c2891716 Mon Sep 17 00:00:00 2001 From: Vaibhav Jain Date: Thu, 30 Jan 2020 09:32:06 +0530 Subject: [PATCH 0488/4444] powerpc/papr_scm: Mark papr_scm_ndctl() as static Function papr_scm_ndctl() is neither exported from the module nor called directly from outside 'papr.c' hence should be marked 'static'. Signed-off-by: Vaibhav Jain Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200130040206.79998-1-vaibhav@linux.ibm.com --- arch/powerpc/platforms/pseries/papr_scm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c index 0b4467e378e5..e4606100e286 100644 --- a/arch/powerpc/platforms/pseries/papr_scm.c +++ b/arch/powerpc/platforms/pseries/papr_scm.c @@ -246,8 +246,9 @@ static int papr_scm_meta_set(struct papr_scm_priv *p, return 0; } -int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, - unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc) +static int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, + struct nvdimm *nvdimm, unsigned int cmd, void *buf, + unsigned int buf_len, int *cmd_rc) { struct nd_cmd_get_config_size *get_size_hdr; struct papr_scm_priv *p; From ba32f4b02105e57627912b42e141d65d90074c64 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Wed, 29 Jan 2020 19:50:07 +0000 Subject: [PATCH 0489/4444] powerpc/process: Remove unneccessary #ifdef CONFIG_PPC64 in copy_thread_tls() is_32bit_task() exists on both PPC64 and PPC32, no need of an ifdefery. Signed-off-by: Christophe Leroy Reviewed-by: Michal Suchanek Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/6ecbda05b4119c40222dc8ec284604e1597c9bff.1580327381.git.christophe.leroy@c-s.fr --- arch/powerpc/kernel/process.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index fad50db9dcf2..e730b8e522b0 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1634,11 +1634,9 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long usp, p->thread.regs = childregs; childregs->gpr[3] = 0; /* Result from fork() */ if (clone_flags & CLONE_SETTLS) { -#ifdef CONFIG_PPC64 if (!is_32bit_task()) childregs->gpr[13] = tls; else -#endif childregs->gpr[2] = tls; } From f52153ab383f04a45c38d8a7f55a4249477b20df Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 11 Dec 2019 21:39:05 +0530 Subject: [PATCH 0490/4444] Documentation/ABI: Add ABI documentation for /sys/kernel/fadump_* Add missing ABI documentation for existing FADump sysfs files. Signed-off-by: Sourabh Jain Reviewed-by: Hari Bathini Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20191211160910.21656-2-sourabhjain@linux.ibm.com --- Documentation/ABI/testing/sysfs-kernel-fadump_enabled | 7 +++++++ Documentation/ABI/testing/sysfs-kernel-fadump_registered | 8 ++++++++ Documentation/ABI/testing/sysfs-kernel-fadump_release_mem | 8 ++++++++ .../ABI/testing/sysfs-kernel-fadump_release_opalcore | 7 +++++++ 4 files changed, 30 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-kernel-fadump_enabled create mode 100644 Documentation/ABI/testing/sysfs-kernel-fadump_registered create mode 100644 Documentation/ABI/testing/sysfs-kernel-fadump_release_mem create mode 100644 Documentation/ABI/testing/sysfs-kernel-fadump_release_opalcore diff --git a/Documentation/ABI/testing/sysfs-kernel-fadump_enabled b/Documentation/ABI/testing/sysfs-kernel-fadump_enabled new file mode 100644 index 000000000000..f73632b1c006 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-kernel-fadump_enabled @@ -0,0 +1,7 @@ +What: /sys/kernel/fadump_enabled +Date: Feb 2012 +Contact: linuxppc-dev@lists.ozlabs.org +Description: read only + Primarily used to identify whether the FADump is enabled in + the kernel or not. +User: Kdump service diff --git a/Documentation/ABI/testing/sysfs-kernel-fadump_registered b/Documentation/ABI/testing/sysfs-kernel-fadump_registered new file mode 100644 index 000000000000..dcf925e53f0f --- /dev/null +++ b/Documentation/ABI/testing/sysfs-kernel-fadump_registered @@ -0,0 +1,8 @@ +What: /sys/kernel/fadump_registered +Date: Feb 2012 +Contact: linuxppc-dev@lists.ozlabs.org +Description: read/write + Helps to control the dump collect feature from userspace. + Setting 1 to this file enables the system to collect the + dump and 0 to disable it. +User: Kdump service diff --git a/Documentation/ABI/testing/sysfs-kernel-fadump_release_mem b/Documentation/ABI/testing/sysfs-kernel-fadump_release_mem new file mode 100644 index 000000000000..9c20d64ab48d --- /dev/null +++ b/Documentation/ABI/testing/sysfs-kernel-fadump_release_mem @@ -0,0 +1,8 @@ +What: /sys/kernel/fadump_release_mem +Date: Feb 2012 +Contact: linuxppc-dev@lists.ozlabs.org +Description: write only + This is a special sysfs file and only available when + the system is booted to capture the vmcore using FADump. + It is used to release the memory reserved by FADump to + save the crash dump. diff --git a/Documentation/ABI/testing/sysfs-kernel-fadump_release_opalcore b/Documentation/ABI/testing/sysfs-kernel-fadump_release_opalcore new file mode 100644 index 000000000000..53313c1d4e7a --- /dev/null +++ b/Documentation/ABI/testing/sysfs-kernel-fadump_release_opalcore @@ -0,0 +1,7 @@ +What: /sys/kernel/fadump_release_opalcore +Date: Sep 2019 +Contact: linuxppc-dev@lists.ozlabs.org +Description: write only + The sysfs file is available when the system is booted to + collect the dump on OPAL based machine. It used to release + the memory used to collect the opalcore. From 9255782f70614c89b1a15ec6997c4b72ce9e630a Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 11 Dec 2019 21:39:06 +0530 Subject: [PATCH 0491/4444] sysfs: Wrap __compat_only_sysfs_link_entry_to_kobj function to change the symlink name The __compat_only_sysfs_link_entry_to_kobj function creates a symlink to a kobject but doesn't provide an option to change the symlink file name. This patch adds a wrapper function compat_only_sysfs_link_entry_to_kobj that extends the __compat_only_sysfs_link_entry_to_kobj functionality which allows function caller to customize the symlink name. Signed-off-by: Sourabh Jain [mpe: Fix compile error when CONFIG_SYSFS=n] Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20191211160910.21656-3-sourabhjain@linux.ibm.com --- fs/sysfs/group.c | 28 +++++++++++++++++++++++++--- include/linux/sysfs.h | 12 ++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index c4ab045926b7..1e2a096057bc 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -424,6 +424,25 @@ EXPORT_SYMBOL_GPL(sysfs_remove_link_from_group); int __compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj, struct kobject *target_kobj, const char *target_name) +{ + return compat_only_sysfs_link_entry_to_kobj(kobj, target_kobj, + target_name, NULL); +} +EXPORT_SYMBOL_GPL(__compat_only_sysfs_link_entry_to_kobj); + +/** + * compat_only_sysfs_link_entry_to_kobj - add a symlink to a kobject pointing + * to a group or an attribute + * @kobj: The kobject containing the group. + * @target_kobj: The target kobject. + * @target_name: The name of the target group or attribute. + * @symlink_name: The name of the symlink file (target_name will be + * considered if symlink_name is NULL). + */ +int compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj, + struct kobject *target_kobj, + const char *target_name, + const char *symlink_name) { struct kernfs_node *target; struct kernfs_node *entry; @@ -448,12 +467,15 @@ int __compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj, return -ENOENT; } - link = kernfs_create_link(kobj->sd, target_name, entry); + if (!symlink_name) + symlink_name = target_name; + + link = kernfs_create_link(kobj->sd, symlink_name, entry); if (PTR_ERR(link) == -EEXIST) - sysfs_warn_dup(kobj->sd, target_name); + sysfs_warn_dup(kobj->sd, symlink_name); kernfs_put(entry); kernfs_put(target); return PTR_ERR_OR_ZERO(link); } -EXPORT_SYMBOL_GPL(__compat_only_sysfs_link_entry_to_kobj); +EXPORT_SYMBOL_GPL(compat_only_sysfs_link_entry_to_kobj); diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index fa7ee503fb76..7462315a643b 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -300,6 +300,10 @@ void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name, int __compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj, struct kobject *target_kobj, const char *target_name); +int compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj, + struct kobject *target_kobj, + const char *target_name, + const char *symlink_name); void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr); @@ -508,6 +512,14 @@ static inline int __compat_only_sysfs_link_entry_to_kobj( return 0; } +static inline int compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj, + struct kobject *target_kobj, + const char *target_name, + const char *symlink_name) +{ + return 0; +} + static inline void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr) { From d418b19f34ed0c751a69810080596f7e749595aa Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 11 Dec 2019 21:39:07 +0530 Subject: [PATCH 0492/4444] powerpc/fadump: Reorganize /sys/kernel/fadump_* sysfs files As the number of FADump sysfs files increases it is hard to manage all of them inside /sys/kernel directory. It's better to have all the FADump related sysfs files in a dedicated directory /sys/kernel/fadump. But in order to maintain backward compatibility a symlink has been added for every sysfs that has moved to new location. As the FADump sysfs files are now part of a dedicated directory there is no need to prefix their name with fadump_, hence sysfs file names are also updated. For example fadump_enabled sysfs file is now referred as enabled. Also consolidate ABI documentation for all the FADump sysfs files in a single file Documentation/ABI/testing/sysfs-kernel-fadump. Signed-off-by: Sourabh Jain Tested-by: Michal Suchanek Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20191211160910.21656-4-sourabhjain@linux.ibm.com --- Documentation/ABI/testing/sysfs-kernel-fadump | 33 +++++ arch/powerpc/kernel/fadump.c | 119 +++++++++++++----- 2 files changed, 118 insertions(+), 34 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-kernel-fadump diff --git a/Documentation/ABI/testing/sysfs-kernel-fadump b/Documentation/ABI/testing/sysfs-kernel-fadump new file mode 100644 index 000000000000..5d988b919e81 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-kernel-fadump @@ -0,0 +1,33 @@ +What: /sys/kernel/fadump/* +Date: Dec 2019 +Contact: linuxppc-dev@lists.ozlabs.org +Description: + The /sys/kernel/fadump/* is a collection of FADump sysfs + file provide information about the configuration status + of Firmware Assisted Dump (FADump). + +What: /sys/kernel/fadump/enabled +Date: Dec 2019 +Contact: linuxppc-dev@lists.ozlabs.org +Description: read only + Primarily used to identify whether the FADump is enabled in + the kernel or not. +User: Kdump service + +What: /sys/kernel/fadump/registered +Date: Dec 2019 +Contact: linuxppc-dev@lists.ozlabs.org +Description: read/write + Helps to control the dump collect feature from userspace. + Setting 1 to this file enables the system to collect the + dump and 0 to disable it. +User: Kdump service + +What: /sys/kernel/fadump/release_mem +Date: Dec 2019 +Contact: linuxppc-dev@lists.ozlabs.org +Description: write only + This is a special sysfs file and only available when + the system is booted to capture the vmcore using FADump. + It is used to release the memory reserved by FADump to + save the crash dump. diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index ff0114aeba9b..1182ae44ef14 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -36,6 +36,8 @@ static struct fw_dump fw_dump; static void __init fadump_reserve_crash_area(u64 base); +struct kobject *fadump_kobj; + #ifndef CONFIG_PRESERVE_FA_DUMP static DEFINE_MUTEX(fadump_mutex); struct fadump_mrange_info crash_mrange_info = { "crash", NULL, 0, 0, 0 }; @@ -1323,9 +1325,9 @@ static void fadump_invalidate_release_mem(void) fw_dump.ops->fadump_init_mem_struct(&fw_dump); } -static ssize_t fadump_release_memory_store(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t count) +static ssize_t release_mem_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) { int input = -1; @@ -1350,23 +1352,33 @@ static ssize_t fadump_release_memory_store(struct kobject *kobj, return count; } -static ssize_t fadump_enabled_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) +/* Release the reserved memory and disable the FADump */ +static void unregister_fadump(void) +{ + fadump_cleanup(); + fadump_release_memory(fw_dump.reserve_dump_area_start, + fw_dump.reserve_dump_area_size); + fw_dump.fadump_enabled = 0; + kobject_put(fadump_kobj); +} + +static ssize_t enabled_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", fw_dump.fadump_enabled); } -static ssize_t fadump_register_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) +static ssize_t registered_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", fw_dump.dump_registered); } -static ssize_t fadump_register_store(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t count) +static ssize_t registered_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) { int ret = 0; int input = -1; @@ -1418,15 +1430,17 @@ static int fadump_region_show(struct seq_file *m, void *private) return 0; } -static struct kobj_attribute fadump_release_attr = __ATTR(fadump_release_mem, - 0200, NULL, - fadump_release_memory_store); -static struct kobj_attribute fadump_attr = __ATTR(fadump_enabled, - 0444, fadump_enabled_show, - NULL); -static struct kobj_attribute fadump_register_attr = __ATTR(fadump_registered, - 0644, fadump_register_show, - fadump_register_store); +static struct kobj_attribute release_attr = __ATTR_WO(release_mem); +static struct kobj_attribute enable_attr = __ATTR_RO(enabled); +static struct kobj_attribute register_attr = __ATTR_RW(registered); + +static struct attribute *fadump_attrs[] = { + &enable_attr.attr, + ®ister_attr.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(fadump); DEFINE_SHOW_ATTRIBUTE(fadump_region); @@ -1435,16 +1449,11 @@ static void fadump_init_files(void) struct dentry *debugfs_file; int rc = 0; - rc = sysfs_create_file(kernel_kobj, &fadump_attr.attr); - if (rc) - printk(KERN_ERR "fadump: unable to create sysfs file" - " fadump_enabled (%d)\n", rc); - - rc = sysfs_create_file(kernel_kobj, &fadump_register_attr.attr); - if (rc) - printk(KERN_ERR "fadump: unable to create sysfs file" - " fadump_registered (%d)\n", rc); - + fadump_kobj = kobject_create_and_add("fadump", kernel_kobj); + if (!fadump_kobj) { + pr_err("failed to create fadump kobject\n"); + return; + } debugfs_file = debugfs_create_file("fadump_region", 0444, powerpc_debugfs_root, NULL, &fadump_region_fops); @@ -1453,10 +1462,52 @@ static void fadump_init_files(void) " fadump_region\n"); if (fw_dump.dump_active) { - rc = sysfs_create_file(kernel_kobj, &fadump_release_attr.attr); + rc = sysfs_create_file(fadump_kobj, &release_attr.attr); if (rc) - printk(KERN_ERR "fadump: unable to create sysfs file" - " fadump_release_mem (%d)\n", rc); + pr_err("unable to create release_mem sysfs file (%d)\n", + rc); + } + + rc = sysfs_create_groups(fadump_kobj, fadump_groups); + if (rc) { + pr_err("sysfs group creation failed (%d), unregistering FADump", + rc); + unregister_fadump(); + return; + } + + /* + * The FADump sysfs are moved from kernel_kobj to fadump_kobj need to + * create symlink at old location to maintain backward compatibility. + * + * - fadump_enabled -> fadump/enabled + * - fadump_registered -> fadump/registered + * - fadump_release_mem -> fadump/release_mem + */ + rc = compat_only_sysfs_link_entry_to_kobj(kernel_kobj, fadump_kobj, + "enabled", "fadump_enabled"); + if (rc) { + pr_err("unable to create fadump_enabled symlink (%d)", rc); + return; + } + + rc = compat_only_sysfs_link_entry_to_kobj(kernel_kobj, fadump_kobj, + "registered", + "fadump_registered"); + if (rc) { + pr_err("unable to create fadump_registered symlink (%d)", rc); + sysfs_remove_link(kernel_kobj, "fadump_enabled"); + return; + } + + if (fw_dump.dump_active) { + rc = compat_only_sysfs_link_entry_to_kobj(kernel_kobj, + fadump_kobj, + "release_mem", + "fadump_release_mem"); + if (rc) + pr_err("unable to create fadump_release_mem symlink (%d)", + rc); } return; } From 8852c07a881b0acfd3d75cf3927adaab815c4ee5 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 11 Dec 2019 21:39:08 +0530 Subject: [PATCH 0493/4444] powerpc/powernv: Move core and fadump_release_opalcore under new kobject The /sys/firmware/opal/core and /sys/kernel/fadump_release_opalcore sysfs files are used to export and release the OPAL memory on PowerNV platform. let's organize them into a new kobject under /sys/firmware/opal/mpipl/ directory. A symlink is added to maintain the backward compatibility for /sys/firmware/opal/core sysfs file. Signed-off-by: Sourabh Jain Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20191211160910.21656-5-sourabhjain@linux.ibm.com --- .../sysfs-kernel-fadump_release_opalcore | 2 + .../powerpc/firmware-assisted-dump.rst | 15 +++-- arch/powerpc/platforms/powernv/opal-core.c | 55 ++++++++++++++----- 3 files changed, 51 insertions(+), 21 deletions(-) rename Documentation/ABI/{testing => removed}/sysfs-kernel-fadump_release_opalcore (82%) diff --git a/Documentation/ABI/testing/sysfs-kernel-fadump_release_opalcore b/Documentation/ABI/removed/sysfs-kernel-fadump_release_opalcore similarity index 82% rename from Documentation/ABI/testing/sysfs-kernel-fadump_release_opalcore rename to Documentation/ABI/removed/sysfs-kernel-fadump_release_opalcore index 53313c1d4e7a..a8d46cd0f4e6 100644 --- a/Documentation/ABI/testing/sysfs-kernel-fadump_release_opalcore +++ b/Documentation/ABI/removed/sysfs-kernel-fadump_release_opalcore @@ -1,3 +1,5 @@ +This ABI is moved to /sys/firmware/opal/mpipl/release_core. + What: /sys/kernel/fadump_release_opalcore Date: Sep 2019 Contact: linuxppc-dev@lists.ozlabs.org diff --git a/Documentation/powerpc/firmware-assisted-dump.rst b/Documentation/powerpc/firmware-assisted-dump.rst index 0455a78486d5..345a3405206e 100644 --- a/Documentation/powerpc/firmware-assisted-dump.rst +++ b/Documentation/powerpc/firmware-assisted-dump.rst @@ -112,13 +112,13 @@ to ensure that crash data is preserved to process later. -- On OPAL based machines (PowerNV), if the kernel is build with CONFIG_OPAL_CORE=y, OPAL memory at the time of crash is also - exported as /sys/firmware/opal/core file. This procfs file is + exported as /sys/firmware/opal/mpipl/core file. This procfs file is helpful in debugging OPAL crashes with GDB. The kernel memory used for exporting this procfs file can be released by echo'ing - '1' to /sys/kernel/fadump_release_opalcore node. + '1' to /sys/firmware/opal/mpipl/release_core node. e.g. - # echo 1 > /sys/kernel/fadump_release_opalcore + # echo 1 > /sys/firmware/opal/mpipl/release_core Implementation details: ----------------------- @@ -283,14 +283,17 @@ Here is the list of files under kernel sysfs: enhanced to use this interface to release the memory reserved for dump and continue without 2nd reboot. - /sys/kernel/fadump_release_opalcore +Note: /sys/kernel/fadump_release_opalcore sysfs has moved to + /sys/firmware/opal/mpipl/release_core + + /sys/firmware/opal/mpipl/release_core This file is available only on OPAL based machines when FADump is active during capture kernel. This is used to release the memory - used by the kernel to export /sys/firmware/opal/core file. To + used by the kernel to export /sys/firmware/opal/mpipl/core file. To release this memory, echo '1' to it: - echo 1 > /sys/kernel/fadump_release_opalcore + echo 1 > /sys/firmware/opal/mpipl/release_core Here is the list of files under powerpc debugfs: (Assuming debugfs is mounted on /sys/kernel/debug directory.) diff --git a/arch/powerpc/platforms/powernv/opal-core.c b/arch/powerpc/platforms/powernv/opal-core.c index ed895d82c048..6dba3b62269f 100644 --- a/arch/powerpc/platforms/powernv/opal-core.c +++ b/arch/powerpc/platforms/powernv/opal-core.c @@ -71,6 +71,7 @@ static LIST_HEAD(opalcore_list); static struct opalcore_config *oc_conf; static const struct opal_mpipl_fadump *opalc_metadata; static const struct opal_mpipl_fadump *opalc_cpu_metadata; +struct kobject *mpipl_kobj; /* * Set crashing CPU's signal to SIGUSR1. if the kernel is triggered @@ -428,7 +429,7 @@ static void opalcore_cleanup(void) return; /* Remove OPAL core sysfs file */ - sysfs_remove_bin_file(opal_kobj, &opal_core_attr); + sysfs_remove_bin_file(mpipl_kobj, &opal_core_attr); oc_conf->ptload_phdr = NULL; oc_conf->ptload_cnt = 0; @@ -563,9 +564,9 @@ error_out: of_node_put(np); } -static ssize_t fadump_release_opalcore_store(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t count) +static ssize_t release_core_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) { int input = -1; @@ -589,9 +590,23 @@ static ssize_t fadump_release_opalcore_store(struct kobject *kobj, return count; } -static struct kobj_attribute opalcore_rel_attr = __ATTR(fadump_release_opalcore, - 0200, NULL, - fadump_release_opalcore_store); +static struct kobj_attribute opalcore_rel_attr = __ATTR_WO(release_core); + +static struct attribute *mpipl_attr[] = { + &opalcore_rel_attr.attr, + NULL, +}; + +static struct bin_attribute *mpipl_bin_attr[] = { + &opal_core_attr, + NULL, + +}; + +static struct attribute_group mpipl_group = { + .attrs = mpipl_attr, + .bin_attrs = mpipl_bin_attr, +}; static int __init opalcore_init(void) { @@ -609,7 +624,7 @@ static int __init opalcore_init(void) * then capture the dump. */ if (!(is_opalcore_usable())) { - pr_err("Failed to export /sys/firmware/opal/core\n"); + pr_err("Failed to export /sys/firmware/opal/mpipl/core\n"); opalcore_cleanup(); return rc; } @@ -617,18 +632,28 @@ static int __init opalcore_init(void) /* Set OPAL core file size */ opal_core_attr.size = oc_conf->opalcore_size; + mpipl_kobj = kobject_create_and_add("mpipl", opal_kobj); + if (!mpipl_kobj) { + pr_err("unable to create mpipl kobject\n"); + return -ENOMEM; + } + /* Export OPAL core sysfs file */ - rc = sysfs_create_bin_file(opal_kobj, &opal_core_attr); - if (rc != 0) { - pr_err("Failed to export /sys/firmware/opal/core\n"); + rc = sysfs_create_group(mpipl_kobj, &mpipl_group); + if (rc) { + pr_err("mpipl sysfs group creation failed (%d)", rc); opalcore_cleanup(); return rc; } - - rc = sysfs_create_file(kernel_kobj, &opalcore_rel_attr.attr); + /* The /sys/firmware/opal/core is moved to /sys/firmware/opal/mpipl/ + * directory, need to create symlink at old location to maintain + * backward compatibility. + */ + rc = compat_only_sysfs_link_entry_to_kobj(opal_kobj, mpipl_kobj, + "core", NULL); if (rc) { - pr_warn("unable to create sysfs file fadump_release_opalcore (%d)\n", - rc); + pr_err("unable to create core symlink (%d)\n", rc); + return rc; } return 0; From 3f5f1f22ef10ee0278cef1243944c93aca01b236 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 11 Dec 2019 21:39:09 +0530 Subject: [PATCH 0494/4444] Documentation/ABI: Mark /sys/kernel/fadump_* sysfs files deprecated Add a deprecation note in FADump sysfs ABI documentation files and move them from ABI/testing to ABI/obsolete directory. Signed-off-by: Sourabh Jain [mpe: Use a proper table to fix errors from the documentation build] Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20191211160910.21656-6-sourabhjain@linux.ibm.com --- .../sysfs-kernel-fadump_enabled | 2 ++ .../sysfs-kernel-fadump_registered | 2 ++ .../sysfs-kernel-fadump_release_mem | 2 ++ Documentation/powerpc/firmware-assisted-dump.rst | 12 ++++++++++++ 4 files changed, 18 insertions(+) rename Documentation/ABI/{testing => obsolete}/sysfs-kernel-fadump_enabled (73%) rename Documentation/ABI/{testing => obsolete}/sysfs-kernel-fadump_registered (77%) rename Documentation/ABI/{testing => obsolete}/sysfs-kernel-fadump_release_mem (78%) diff --git a/Documentation/ABI/testing/sysfs-kernel-fadump_enabled b/Documentation/ABI/obsolete/sysfs-kernel-fadump_enabled similarity index 73% rename from Documentation/ABI/testing/sysfs-kernel-fadump_enabled rename to Documentation/ABI/obsolete/sysfs-kernel-fadump_enabled index f73632b1c006..e9c2de8b3688 100644 --- a/Documentation/ABI/testing/sysfs-kernel-fadump_enabled +++ b/Documentation/ABI/obsolete/sysfs-kernel-fadump_enabled @@ -1,3 +1,5 @@ +This ABI is renamed and moved to a new location /sys/kernel/fadump/enabled. + What: /sys/kernel/fadump_enabled Date: Feb 2012 Contact: linuxppc-dev@lists.ozlabs.org diff --git a/Documentation/ABI/testing/sysfs-kernel-fadump_registered b/Documentation/ABI/obsolete/sysfs-kernel-fadump_registered similarity index 77% rename from Documentation/ABI/testing/sysfs-kernel-fadump_registered rename to Documentation/ABI/obsolete/sysfs-kernel-fadump_registered index dcf925e53f0f..0360be39c98e 100644 --- a/Documentation/ABI/testing/sysfs-kernel-fadump_registered +++ b/Documentation/ABI/obsolete/sysfs-kernel-fadump_registered @@ -1,3 +1,5 @@ +This ABI is renamed and moved to a new location /sys/kernel/fadump/registered.¬ + What: /sys/kernel/fadump_registered Date: Feb 2012 Contact: linuxppc-dev@lists.ozlabs.org diff --git a/Documentation/ABI/testing/sysfs-kernel-fadump_release_mem b/Documentation/ABI/obsolete/sysfs-kernel-fadump_release_mem similarity index 78% rename from Documentation/ABI/testing/sysfs-kernel-fadump_release_mem rename to Documentation/ABI/obsolete/sysfs-kernel-fadump_release_mem index 9c20d64ab48d..6ce0b129ab12 100644 --- a/Documentation/ABI/testing/sysfs-kernel-fadump_release_mem +++ b/Documentation/ABI/obsolete/sysfs-kernel-fadump_release_mem @@ -1,3 +1,5 @@ +This ABI is renamed and moved to a new location /sys/kernel/fadump/release_mem.¬ + What: /sys/kernel/fadump_release_mem Date: Feb 2012 Contact: linuxppc-dev@lists.ozlabs.org diff --git a/Documentation/powerpc/firmware-assisted-dump.rst b/Documentation/powerpc/firmware-assisted-dump.rst index 345a3405206e..2cd65a0df9b8 100644 --- a/Documentation/powerpc/firmware-assisted-dump.rst +++ b/Documentation/powerpc/firmware-assisted-dump.rst @@ -295,6 +295,18 @@ Note: /sys/kernel/fadump_release_opalcore sysfs has moved to echo 1 > /sys/firmware/opal/mpipl/release_core +Note: The following FADump sysfs files are deprecated. + ++----------------------------------+--------------------------------+ +| Deprecated | Alternative | ++----------------------------------+--------------------------------+ +| /sys/kernel/fadump_enabled | /sys/kernel/fadump/enabled | ++----------------------------------+--------------------------------+ +| /sys/kernel/fadump_registered | /sys/kernel/fadump/registered | ++----------------------------------+--------------------------------+ +| /sys/kernel/fadump_release_mem | /sys/kernel/fadump/release_mem | ++----------------------------------+--------------------------------+ + Here is the list of files under powerpc debugfs: (Assuming debugfs is mounted on /sys/kernel/debug directory.) From d8e73458f33a24810413ee3a0cd020b644de2f98 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 11 Dec 2019 21:39:10 +0530 Subject: [PATCH 0495/4444] powerpc/fadump: sysfs for fadump memory reservation Add a sys interface to allow querying the memory reserved by FADump for saving the crash dump. Also added Documentation/ABI for the new sysfs file. Signed-off-by: Sourabh Jain Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20191211160910.21656-7-sourabhjain@linux.ibm.com --- Documentation/ABI/testing/sysfs-kernel-fadump | 7 +++++++ Documentation/powerpc/firmware-assisted-dump.rst | 5 +++++ arch/powerpc/kernel/fadump.c | 9 +++++++++ 3 files changed, 21 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-kernel-fadump b/Documentation/ABI/testing/sysfs-kernel-fadump index 5d988b919e81..8f7a64a81783 100644 --- a/Documentation/ABI/testing/sysfs-kernel-fadump +++ b/Documentation/ABI/testing/sysfs-kernel-fadump @@ -31,3 +31,10 @@ Description: write only the system is booted to capture the vmcore using FADump. It is used to release the memory reserved by FADump to save the crash dump. + +What: /sys/kernel/fadump/mem_reserved +Date: Dec 2019 +Contact: linuxppc-dev@lists.ozlabs.org +Description: read only + Provide information about the amount of memory reserved by + FADump to save the crash dump in bytes. diff --git a/Documentation/powerpc/firmware-assisted-dump.rst b/Documentation/powerpc/firmware-assisted-dump.rst index 2cd65a0df9b8..b3f3ee135dbe 100644 --- a/Documentation/powerpc/firmware-assisted-dump.rst +++ b/Documentation/powerpc/firmware-assisted-dump.rst @@ -268,6 +268,11 @@ Here is the list of files under kernel sysfs: be handled and vmcore will not be captured. This interface can be easily integrated with kdump service start/stop. + /sys/kernel/fadump/mem_reserved + + This is used to display the memory reserved by FADump for saving the + crash dump. + /sys/kernel/fadump_release_mem This file is available only when FADump is active during second kernel. This is used to release the reserved memory diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index 1182ae44ef14..265b4aa72252 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -1369,6 +1369,13 @@ static ssize_t enabled_show(struct kobject *kobj, return sprintf(buf, "%d\n", fw_dump.fadump_enabled); } +static ssize_t mem_reserved_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "%ld\n", fw_dump.reserve_dump_area_size); +} + static ssize_t registered_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) @@ -1433,10 +1440,12 @@ static int fadump_region_show(struct seq_file *m, void *private) static struct kobj_attribute release_attr = __ATTR_WO(release_mem); static struct kobj_attribute enable_attr = __ATTR_RO(enabled); static struct kobj_attribute register_attr = __ATTR_RW(registered); +static struct kobj_attribute mem_reserved_attr = __ATTR_RO(mem_reserved); static struct attribute *fadump_attrs[] = { &enable_attr.attr, ®ister_attr.attr, + &mem_reserved_attr.attr, NULL, }; From 030e347430957f6f7f29db9099368f8b86c0bf76 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Sat, 1 Feb 2020 08:04:31 +0000 Subject: [PATCH 0496/4444] powerpc/32s: Don't flush all TLBs when flushing one page When flushing any memory range, the flushing function flushes all TLBs. When (start) and (end - 1) are in the same memory page, flush that page instead. Signed-off-by: Christophe Leroy Reviewed-by: Segher Boessenkool Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/b30b2eae6960502eaf0d9e36c60820b839693c33.1580542939.git.christophe.leroy@c-s.fr --- arch/powerpc/mm/book3s32/tlb.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/mm/book3s32/tlb.c b/arch/powerpc/mm/book3s32/tlb.c index 2fcd321040ff..724c0490fb17 100644 --- a/arch/powerpc/mm/book3s32/tlb.c +++ b/arch/powerpc/mm/book3s32/tlb.c @@ -79,11 +79,14 @@ static void flush_range(struct mm_struct *mm, unsigned long start, int count; unsigned int ctx = mm->context.id; + start &= PAGE_MASK; if (!Hash) { - _tlbia(); + if (end - start <= PAGE_SIZE) + _tlbie(start); + else + _tlbia(); return; } - start &= PAGE_MASK; if (start >= end) return; end = (end - 1) | ~PAGE_MASK; From 9e27086292aa880921a0f2b8501e5189d5efcf03 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Fri, 31 Jan 2020 11:34:54 +0000 Subject: [PATCH 0497/4444] powerpc/32: Warn and return ENOSYS on syscalls from kernel Since commit b86fb88855ea ("powerpc/32: implement fast entry for syscalls on non BOOKE") and commit 1a4b739bbb4f ("powerpc/32: implement fast entry for syscalls on BOOKE"), syscalls from kernel are unexpected and can have catastrophic consequences as it will destroy the kernel stack. Test MSR_PR on syscall entry. In case syscall is from kernel, emit a warning and return ENOSYS error. Signed-off-by: Christophe Leroy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/8ee3bdbbdfdfc64ca7001e90c43b2aee6f333578.1580470482.git.christophe.leroy@c-s.fr --- arch/powerpc/kernel/entry_32.S | 27 +++++++++++++++++++++++++++ arch/powerpc/kernel/head_32.h | 16 +++++++++------- arch/powerpc/kernel/head_booke.h | 5 ++++- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 0713daa651d9..ad000cbb5252 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -575,6 +575,33 @@ syscall_exit_work: bl do_syscall_trace_leave b ret_from_except_full + /* + * System call was called from kernel. We get here with SRR1 in r9. + * Mark the exception as recoverable once we have retrieved SRR0, + * trap a warning and return ENOSYS with CR[SO] set. + */ + .globl ret_from_kernel_syscall +ret_from_kernel_syscall: + mfspr r9, SPRN_SRR0 + mfspr r10, SPRN_SRR1 +#if !defined(CONFIG_4xx) && !defined(CONFIG_BOOKE) + LOAD_REG_IMMEDIATE(r11, MSR_KERNEL & ~(MSR_IR|MSR_DR)) + mtmsr r11 +#endif + +0: trap + EMIT_BUG_ENTRY 0b,__FILE__,__LINE__, BUGFLAG_WARNING + + li r3, ENOSYS + crset so +#if defined(CONFIG_PPC_8xx) && defined(CONFIG_PERF_EVENTS) + mtspr SPRN_NRI, r0 +#endif + mtspr SPRN_SRR0, r9 + mtspr SPRN_SRR1, r10 + SYNC + RFI + /* * The fork/clone functions need to copy the full register set into * the child process. Therefore we need to save all the nonvolatile diff --git a/arch/powerpc/kernel/head_32.h b/arch/powerpc/kernel/head_32.h index a6a5fbbf8504..0e7bf28fe53a 100644 --- a/arch/powerpc/kernel/head_32.h +++ b/arch/powerpc/kernel/head_32.h @@ -111,14 +111,16 @@ .macro SYSCALL_ENTRY trapno mfspr r12,SPRN_SPRG_THREAD + mfspr r9, SPRN_SRR1 #ifdef CONFIG_VMAP_STACK - mfspr r9, SPRN_SRR0 - mfspr r11, SPRN_SRR1 - stw r9, SRR0(r12) - stw r11, SRR1(r12) + mfspr r11, SPRN_SRR0 + stw r11, SRR0(r12) + stw r9, SRR1(r12) #endif mfcr r10 + andi. r11, r9, MSR_PR lwz r11,TASK_STACK-THREAD(r12) + beq- 99f rlwinm r10,r10,0,4,2 /* Clear SO bit in CR */ addi r11, r11, THREAD_SIZE - INT_FRAME_SIZE #ifdef CONFIG_VMAP_STACK @@ -128,15 +130,14 @@ #endif tovirt_vmstack r12, r12 tophys_novmstack r11, r11 - mflr r9 stw r10,_CCR(r11) /* save registers */ - stw r9, _LINK(r11) + mflr r10 + stw r10, _LINK(r11) #ifdef CONFIG_VMAP_STACK lwz r10, SRR0(r12) lwz r9, SRR1(r12) #else mfspr r10,SPRN_SRR0 - mfspr r9,SPRN_SRR1 #endif stw r1,GPR1(r11) stw r1,0(r11) @@ -209,6 +210,7 @@ mtspr SPRN_SRR0,r11 SYNC RFI /* jump to handler, enable MMU */ +99: b ret_from_kernel_syscall .endm .macro save_dar_dsisr_on_stack reg1, reg2, sp diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h index 37fc84ed90e3..bd2e5ed8dd50 100644 --- a/arch/powerpc/kernel/head_booke.h +++ b/arch/powerpc/kernel/head_booke.h @@ -104,16 +104,18 @@ FTR_SECTION_ELSE #ifdef CONFIG_KVM_BOOKE_HV ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV) #endif + mfspr r9, SPRN_SRR1 BOOKE_CLEAR_BTB(r11) + andi. r11, r9, MSR_PR lwz r11, TASK_STACK - THREAD(r10) rlwinm r12,r12,0,4,2 /* Clear SO bit in CR */ + beq- 99f ALLOC_STACK_FRAME(r11, THREAD_SIZE - INT_FRAME_SIZE) stw r12, _CCR(r11) /* save various registers */ mflr r12 stw r12,_LINK(r11) mfspr r12,SPRN_SRR0 stw r1, GPR1(r11) - mfspr r9,SPRN_SRR1 stw r1, 0(r11) mr r1, r11 stw r12,_NIP(r11) @@ -176,6 +178,7 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV) mtspr SPRN_SRR0,r11 SYNC RFI /* jump to handler, enable MMU */ +99: b ret_from_kernel_syscall .endm /* To handle the additional exception priority levels on 40x and Book-E From c06f0aff035ed5a7eaff5daa8e11e7ad28ab0d54 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Fri, 31 Jan 2020 11:34:55 +0000 Subject: [PATCH 0498/4444] powerpc: Don't use thread struct for saving SRR0/1 on syscall. CR0 can be saved later, and CTR can also be used for saving. Keep SRR1 in r9 and stash SRR0 in CTR, this avoids using thread_struct in memory for that. Saves 3 cycles (ie 1%) in null_syscall selftest on 8xx. Signed-off-by: Christophe Leroy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/b94c3bc03bac9431fec2dadb686384c481889422.1580470483.git.christophe.leroy@c-s.fr --- arch/powerpc/kernel/head_32.h | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/arch/powerpc/kernel/head_32.h b/arch/powerpc/kernel/head_32.h index 0e7bf28fe53a..4a1faeded069 100644 --- a/arch/powerpc/kernel/head_32.h +++ b/arch/powerpc/kernel/head_32.h @@ -114,28 +114,23 @@ mfspr r9, SPRN_SRR1 #ifdef CONFIG_VMAP_STACK mfspr r11, SPRN_SRR0 - stw r11, SRR0(r12) - stw r9, SRR1(r12) + mtctr r11 #endif - mfcr r10 andi. r11, r9, MSR_PR lwz r11,TASK_STACK-THREAD(r12) beq- 99f - rlwinm r10,r10,0,4,2 /* Clear SO bit in CR */ addi r11, r11, THREAD_SIZE - INT_FRAME_SIZE #ifdef CONFIG_VMAP_STACK - li r9, MSR_KERNEL & ~(MSR_IR | MSR_RI) /* can take DTLB miss */ - mtmsr r9 + li r10, MSR_KERNEL & ~(MSR_IR | MSR_RI) /* can take DTLB miss */ + mtmsr r10 isync #endif tovirt_vmstack r12, r12 tophys_novmstack r11, r11 - stw r10,_CCR(r11) /* save registers */ mflr r10 stw r10, _LINK(r11) #ifdef CONFIG_VMAP_STACK - lwz r10, SRR0(r12) - lwz r9, SRR1(r12) + mfctr r10 #else mfspr r10,SPRN_SRR0 #endif @@ -143,6 +138,9 @@ stw r1,0(r11) tovirt_novmstack r1, r11 /* set new kernel sp */ stw r10,_NIP(r11) + mfcr r10 + rlwinm r10,r10,0,4,2 /* Clear SO bit in CR */ + stw r10,_CCR(r11) /* save registers */ #ifdef CONFIG_40x rlwinm r9,r9,0,14,12 /* clear MSR_WE (necessary?) */ #else From a83836dbc53e96f13fec248ecc201d18e1e3111d Mon Sep 17 00:00:00 2001 From: Libor Pechacek Date: Fri, 31 Jan 2020 14:28:29 +0100 Subject: [PATCH 0499/4444] powerpc/pseries: Avoid NULL pointer dereference when drmem is unavailable In guests without hotplugagble memory drmem structure is only zero initialized. Trying to manipulate DLPAR parameters results in a crash. $ echo "memory add count 1" > /sys/kernel/dlpar Oops: Kernel access of bad area, sig: 11 [#1] LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries ... NIP: c0000000000ff294 LR: c0000000000ff248 CTR: 0000000000000000 REGS: c0000000fb9d3880 TRAP: 0300 Tainted: G E (5.5.0-rc6-2-default) MSR: 8000000000009033 CR: 28242428 XER: 20000000 CFAR: c0000000009a6c10 DAR: 0000000000000010 DSISR: 40000000 IRQMASK: 0 ... NIP dlpar_memory+0x6e4/0xd00 LR dlpar_memory+0x698/0xd00 Call Trace: dlpar_memory+0x698/0xd00 (unreliable) handle_dlpar_errorlog+0xc0/0x190 dlpar_store+0x198/0x4a0 kobj_attr_store+0x30/0x50 sysfs_kf_write+0x64/0x90 kernfs_fop_write+0x1b0/0x290 __vfs_write+0x3c/0x70 vfs_write+0xd0/0x260 ksys_write+0xdc/0x130 system_call+0x5c/0x68 Taking closer look at the code, I can see that for_each_drmem_lmb is a macro expanding into `for (lmb = &drmem_info->lmbs[0]; lmb <= &drmem_info->lmbs[drmem_info->n_lmbs - 1]; lmb++)`. When drmem_info->lmbs is NULL, the loop would iterate through the whole address range if it weren't stopped by the NULL pointer dereference on the next line. This patch aligns for_each_drmem_lmb and for_each_drmem_lmb_in_range macro behavior with the common C semantics, where the end marker does not belong to the scanned range, and alters get_lmb_range() semantics. As a side effect, the wraparound observed in the crash is prevented. Fixes: 6c6ea53725b3 ("powerpc/mm: Separate ibm, dynamic-memory data from DT format") Cc: stable@vger.kernel.org # v4.16+ Signed-off-by: Libor Pechacek Signed-off-by: Michal Suchanek Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200131132829.10281-1-msuchanek@suse.de --- arch/powerpc/include/asm/drmem.h | 4 ++-- arch/powerpc/platforms/pseries/hotplug-memory.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/include/asm/drmem.h b/arch/powerpc/include/asm/drmem.h index 3d76e1c388c2..28c3d936fdf3 100644 --- a/arch/powerpc/include/asm/drmem.h +++ b/arch/powerpc/include/asm/drmem.h @@ -27,12 +27,12 @@ struct drmem_lmb_info { extern struct drmem_lmb_info *drmem_info; #define for_each_drmem_lmb_in_range(lmb, start, end) \ - for ((lmb) = (start); (lmb) <= (end); (lmb)++) + for ((lmb) = (start); (lmb) < (end); (lmb)++) #define for_each_drmem_lmb(lmb) \ for_each_drmem_lmb_in_range((lmb), \ &drmem_info->lmbs[0], \ - &drmem_info->lmbs[drmem_info->n_lmbs - 1]) + &drmem_info->lmbs[drmem_info->n_lmbs]) /* * The of_drconf_cell_v1 struct defines the layout of the LMB data diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index a4d40a3ceea3..fd22ec41c008 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -223,7 +223,7 @@ static int get_lmb_range(u32 drc_index, int n_lmbs, struct drmem_lmb **end_lmb) { struct drmem_lmb *lmb, *start, *end; - struct drmem_lmb *last_lmb; + struct drmem_lmb *limit; start = NULL; for_each_drmem_lmb(lmb) { @@ -236,10 +236,10 @@ static int get_lmb_range(u32 drc_index, int n_lmbs, if (!start) return -EINVAL; - end = &start[n_lmbs - 1]; + end = &start[n_lmbs]; - last_lmb = &drmem_info->lmbs[drmem_info->n_lmbs - 1]; - if (end > last_lmb) + limit = &drmem_info->lmbs[drmem_info->n_lmbs]; + if (end > limit) return -EINVAL; *start_lmb = start; From e1347a020b81fe47c80cd277bfaa61295a9482a4 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Mon, 3 Feb 2020 16:47:37 +0000 Subject: [PATCH 0500/4444] powerpc/32s: Slenderize _tlbia() for powerpc 603/603e _tlbia() is a function used only on 603/603e core, ie on CPUs which don't have a hash table. _tlbia() uses the tlbia macro which implements a loop of 1024 tlbie. On the 603/603e core, flushing the entire TLB requires no more than 32 tlbie. Replace tlbia by a loop of 32 tlbie. Signed-off-by: Christophe Leroy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/12f4f4f0ff89aeab3b937fc96c84fb35e1b2517e.1580748445.git.christophe.leroy@c-s.fr --- arch/powerpc/mm/book3s32/hash_low.S | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/mm/book3s32/hash_low.S b/arch/powerpc/mm/book3s32/hash_low.S index c11b0a005196..a5039ad10429 100644 --- a/arch/powerpc/mm/book3s32/hash_low.S +++ b/arch/powerpc/mm/book3s32/hash_low.S @@ -696,18 +696,21 @@ _GLOBAL(_tlbia) bne- 10b stwcx. r8,0,r9 bne- 10b +#endif /* CONFIG_SMP */ + li r5, 32 + lis r4, KERNELBASE@h + mtctr r5 sync - tlbia +0: tlbie r4 + addi r4, r4, 0x1000 + bdnz 0b sync +#ifdef CONFIG_SMP TLBSYNC li r0,0 stw r0,0(r9) /* clear mmu_hash_lock */ mtmsr r10 SYNC_601 isync -#else /* CONFIG_SMP */ - sync - tlbia - sync #endif /* CONFIG_SMP */ blr From bfb59d4a330e584838861d4ed2a4fb046ea0afb1 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 14 Feb 2020 11:14:35 -0600 Subject: [PATCH 0501/4444] dmaengine: sa11x0: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200214171435.GA22930@embeddedor Signed-off-by: Vinod Koul --- drivers/dma/sa11x0-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c index afb68055ed1b..0fa7f14a65a1 100644 --- a/drivers/dma/sa11x0-dma.c +++ b/drivers/dma/sa11x0-dma.c @@ -78,7 +78,7 @@ struct sa11x0_dma_desc { bool cyclic; unsigned sglen; - struct sa11x0_dma_sg sg[0]; + struct sa11x0_dma_sg sg[]; }; struct sa11x0_dma_phy; From a18cd9bebdca50722534329948adf614239b8c4d Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 14 Feb 2020 11:15:36 -0600 Subject: [PATCH 0502/4444] dmaengine: sprd: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Reviewed-by: Baolin Wang Link: https://lore.kernel.org/r/20200214171536.GA24077@embeddedor Signed-off-by: Vinod Koul --- drivers/dma/sprd-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/sprd-dma.c b/drivers/dma/sprd-dma.c index 9a31a315dbef..954eff32cc05 100644 --- a/drivers/dma/sprd-dma.c +++ b/drivers/dma/sprd-dma.c @@ -212,7 +212,7 @@ struct sprd_dma_dev { struct clk *ashb_clk; int irq; u32 total_chns; - struct sprd_dma_chn channels[0]; + struct sprd_dma_chn channels[]; }; static void sprd_dma_free_desc(struct virt_dma_desc *vd); From 1ee44529cc79e1ae95dd613e03b0c2434da8d052 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 14 Feb 2020 11:16:57 -0600 Subject: [PATCH 0503/4444] dmaengine: tegra210-adma: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200214171657.GA25663@embeddedor Signed-off-by: Vinod Koul --- drivers/dma/tegra210-adma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c index 6e1268552f74..c4ce5dfb149b 100644 --- a/drivers/dma/tegra210-adma.c +++ b/drivers/dma/tegra210-adma.c @@ -164,7 +164,7 @@ struct tegra_adma { const struct tegra_adma_chip_data *cdata; /* Last member of the structure */ - struct tegra_adma_chan channels[0]; + struct tegra_adma_chan channels[]; }; static inline void tdma_write(struct tegra_adma *tdma, u32 reg, u32 val) From 35e032462bf8c7847d4ef7b70a3c8dc17f814c97 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 14 Feb 2020 11:13:02 -0600 Subject: [PATCH 0504/4444] dmanegine: ioat/dca: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200214171302.GA20586@embeddedor Signed-off-by: Vinod Koul --- drivers/dma/ioat/dca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/ioat/dca.c b/drivers/dma/ioat/dca.c index be61c32a876f..0be385587c4c 100644 --- a/drivers/dma/ioat/dca.c +++ b/drivers/dma/ioat/dca.c @@ -102,7 +102,7 @@ struct ioat_dca_priv { int max_requesters; int requester_count; u8 tag_map[IOAT_TAG_MAP_LEN]; - struct ioat_dca_slot req_slots[0]; + struct ioat_dca_slot req_slots[]; }; static int ioat_dca_dev_managed(struct dca_provider *dca, From eaa2330bfcbf1d600776e219c5d2080f36a3c59c Mon Sep 17 00:00:00 2001 From: Jeff Chang Date: Wed, 19 Feb 2020 17:04:24 +0800 Subject: [PATCH 0505/4444] ASoC: MT6660 update to 1.0.8_G 1. add mt6660_component_settign for Component INIT Setting Signed-off-by: Jeff Chang Link: https://lore.kernel.org/r/1582103064-25088-1-git-send-email-richtek.jeff.chang@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/mt6660.c | 78 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/mt6660.c b/sound/soc/codecs/mt6660.c index 1a3515df1764..bcec82aa57fb 100644 --- a/sound/soc/codecs/mt6660.c +++ b/sound/soc/codecs/mt6660.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -224,14 +223,87 @@ static int _mt6660_chip_power_on(struct mt6660_chip *chip, int on_off) 0x01, on_off ? 0x00 : 0x01); } +struct reg_table { + uint32_t addr; + uint32_t mask; + uint32_t val; +}; + +static const struct reg_table mt6660_setting_table[] = { + { 0x20, 0x80, 0x00 }, + { 0x30, 0x01, 0x00 }, + { 0x50, 0x1c, 0x04 }, + { 0xB1, 0x0c, 0x00 }, + { 0xD3, 0x03, 0x03 }, + { 0xE0, 0x01, 0x00 }, + { 0x98, 0x44, 0x04 }, + { 0xB9, 0xff, 0x82 }, + { 0xB7, 0x7777, 0x7273 }, + { 0xB6, 0x07, 0x03 }, + { 0x6B, 0xe0, 0x20 }, + { 0x07, 0xff, 0x70 }, + { 0xBB, 0xff, 0x20 }, + { 0x69, 0xff, 0x40 }, + { 0xBD, 0xffff, 0x17f8 }, + { 0x70, 0xff, 0x15 }, + { 0x7C, 0xff, 0x00 }, + { 0x46, 0xff, 0x1d }, + { 0x1A, 0xffffffff, 0x7fdb7ffe }, + { 0x1B, 0xffffffff, 0x7fdb7ffe }, + { 0x51, 0xff, 0x58 }, + { 0xA2, 0xff, 0xce }, + { 0x33, 0xffff, 0x7fff }, + { 0x4C, 0xffff, 0x0116 }, + { 0x16, 0x1800, 0x0800 }, + { 0x68, 0x1f, 0x07 }, +}; + +static int mt6660_component_setting(struct snd_soc_component *component) +{ + struct mt6660_chip *chip = snd_soc_component_get_drvdata(component); + int ret = 0; + size_t i = 0; + + ret = _mt6660_chip_power_on(chip, 1); + if (ret < 0) { + dev_err(component->dev, "%s chip power on failed\n", __func__); + return ret; + } + + for (i = 0; i < ARRAY_SIZE(mt6660_setting_table); i++) { + ret = snd_soc_component_update_bits(component, + mt6660_setting_table[i].addr, + mt6660_setting_table[i].mask, + mt6660_setting_table[i].val); + if (ret < 0) { + dev_err(component->dev, "%s update 0x%02x failed\n", + __func__, mt6660_setting_table[i].addr); + return ret; + } + } + + ret = _mt6660_chip_power_on(chip, 0); + if (ret < 0) { + dev_err(component->dev, "%s chip power off failed\n", __func__); + return ret; + } + + return 0; +} + static int mt6660_component_probe(struct snd_soc_component *component) { struct mt6660_chip *chip = snd_soc_component_get_drvdata(component); + int ret; dev_dbg(component->dev, "%s\n", __func__); snd_soc_component_init_regmap(component, chip->regmap); - return 0; + ret = mt6660_component_setting(component); + if (ret < 0) + dev_err(chip->dev, "mt6660 component setting failed\n"); + + return ret; } static void mt6660_component_remove(struct snd_soc_component *component) @@ -505,4 +577,4 @@ module_i2c_driver(mt6660_i2c_driver); MODULE_AUTHOR("Jeff Chang "); MODULE_DESCRIPTION("MT6660 SPKAMP Driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION("1.0.7_G"); +MODULE_VERSION("1.0.8_G"); From 6b62fa95b56bcc77cbbcc76e45f5170b4ec229b1 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 19 Feb 2020 11:25:26 +0100 Subject: [PATCH 0506/4444] ASoC: fix card registration regression. This reverts commit b2354e4009a773c00054b964d937e1b81cb92078. This change might have been desirable to ensure the uniqueness of the component name. It would have helped to better support linux devices which register multiple components, something is which more common than initially thought. However, some card driver are directly using dev_name() to fill the component names of the dai_link which is a problem if want to change the way ASoC generates the component names. Until we figure out the appropriate way to deal with this, revert the change and keep the names as they were. There might be a couple of warning related to debugfs (which were already present before the change) but it is still better than breaking working audio cards. Signed-off-by: Jerome Brunet Tested-by: Marek Szyprowski Cc: Marek Szyprowski Link: https://lore.kernel.org/r/20200219102526.692126-1-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 30c17fde14ca..518b652cf872 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2442,33 +2442,6 @@ err: return ret; } -static char *snd_soc_component_unique_name(struct device *dev, - struct snd_soc_component *component) -{ - struct snd_soc_component *pos; - int count = 0; - char *name, *unique; - - name = fmt_single_name(dev, &component->id); - if (!name) - return name; - - /* Count the number of components registred by the device */ - for_each_component(pos) { - if (dev == pos->dev) - count++; - } - - /* Keep naming as it is for the 1st component */ - if (!count) - return name; - - unique = devm_kasprintf(dev, GFP_KERNEL, "%s-%d", name, count); - devm_kfree(dev, name); - - return unique; -} - static int snd_soc_component_initialize(struct snd_soc_component *component, const struct snd_soc_component_driver *driver, struct device *dev) { @@ -2477,7 +2450,7 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, INIT_LIST_HEAD(&component->card_list); mutex_init(&component->io_mutex); - component->name = snd_soc_component_unique_name(dev, component); + component->name = fmt_single_name(dev, &component->id); if (!component->name) { dev_err(dev, "ASoC: Failed to allocate name\n"); return -ENOMEM; From ec06dc15c358d3f41e9fd05872d772ed0f9fa32a Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 19 Feb 2020 17:38:38 +0800 Subject: [PATCH 0507/4444] ASoC: dapm: select sleep_state when initializing PINCTRL widget Selects sleep_state when initializing PINCTRL widget. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200219170951.1.I61f6559a37a6a40a6fde0737cb16100fb17c0480@changeid Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index cc17a3730d3d..69eff234b26f 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3628,6 +3628,9 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, ret = PTR_ERR(w->pinctrl); goto request_failed; } + + /* set to sleep_state when initializing */ + dapm_pinctrl_event(w, NULL, SND_SOC_DAPM_POST_PMD); break; case snd_soc_dapm_clock_supply: w->clk = devm_clk_get(dapm->dev, w->name); From c77b8317ee3ab43634421afb73fdb1ea253d3d47 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 19 Feb 2020 17:38:39 +0800 Subject: [PATCH 0508/4444] ASoC: mediatek: mt8183-da7219: use SND_SOC_DAPM_PINCTRL in TDM out Uses SND_SOC_DAPM_PINCTRL in TDM out to simplify code. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20200219170951.2.I7ed16ef57d9e0bcafc37e766142f68cbad5b54c6@changeid Signed-off-by: Mark Brown --- .../mediatek/mt8183/mt8183-da7219-max98357.c | 98 ++----------------- 1 file changed, 10 insertions(+), 88 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index c0c85972cfb7..03d104fbe185 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -16,20 +16,7 @@ #include "../../codecs/da7219-aad.h" #include "../../codecs/da7219.h" -enum PINCTRL_PIN_STATE { - PIN_STATE_DEFAULT = 0, - PIN_TDM_OUT_ON, - PIN_TDM_OUT_OFF, - PIN_STATE_MAX -}; - -static const char * const mt8183_pin_str[PIN_STATE_MAX] = { - "default", "aud_tdm_out_on", "aud_tdm_out_off", -}; - struct mt8183_da7219_max98357_priv { - struct pinctrl *pinctrl; - struct pinctrl_state *pin_states[PIN_STATE_MAX]; struct snd_soc_jack headset_jack; }; @@ -259,47 +246,6 @@ SND_SOC_DAILINK_DEFS(tdm, DAILINK_COMP_ARRAY(COMP_DUMMY()), DAILINK_COMP_ARRAY(COMP_EMPTY())); -static int mt8183_da7219_tdm_startup(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct mt8183_da7219_max98357_priv *priv = - snd_soc_card_get_drvdata(rtd->card); - int ret; - - if (IS_ERR(priv->pin_states[PIN_TDM_OUT_ON])) - return PTR_ERR(priv->pin_states[PIN_TDM_OUT_ON]); - - ret = pinctrl_select_state(priv->pinctrl, - priv->pin_states[PIN_TDM_OUT_ON]); - if (ret) - dev_err(rtd->card->dev, "%s failed to select state %d\n", - __func__, ret); - - return ret; -} - -static void mt8183_da7219_tdm_shutdown(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct mt8183_da7219_max98357_priv *priv = - snd_soc_card_get_drvdata(rtd->card); - int ret; - - if (IS_ERR(priv->pin_states[PIN_TDM_OUT_OFF])) - return; - - ret = pinctrl_select_state(priv->pinctrl, - priv->pin_states[PIN_TDM_OUT_OFF]); - if (ret) - dev_err(rtd->card->dev, "%s failed to select state %d\n", - __func__, ret); -} - -static struct snd_soc_ops mt8183_da7219_tdm_ops = { - .startup = mt8183_da7219_tdm_startup, - .shutdown = mt8183_da7219_tdm_shutdown, -}; - static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { /* FE */ { @@ -455,7 +401,6 @@ static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { .dpcm_playback = 1, .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, - .ops = &mt8183_da7219_tdm_ops, SND_SOC_DAILINK_REG(tdm), }, }; @@ -482,10 +427,13 @@ static const struct snd_kcontrol_new mt8183_da7219_max98357_snd_controls[] = { static const struct snd_soc_dapm_widget mt8183_da7219_max98357_dapm_widgets[] = { SND_SOC_DAPM_SPK("Speakers", NULL), + SND_SOC_DAPM_PINCTRL("TDM_OUT_PINCTRL", + "aud_tdm_out_on", "aud_tdm_out_off"), }; static const struct snd_soc_dapm_route mt8183_da7219_max98357_dapm_routes[] = { {"Speakers", NULL, "Speaker"}, + {"I2S Playback", NULL, "TDM_OUT_PINCTRL"}, }; static struct snd_soc_card mt8183_da7219_max98357_card = { @@ -534,6 +482,7 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) struct device_node *platform_node; struct snd_soc_dai_link *dai_link; struct mt8183_da7219_max98357_priv *priv; + struct pinctrl *pinctrl; int ret, i; card->dev = &pdev->dev; @@ -566,39 +515,12 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(card, priv); - priv->pinctrl = devm_pinctrl_get(&pdev->dev); - if (IS_ERR(priv->pinctrl)) { - dev_err(&pdev->dev, "%s devm_pinctrl_get failed\n", - __func__); - return PTR_ERR(priv->pinctrl); - } - - for (i = 0; i < PIN_STATE_MAX; i++) { - priv->pin_states[i] = pinctrl_lookup_state(priv->pinctrl, - mt8183_pin_str[i]); - if (IS_ERR(priv->pin_states[i])) { - ret = PTR_ERR(priv->pin_states[i]); - dev_info(&pdev->dev, "%s Can't find pin state %s %d\n", - __func__, mt8183_pin_str[i], ret); - } - } - - if (!IS_ERR(priv->pin_states[PIN_TDM_OUT_OFF])) { - ret = pinctrl_select_state(priv->pinctrl, - priv->pin_states[PIN_TDM_OUT_OFF]); - if (ret) - dev_info(&pdev->dev, - "%s failed to select state %d\n", - __func__, ret); - } - - if (!IS_ERR(priv->pin_states[PIN_STATE_DEFAULT])) { - ret = pinctrl_select_state(priv->pinctrl, - priv->pin_states[PIN_STATE_DEFAULT]); - if (ret) - dev_info(&pdev->dev, - "%s failed to select state %d\n", - __func__, ret); + pinctrl = devm_pinctrl_get_select(&pdev->dev, PINCTRL_STATE_DEFAULT); + if (IS_ERR(pinctrl)) { + ret = PTR_ERR(pinctrl); + dev_err(&pdev->dev, "%s failed to select default state %d\n", + __func__, ret); + return ret; } return devm_snd_soc_register_card(&pdev->dev, card); From 56cc3af4e8c8eaba91b51efa6081a868adbd97c3 Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Wed, 8 Jan 2020 11:47:46 +0100 Subject: [PATCH 0509/4444] pinctrl: da9062: add driver support The DA9062 is a mfd pmic device which supports 5 GPIOs. The GPIOs can be used as input, output or have a special use-case. The patch adds the support for the normal input/output use-case. Signed-off-by: Marco Felsch Link: https://lore.kernel.org/r/20200108104746.1765-4-m.felsch@pengutronix.de Reviewed-by: Adam Thomson Signed-off-by: Linus Walleij --- MAINTAINERS | 1 + drivers/pinctrl/Kconfig | 12 ++ drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-da9062.c | 300 +++++++++++++++++++++++++++++++ 4 files changed, 314 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-da9062.c diff --git a/MAINTAINERS b/MAINTAINERS index 408fd7c660aa..260c0c4c6e74 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4921,6 +4921,7 @@ F: drivers/leds/leds-da90??.c F: drivers/mfd/da903x.c F: drivers/mfd/da90??-*.c F: drivers/mfd/da91??-*.c +F: drivers/pinctrl/pinctrl-da90??.c F: drivers/power/supply/da9052-battery.c F: drivers/power/supply/da91??-*.c F: drivers/regulator/da903x.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index df0ef69dd474..834c59950d1c 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -126,6 +126,18 @@ config PINCTRL_DA850_PUPD Driver for TI DA850/OMAP-L138/AM18XX pinconf. Used to control pullup/pulldown pin groups. +config PINCTRL_DA9062 + tristate "Dialog Semiconductor DA9062 PMIC pinctrl and GPIO Support" + depends on MFD_DA9062 + select GPIOLIB + help + The Dialog DA9062 PMIC provides multiple GPIOs that can be muxed for + different functions. This driver bundles a pinctrl driver to select the + function muxing and a GPIO driver to handle the GPIO when the GPIO + function is selected. + + Say yes to enable pinctrl and GPIO support for the DA9062 PMIC. + config PINCTRL_DIGICOLOR bool depends on OF && (ARCH_DIGICOLOR || COMPILE_TEST) diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 879f312bfb75..0b36a1cfca8a 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_PINCTRL_AT91PIO4) += pinctrl-at91-pio4.o obj-$(CONFIG_PINCTRL_AMD) += pinctrl-amd.o obj-$(CONFIG_PINCTRL_BM1880) += pinctrl-bm1880.o obj-$(CONFIG_PINCTRL_DA850_PUPD) += pinctrl-da850-pupd.o +obj-$(CONFIG_PINCTRL_DA9062) += pinctrl-da9062.o obj-$(CONFIG_PINCTRL_DIGICOLOR) += pinctrl-digicolor.o obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o obj-$(CONFIG_PINCTRL_GEMINI) += pinctrl-gemini.o diff --git a/drivers/pinctrl/pinctrl-da9062.c b/drivers/pinctrl/pinctrl-da9062.c new file mode 100644 index 000000000000..f704ee0b2fd9 --- /dev/null +++ b/drivers/pinctrl/pinctrl-da9062.c @@ -0,0 +1,300 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Dialog DA9062 pinctrl and GPIO driver. + * Based on DA9055 GPIO driver. + * + * TODO: + * - add pinmux and pinctrl support (gpio alternate mode) + * + * Documents: + * [1] https://www.dialog-semiconductor.com/sites/default/files/da9062_datasheet_3v6.pdf + * + * Copyright (C) 2019 Pengutronix, Marco Felsch + */ +#include +#include +#include +#include + +#include + +#include +#include + +/* + * We need this get the gpio_desc from a tuple to decide if + * the gpio is active low without a vendor specific dt-binding. + */ +#include <../gpio/gpiolib.h> + +#define DA9062_TYPE(offset) (4 * (offset % 2)) +#define DA9062_PIN_SHIFT(offset) (4 * (offset % 2)) +#define DA9062_PIN_ALTERNATE 0x00 /* gpio alternate mode */ +#define DA9062_PIN_GPI 0x01 /* gpio in */ +#define DA9062_PIN_GPO_OD 0x02 /* gpio out open-drain */ +#define DA9062_PIN_GPO_PP 0x03 /* gpio out push-pull */ +#define DA9062_GPIO_NUM 5 + +struct da9062_pctl { + struct da9062 *da9062; + struct gpio_chip gc; + unsigned int pin_config[DA9062_GPIO_NUM]; +}; + +static int da9062_pctl_get_pin_mode(struct da9062_pctl *pctl, + unsigned int offset) +{ + struct regmap *regmap = pctl->da9062->regmap; + int ret, val; + + ret = regmap_read(regmap, DA9062AA_GPIO_0_1 + (offset >> 1), &val); + if (ret < 0) + return ret; + + val >>= DA9062_PIN_SHIFT(offset); + val &= DA9062AA_GPIO0_PIN_MASK; + + return val; +} + +static int da9062_pctl_set_pin_mode(struct da9062_pctl *pctl, + unsigned int offset, unsigned int mode_req) +{ + struct regmap *regmap = pctl->da9062->regmap; + unsigned int mode = mode_req; + unsigned int mask; + int ret; + + mode &= DA9062AA_GPIO0_PIN_MASK; + mode <<= DA9062_PIN_SHIFT(offset); + mask = DA9062AA_GPIO0_PIN_MASK << DA9062_PIN_SHIFT(offset); + + ret = regmap_update_bits(regmap, DA9062AA_GPIO_0_1 + (offset >> 1), + mask, mode); + if (!ret) + pctl->pin_config[offset] = mode_req; + + return ret; +} + +static int da9062_gpio_get(struct gpio_chip *gc, unsigned int offset) +{ + struct da9062_pctl *pctl = gpiochip_get_data(gc); + struct regmap *regmap = pctl->da9062->regmap; + int gpio_mode, val; + int ret; + + gpio_mode = da9062_pctl_get_pin_mode(pctl, offset); + if (gpio_mode < 0) + return gpio_mode; + + switch (gpio_mode) { + case DA9062_PIN_ALTERNATE: + return -ENOTSUPP; + case DA9062_PIN_GPI: + ret = regmap_read(regmap, DA9062AA_STATUS_B, &val); + if (ret < 0) + return ret; + break; + case DA9062_PIN_GPO_OD: + case DA9062_PIN_GPO_PP: + ret = regmap_read(regmap, DA9062AA_GPIO_MODE0_4, &val); + if (ret < 0) + return ret; + } + + return !!(val & BIT(offset)); +} + +static void da9062_gpio_set(struct gpio_chip *gc, unsigned int offset, + int value) +{ + struct da9062_pctl *pctl = gpiochip_get_data(gc); + struct regmap *regmap = pctl->da9062->regmap; + + regmap_update_bits(regmap, DA9062AA_GPIO_MODE0_4, BIT(offset), + value << offset); +} + +static int da9062_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) +{ + struct da9062_pctl *pctl = gpiochip_get_data(gc); + int gpio_mode; + + gpio_mode = da9062_pctl_get_pin_mode(pctl, offset); + if (gpio_mode < 0) + return gpio_mode; + + switch (gpio_mode) { + case DA9062_PIN_ALTERNATE: + return -ENOTSUPP; + case DA9062_PIN_GPI: + return GPIO_LINE_DIRECTION_IN; + case DA9062_PIN_GPO_OD: + case DA9062_PIN_GPO_PP: + return GPIO_LINE_DIRECTION_OUT; + } + + return -EINVAL; +} + +static int da9062_gpio_direction_input(struct gpio_chip *gc, + unsigned int offset) +{ + struct da9062_pctl *pctl = gpiochip_get_data(gc); + struct regmap *regmap = pctl->da9062->regmap; + struct gpio_desc *desc = gpiochip_get_desc(gc, offset); + unsigned int gpi_type; + int ret; + + ret = da9062_pctl_set_pin_mode(pctl, offset, DA9062_PIN_GPI); + if (ret) + return ret; + + /* + * If the gpio is active low we should set it in hw too. No worries + * about gpio_get() because we read and return the gpio-level. So the + * gpiolib active_low handling is still correct. + * + * 0 - active low, 1 - active high + */ + gpi_type = !gpiod_is_active_low(desc); + + return regmap_update_bits(regmap, DA9062AA_GPIO_0_1 + (offset >> 1), + DA9062AA_GPIO0_TYPE_MASK << DA9062_TYPE(offset), + gpi_type << DA9062_TYPE(offset)); +} + +static int da9062_gpio_direction_output(struct gpio_chip *gc, + unsigned int offset, int value) +{ + struct da9062_pctl *pctl = gpiochip_get_data(gc); + unsigned int pin_config = pctl->pin_config[offset]; + int ret; + + ret = da9062_pctl_set_pin_mode(pctl, offset, pin_config); + if (ret) + return ret; + + da9062_gpio_set(gc, offset, value); + + return 0; +} + +static int da9062_gpio_set_config(struct gpio_chip *gc, unsigned int offset, + unsigned long config) +{ + struct da9062_pctl *pctl = gpiochip_get_data(gc); + struct regmap *regmap = pctl->da9062->regmap; + int gpio_mode; + + /* + * We need to meet the following restrictions [1, Figure 18]: + * - PIN_CONFIG_BIAS_PULL_DOWN -> only allowed if the pin is used as + * gpio input + * - PIN_CONFIG_BIAS_PULL_UP -> only allowed if the pin is used as + * gpio output open-drain. + */ + + switch (pinconf_to_config_param(config)) { + case PIN_CONFIG_BIAS_DISABLE: + return regmap_update_bits(regmap, DA9062AA_CONFIG_K, + BIT(offset), 0); + case PIN_CONFIG_BIAS_PULL_DOWN: + gpio_mode = da9062_pctl_get_pin_mode(pctl, offset); + if (gpio_mode < 0) + return -EINVAL; + else if (gpio_mode != DA9062_PIN_GPI) + return -ENOTSUPP; + return regmap_update_bits(regmap, DA9062AA_CONFIG_K, + BIT(offset), BIT(offset)); + case PIN_CONFIG_BIAS_PULL_UP: + gpio_mode = da9062_pctl_get_pin_mode(pctl, offset); + if (gpio_mode < 0) + return -EINVAL; + else if (gpio_mode != DA9062_PIN_GPO_OD) + return -ENOTSUPP; + return regmap_update_bits(regmap, DA9062AA_CONFIG_K, + BIT(offset), BIT(offset)); + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + return da9062_pctl_set_pin_mode(pctl, offset, + DA9062_PIN_GPO_OD); + case PIN_CONFIG_DRIVE_PUSH_PULL: + return da9062_pctl_set_pin_mode(pctl, offset, + DA9062_PIN_GPO_PP); + default: + return -ENOTSUPP; + } +} + +static int da9062_gpio_to_irq(struct gpio_chip *gc, unsigned int offset) +{ + struct da9062_pctl *pctl = gpiochip_get_data(gc); + struct da9062 *da9062 = pctl->da9062; + + return regmap_irq_get_virq(da9062->regmap_irq, + DA9062_IRQ_GPI0 + offset); +} + +static const struct gpio_chip reference_gc = { + .owner = THIS_MODULE, + .get = da9062_gpio_get, + .set = da9062_gpio_set, + .get_direction = da9062_gpio_get_direction, + .direction_input = da9062_gpio_direction_input, + .direction_output = da9062_gpio_direction_output, + .set_config = da9062_gpio_set_config, + .to_irq = da9062_gpio_to_irq, + .can_sleep = true, + .ngpio = DA9062_GPIO_NUM, + .base = -1, +}; + +static int da9062_pctl_probe(struct platform_device *pdev) +{ + struct device *parent = pdev->dev.parent; + struct da9062_pctl *pctl; + int i; + + pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL); + if (!pctl) + return -ENOMEM; + + pctl->da9062 = dev_get_drvdata(parent); + if (!pctl->da9062) + return -EINVAL; + + if (!device_property_present(parent, "gpio-controller")) + return 0; + + for (i = 0; i < ARRAY_SIZE(pctl->pin_config); i++) + pctl->pin_config[i] = DA9062_PIN_GPO_PP; + + /* + * Currently the driver handles only the GPIO support. The + * pinctrl/pinmux support can be added later if needed. + */ + pctl->gc = reference_gc; + pctl->gc.label = dev_name(&pdev->dev); + pctl->gc.parent = &pdev->dev; +#ifdef CONFIG_OF_GPIO + pctl->gc.of_node = parent->of_node; +#endif + + platform_set_drvdata(pdev, pctl); + + return devm_gpiochip_add_data(&pdev->dev, &pctl->gc, pctl); +} + +static struct platform_driver da9062_pctl_driver = { + .probe = da9062_pctl_probe, + .driver = { + .name = "da9062-gpio", + }, +}; +module_platform_driver(da9062_pctl_driver); + +MODULE_AUTHOR("Marco Felsch "); +MODULE_DESCRIPTION("DA9062 PMIC pinctrl and GPIO Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:da9062-gpio"); From dd62abd2d84d8fe09c644a7407a34c22cb3d43be Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Mon, 10 Feb 2020 14:56:41 +0100 Subject: [PATCH 0510/4444] s390/qdio: clean up cdev access in qdio_setup_irq() Some parts use init_data->cdev, others use irq_ptr->cdev. In the end it's all the same, but unnecessarily confusing. Use a single reference instead. Signed-off-by: Julian Wiedmann Reviewed-by: Steffen Maier Reviewed-by: Benjamin Block Signed-off-by: Vasily Gorbik --- drivers/s390/cio/qdio_setup.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 3ab8e80d7bbc..36890ed68083 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -453,7 +453,8 @@ static void setup_qib(struct qdio_irq *irq_ptr, int qdio_setup_irq(struct qdio_initialize *init_data) { struct ciw *ciw; - struct qdio_irq *irq_ptr = init_data->cdev->private->qdio_data; + struct ccw_device *cdev = init_data->cdev; + struct qdio_irq *irq_ptr = cdev->private->qdio_data; memset(&irq_ptr->qib, 0, sizeof(irq_ptr->qib)); memset(&irq_ptr->siga_flag, 0, sizeof(irq_ptr->siga_flag)); @@ -470,9 +471,9 @@ int qdio_setup_irq(struct qdio_initialize *init_data) irq_ptr->int_parm = init_data->int_parm; irq_ptr->nr_input_qs = init_data->no_input_qs; irq_ptr->nr_output_qs = init_data->no_output_qs; - irq_ptr->cdev = init_data->cdev; + irq_ptr->cdev = cdev; irq_ptr->scan_threshold = init_data->scan_threshold; - ccw_device_get_schid(irq_ptr->cdev, &irq_ptr->schid); + ccw_device_get_schid(cdev, &irq_ptr->schid); setup_queues(irq_ptr, init_data); setup_qib(irq_ptr, init_data); @@ -488,14 +489,14 @@ int qdio_setup_irq(struct qdio_initialize *init_data) /* qdr, qib, sls, slsbs, slibs, sbales are filled now */ /* get qdio commands */ - ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_EQUEUE); + ciw = ccw_device_get_ciw(cdev, CIW_TYPE_EQUEUE); if (!ciw) { DBF_ERROR("%4x NO EQ", irq_ptr->schid.sch_no); return -EINVAL; } irq_ptr->equeue = *ciw; - ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_AQUEUE); + ciw = ccw_device_get_ciw(cdev, CIW_TYPE_AQUEUE); if (!ciw) { DBF_ERROR("%4x NO AQ", irq_ptr->schid.sch_no); return -EINVAL; @@ -503,10 +504,10 @@ int qdio_setup_irq(struct qdio_initialize *init_data) irq_ptr->aqueue = *ciw; /* set new interrupt handler */ - spin_lock_irq(get_ccwdev_lock(irq_ptr->cdev)); - irq_ptr->orig_handler = init_data->cdev->handler; - init_data->cdev->handler = qdio_int_handler; - spin_unlock_irq(get_ccwdev_lock(irq_ptr->cdev)); + spin_lock_irq(get_ccwdev_lock(cdev)); + irq_ptr->orig_handler = cdev->handler; + cdev->handler = qdio_int_handler; + spin_unlock_irq(get_ccwdev_lock(cdev)); return 0; } From 014816b66218d9f5f90e6d92951abc9d3749b4cd Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Mon, 10 Feb 2020 14:58:07 +0100 Subject: [PATCH 0511/4444] s390/qdio: reduce access to cdev->private->qdio_data Remove all usage of cdev->private->qdio_data that's buried deep in internal code. This should only be used by the exported driver API, which can then pass around a proper qdio_irq pointer. Also trivially merge some initializations with their definitions. Signed-off-by: Julian Wiedmann Reviewed-by: Benjamin Block Signed-off-by: Vasily Gorbik --- drivers/s390/cio/qdio.h | 2 +- drivers/s390/cio/qdio_main.c | 13 +++++-------- drivers/s390/cio/qdio_setup.c | 3 +-- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index ff74eb5fce50..85d530927e4e 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -392,7 +392,7 @@ void qdio_setup_ssqd_info(struct qdio_irq *irq_ptr); int qdio_setup_get_ssqd(struct qdio_irq *irq_ptr, struct subchannel_id *schid, struct qdio_ssqd_desc *data); -int qdio_setup_irq(struct qdio_initialize *init_data); +int qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data); void qdio_print_subchannel_info(struct qdio_irq *irq_ptr, struct ccw_device *cdev); void qdio_release_memory(struct qdio_irq *irq_ptr); diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 3475317c42e5..2886b95f4741 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -1105,9 +1105,8 @@ int qdio_get_ssqd_desc(struct ccw_device *cdev, } EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); -static void qdio_shutdown_queues(struct ccw_device *cdev) +static void qdio_shutdown_queues(struct qdio_irq *irq_ptr) { - struct qdio_irq *irq_ptr = cdev->private->qdio_data; struct qdio_q *q; int i; @@ -1155,7 +1154,7 @@ int qdio_shutdown(struct ccw_device *cdev, int how) qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED); tiqdio_remove_device(irq_ptr); - qdio_shutdown_queues(cdev); + qdio_shutdown_queues(irq_ptr); qdio_shutdown_debug_entries(irq_ptr); /* cleanup subchannel */ @@ -1316,19 +1315,18 @@ static void qdio_detect_hsicq(struct qdio_irq *irq_ptr) int qdio_establish(struct qdio_initialize *init_data) { struct ccw_device *cdev = init_data->cdev; + struct qdio_irq *irq_ptr = cdev->private->qdio_data; struct subchannel_id schid; - struct qdio_irq *irq_ptr; int rc; ccw_device_get_schid(cdev, &schid); DBF_EVENT("qestablish:%4x", schid.sch_no); - irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; mutex_lock(&irq_ptr->setup_mutex); - qdio_setup_irq(init_data); + qdio_setup_irq(irq_ptr, init_data); rc = qdio_establish_thinint(irq_ptr); if (rc) { @@ -1386,14 +1384,13 @@ EXPORT_SYMBOL_GPL(qdio_establish); */ int qdio_activate(struct ccw_device *cdev) { + struct qdio_irq *irq_ptr = cdev->private->qdio_data; struct subchannel_id schid; - struct qdio_irq *irq_ptr; int rc; ccw_device_get_schid(cdev, &schid); DBF_EVENT("qactivate:%4x", schid.sch_no); - irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 36890ed68083..c56ff92c6e0c 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -450,11 +450,10 @@ static void setup_qib(struct qdio_irq *irq_ptr, memcpy(irq_ptr->qib.ebcnam, init_data->adapter_name, 8); } -int qdio_setup_irq(struct qdio_initialize *init_data) +int qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data) { struct ciw *ciw; struct ccw_device *cdev = init_data->cdev; - struct qdio_irq *irq_ptr = cdev->private->qdio_data; memset(&irq_ptr->qib, 0, sizeof(irq_ptr->qib)); memset(&irq_ptr->siga_flag, 0, sizeof(irq_ptr->siga_flag)); From b059a39cfa27c04e8e03e4ddf44f16501f36357d Mon Sep 17 00:00:00 2001 From: Stefan Raspl Date: Mon, 20 Jan 2020 13:10:37 +0100 Subject: [PATCH 0512/4444] s390/arch: install kernels with their proper version ID In case $INSTALLKERNEL is not available, we should install the kernel image with its version number, and save the previous one accordingly. Also, we're adding a hint so users know that they still need to perform one more configuration step (usually adjusting zipl config). Signed-off-by: Stefan Raspl Signed-off-by: Vasily Gorbik --- arch/s390/boot/install.sh | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/arch/s390/boot/install.sh b/arch/s390/boot/install.sh index bed227f267ae..515b27a996b3 100644 --- a/arch/s390/boot/install.sh +++ b/arch/s390/boot/install.sh @@ -21,15 +21,10 @@ if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi -# Default install - same as make zlilo +echo "Warning: '${INSTALLKERNEL}' command not available - additional " \ + "bootloader config required" >&2 +if [ -f $4/vmlinuz-$1 ]; then mv $4/vmlinuz-$1 $4/vmlinuz-$1.old; fi +if [ -f $4/System.map-$1 ]; then mv $4/System.map-$1 $4/System.map-$1.old; fi -if [ -f $4/vmlinuz ]; then - mv $4/vmlinuz $4/vmlinuz.old -fi - -if [ -f $4/System.map ]; then - mv $4/System.map $4/System.old -fi - -cat $2 > $4/vmlinuz -cp $3 $4/System.map +cat $2 > $4/vmlinuz-$1 +cp $3 $4/System.map-$1 From 69e53129d01317d94e8b97ec11688880106a2f97 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Wed, 19 Feb 2020 07:46:22 -0600 Subject: [PATCH 0513/4444] ASoC: tas2562: Add support for ISENSE and VSENSE Add additional support for ISENSE and VSENSE feature for the TAS2562. This feature monitors the output to the loud speaker attempts to eliminate IR drop errors due to packaging. This feature is defined in Section 8.4.5 IV Sense of the data sheet. Signed-off-by: Dan Murphy Link: https://lore.kernel.org/r/20200219134622.22066-1-dmurphy@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2562.c | 32 +++++++++++++++++++++++++++----- sound/soc/codecs/tas2562.h | 6 +++--- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c index 729acd874c48..b517ada7e809 100644 --- a/sound/soc/codecs/tas2562.c +++ b/sound/soc/codecs/tas2562.c @@ -382,18 +382,34 @@ static int tas2562_dac_event(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); + int ret; switch (event) { case SND_SOC_DAPM_POST_PMU: - dev_info(tas2562->dev, "SND_SOC_DAPM_POST_PMU\n"); + ret = snd_soc_component_update_bits(component, + TAS2562_PWR_CTRL, + TAS2562_MODE_MASK, + TAS2562_MUTE); + if (ret) + goto end; break; case SND_SOC_DAPM_PRE_PMD: - dev_info(tas2562->dev, "SND_SOC_DAPM_PRE_PMD\n"); + ret = snd_soc_component_update_bits(component, + TAS2562_PWR_CTRL, + TAS2562_MODE_MASK, + TAS2562_SHUTDOWN); + if (ret) + goto end; break; default: - break; + dev_err(tas2562->dev, "Not supported evevt\n"); + return -EINVAL; } +end: + if (ret < 0) + return ret; + return 0; } @@ -415,7 +431,6 @@ static const struct snd_kcontrol_new tas2562_snd_controls[] = { static const struct snd_soc_dapm_widget tas2562_dapm_widgets[] = { SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2562_asi1_mux), - SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2562_dac_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_SWITCH("ISENSE", TAS2562_PWR_CTRL, 3, 1, &isense_switch), @@ -430,7 +445,7 @@ static const struct snd_soc_dapm_route tas2562_audio_map[] = { {"ASI1 Sel", "Left", "ASI1"}, {"ASI1 Sel", "Right", "ASI1"}, {"ASI1 Sel", "LeftRightDiv2", "ASI1"}, - { "DAC", NULL, "DAC IN" }, + { "DAC", NULL, "ASI1 Sel" }, { "OUT", NULL, "DAC" }, {"ISENSE", "Switch", "IMON"}, {"VSENSE", "Switch", "VMON"}, @@ -471,6 +486,13 @@ static struct snd_soc_dai_driver tas2562_dai[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = TAS2562_FORMATS, }, + .capture = { + .stream_name = "ASI1 Capture", + .channels_min = 0, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = TAS2562_FORMATS, + }, .ops = &tas2562_speaker_dai_ops, }, }; diff --git a/sound/soc/codecs/tas2562.h b/sound/soc/codecs/tas2562.h index 62e659ab786d..6f55ebcf19ea 100644 --- a/sound/soc/codecs/tas2562.h +++ b/sound/soc/codecs/tas2562.h @@ -40,7 +40,7 @@ #define TAS2562_RESET BIT(0) -#define TAS2562_MODE_MASK 0x3 +#define TAS2562_MODE_MASK GENMASK(1,0) #define TAS2562_ACTIVE 0x0 #define TAS2562_MUTE 0x1 #define TAS2562_SHUTDOWN 0x2 @@ -73,8 +73,8 @@ #define TAS2562_TDM_CFG2_RXWLEN_24B BIT(3) #define TAS2562_TDM_CFG2_RXWLEN_32B (BIT(2) | BIT(3)) -#define TAS2562_VSENSE_POWER_EN BIT(2) -#define TAS2562_ISENSE_POWER_EN BIT(3) +#define TAS2562_VSENSE_POWER_EN 2 +#define TAS2562_ISENSE_POWER_EN 3 #define TAS2562_TDM_CFG5_VSNS_EN BIT(6) #define TAS2562_TDM_CFG5_VSNS_SLOT_MASK GENMASK(5, 0) From ce83baca8526689c332135c0abca2667ba056009 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Feb 2020 15:55:53 +0900 Subject: [PATCH 0514/4444] ASoC: soundwaire: qcom: use for_each_rtd_codec_dai() macro Signed-off-by: Kuninori Morimoto Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87o8tvjcbc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- drivers/soundwire/qcom.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index 1c6c6a2e0def..fb30bbec999a 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -594,6 +594,7 @@ static int qcom_swrm_startup(struct snd_pcm_substream *substream, struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dai->dev); struct snd_soc_pcm_runtime *rtd = substream->private_data; struct sdw_stream_runtime *sruntime; + struct snd_soc_dai *codec_dai; int ret, i; sruntime = sdw_alloc_stream(dai->name); @@ -602,12 +603,12 @@ static int qcom_swrm_startup(struct snd_pcm_substream *substream, ctrl->sruntime[dai->id] = sruntime; - for (i = 0; i < rtd->num_codecs; i++) { - ret = snd_soc_dai_set_sdw_stream(rtd->codec_dais[i], sruntime, + for_each_rtd_codec_dai(rtd, i, codec_dai) { + ret = snd_soc_dai_set_sdw_stream(codec_dai, sruntime, substream->stream); if (ret < 0 && ret != -ENOTSUPP) { dev_err(dai->dev, "Failed to set sdw stream on %s", - rtd->codec_dais[i]->name); + codec_dai->name); sdw_release_stream(sruntime); return ret; } From a4eb41eef331d31b8593defa10b249e155e0314f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Feb 2020 15:56:01 +0900 Subject: [PATCH 0515/4444] ASoC: qcom: sdm845: use for_each_rtd_codec_dai() macro Signed-off-by: Kuninori Morimoto Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87mu9fjcb4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/qcom/sdm845.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c index 3b5547a27aad..5a23597261ac 100644 --- a/sound/soc/qcom/sdm845.c +++ b/sound/soc/qcom/sdm845.c @@ -43,14 +43,14 @@ static int sdm845_slim_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai_link *dai_link = rtd->dai_link; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai; u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS]; u32 rx_ch_cnt = 0, tx_ch_cnt = 0; int ret = 0, i; - for (i = 0 ; i < dai_link->num_codecs; i++) { - ret = snd_soc_dai_get_channel_map(rtd->codec_dais[i], + for_each_rtd_codec_dai(rtd, i, codec_dai) { + ret = snd_soc_dai_get_channel_map(codec_dai, &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch); if (ret != 0 && ret != -ENOTSUPP) { @@ -77,6 +77,7 @@ static int sdm845_tdm_snd_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai; int ret = 0, j; int channels, slot_width; @@ -125,8 +126,7 @@ static int sdm845_tdm_snd_hw_params(struct snd_pcm_substream *substream, } } - for (j = 0; j < rtd->num_codecs; j++) { - struct snd_soc_dai *codec_dai = rtd->codec_dais[j]; + for_each_rtd_codec_dai(rtd, j, codec_dai) { if (!strcmp(codec_dai->component->name_prefix, "Left")) { ret = snd_soc_dai_set_tdm_slot( @@ -214,7 +214,6 @@ static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(card); struct snd_jack *jack; - struct snd_soc_dai_link *dai_link = rtd->dai_link; /* * Codec SLIMBUS configuration * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13 @@ -266,8 +265,8 @@ static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd) } break; case SLIMBUS_0_RX...SLIMBUS_6_TX: - for (i = 0 ; i < dai_link->num_codecs; i++) { - rval = snd_soc_dai_set_channel_map(rtd->codec_dais[i], + for_each_rtd_codec_dai(rtd, i, codec_dai) { + rval = snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch), tx_ch, ARRAY_SIZE(rx_ch), @@ -275,7 +274,7 @@ static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd) if (rval != 0 && rval != -ENOTSUPP) return rval; - snd_soc_dai_set_sysclk(rtd->codec_dais[i], 0, + snd_soc_dai_set_sysclk(codec_dai, 0, WCD934X_DEFAULT_MCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); } @@ -345,8 +344,7 @@ static int sdm845_snd_startup(struct snd_pcm_substream *substream) codec_dai_fmt |= SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_DSP_B; - for (j = 0; j < rtd->num_codecs; j++) { - codec_dai = rtd->codec_dais[j]; + for_each_rtd_codec_dai(rtd, j, codec_dai) { if (!strcmp(codec_dai->component->name_prefix, "Left")) { From cf4dae032096f1299cf390fd55da489cb445dcbb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Feb 2020 15:56:09 +0900 Subject: [PATCH 0516/4444] ASoC: qcom: apq8016_sbc: use for_each_rtd_codec_dai() macro Signed-off-by: Kuninori Morimoto Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87lfozjcaw.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/qcom/apq8016_sbc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index ac75838bbfab..2d064f3bc9b6 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -34,8 +34,8 @@ struct apq8016_sbc_data { static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai; struct snd_soc_component *component; - struct snd_soc_dai_link *dai_link = rtd->dai_link; struct snd_soc_card *card = rtd->card; struct apq8016_sbc_data *pdata = snd_soc_card_get_drvdata(card); int i, rval; @@ -90,10 +90,9 @@ static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd) pdata->jack_setup = true; } - for (i = 0 ; i < dai_link->num_codecs; i++) { - struct snd_soc_dai *dai = rtd->codec_dais[i]; + for_each_rtd_codec_dai(rtd, i, codec_dai) { - component = dai->component; + component = codec_dai->component; /* Set default mclk for internal codec */ rval = snd_soc_component_set_sysclk(component, 0, 0, DEFAULT_MCLK_RATE, SND_SOC_CLOCK_IN); From 225c53a8cfb6fdd8defbbf72e8dcfb3801f7f51e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Feb 2020 15:56:15 +0900 Subject: [PATCH 0517/4444] ASoC: intel: cml_rt1011_rt5682: use for_each_rtd_codec_dai() macro Signed-off-by: Kuninori Morimoto Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87k14jjcaq.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/cml_rt1011_rt5682.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/cml_rt1011_rt5682.c b/sound/soc/intel/boards/cml_rt1011_rt5682.c index dd80d0186a6c..02aa18d24319 100644 --- a/sound/soc/intel/boards/cml_rt1011_rt5682.c +++ b/sound/soc/intel/boards/cml_rt1011_rt5682.c @@ -164,8 +164,7 @@ static int cml_rt1011_hw_params(struct snd_pcm_substream *substream, srate = params_rate(params); - for (i = 0; i < rtd->num_codecs; i++) { - codec_dai = rtd->codec_dais[i]; + for_each_rtd_codec_dai(rtd, i, codec_dai) { /* 100 Fs to drive 24 bit data */ ret = snd_soc_dai_set_pll(codec_dai, 0, RT1011_PLL1_S_BCLK, From 89a2870f6be6aa75de2df22f8baa982c2d7d86e8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Feb 2020 15:56:20 +0900 Subject: [PATCH 0518/4444] ASoC: intel: kbl_da7219_max98927: use for_each_rtd_codec_dai() macro Signed-off-by: Kuninori Morimoto Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87imk3jcal.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_da7219_max98927.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c index 7a13e9b35187..88f69e3697d2 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98927.c +++ b/sound/soc/intel/boards/kbl_da7219_max98927.c @@ -176,10 +176,10 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *runtime = substream->private_data; + struct snd_soc_dai *codec_dai; int ret, j; - for (j = 0; j < runtime->num_codecs; j++) { - struct snd_soc_dai *codec_dai = runtime->codec_dais[j]; + for_each_rtd_codec_dai(runtime, j, codec_dai) { if (!strcmp(codec_dai->component->name, MAX98927_DEV0_NAME)) { ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x30, 3, 8, 16); @@ -221,10 +221,10 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, static int kabylake_ssp0_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai; int j, ret; - for (j = 0; j < rtd->num_codecs; j++) { - struct snd_soc_dai *codec_dai = rtd->codec_dais[j]; + for_each_rtd_codec_dai(rtd, j, codec_dai) { const char *name = codec_dai->component->name; struct snd_soc_component *component = codec_dai->component; struct snd_soc_dapm_context *dapm = From 56f1003f65830697bd68ae1e26b5561e4cbe6523 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Feb 2020 15:56:25 +0900 Subject: [PATCH 0519/4444] ASoC: mediatek: mt8183-da7219-max98357: use for_each_rtd_codec_dai() macro Signed-off-by: Kuninori Morimoto Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87h7znjcag.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index 03d104fbe185..4a5ef07e956b 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -40,6 +40,7 @@ static int mt8183_da7219_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai; unsigned int rate = params_rate(params); unsigned int mclk_fs_ratio = 256; unsigned int mclk_fs = rate * mclk_fs_ratio; @@ -51,8 +52,7 @@ static int mt8183_da7219_i2s_hw_params(struct snd_pcm_substream *substream, if (ret < 0) dev_err(rtd->dev, "failed to set cpu dai sysclk\n"); - for (j = 0; j < rtd->num_codecs; j++) { - struct snd_soc_dai *codec_dai = rtd->codec_dais[j]; + for_each_rtd_codec_dai(rtd, j, codec_dai) { if (!strcmp(codec_dai->component->name, "da7219.5-001a")) { ret = snd_soc_dai_set_sysclk(codec_dai, @@ -82,10 +82,10 @@ static int mt8183_da7219_i2s_hw_params(struct snd_pcm_substream *substream, static int mt8183_da7219_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai; int ret = 0, j; - for (j = 0; j < rtd->num_codecs; j++) { - struct snd_soc_dai *codec_dai = rtd->codec_dais[j]; + for_each_rtd_codec_dai(rtd, j, codec_dai) { if (!strcmp(codec_dai->component->name, "da7219.5-001a")) { ret = snd_soc_dai_set_pll(codec_dai, From f87249dd1c9b3bf06c2252419ccf2ee65592b538 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 18 Feb 2020 08:43:06 +0100 Subject: [PATCH 0520/4444] ARM: exynos_defconfig: Enable SquashFS and increase RAM block device size All modules built from exynos_defconfig occupy about 55M, so enable squashfs filesystem support and increase default ram block device size to 32M to enable deploying them on initrd. Such initrd, using squashfs requires at least 24M. Signed-off-by: Marek Szyprowski Signed-off-by: Krzysztof Kozlowski --- arch/arm/configs/exynos_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig index c8e0c14092e8..65c4daddefe3 100644 --- a/arch/arm/configs/exynos_defconfig +++ b/arch/arm/configs/exynos_defconfig @@ -92,7 +92,7 @@ CONFIG_DEVTMPFS_MOUNT=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_CRYPTOLOOP=y CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_RAM_SIZE=32768 CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_SG=y @@ -320,6 +320,7 @@ CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_CRAMFS=y +CONFIG_SQUASHFS=y CONFIG_ROMFS_FS=y CONFIG_NFS_FS=y CONFIG_NFS_V4=y From 42be7c41a5edc990e329b991b4ad6ec172e72e18 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 19 Feb 2020 09:49:27 +0100 Subject: [PATCH 0521/4444] dt-bindings: clk: g12a-clkc: add SPICC SCLK Source clock IDs Add clock ids used by the SPICC Controllers of the G12A and compatible SoCs Signed-off-by: Neil Armstrong Signed-off-by: Jerome Brunet --- include/dt-bindings/clock/g12a-clkc.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/dt-bindings/clock/g12a-clkc.h b/include/dt-bindings/clock/g12a-clkc.h index 0837c1a7ae49..b0d65d73db96 100644 --- a/include/dt-bindings/clock/g12a-clkc.h +++ b/include/dt-bindings/clock/g12a-clkc.h @@ -143,5 +143,7 @@ #define CLKID_CPU1_CLK 253 #define CLKID_CPU2_CLK 254 #define CLKID_CPU3_CLK 255 +#define CLKID_SPICC0_SCLK 258 +#define CLKID_SPICC1_SCLK 261 #endif /* __G12A_CLKC_H */ From a18c8e0b76979881f3b31e96c398e62ab30a1662 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 19 Feb 2020 09:49:28 +0100 Subject: [PATCH 0522/4444] clk: meson: g12a: add support for the SPICC SCLK Source clocks This adds the clocks used for the Amlogic G12A and compatible SoCs SPICC controller to provide a more complete range of frequencies instead of the SPICC internal divider over Xtal. Signed-off-by: Neil Armstrong Signed-off-by: Jerome Brunet --- drivers/clk/meson/g12a.c | 129 +++++++++++++++++++++++++++++++++++++++ drivers/clk/meson/g12a.h | 6 +- 2 files changed, 134 insertions(+), 1 deletion(-) diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index d2760a021301..fad616cac01e 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -3862,6 +3862,111 @@ static struct clk_regmap g12a_ts = { }, }; +/* SPICC SCLK source clock */ + +static const struct clk_parent_data spicc_sclk_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &g12a_clk81.hw }, + { .hw = &g12a_fclk_div4.hw }, + { .hw = &g12a_fclk_div3.hw }, + { .hw = &g12a_fclk_div5.hw }, + { .hw = &g12a_fclk_div7.hw }, +}; + +static struct clk_regmap g12a_spicc0_sclk_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_SPICC_CLK_CNTL, + .mask = 7, + .shift = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc0_sclk_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = spicc_sclk_parent_data, + .num_parents = ARRAY_SIZE(spicc_sclk_parent_data), + }, +}; + +static struct clk_regmap g12a_spicc0_sclk_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_SPICC_CLK_CNTL, + .shift = 0, + .width = 6, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc0_sclk_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &g12a_spicc0_sclk_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap g12a_spicc0_sclk = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_SPICC_CLK_CNTL, + .bit_idx = 6, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc0_sclk", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &g12a_spicc0_sclk_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap g12a_spicc1_sclk_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_SPICC_CLK_CNTL, + .mask = 7, + .shift = 23, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc1_sclk_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = spicc_sclk_parent_data, + .num_parents = ARRAY_SIZE(spicc_sclk_parent_data), + }, +}; + +static struct clk_regmap g12a_spicc1_sclk_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_SPICC_CLK_CNTL, + .shift = 16, + .width = 6, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc1_sclk_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &g12a_spicc1_sclk_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap g12a_spicc1_sclk = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_SPICC_CLK_CNTL, + .bit_idx = 22, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc1_sclk", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &g12a_spicc1_sclk_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + #define MESON_GATE(_name, _reg, _bit) \ MESON_PCLK(_name, _reg, _bit, &g12a_clk81.hw) @@ -4159,6 +4264,12 @@ static struct clk_hw_onecell_data g12a_hw_onecell_data = { [CLKID_VDEC_HEVCF] = &g12a_vdec_hevcf.hw, [CLKID_TS_DIV] = &g12a_ts_div.hw, [CLKID_TS] = &g12a_ts.hw, + [CLKID_SPICC0_SCLK_SEL] = &g12a_spicc0_sclk_sel.hw, + [CLKID_SPICC0_SCLK_DIV] = &g12a_spicc0_sclk_div.hw, + [CLKID_SPICC0_SCLK] = &g12a_spicc0_sclk.hw, + [CLKID_SPICC1_SCLK_SEL] = &g12a_spicc1_sclk_sel.hw, + [CLKID_SPICC1_SCLK_DIV] = &g12a_spicc1_sclk_div.hw, + [CLKID_SPICC1_SCLK] = &g12a_spicc1_sclk.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -4408,6 +4519,12 @@ static struct clk_hw_onecell_data g12b_hw_onecell_data = { [CLKID_CPUB_CLK_AXI] = &g12b_cpub_clk_axi.hw, [CLKID_CPUB_CLK_TRACE_SEL] = &g12b_cpub_clk_trace_sel.hw, [CLKID_CPUB_CLK_TRACE] = &g12b_cpub_clk_trace.hw, + [CLKID_SPICC0_SCLK_SEL] = &g12a_spicc0_sclk_sel.hw, + [CLKID_SPICC0_SCLK_DIV] = &g12a_spicc0_sclk_div.hw, + [CLKID_SPICC0_SCLK] = &g12a_spicc0_sclk.hw, + [CLKID_SPICC1_SCLK_SEL] = &g12a_spicc1_sclk_sel.hw, + [CLKID_SPICC1_SCLK_DIV] = &g12a_spicc1_sclk_div.hw, + [CLKID_SPICC1_SCLK] = &g12a_spicc1_sclk.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -4642,6 +4759,12 @@ static struct clk_hw_onecell_data sm1_hw_onecell_data = { [CLKID_CPU1_CLK] = &sm1_cpu1_clk.hw, [CLKID_CPU2_CLK] = &sm1_cpu2_clk.hw, [CLKID_CPU3_CLK] = &sm1_cpu3_clk.hw, + [CLKID_SPICC0_SCLK_SEL] = &g12a_spicc0_sclk_sel.hw, + [CLKID_SPICC0_SCLK_DIV] = &g12a_spicc0_sclk_div.hw, + [CLKID_SPICC0_SCLK] = &g12a_spicc0_sclk.hw, + [CLKID_SPICC1_SCLK_SEL] = &g12a_spicc1_sclk_sel.hw, + [CLKID_SPICC1_SCLK_DIV] = &g12a_spicc1_sclk_div.hw, + [CLKID_SPICC1_SCLK] = &g12a_spicc1_sclk.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -4877,6 +5000,12 @@ static struct clk_regmap *const g12a_clk_regmaps[] = { &sm1_cpu1_clk, &sm1_cpu2_clk, &sm1_cpu3_clk, + &g12a_spicc0_sclk_sel, + &g12a_spicc0_sclk_div, + &g12a_spicc0_sclk, + &g12a_spicc1_sclk_sel, + &g12a_spicc1_sclk_div, + &g12a_spicc1_sclk, }; static const struct reg_sequence g12a_init_regs[] = { diff --git a/drivers/clk/meson/g12a.h b/drivers/clk/meson/g12a.h index 9df4068aced1..a8852556836e 100644 --- a/drivers/clk/meson/g12a.h +++ b/drivers/clk/meson/g12a.h @@ -255,8 +255,12 @@ #define CLKID_DSU_CLK_DYN1 249 #define CLKID_DSU_CLK_DYN 250 #define CLKID_DSU_CLK_FINAL 251 +#define CLKID_SPICC0_SCLK_SEL 256 +#define CLKID_SPICC0_SCLK_DIV 257 +#define CLKID_SPICC1_SCLK_SEL 259 +#define CLKID_SPICC1_SCLK_DIV 260 -#define NR_CLKS 256 +#define NR_CLKS 262 /* include the CLKIDs that have been made part of the DT binding */ #include From e14980976534d9d94f5cddd70033707965482ede Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Tue, 18 Feb 2020 21:31:58 +0000 Subject: [PATCH 0523/4444] ASoC: dt-bindings: Make RK3328 codec GPIO explicit Existing RK3328 codec drivers have overloaded the GRF phandle to assume implicit control of the limited-function GPIO_MUTE pin, which is usually used to enable an external audio line driver IC. Since this pin has a proper binding of its own (see gpio/rockchip,rk3328-grf-gpio.txt), make a GPIO explicit in the codec binding too. This will help avoid ambiguity on boards that use that pin for some other purpose. (and while touching the example, enforce the "don't include status" rule) Signed-off-by: Robin Murphy Link: https://lore.kernel.org/r/5f7a399dea8a9dedef57f6f99f0f6ab1c1fdc56a.1581376744.git.robin.murphy@arm.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/rockchip,rk3328-codec.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.txt b/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.txt index 2469588c7ccb..1ecd75d2032a 100644 --- a/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.txt +++ b/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.txt @@ -10,6 +10,11 @@ Required properties: - clock-names: should be "pclk". - spk-depop-time-ms: speak depop time msec. +Optional properties: + +- mute-gpios: GPIO specifier for external line driver control (typically the + dedicated GPIO_MUTE pin) + Example for rk3328 internal codec: codec: codec@ff410000 { @@ -18,6 +23,6 @@ codec: codec@ff410000 { rockchip,grf = <&grf>; clocks = <&cru PCLK_ACODEC>; clock-names = "pclk"; + mute-gpios = <&grf_gpio 0 GPIO_ACTIVE_LOW>; spk-depop-time-ms = 100; - status = "disabled"; }; From 87d12d5545fa72d67d99d797cdb464c0c7efb9c9 Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Tue, 18 Feb 2020 21:31:59 +0000 Subject: [PATCH 0524/4444] ASoC: rockchip: Make RK3328 GPIO_MUTE control explicit The RK3328 reference design uses an external line driver IC as a buffer on the analog codec output, enabled by the GPIO_MUTE pin, and such a configuration is currently assumed in the codec driver's direct poking of GRF_SOC_CON10 to control the GPIO_MUTE output value. However, some boards wire up analog audio yet use that pin for some other purpose, so that assumption doesn't always hold. Update this functionality to rely on an explicit GPIO descriptor, such that it can be managed at the board level. Signed-off-by: Robin Murphy Link: https://lore.kernel.org/r/5bc383ed1832f0f5d1dcb3c97ad92fd68e5217e3.1581376744.git.robin.murphy@arm.com Signed-off-by: Mark Brown --- sound/soc/codecs/rk3328_codec.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/sound/soc/codecs/rk3328_codec.c b/sound/soc/codecs/rk3328_codec.c index 287c962ba00d..115706a55577 100644 --- a/sound/soc/codecs/rk3328_codec.c +++ b/sound/soc/codecs/rk3328_codec.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -31,7 +32,7 @@ struct rk3328_codec_priv { struct regmap *regmap; - struct regmap *grf; + struct gpio_desc *mute; struct clk *mclk; struct clk *pclk; unsigned int sclk; @@ -106,16 +107,6 @@ static int rk3328_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) return 0; } -static void rk3328_analog_output(struct rk3328_codec_priv *rk3328, int mute) -{ - unsigned int val = BIT(17); - - if (mute) - val |= BIT(1); - - regmap_write(rk3328->grf, RK3328_GRF_SOC_CON10, val); -} - static int rk3328_digital_mute(struct snd_soc_dai *dai, int mute) { struct rk3328_codec_priv *rk3328 = @@ -205,7 +196,7 @@ static int rk3328_codec_open_playback(struct rk3328_codec_priv *rk3328) } msleep(rk3328->spk_depop_time); - rk3328_analog_output(rk3328, 1); + gpiod_set_value(rk3328->mute, 0); regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL, HPOUTL_GAIN_MASK, OUT_VOLUME); @@ -246,7 +237,7 @@ static int rk3328_codec_close_playback(struct rk3328_codec_priv *rk3328) { size_t i; - rk3328_analog_output(rk3328, 0); + gpiod_set_value(rk3328->mute, 1); regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL, HPOUTL_GAIN_MASK, 0); @@ -446,7 +437,6 @@ static int rk3328_platform_probe(struct platform_device *pdev) dev_err(&pdev->dev, "missing 'rockchip,grf'\n"); return PTR_ERR(grf); } - rk3328->grf = grf; /* enable i2s_acodec_en */ regmap_write(grf, RK3328_GRF_SOC_CON2, (BIT(14) << 16 | BIT(14))); @@ -458,7 +448,18 @@ static int rk3328_platform_probe(struct platform_device *pdev) rk3328->spk_depop_time = 200; } - rk3328_analog_output(rk3328, 0); + rk3328->mute = gpiod_get_optional(&pdev->dev, "mute", GPIOD_OUT_HIGH); + if (IS_ERR(rk3328->mute)) + return PTR_ERR(rk3328->mute); + /* + * Rock64 is the only supported platform to have widely relied on + * this; if we do happen to come across an old DTB, just leave the + * external mute forced off. + */ + if (!rk3328->mute && of_machine_is_compatible("pine64,rock64")) { + dev_warn(&pdev->dev, "assuming implicit control of GPIO_MUTE; update devicetree if possible\n"); + regmap_write(grf, RK3328_GRF_SOC_CON10, BIT(17) | BIT(1)); + } rk3328->mclk = devm_clk_get(&pdev->dev, "mclk"); if (IS_ERR(rk3328->mclk)) From 1d0827b75ee7df497f611a2ac412a88135fb0ef5 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 30 Jan 2020 12:06:01 -0800 Subject: [PATCH 0525/4444] mm/memremap_pages: Kill unused __devm_memremap_pages() Kill this definition that was introduced in commit 41e94a851304 ("add devm_memremap_pages") add never used. Cc: Christoph Hellwig Reviewed-by: Aneesh Kumar K.V Reviewed-by: Christoph Hellwig Link: https://lore.kernel.org/r/158041476158.3889308.4221100673554151124.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Dan Williams --- include/linux/io.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/io.h b/include/linux/io.h index b1c44bb4b2d7..8394c56babc2 100644 --- a/include/linux/io.h +++ b/include/linux/io.h @@ -77,8 +77,6 @@ void *devm_memremap(struct device *dev, resource_size_t offset, size_t size, unsigned long flags); void devm_memunmap(struct device *dev, void *addr); -void *__devm_memremap_pages(struct device *dev, struct resource *res); - #ifdef CONFIG_PCI /* * The PCI specifications (Rev 3.0, 3.2.5 "Transaction Ordering and From 2f384801a4e0bcca7f5846c346decffed44f0c0b Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Fri, 7 Feb 2020 11:03:05 +0100 Subject: [PATCH 0526/4444] dt-bindinsg: net: can: Convert can-transceiver to json-schema Convert can-transceiver property to json-schema Signed-off-by: Benjamin Gaignard Signed-off-by: Rob Herring --- .../bindings/net/can/can-transceiver.txt | 24 ------------------- .../bindings/net/can/can-transceiver.yaml | 18 ++++++++++++++ 2 files changed, 18 insertions(+), 24 deletions(-) delete mode 100644 Documentation/devicetree/bindings/net/can/can-transceiver.txt create mode 100644 Documentation/devicetree/bindings/net/can/can-transceiver.yaml diff --git a/Documentation/devicetree/bindings/net/can/can-transceiver.txt b/Documentation/devicetree/bindings/net/can/can-transceiver.txt deleted file mode 100644 index 0011f53ff159..000000000000 --- a/Documentation/devicetree/bindings/net/can/can-transceiver.txt +++ /dev/null @@ -1,24 +0,0 @@ -Generic CAN transceiver Device Tree binding ------------------------------- - -CAN transceiver typically limits the max speed in standard CAN and CAN FD -modes. Typically these limitations are static and the transceivers themselves -provide no way to detect this limitation at runtime. For this situation, -the "can-transceiver" node can be used. - -Required Properties: - max-bitrate: a positive non 0 value that determines the max - speed that CAN/CAN-FD can run. Any other value - will be ignored. - -Examples: - -Based on Texas Instrument's TCAN1042HGV CAN Transceiver - -m_can0 { - .... - can-transceiver { - max-bitrate = <5000000>; - }; - ... -}; diff --git a/Documentation/devicetree/bindings/net/can/can-transceiver.yaml b/Documentation/devicetree/bindings/net/can/can-transceiver.yaml new file mode 100644 index 000000000000..6396977d29e5 --- /dev/null +++ b/Documentation/devicetree/bindings/net/can/can-transceiver.yaml @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/can/can-transceiver.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: CAN transceiver Bindings + +description: CAN transceiver generic properties bindings + +maintainers: + - Rob Herring + +properties: + max-bitrate: + $ref: /schemas/types.yaml#/definitions/uint32 + description: a positive non 0 value that determines the max speed that CAN/CAN-FD can run. + minimum: 1 From 824674b59f72e8aed2c6b36e12ab07a2eb54769a Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Fri, 7 Feb 2020 11:03:06 +0100 Subject: [PATCH 0527/4444] dt-bindings: net: can: Convert M_CAN to json-schema Convert M_CAN bindings to json-schema Signed-off-by: Benjamin Gaignard Signed-off-by: Rob Herring --- .../bindings/net/can/bosch,m_can.yaml | 144 ++++++++++++++++++ .../devicetree/bindings/net/can/m_can.txt | 75 --------- 2 files changed, 144 insertions(+), 75 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/can/bosch,m_can.yaml delete mode 100644 Documentation/devicetree/bindings/net/can/m_can.txt diff --git a/Documentation/devicetree/bindings/net/can/bosch,m_can.yaml b/Documentation/devicetree/bindings/net/can/bosch,m_can.yaml new file mode 100644 index 000000000000..cccf8202c8f7 --- /dev/null +++ b/Documentation/devicetree/bindings/net/can/bosch,m_can.yaml @@ -0,0 +1,144 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/can/bosch,m_can.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Bosch MCAN controller Bindings + +description: Bosch MCAN controller for CAN bus + +maintainers: + - Sriram Dash + +properties: + compatible: + const: bosch,m_can + + reg: + items: + - description: M_CAN registers map + - description: message RAM + + reg-names: + items: + - const: m_can + - const: message_ram + + interrupts: + items: + - description: interrupt line0 + - description: interrupt line1 + minItems: 1 + maxItems: 2 + + interrupt-names: + items: + - const: int0 + - const: int1 + minItems: 1 + maxItems: 2 + + clocks: + items: + - description: peripheral clock + - description: bus clock + + clock-names: + items: + - const: hclk + - const: cclk + + bosch,mram-cfg: + description: | + Message RAM configuration data. + Multiple M_CAN instances can share the same Message RAM + and each element(e.g Rx FIFO or Tx Buffer and etc) number + in Message RAM is also configurable, so this property is + telling driver how the shared or private Message RAM are + used by this M_CAN controller. + + The format should be as follows: + + The 'offset' is an address offset of the Message RAM where + the following elements start from. This is usually set to + 0x0 if you're using a private Message RAM. The remain cells + are used to specify how many elements are used for each FIFO/Buffer. + + M_CAN includes the following elements according to user manual: + 11-bit Filter 0-128 elements / 0-128 words + 29-bit Filter 0-64 elements / 0-128 words + Rx FIFO 0 0-64 elements / 0-1152 words + Rx FIFO 1 0-64 elements / 0-1152 words + Rx Buffers 0-64 elements / 0-1152 words + Tx Event FIFO 0-32 elements / 0-64 words + Tx Buffers 0-32 elements / 0-576 words + + Please refer to 2.4.1 Message RAM Configuration in Bosch + M_CAN user manual for details. + allOf: + - $ref: /schemas/types.yaml#/definitions/int32-array + - items: + items: + - description: The 'offset' is an address offset of the Message RAM + where the following elements start from. This is usually + set to 0x0 if you're using a private Message RAM. + default: 0 + - description: 11-bit Filter 0-128 elements / 0-128 words + minimum: 0 + maximum: 128 + - description: 29-bit Filter 0-64 elements / 0-128 words + minimum: 0 + maximum: 64 + - description: Rx FIFO 0 0-64 elements / 0-1152 words + minimum: 0 + maximum: 64 + - description: Rx FIFO 1 0-64 elements / 0-1152 words + minimum: 0 + maximum: 64 + - description: Rx Buffers 0-64 elements / 0-1152 words + minimum: 0 + maximum: 64 + - description: Tx Event FIFO 0-32 elements / 0-64 words + minimum: 0 + maximum: 32 + - description: Tx Buffers 0-32 elements / 0-576 words + minimum: 0 + maximum: 32 + maxItems: 1 + + can-transceiver: + $ref: can-transceiver.yaml# + +required: + - compatible + - reg + - reg-names + - interrupts + - interrupt-names + - clocks + - clock-names + - bosch,mram-cfg + +additionalProperties: false + +examples: + - | + #include + can@20e8000 { + compatible = "bosch,m_can"; + reg = <0x020e8000 0x4000>, <0x02298000 0x4000>; + reg-names = "m_can", "message_ram"; + interrupts = <0 114 0x04>, <0 114 0x04>; + interrupt-names = "int0", "int1"; + clocks = <&clks IMX6SX_CLK_CANFD>, + <&clks IMX6SX_CLK_CANFD>; + clock-names = "hclk", "cclk"; + bosch,mram-cfg = <0x0 0 0 32 0 0 0 1>; + + can-transceiver { + max-bitrate = <5000000>; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/net/can/m_can.txt b/Documentation/devicetree/bindings/net/can/m_can.txt deleted file mode 100644 index ed614383af9c..000000000000 --- a/Documentation/devicetree/bindings/net/can/m_can.txt +++ /dev/null @@ -1,75 +0,0 @@ -Bosch MCAN controller Device Tree Bindings -------------------------------------------------- - -Required properties: -- compatible : Should be "bosch,m_can" for M_CAN controllers -- reg : physical base address and size of the M_CAN - registers map and Message RAM -- reg-names : Should be "m_can" and "message_ram" -- interrupts : Should be the interrupt number of M_CAN interrupt - line 0 and line 1, could be same if sharing - the same interrupt. -- interrupt-names : Should contain "int0" and "int1" -- clocks : Clocks used by controller, should be host clock - and CAN clock. -- clock-names : Should contain "hclk" and "cclk" -- pinctrl- : Pinctrl states as described in bindings/pinctrl/pinctrl-bindings.txt -- pinctrl-names : Names corresponding to the numbered pinctrl states -- bosch,mram-cfg : Message RAM configuration data. - Multiple M_CAN instances can share the same Message - RAM and each element(e.g Rx FIFO or Tx Buffer and etc) - number in Message RAM is also configurable, - so this property is telling driver how the shared or - private Message RAM are used by this M_CAN controller. - - The format should be as follows: - - The 'offset' is an address offset of the Message RAM - where the following elements start from. This is - usually set to 0x0 if you're using a private Message - RAM. The remain cells are used to specify how many - elements are used for each FIFO/Buffer. - - M_CAN includes the following elements according to user manual: - 11-bit Filter 0-128 elements / 0-128 words - 29-bit Filter 0-64 elements / 0-128 words - Rx FIFO 0 0-64 elements / 0-1152 words - Rx FIFO 1 0-64 elements / 0-1152 words - Rx Buffers 0-64 elements / 0-1152 words - Tx Event FIFO 0-32 elements / 0-64 words - Tx Buffers 0-32 elements / 0-576 words - - Please refer to 2.4.1 Message RAM Configuration in - Bosch M_CAN user manual for details. - -Optional Subnode: -- can-transceiver : Can-transceiver subnode describing maximum speed - that can be used for CAN/CAN-FD modes. See - Documentation/devicetree/bindings/net/can/can-transceiver.txt - for details. -Example: -SoC dtsi: -m_can1: can@20e8000 { - compatible = "bosch,m_can"; - reg = <0x020e8000 0x4000>, <0x02298000 0x4000>; - reg-names = "m_can", "message_ram"; - interrupts = <0 114 0x04>, - <0 114 0x04>; - interrupt-names = "int0", "int1"; - clocks = <&clks IMX6SX_CLK_CANFD>, - <&clks IMX6SX_CLK_CANFD>; - clock-names = "hclk", "cclk"; - bosch,mram-cfg = <0x0 0 0 32 0 0 0 1>; -}; - -Board dts: -&m_can1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_m_can1>; - status = "enabled"; - - can-transceiver { - max-bitrate = <5000000>; - }; -}; From 9eb05a5583704bc96aa970b64535c7947d4ed3ac Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Thu, 6 Feb 2020 12:04:57 +0000 Subject: [PATCH 0528/4444] MAINTAINERS: remove myself from DT bindings entry For quite a while Rob has been handling DT binding maintenance, and I haven't had the time to review bindings outside of a few targetted cases. Given that, I think being listed in MAINTAINERS is more misleading than helpful. Signed-off-by: Mark Rutland Cc: Rob Herring Cc: devicetree@vger.kernel.org Signed-off-by: Rob Herring --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 38fe2f3f7b6f..8044aa190bcb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12418,7 +12418,6 @@ F: Documentation/ABI/testing/sysfs-firmware-ofw OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS M: Rob Herring -M: Mark Rutland L: devicetree@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git Q: http://patchwork.ozlabs.org/project/devicetree-bindings/list/ From 1c27e9ae0f69f1947a95b01ab21526204ed6a24c Mon Sep 17 00:00:00 2001 From: Bastian Germann Date: Fri, 14 Feb 2020 12:10:01 +0100 Subject: [PATCH 0529/4444] dt-bindings: Add vendor prefix for Linutronix Add a vendor prefix for Linutronix GmbH. Website: https://linutronix.de/ Co-developed-by: Benedikt Spranger Signed-off-by: Benedikt Spranger Signed-off-by: Bastian Germann Acked-by: Maxime Ripard Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index ac6aa3332b28..9260980bc83a 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -547,6 +547,8 @@ patternProperties: description: LinkSprite Technologies, Inc. "^linksys,.*": description: Belkin International, Inc. (Linksys) + "^linutronix,.*": + description: Linutronix GmbH "^linux,.*": description: Linux-specific binding "^linx,.*": From 5c36abcd2621adc3d50d05628f0ef0be6e7840a9 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 19 Feb 2020 18:35:02 +0100 Subject: [PATCH 0530/4444] ASoC: meson: add t9015 internal codec binding documentation Add the DT binding documention of the internal DAC found in the Amlogic gxl, g12a and sm1 SoC family. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200219173503.1112561-2-jbrunet@baylibre.com Signed-off-by: Mark Brown --- .../bindings/sound/amlogic,t9015.yaml | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/amlogic,t9015.yaml diff --git a/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml b/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml new file mode 100644 index 000000000000..b7c38c2b5b54 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/amlogic,t9015.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic T9015 Internal Audio DAC + +maintainers: + - Jerome Brunet + +properties: + $nodename: + pattern: "^audio-controller@.*" + + "#sound-dai-cells": + const: 0 + + compatible: + items: + - const: amlogic,t9015 + + clocks: + items: + - description: Peripheral clock + + clock-names: + items: + - const: pclk + + reg: + maxItems: 1 + + resets: + maxItems: 1 + +required: + - "#sound-dai-cells" + - compatible + - reg + - clocks + - clock-names + - resets + +examples: + - | + #include + #include + + acodec: audio-controller@32000 { + compatible = "amlogic,t9015"; + reg = <0x0 0x32000 0x0 0x14>; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_AUDIO_CODEC>; + clock-names = "pclk"; + resets = <&reset RESET_AUDIO_CODEC>; + }; + From 33901f5b9b16d212ee58865e9e8e80fc813f12da Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 19 Feb 2020 18:35:03 +0100 Subject: [PATCH 0531/4444] ASoC: meson: add t9015 internal DAC driver Add the codec driver of the internal DAC found on Amlogic gxl, g12a and sm1 family. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200219173503.1112561-3-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/Kconfig | 8 + sound/soc/meson/Makefile | 2 + sound/soc/meson/t9015.c | 333 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 343 insertions(+) create mode 100644 sound/soc/meson/t9015.c diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index 22d2af75b59e..897a706dcda0 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -6,6 +6,7 @@ config SND_MESON_AIU tristate "Amlogic AIU" select SND_MESON_CODEC_GLUE select SND_PCM_IEC958 + imply SND_SOC_MESON_T9015 imply SND_SOC_HDMI_CODEC if DRM_MESON_DW_HDMI help Select Y or M to add support for the Audio output subsystem found @@ -116,4 +117,11 @@ config SND_MESON_G12A_TOHDMITX help Select Y or M to add support for HDMI audio on the g12a SoC family + +config SND_SOC_MESON_T9015 + tristate "Amlogic T9015 DAC" + select REGMAP_MMIO + help + Say Y or M if you want to add support for the internal DAC found + on GXL, G12 and SM1 SoC family. endmenu diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index f9c90c391498..3c9d48846816 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -23,6 +23,7 @@ snd-soc-meson-card-utils-objs := meson-card-utils.o snd-soc-meson-codec-glue-objs := meson-codec-glue.o snd-soc-meson-gx-sound-card-objs := gx-card.o snd-soc-meson-g12a-tohdmitx-objs := g12a-tohdmitx.o +snd-soc-meson-t9015-objs := t9015.o obj-$(CONFIG_SND_MESON_AIU) += snd-soc-meson-aiu.o obj-$(CONFIG_SND_MESON_AXG_FIFO) += snd-soc-meson-axg-fifo.o @@ -40,3 +41,4 @@ obj-$(CONFIG_SND_MESON_CARD_UTILS) += snd-soc-meson-card-utils.o obj-$(CONFIG_SND_MESON_CODEC_GLUE) += snd-soc-meson-codec-glue.o obj-$(CONFIG_SND_MESON_GX_SOUND_CARD) += snd-soc-meson-gx-sound-card.o obj-$(CONFIG_SND_MESON_G12A_TOHDMITX) += snd-soc-meson-g12a-tohdmitx.o +obj-$(CONFIG_SND_SOC_MESON_T9015) += snd-soc-meson-t9015.o diff --git a/sound/soc/meson/t9015.c b/sound/soc/meson/t9015.c new file mode 100644 index 000000000000..56d2592c16d5 --- /dev/null +++ b/sound/soc/meson/t9015.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2020 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include +#include +#include +#include +#include + +#define BLOCK_EN 0x00 +#define LORN_EN 0 +#define LORP_EN 1 +#define LOLN_EN 2 +#define LOLP_EN 3 +#define DACR_EN 4 +#define DACL_EN 5 +#define DACR_INV 20 +#define DACL_INV 21 +#define DACR_SRC 22 +#define DACL_SRC 23 +#define REFP_BUF_EN BIT(12) +#define BIAS_CURRENT_EN BIT(13) +#define VMID_GEN_FAST BIT(14) +#define VMID_GEN_EN BIT(15) +#define I2S_MODE BIT(30) +#define VOL_CTRL0 0x04 +#define GAIN_H 31 +#define GAIN_L 23 +#define VOL_CTRL1 0x08 +#define DAC_MONO 8 +#define RAMP_RATE 10 +#define VC_RAMP_MODE 12 +#define MUTE_MODE 13 +#define UNMUTE_MODE 14 +#define DAC_SOFT_MUTE 15 +#define DACR_VC 16 +#define DACL_VC 24 +#define LINEOUT_CFG 0x0c +#define LORN_POL 0 +#define LORP_POL 4 +#define LOLN_POL 8 +#define LOLP_POL 12 +#define POWER_CFG 0x10 + +struct t9015 { + struct clk *pclk; + struct regulator *avdd; +}; + +static int t9015_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_component *component = dai->component; + unsigned int val; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + val = I2S_MODE; + break; + + case SND_SOC_DAIFMT_CBS_CFS: + val = 0; + break; + + default: + return -EINVAL; + } + + snd_soc_component_update_bits(component, BLOCK_EN, I2S_MODE, val); + + if (((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S) && + ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_LEFT_J)) + return -EINVAL; + + return 0; +} + +static const struct snd_soc_dai_ops t9015_dai_ops = { + .set_fmt = t9015_dai_set_fmt, +}; + +static struct snd_soc_dai_driver t9015_dai = { + .name = "t9015-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = (SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S20_LE | + SNDRV_PCM_FMTBIT_S24_LE), + }, + .ops = &t9015_dai_ops, +}; + +static const DECLARE_TLV_DB_MINMAX_MUTE(dac_vol_tlv, -9525, 0); + +static const char * const ramp_rate_txt[] = { "Fast", "Slow" }; +static SOC_ENUM_SINGLE_DECL(ramp_rate_enum, VOL_CTRL1, RAMP_RATE, + ramp_rate_txt); + +static const char * const dacr_in_txt[] = { "Right", "Left" }; +static SOC_ENUM_SINGLE_DECL(dacr_in_enum, BLOCK_EN, DACR_SRC, dacr_in_txt); + +static const char * const dacl_in_txt[] = { "Left", "Right" }; +static SOC_ENUM_SINGLE_DECL(dacl_in_enum, BLOCK_EN, DACL_SRC, dacl_in_txt); + +static const char * const mono_txt[] = { "Stereo", "Mono"}; +static SOC_ENUM_SINGLE_DECL(mono_enum, VOL_CTRL1, DAC_MONO, mono_txt); + +static const struct snd_kcontrol_new t9015_snd_controls[] = { + /* Volume Controls */ + SOC_ENUM("Playback Channel Mode", mono_enum), + SOC_SINGLE("Playback Switch", VOL_CTRL1, DAC_SOFT_MUTE, 1, 1), + SOC_DOUBLE_TLV("Playback Volume", VOL_CTRL1, DACL_VC, DACR_VC, + 0xff, 0, dac_vol_tlv), + + /* Ramp Controls */ + SOC_ENUM("Ramp Rate", ramp_rate_enum), + SOC_SINGLE("Volume Ramp Switch", VOL_CTRL1, VC_RAMP_MODE, 1, 0), + SOC_SINGLE("Mute Ramp Switch", VOL_CTRL1, MUTE_MODE, 1, 0), + SOC_SINGLE("Unmute Ramp Switch", VOL_CTRL1, UNMUTE_MODE, 1, 0), +}; + +static const struct snd_kcontrol_new t9015_right_dac_mux = + SOC_DAPM_ENUM("Right DAC Source", dacr_in_enum); +static const struct snd_kcontrol_new t9015_left_dac_mux = + SOC_DAPM_ENUM("Left DAC Source", dacl_in_enum); + +static const struct snd_soc_dapm_widget t9015_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("Right IN", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("Left IN", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_MUX("Right DAC Sel", SND_SOC_NOPM, 0, 0, + &t9015_right_dac_mux), + SND_SOC_DAPM_MUX("Left DAC Sel", SND_SOC_NOPM, 0, 0, + &t9015_left_dac_mux), + SND_SOC_DAPM_DAC("Right DAC", NULL, BLOCK_EN, DACR_EN, 0), + SND_SOC_DAPM_DAC("Left DAC", NULL, BLOCK_EN, DACL_EN, 0), + SND_SOC_DAPM_OUT_DRV("Right- Driver", BLOCK_EN, LORN_EN, 0, + NULL, 0), + SND_SOC_DAPM_OUT_DRV("Right+ Driver", BLOCK_EN, LORP_EN, 0, + NULL, 0), + SND_SOC_DAPM_OUT_DRV("Left- Driver", BLOCK_EN, LOLN_EN, 0, + NULL, 0), + SND_SOC_DAPM_OUT_DRV("Left+ Driver", BLOCK_EN, LOLP_EN, 0, + NULL, 0), + SND_SOC_DAPM_OUTPUT("LORN"), + SND_SOC_DAPM_OUTPUT("LORP"), + SND_SOC_DAPM_OUTPUT("LOLN"), + SND_SOC_DAPM_OUTPUT("LOLP"), +}; + +static const struct snd_soc_dapm_route t9015_dapm_routes[] = { + { "Right IN", NULL, "Playback" }, + { "Left IN", NULL, "Playback" }, + { "Right DAC Sel", "Right", "Right IN" }, + { "Right DAC Sel", "Left", "Left IN" }, + { "Left DAC Sel", "Right", "Right IN" }, + { "Left DAC Sel", "Left", "Left IN" }, + { "Right DAC", NULL, "Right DAC Sel" }, + { "Left DAC", NULL, "Left DAC Sel" }, + { "Right- Driver", NULL, "Right DAC" }, + { "Right+ Driver", NULL, "Right DAC" }, + { "Left- Driver", NULL, "Left DAC" }, + { "Left+ Driver", NULL, "Left DAC" }, + { "LORN", NULL, "Right- Driver", }, + { "LORP", NULL, "Right+ Driver", }, + { "LOLN", NULL, "Left- Driver", }, + { "LOLP", NULL, "Left+ Driver", }, +}; + +static int t9015_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + struct t9015 *priv = snd_soc_component_get_drvdata(component); + enum snd_soc_bias_level now = + snd_soc_component_get_bias_level(component); + int ret; + + switch (level) { + case SND_SOC_BIAS_ON: + snd_soc_component_update_bits(component, BLOCK_EN, + BIAS_CURRENT_EN, + BIAS_CURRENT_EN); + break; + case SND_SOC_BIAS_PREPARE: + snd_soc_component_update_bits(component, BLOCK_EN, + BIAS_CURRENT_EN, + 0); + break; + case SND_SOC_BIAS_STANDBY: + ret = regulator_enable(priv->avdd); + if (ret) { + dev_err(component->dev, "AVDD enable failed\n"); + return ret; + } + + if (now == SND_SOC_BIAS_OFF) { + snd_soc_component_update_bits(component, BLOCK_EN, + VMID_GEN_EN | VMID_GEN_FAST | REFP_BUF_EN, + VMID_GEN_EN | VMID_GEN_FAST | REFP_BUF_EN); + + mdelay(200); + snd_soc_component_update_bits(component, BLOCK_EN, + VMID_GEN_FAST, + 0); + } + + break; + case SND_SOC_BIAS_OFF: + snd_soc_component_update_bits(component, BLOCK_EN, + VMID_GEN_EN | VMID_GEN_FAST | REFP_BUF_EN, + 0); + + regulator_disable(priv->avdd); + break; + } + + return 0; +} + +static const struct snd_soc_component_driver t9015_codec_driver = { + .set_bias_level = t9015_set_bias_level, + .controls = t9015_snd_controls, + .num_controls = ARRAY_SIZE(t9015_snd_controls), + .dapm_widgets = t9015_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(t9015_dapm_widgets), + .dapm_routes = t9015_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(t9015_dapm_routes), + .suspend_bias_off = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static const struct regmap_config t9015_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = POWER_CFG, +}; + +static int t9015_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct t9015 *priv; + void __iomem *regs; + struct regmap *regmap; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + platform_set_drvdata(pdev, priv); + + priv->pclk = devm_clk_get(dev, "pclk"); + if (IS_ERR(priv->pclk)) { + if (PTR_ERR(priv->pclk) != -EPROBE_DEFER) + dev_err(dev, "failed to get core clock\n"); + return PTR_ERR(priv->pclk); + } + + priv->avdd = devm_regulator_get(dev, "AVDD"); + if (IS_ERR(priv->avdd)) { + if (PTR_ERR(priv->avdd) != -EPROBE_DEFER) + dev_err(dev, "failed to AVDD\n"); + return PTR_ERR(priv->avdd); + } + + ret = clk_prepare_enable(priv->pclk); + if (ret) { + dev_err(dev, "core clock enable failed\n"); + return ret; + } + + ret = devm_add_action_or_reset(dev, + (void(*)(void *))clk_disable_unprepare, + priv->pclk); + if (ret) + return ret; + + ret = device_reset(dev); + if (ret) { + dev_err(dev, "reset failed\n"); + return ret; + } + + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) { + dev_err(dev, "register map failed\n"); + return PTR_ERR(regs); + } + + regmap = devm_regmap_init_mmio(dev, regs, &t9015_regmap_config); + if (IS_ERR(regmap)) { + dev_err(dev, "regmap init failed\n"); + return PTR_ERR(regmap); + } + + /* + * Initialize output polarity: + * ATM the output polarity is fixed but in the future it might useful + * to add DT property to set this depending on the platform needs + */ + regmap_write(regmap, LINEOUT_CFG, 0x1111); + + return devm_snd_soc_register_component(dev, &t9015_codec_driver, + &t9015_dai, 1); +} + +static const struct of_device_id t9015_ids[] = { + { .compatible = "amlogic,t9015", }, + { } +}; +MODULE_DEVICE_TABLE(of, t9015_ids); + +static struct platform_driver t9015_driver = { + .driver = { + .name = "t9015-codec", + .of_match_table = of_match_ptr(t9015_ids), + }, + .probe = t9015_probe, +}; + +module_platform_driver(t9015_driver); + +MODULE_DESCRIPTION("ASoC Amlogic T9015 codec driver"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("GPL"); From 95e9e205fcbe34d003c558e0a98e6ae6f9ab3a61 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Fri, 7 Feb 2020 13:03:45 +0100 Subject: [PATCH 0532/4444] ASoC: dt-bindings: stm32: convert i2s to json-schema Convert the STM32 I2S bindings to DT schema format using json-schema. Signed-off-by: Olivier Moysan Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20200207120345.24672-1-olivier.moysan@st.com Signed-off-by: Mark Brown --- .../bindings/sound/st,stm32-i2s.txt | 62 ------------- .../bindings/sound/st,stm32-i2s.yaml | 87 +++++++++++++++++++ 2 files changed, 87 insertions(+), 62 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/st,stm32-i2s.txt create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt deleted file mode 100644 index cbf24bcd1b8d..000000000000 --- a/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt +++ /dev/null @@ -1,62 +0,0 @@ -STMicroelectronics STM32 SPI/I2S Controller - -The SPI/I2S block supports I2S/PCM protocols when configured on I2S mode. -Only some SPI instances support I2S. - -Required properties: - - compatible: Must be "st,stm32h7-i2s" - - reg: Offset and length of the device's register set. - - interrupts: Must contain the interrupt line id. - - clocks: Must contain phandle and clock specifier pairs for each entry - in clock-names. - - clock-names: Must contain "i2sclk", "pclk", "x8k" and "x11k". - "i2sclk": clock which feeds the internal clock generator - "pclk": clock which feeds the peripheral bus interface - "x8k": I2S parent clock for sampling rates multiple of 8kHz. - "x11k": I2S parent clock for sampling rates multiple of 11.025kHz. - - dmas: DMA specifiers for tx and rx dma. - See Documentation/devicetree/bindings/dma/stm32-dma.txt. - - dma-names: Identifier for each DMA request line. Must be "tx" and "rx". - - pinctrl-names: should contain only value "default" - - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml - -Optional properties: - - resets: Reference to a reset controller asserting the reset controller - -The device node should contain one 'port' child node with one child 'endpoint' -node, according to the bindings defined in Documentation/devicetree/bindings/ -graph.txt. - -Example: -sound_card { - compatible = "audio-graph-card"; - dais = <&i2s2_port>; -}; - -i2s2: audio-controller@40003800 { - compatible = "st,stm32h7-i2s"; - reg = <0x40003800 0x400>; - interrupts = <36>; - clocks = <&rcc PCLK1>, <&rcc SPI2_CK>, <&rcc PLL1_Q>, <&rcc PLL2_P>; - clock-names = "pclk", "i2sclk", "x8k", "x11k"; - dmas = <&dmamux2 2 39 0x400 0x1>, - <&dmamux2 3 40 0x400 0x1>; - dma-names = "rx", "tx"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_i2s2>; - - i2s2_port: port@0 { - cpu_endpoint: endpoint { - remote-endpoint = <&codec_endpoint>; - format = "i2s"; - }; - }; -}; - -audio-codec { - codec_port: port@0 { - codec_endpoint: endpoint { - remote-endpoint = <&cpu_endpoint>; - }; - }; -}; diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml new file mode 100644 index 000000000000..f32410890589 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml @@ -0,0 +1,87 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/st,stm32-i2s.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectronics STM32 SPI/I2S Controller + +maintainers: + - Olivier Moysan + +description: + The SPI/I2S block supports I2S/PCM protocols when configured on I2S mode. + Only some SPI instances support I2S. + +properties: + compatible: + enum: + - st,stm32h7-i2s + + "#sound-dai-cells": + const: 0 + + reg: + maxItems: 1 + + clocks: + items: + - description: clock feeding the peripheral bus interface. + - description: clock feeding the internal clock generator. + - description: I2S parent clock for sampling rates multiple of 8kHz. + - description: I2S parent clock for sampling rates multiple of 11.025kHz. + + clock-names: + items: + - const: pclk + - const: i2sclk + - const: x8k + - const: x11k + + interrupts: + maxItems: 1 + + dmas: + items: + - description: audio capture DMA. + - description: audio playback DMA. + + dma-names: + items: + - const: rx + - const: tx + + resets: + maxItems: 1 + +required: + - compatible + - "#sound-dai-cells" + - reg + - clocks + - clock-names + - interrupts + - dmas + - dma-names + +additionalProperties: false + +examples: + - | + #include + #include + i2s2: audio-controller@4000b000 { + compatible = "st,stm32h7-i2s"; + #sound-dai-cells = <0>; + reg = <0x4000b000 0x400>; + clocks = <&rcc SPI2>, <&rcc SPI2_K>, <&rcc PLL3_Q>, <&rcc PLL3_R>; + clock-names = "pclk", "i2sclk", "x8k", "x11k"; + interrupts = ; + dmas = <&dmamux1 39 0x400 0x01>, + <&dmamux1 40 0x400 0x01>; + dma-names = "rx", "tx"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s2_pins_a>; + }; + +... From 9d98809711ae0ebcfb8115a0bc54604c59908710 Mon Sep 17 00:00:00 2001 From: Youri Querry Date: Thu, 12 Dec 2019 17:01:13 +0000 Subject: [PATCH 0533/4444] soc: fsl: dpio: Adding QMAN multiple enqueue interface Update of QMAN the interface to enqueue frame. We now support multiple enqueue (qbman_swp_enqueue_multiple) and multiple enqueue with a table of descriptor (qbman_swp_enqueue_multiple_desc). Signed-off-by: Youri Querry Acked-by: Roy Pledge Signed-off-by: Li Yang --- drivers/soc/fsl/dpio/dpio-service.c | 69 ++++++++++++++++++++++-- drivers/soc/fsl/dpio/qbman-portal.c | 83 ++++++++++++++++++++++++----- drivers/soc/fsl/dpio/qbman-portal.h | 24 +++++++++ include/soc/fsl/dpaa2-io.h | 6 ++- 4 files changed, 165 insertions(+), 17 deletions(-) diff --git a/drivers/soc/fsl/dpio/dpio-service.c b/drivers/soc/fsl/dpio/dpio-service.c index 518a8e081b49..cd4f6410e8c2 100644 --- a/drivers/soc/fsl/dpio/dpio-service.c +++ b/drivers/soc/fsl/dpio/dpio-service.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright 2014-2016 Freescale Semiconductor Inc. - * Copyright 2016 NXP + * Copyright 2016-2019 NXP * */ #include @@ -432,6 +432,69 @@ int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, } EXPORT_SYMBOL(dpaa2_io_service_enqueue_fq); +/** + * dpaa2_io_service_enqueue_multiple_fq() - Enqueue multiple frames + * to a frame queue using one fqid. + * @d: the given DPIO service. + * @fqid: the given frame queue id. + * @fd: the frame descriptor which is enqueued. + * @nb: number of frames to be enqueud + * + * Return 0 for successful enqueue, -EBUSY if the enqueue ring is not ready, + * or -ENODEV if there is no dpio service. + */ +int dpaa2_io_service_enqueue_multiple_fq(struct dpaa2_io *d, + u32 fqid, + const struct dpaa2_fd *fd, + int nb) +{ + struct qbman_eq_desc ed; + + d = service_select(d); + if (!d) + return -ENODEV; + + qbman_eq_desc_clear(&ed); + qbman_eq_desc_set_no_orp(&ed, 0); + qbman_eq_desc_set_fq(&ed, fqid); + + return qbman_swp_enqueue_multiple(d->swp, &ed, fd, 0, nb); +} +EXPORT_SYMBOL(dpaa2_io_service_enqueue_multiple_fq); + +/** + * dpaa2_io_service_enqueue_multiple_desc_fq() - Enqueue multiple frames + * to different frame queue using a list of fqids. + * @d: the given DPIO service. + * @fqid: the given list of frame queue ids. + * @fd: the frame descriptor which is enqueued. + * @nb: number of frames to be enqueud + * + * Return 0 for successful enqueue, -EBUSY if the enqueue ring is not ready, + * or -ENODEV if there is no dpio service. + */ +int dpaa2_io_service_enqueue_multiple_desc_fq(struct dpaa2_io *d, + u32 *fqid, + const struct dpaa2_fd *fd, + int nb) +{ + int i; + struct qbman_eq_desc ed[32]; + + d = service_select(d); + if (!d) + return -ENODEV; + + for (i = 0; i < nb; i++) { + qbman_eq_desc_clear(&ed[i]); + qbman_eq_desc_set_no_orp(&ed[i], 0); + qbman_eq_desc_set_fq(&ed[i], fqid[i]); + } + + return qbman_swp_enqueue_multiple_desc(d->swp, &ed[0], fd, nb); +} +EXPORT_SYMBOL(dpaa2_io_service_enqueue_multiple_desc_fq); + /** * dpaa2_io_service_enqueue_qd() - Enqueue a frame to a QD. * @d: the given DPIO service. @@ -526,7 +589,7 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_acquire); /** * dpaa2_io_store_create() - Create the dma memory storage for dequeue result. - * @max_frames: the maximum number of dequeued result for frames, must be <= 16. + * @max_frames: the maximum number of dequeued result for frames, must be <= 32. * @dev: the device to allow mapping/unmapping the DMAable region. * * The size of the storage is "max_frames*sizeof(struct dpaa2_dq)". @@ -541,7 +604,7 @@ struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames, struct dpaa2_io_store *ret; size_t size; - if (!max_frames || (max_frames > 16)) + if (!max_frames || (max_frames > 32)) return NULL; ret = kmalloc(sizeof(*ret), GFP_KERNEL); diff --git a/drivers/soc/fsl/dpio/qbman-portal.c b/drivers/soc/fsl/dpio/qbman-portal.c index c66f5b73777c..5a37ac8a171c 100644 --- a/drivers/soc/fsl/dpio/qbman-portal.c +++ b/drivers/soc/fsl/dpio/qbman-portal.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. - * Copyright 2016 NXP + * Copyright 2016-2019 NXP * */ @@ -12,13 +12,6 @@ #include "qbman-portal.h" -#define QMAN_REV_4000 0x04000000 -#define QMAN_REV_4100 0x04010000 -#define QMAN_REV_4101 0x04010001 -#define QMAN_REV_5000 0x05000000 - -#define QMAN_REV_MASK 0xffff0000 - /* All QBMan command and result structures use this "valid bit" encoding */ #define QB_VALID_BIT ((u32)0x80) @@ -156,7 +149,7 @@ static inline u32 qbman_set_swp_cfg(u8 max_fill, u8 wn, u8 est, u8 rpm, u8 dcm, */ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) { - struct qbman_swp *p = kmalloc(sizeof(*p), GFP_KERNEL); + struct qbman_swp *p = kzalloc(sizeof(*p), GFP_KERNEL); u32 reg; if (!p) @@ -467,22 +460,32 @@ static inline void qbman_write_eqcr_am_rt_register(struct qbman_swp *p, int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d, const struct dpaa2_fd *fd) { - struct qbman_eq_desc *p; + struct qbman_eq_desc_with_fd *p; u32 eqar = qbman_read_register(s, QBMAN_CINH_SWP_EQAR); if (!EQAR_SUCCESS(eqar)) return -EBUSY; p = qbman_get_cmd(s, QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar))); - memcpy(&p->dca, &d->dca, 31); + /* This is mapped as DEVICE type memory, writes are + * with address alignment: + * desc.dca address alignment = 1 + * desc.seqnum address alignment = 2 + * desc.orpid address alignment = 4 + * desc.tgtid address alignment = 8 + */ + p->desc.dca = d->dca; + p->desc.seqnum = d->seqnum; + p->desc.orpid = d->orpid; + memcpy(&p->desc.tgtid, &d->tgtid, 24); memcpy(&p->fd, fd, sizeof(*fd)); if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) { /* Set the verb byte, have to substitute in the valid-bit */ dma_wmb(); - p->verb = d->verb | EQAR_VB(eqar); + p->desc.verb = d->verb | EQAR_VB(eqar); } else { - p->verb = d->verb | EQAR_VB(eqar); + p->desc.verb = d->verb | EQAR_VB(eqar); dma_wmb(); qbman_write_eqcr_am_rt_register(s, EQAR_IDX(eqar)); } @@ -490,6 +493,60 @@ int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d, return 0; } +/** + * qbman_swp_enqueue_multiple() - Issue a multi enqueue command + * using one enqueue descriptor + * @s: the software portal used for enqueue + * @d: the enqueue descriptor + * @fd: table pointer of frame descriptor table to be enqueued + * @flags: table pointer of flags, not used for the moment + * @num_frames: number of fd to be enqueued + * + * Return the number of fd enqueued, or a negative error number. + */ +int qbman_swp_enqueue_multiple(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd, + uint32_t *flags, + int num_frames) +{ + int count = 0; + + while (count < num_frames) { + if (qbman_swp_enqueue(s, d, fd) != 0) + break; + count++; + } + + return count; +} + +/** + * qbman_swp_enqueue_multiple_desc() - Issue a multi enqueue command + * using multiple enqueue descriptor + * @s: the software portal used for enqueue + * @d: table of minimal enqueue descriptor + * @fd: table pointer of frame descriptor table to be enqueued + * @num_frames: number of fd to be enqueued + * + * Return the number of fd enqueued, or a negative error number. + */ +int qbman_swp_enqueue_multiple_desc(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd, + int num_frames) +{ + int count = 0; + + while (count < num_frames) { + if (qbman_swp_enqueue(s, &(d[count]), fd) != 0) + break; + count++; + } + + return count; +} + /* Static (push) dequeue */ /** diff --git a/drivers/soc/fsl/dpio/qbman-portal.h b/drivers/soc/fsl/dpio/qbman-portal.h index f3ec5d2044fb..ac58a9741d33 100644 --- a/drivers/soc/fsl/dpio/qbman-portal.h +++ b/drivers/soc/fsl/dpio/qbman-portal.h @@ -9,6 +9,13 @@ #include +#define QMAN_REV_4000 0x04000000 +#define QMAN_REV_4100 0x04010000 +#define QMAN_REV_4101 0x04010001 +#define QMAN_REV_5000 0x05000000 + +#define QMAN_REV_MASK 0xffff0000 + struct dpaa2_dq; struct qbman_swp; @@ -81,6 +88,10 @@ struct qbman_eq_desc { u8 wae; u8 rspid; __le64 rsp_addr; +}; + +struct qbman_eq_desc_with_fd { + struct qbman_eq_desc desc; u8 fd[32]; }; @@ -193,6 +204,19 @@ void *qbman_swp_mc_start(struct qbman_swp *p); void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, u8 cmd_verb); void *qbman_swp_mc_result(struct qbman_swp *p); +int +qbman_swp_enqueue_multiple(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd, + uint32_t *flags, + int num_frames); + +int +qbman_swp_enqueue_multiple_desc(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd, + int num_frames); + /** * qbman_result_is_DQ() - check if the dequeue result is a dequeue response * @dq: the dequeue result to be checked diff --git a/include/soc/fsl/dpaa2-io.h b/include/soc/fsl/dpaa2-io.h index 672cfb58046f..c9d849924f89 100644 --- a/include/soc/fsl/dpaa2-io.h +++ b/include/soc/fsl/dpaa2-io.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ /* * Copyright 2014-2016 Freescale Semiconductor Inc. - * Copyright NXP + * Copyright 2017-2019 NXP * */ #ifndef __FSL_DPAA2_IO_H @@ -109,6 +109,10 @@ int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid, int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, u32 fqid, const struct dpaa2_fd *fd); +int dpaa2_io_service_enqueue_multiple_fq(struct dpaa2_io *d, u32 fqid, + const struct dpaa2_fd *fd, int number_of_frame); +int dpaa2_io_service_enqueue_multiple_desc_fq(struct dpaa2_io *d, u32 *fqid, + const struct dpaa2_fd *fd, int number_of_frame); int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, u32 qdid, u8 prio, u16 qdbin, const struct dpaa2_fd *fd); int dpaa2_io_service_release(struct dpaa2_io *d, u16 bpid, From b46fe745e4f6102fa944383f87f5d8820398f4ad Mon Sep 17 00:00:00 2001 From: Youri Querry Date: Thu, 12 Dec 2019 17:01:15 +0000 Subject: [PATCH 0534/4444] soc: fsl: dpio: QMAN performance improvement with function pointer indirection We are making the access decision in the initialization and setting the function pointers accordingly. Signed-off-by: Youri Querry Acked-by: Roy Pledge Signed-off-by: Li Yang --- drivers/soc/fsl/dpio/qbman-portal.c | 451 ++++++++++++++++++++++++---- drivers/soc/fsl/dpio/qbman-portal.h | 129 +++++++- 2 files changed, 507 insertions(+), 73 deletions(-) diff --git a/drivers/soc/fsl/dpio/qbman-portal.c b/drivers/soc/fsl/dpio/qbman-portal.c index 5a37ac8a171c..0ffe018afb17 100644 --- a/drivers/soc/fsl/dpio/qbman-portal.c +++ b/drivers/soc/fsl/dpio/qbman-portal.c @@ -83,6 +83,82 @@ enum qbman_sdqcr_fc { qbman_sdqcr_fc_up_to_3 = 1 }; +/* Internal Function declaration */ +static int qbman_swp_enqueue_direct(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd); +static int qbman_swp_enqueue_mem_back(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd); +static int qbman_swp_enqueue_multiple_direct(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd, + uint32_t *flags, + int num_frames); +static int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd, + uint32_t *flags, + int num_frames); +static int +qbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd, + int num_frames); +static +int qbman_swp_enqueue_multiple_desc_mem_back(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd, + int num_frames); +static int qbman_swp_pull_direct(struct qbman_swp *s, + struct qbman_pull_desc *d); +static int qbman_swp_pull_mem_back(struct qbman_swp *s, + struct qbman_pull_desc *d); + +const struct dpaa2_dq *qbman_swp_dqrr_next_direct(struct qbman_swp *s); +const struct dpaa2_dq *qbman_swp_dqrr_next_mem_back(struct qbman_swp *s); + +static int qbman_swp_release_direct(struct qbman_swp *s, + const struct qbman_release_desc *d, + const u64 *buffers, + unsigned int num_buffers); +static int qbman_swp_release_mem_back(struct qbman_swp *s, + const struct qbman_release_desc *d, + const u64 *buffers, + unsigned int num_buffers); + +/* Function pointers */ +int (*qbman_swp_enqueue_ptr)(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd) + = qbman_swp_enqueue_direct; + +int (*qbman_swp_enqueue_multiple_ptr)(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd, + uint32_t *flags, + int num_frames) + = qbman_swp_enqueue_multiple_direct; + +int +(*qbman_swp_enqueue_multiple_desc_ptr)(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd, + int num_frames) + = qbman_swp_enqueue_multiple_desc_direct; + +int (*qbman_swp_pull_ptr)(struct qbman_swp *s, struct qbman_pull_desc *d) + = qbman_swp_pull_direct; + +const struct dpaa2_dq *(*qbman_swp_dqrr_next_ptr)(struct qbman_swp *s) + = qbman_swp_dqrr_next_direct; + +int (*qbman_swp_release_ptr)(struct qbman_swp *s, + const struct qbman_release_desc *d, + const u64 *buffers, + unsigned int num_buffers) + = qbman_swp_release_direct; + /* Portal Access */ static inline u32 qbman_read_register(struct qbman_swp *p, u32 offset) @@ -218,6 +294,19 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) * applied when dequeues from a specific channel are enabled. */ qbman_write_register(p, QBMAN_CINH_SWP_SDQCR, 0); + + if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000) { + qbman_swp_enqueue_ptr = + qbman_swp_enqueue_mem_back; + qbman_swp_enqueue_multiple_ptr = + qbman_swp_enqueue_multiple_mem_back; + qbman_swp_enqueue_multiple_desc_ptr = + qbman_swp_enqueue_multiple_desc_mem_back; + qbman_swp_pull_ptr = qbman_swp_pull_mem_back; + qbman_swp_dqrr_next_ptr = qbman_swp_dqrr_next_mem_back; + qbman_swp_release_ptr = qbman_swp_release_mem_back; + } + return p; } @@ -447,7 +536,7 @@ static inline void qbman_write_eqcr_am_rt_register(struct qbman_swp *p, } /** - * qbman_swp_enqueue() - Issue an enqueue command + * qbman_swp_enqueue_direct() - Issue an enqueue command * @s: the software portal used for enqueue * @d: the enqueue descriptor * @fd: the frame descriptor to be enqueued @@ -457,7 +546,7 @@ static inline void qbman_write_eqcr_am_rt_register(struct qbman_swp *p, * * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready. */ -int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d, +int qbman_swp_enqueue_direct(struct qbman_swp *s, const struct qbman_eq_desc *d, const struct dpaa2_fd *fd) { struct qbman_eq_desc_with_fd *p; @@ -480,21 +569,57 @@ int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d, memcpy(&p->desc.tgtid, &d->tgtid, 24); memcpy(&p->fd, fd, sizeof(*fd)); - if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) { - /* Set the verb byte, have to substitute in the valid-bit */ - dma_wmb(); - p->desc.verb = d->verb | EQAR_VB(eqar); - } else { - p->desc.verb = d->verb | EQAR_VB(eqar); - dma_wmb(); - qbman_write_eqcr_am_rt_register(s, EQAR_IDX(eqar)); - } + /* Set the verb byte, have to substitute in the valid-bit */ + dma_wmb(); + p->desc.verb = d->verb | EQAR_VB(eqar); return 0; } /** - * qbman_swp_enqueue_multiple() - Issue a multi enqueue command + * qbman_swp_enqueue_mem_back() - Issue an enqueue command + * @s: the software portal used for enqueue + * @d: the enqueue descriptor + * @fd: the frame descriptor to be enqueued + * + * Please note that 'fd' should only be NULL if the "action" of the + * descriptor is "orp_hole" or "orp_nesn". + * + * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready. + */ +int qbman_swp_enqueue_mem_back(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd) +{ + struct qbman_eq_desc_with_fd *p; + u32 eqar = qbman_read_register(s, QBMAN_CINH_SWP_EQAR); + + if (!EQAR_SUCCESS(eqar)) + return -EBUSY; + + p = qbman_get_cmd(s, QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar))); + /* This is mapped as DEVICE type memory, writes are + * with address alignment: + * desc.dca address alignment = 1 + * desc.seqnum address alignment = 2 + * desc.orpid address alignment = 4 + * desc.tgtid address alignment = 8 + */ + p->desc.dca = d->dca; + p->desc.seqnum = d->seqnum; + p->desc.orpid = d->orpid; + memcpy(&p->desc.tgtid, &d->tgtid, 24); + memcpy(&p->fd, fd, sizeof(*fd)); + + p->desc.verb = d->verb | EQAR_VB(eqar); + dma_wmb(); + qbman_write_eqcr_am_rt_register(s, EQAR_IDX(eqar)); + + return 0; +} + +/** + * qbman_swp_enqueue_multiple_direct() - Issue a multi enqueue command * using one enqueue descriptor * @s: the software portal used for enqueue * @d: the enqueue descriptor @@ -504,16 +629,16 @@ int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d, * * Return the number of fd enqueued, or a negative error number. */ -int qbman_swp_enqueue_multiple(struct qbman_swp *s, - const struct qbman_eq_desc *d, - const struct dpaa2_fd *fd, - uint32_t *flags, - int num_frames) +int qbman_swp_enqueue_multiple_direct(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd, + uint32_t *flags, + int num_frames) { int count = 0; while (count < num_frames) { - if (qbman_swp_enqueue(s, d, fd) != 0) + if (qbman_swp_enqueue_direct(s, d, fd) != 0) break; count++; } @@ -522,7 +647,35 @@ int qbman_swp_enqueue_multiple(struct qbman_swp *s, } /** - * qbman_swp_enqueue_multiple_desc() - Issue a multi enqueue command + * qbman_swp_enqueue_multiple_mem_back() - Issue a multi enqueue command + * using one enqueue descriptor + * @s: the software portal used for enqueue + * @d: the enqueue descriptor + * @fd: table pointer of frame descriptor table to be enqueued + * @flags: table pointer of flags, not used for the moment + * @num_frames: number of fd to be enqueued + * + * Return the number of fd enqueued, or a negative error number. + */ +int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd, + uint32_t *flags, + int num_frames) +{ + int count = 0; + + while (count < num_frames) { + if (qbman_swp_enqueue_mem_back(s, d, fd) != 0) + break; + count++; + } + + return count; +} + +/** + * qbman_swp_enqueue_multiple_desc_direct() - Issue a multi enqueue command * using multiple enqueue descriptor * @s: the software portal used for enqueue * @d: table of minimal enqueue descriptor @@ -531,15 +684,41 @@ int qbman_swp_enqueue_multiple(struct qbman_swp *s, * * Return the number of fd enqueued, or a negative error number. */ -int qbman_swp_enqueue_multiple_desc(struct qbman_swp *s, - const struct qbman_eq_desc *d, - const struct dpaa2_fd *fd, - int num_frames) +int qbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd, + int num_frames) { int count = 0; while (count < num_frames) { - if (qbman_swp_enqueue(s, &(d[count]), fd) != 0) + if (qbman_swp_enqueue_direct(s, &(d[count]), fd) != 0) + break; + count++; + } + + return count; +} + +/** + * qbman_swp_enqueue_multiple_desc_mem_back() - Issue a multi enqueue command + * using multiple enqueue descriptor + * @s: the software portal used for enqueue + * @d: table of minimal enqueue descriptor + * @fd: table pointer of frame descriptor table to be enqueued + * @num_frames: number of fd to be enqueued + * + * Return the number of fd enqueued, or a negative error number. + */ +int qbman_swp_enqueue_multiple_desc_mem_back(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd, + int num_frames) +{ + int count = 0; + + while (count < num_frames) { + if (qbman_swp_enqueue_mem_back(s, &(d[count]), fd) != 0) break; count++; } @@ -702,7 +881,7 @@ void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid, } /** - * qbman_swp_pull() - Issue the pull dequeue command + * qbman_swp_pull_direct() - Issue the pull dequeue command * @s: the software portal object * @d: the software portal descriptor which has been configured with * the set of qbman_pull_desc_set_*() calls @@ -710,7 +889,7 @@ void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid, * Return 0 for success, and -EBUSY if the software portal is not ready * to do pull dequeue. */ -int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d) +int qbman_swp_pull_direct(struct qbman_swp *s, struct qbman_pull_desc *d) { struct qbman_pull_desc *p; @@ -728,18 +907,45 @@ int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d) p->dq_src = d->dq_src; p->rsp_addr = d->rsp_addr; p->rsp_addr_virt = d->rsp_addr_virt; + dma_wmb(); + /* Set the verb byte, have to substitute in the valid-bit */ + p->verb = d->verb | s->vdq.valid_bit; + s->vdq.valid_bit ^= QB_VALID_BIT; - if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) { - dma_wmb(); - /* Set the verb byte, have to substitute in the valid-bit */ - p->verb = d->verb | s->vdq.valid_bit; - s->vdq.valid_bit ^= QB_VALID_BIT; - } else { - p->verb = d->verb | s->vdq.valid_bit; - s->vdq.valid_bit ^= QB_VALID_BIT; - dma_wmb(); - qbman_write_register(s, QBMAN_CINH_SWP_VDQCR_RT, QMAN_RT_MODE); + return 0; +} + +/** + * qbman_swp_pull_mem_back() - Issue the pull dequeue command + * @s: the software portal object + * @d: the software portal descriptor which has been configured with + * the set of qbman_pull_desc_set_*() calls + * + * Return 0 for success, and -EBUSY if the software portal is not ready + * to do pull dequeue. + */ +int qbman_swp_pull_mem_back(struct qbman_swp *s, struct qbman_pull_desc *d) +{ + struct qbman_pull_desc *p; + + if (!atomic_dec_and_test(&s->vdq.available)) { + atomic_inc(&s->vdq.available); + return -EBUSY; } + s->vdq.storage = (void *)(uintptr_t)d->rsp_addr_virt; + if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) + p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR); + else + p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR_MEM); + p->numf = d->numf; + p->tok = QMAN_DQ_TOKEN_VALID; + p->dq_src = d->dq_src; + p->rsp_addr = d->rsp_addr; + p->rsp_addr_virt = d->rsp_addr_virt; + p->verb = d->verb | s->vdq.valid_bit; + s->vdq.valid_bit ^= QB_VALID_BIT; + dma_wmb(); + qbman_write_register(s, QBMAN_CINH_SWP_VDQCR_RT, QMAN_RT_MODE); return 0; } @@ -747,14 +953,14 @@ int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d) #define QMAN_DQRR_PI_MASK 0xf /** - * qbman_swp_dqrr_next() - Get an valid DQRR entry + * qbman_swp_dqrr_next_direct() - Get an valid DQRR entry * @s: the software portal object * * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry * only once, so repeated calls can return a sequence of DQRR entries, without * requiring they be consumed immediately or in any particular order. */ -const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s) +const struct dpaa2_dq *qbman_swp_dqrr_next_direct(struct qbman_swp *s) { u32 verb; u32 response_verb; @@ -797,10 +1003,99 @@ const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s) QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx))); } - if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) - p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); - else - p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR_MEM(s->dqrr.next_idx)); + p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); + verb = p->dq.verb; + + /* + * If the valid-bit isn't of the expected polarity, nothing there. Note, + * in the DQRR reset bug workaround, we shouldn't need to skip these + * check, because we've already determined that a new entry is available + * and we've invalidated the cacheline before reading it, so the + * valid-bit behaviour is repaired and should tell us what we already + * knew from reading PI. + */ + if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) { + prefetch(qbman_get_cmd(s, + QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx))); + return NULL; + } + /* + * There's something there. Move "next_idx" attention to the next ring + * entry (and prefetch it) before returning what we found. + */ + s->dqrr.next_idx++; + s->dqrr.next_idx &= s->dqrr.dqrr_size - 1; /* Wrap around */ + if (!s->dqrr.next_idx) + s->dqrr.valid_bit ^= QB_VALID_BIT; + + /* + * If this is the final response to a volatile dequeue command + * indicate that the vdq is available + */ + flags = p->dq.stat; + response_verb = verb & QBMAN_RESULT_MASK; + if ((response_verb == QBMAN_RESULT_DQ) && + (flags & DPAA2_DQ_STAT_VOLATILE) && + (flags & DPAA2_DQ_STAT_EXPIRED)) + atomic_inc(&s->vdq.available); + + prefetch(qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx))); + + return p; +} + +/** + * qbman_swp_dqrr_next_mem_back() - Get an valid DQRR entry + * @s: the software portal object + * + * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry + * only once, so repeated calls can return a sequence of DQRR entries, without + * requiring they be consumed immediately or in any particular order. + */ +const struct dpaa2_dq *qbman_swp_dqrr_next_mem_back(struct qbman_swp *s) +{ + u32 verb; + u32 response_verb; + u32 flags; + struct dpaa2_dq *p; + + /* Before using valid-bit to detect if something is there, we have to + * handle the case of the DQRR reset bug... + */ + if (unlikely(s->dqrr.reset_bug)) { + /* + * We pick up new entries by cache-inhibited producer index, + * which means that a non-coherent mapping would require us to + * invalidate and read *only* once that PI has indicated that + * there's an entry here. The first trip around the DQRR ring + * will be much less efficient than all subsequent trips around + * it... + */ + u8 pi = qbman_read_register(s, QBMAN_CINH_SWP_DQPI) & + QMAN_DQRR_PI_MASK; + + /* there are new entries if pi != next_idx */ + if (pi == s->dqrr.next_idx) + return NULL; + + /* + * if next_idx is/was the last ring index, and 'pi' is + * different, we can disable the workaround as all the ring + * entries have now been DMA'd to so valid-bit checking is + * repaired. Note: this logic needs to be based on next_idx + * (which increments one at a time), rather than on pi (which + * can burst and wrap-around between our snapshots of it). + */ + if (s->dqrr.next_idx == (s->dqrr.dqrr_size - 1)) { + pr_debug("next_idx=%d, pi=%d, clear reset bug\n", + s->dqrr.next_idx, pi); + s->dqrr.reset_bug = 0; + } + prefetch(qbman_get_cmd(s, + QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx))); + } + + p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR_MEM(s->dqrr.next_idx)); verb = p->dq.verb; /* @@ -929,7 +1224,7 @@ void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable) #define RAR_SUCCESS(rar) ((rar) & 0x100) /** - * qbman_swp_release() - Issue a buffer release command + * qbman_swp_release_direct() - Issue a buffer release command * @s: the software portal object * @d: the release descriptor * @buffers: a pointer pointing to the buffer address to be released @@ -937,8 +1232,9 @@ void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable) * * Return 0 for success, -EBUSY if the release command ring is not ready. */ -int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d, - const u64 *buffers, unsigned int num_buffers) +int qbman_swp_release_direct(struct qbman_swp *s, + const struct qbman_release_desc *d, + const u64 *buffers, unsigned int num_buffers) { int i; struct qbman_release_desc *p; @@ -952,28 +1248,59 @@ int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d, return -EBUSY; /* Start the release command */ - if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) - p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR(RAR_IDX(rar))); - else - p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR_MEM(RAR_IDX(rar))); + p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR(RAR_IDX(rar))); + /* Copy the caller's buffer pointers to the command */ for (i = 0; i < num_buffers; i++) p->buf[i] = cpu_to_le64(buffers[i]); p->bpid = d->bpid; - if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) { - /* - * Set the verb byte, have to substitute in the valid-bit - * and the number of buffers. - */ - dma_wmb(); - p->verb = d->verb | RAR_VB(rar) | num_buffers; - } else { - p->verb = d->verb | RAR_VB(rar) | num_buffers; - dma_wmb(); - qbman_write_register(s, QBMAN_CINH_SWP_RCR_AM_RT + - RAR_IDX(rar) * 4, QMAN_RT_MODE); - } + /* + * Set the verb byte, have to substitute in the valid-bit + * and the number of buffers. + */ + dma_wmb(); + p->verb = d->verb | RAR_VB(rar) | num_buffers; + + return 0; +} + +/** + * qbman_swp_release_mem_back() - Issue a buffer release command + * @s: the software portal object + * @d: the release descriptor + * @buffers: a pointer pointing to the buffer address to be released + * @num_buffers: number of buffers to be released, must be less than 8 + * + * Return 0 for success, -EBUSY if the release command ring is not ready. + */ +int qbman_swp_release_mem_back(struct qbman_swp *s, + const struct qbman_release_desc *d, + const u64 *buffers, unsigned int num_buffers) +{ + int i; + struct qbman_release_desc *p; + u32 rar; + + if (!num_buffers || (num_buffers > 7)) + return -EINVAL; + + rar = qbman_read_register(s, QBMAN_CINH_SWP_RAR); + if (!RAR_SUCCESS(rar)) + return -EBUSY; + + /* Start the release command */ + p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR_MEM(RAR_IDX(rar))); + + /* Copy the caller's buffer pointers to the command */ + for (i = 0; i < num_buffers; i++) + p->buf[i] = cpu_to_le64(buffers[i]); + p->bpid = d->bpid; + + p->verb = d->verb | RAR_VB(rar) | num_buffers; + dma_wmb(); + qbman_write_register(s, QBMAN_CINH_SWP_RCR_AM_RT + + RAR_IDX(rar) * 4, QMAN_RT_MODE); return 0; } diff --git a/drivers/soc/fsl/dpio/qbman-portal.h b/drivers/soc/fsl/dpio/qbman-portal.h index ac58a9741d33..3b3fb86d180b 100644 --- a/drivers/soc/fsl/dpio/qbman-portal.h +++ b/drivers/soc/fsl/dpio/qbman-portal.h @@ -145,6 +145,33 @@ struct qbman_swp { } dqrr; }; +/* Function pointers */ +extern +int (*qbman_swp_enqueue_ptr)(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd); +extern +int (*qbman_swp_enqueue_multiple_ptr)(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd, + uint32_t *flags, + int num_frames); +extern +int (*qbman_swp_enqueue_multiple_desc_ptr)(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd, + int num_frames); +extern +int (*qbman_swp_pull_ptr)(struct qbman_swp *s, struct qbman_pull_desc *d); +extern +const struct dpaa2_dq *(*qbman_swp_dqrr_next_ptr)(struct qbman_swp *s); +extern +int (*qbman_swp_release_ptr)(struct qbman_swp *s, + const struct qbman_release_desc *d, + const u64 *buffers, + unsigned int num_buffers); + +/* Functions */ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d); void qbman_swp_finish(struct qbman_swp *p); u32 qbman_swp_interrupt_read_status(struct qbman_swp *p); @@ -169,9 +196,6 @@ void qbman_pull_desc_set_wq(struct qbman_pull_desc *d, u32 wqid, void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid, enum qbman_pull_type_e dct); -int qbman_swp_pull(struct qbman_swp *p, struct qbman_pull_desc *d); - -const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s); void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct dpaa2_dq *dq); int qbman_result_has_new_result(struct qbman_swp *p, const struct dpaa2_dq *dq); @@ -183,15 +207,11 @@ void qbman_eq_desc_set_fq(struct qbman_eq_desc *d, u32 fqid); void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, u32 qdid, u32 qd_bin, u32 qd_prio); -int qbman_swp_enqueue(struct qbman_swp *p, const struct qbman_eq_desc *d, - const struct dpaa2_fd *fd); void qbman_release_desc_clear(struct qbman_release_desc *d); void qbman_release_desc_set_bpid(struct qbman_release_desc *d, u16 bpid); void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable); -int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d, - const u64 *buffers, unsigned int num_buffers); int qbman_swp_acquire(struct qbman_swp *s, u16 bpid, u64 *buffers, unsigned int num_buffers); int qbman_swp_alt_fq_state(struct qbman_swp *s, u32 fqid, @@ -204,18 +224,60 @@ void *qbman_swp_mc_start(struct qbman_swp *p); void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, u8 cmd_verb); void *qbman_swp_mc_result(struct qbman_swp *p); -int +/** + * qbman_swp_enqueue() - Issue an enqueue command + * @s: the software portal used for enqueue + * @d: the enqueue descriptor + * @fd: the frame descriptor to be enqueued + * + * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready. + */ +static inline int +qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd) +{ + return qbman_swp_enqueue_ptr(s, d, fd); +} + +/** + * qbman_swp_enqueue_multiple() - Issue a multi enqueue command + * using one enqueue descriptor + * @s: the software portal used for enqueue + * @d: the enqueue descriptor + * @fd: table pointer of frame descriptor table to be enqueued + * @flags: table pointer of QBMAN_ENQUEUE_FLAG_DCA flags, not used if NULL + * @num_frames: number of fd to be enqueued + * + * Return the number of fd enqueued, or a negative error number. + */ +static inline int qbman_swp_enqueue_multiple(struct qbman_swp *s, const struct qbman_eq_desc *d, const struct dpaa2_fd *fd, uint32_t *flags, - int num_frames); + int num_frames) +{ + return qbman_swp_enqueue_multiple_ptr(s, d, fd, flags, num_frames); +} -int +/** + * qbman_swp_enqueue_multiple_desc() - Issue a multi enqueue command + * using multiple enqueue descriptor + * @s: the software portal used for enqueue + * @d: table of minimal enqueue descriptor + * @fd: table pointer of frame descriptor table to be enqueued + * @num_frames: number of fd to be enqueued + * + * Return the number of fd enqueued, or a negative error number. + */ +static inline int qbman_swp_enqueue_multiple_desc(struct qbman_swp *s, const struct qbman_eq_desc *d, const struct dpaa2_fd *fd, - int num_frames); + int num_frames) +{ + return qbman_swp_enqueue_multiple_desc_ptr(s, d, fd, num_frames); +} /** * qbman_result_is_DQ() - check if the dequeue result is a dequeue response @@ -528,4 +590,49 @@ int qbman_bp_query(struct qbman_swp *s, u16 bpid, u32 qbman_bp_info_num_free_bufs(struct qbman_bp_query_rslt *a); +/** + * qbman_swp_release() - Issue a buffer release command + * @s: the software portal object + * @d: the release descriptor + * @buffers: a pointer pointing to the buffer address to be released + * @num_buffers: number of buffers to be released, must be less than 8 + * + * Return 0 for success, -EBUSY if the release command ring is not ready. + */ +static inline int qbman_swp_release(struct qbman_swp *s, + const struct qbman_release_desc *d, + const u64 *buffers, + unsigned int num_buffers) +{ + return qbman_swp_release_ptr(s, d, buffers, num_buffers); +} + +/** + * qbman_swp_pull() - Issue the pull dequeue command + * @s: the software portal object + * @d: the software portal descriptor which has been configured with + * the set of qbman_pull_desc_set_*() calls + * + * Return 0 for success, and -EBUSY if the software portal is not ready + * to do pull dequeue. + */ +static inline int qbman_swp_pull(struct qbman_swp *s, + struct qbman_pull_desc *d) +{ + return qbman_swp_pull_ptr(s, d); +} + +/** + * qbman_swp_dqrr_next() - Get an valid DQRR entry + * @s: the software portal object + * + * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry + * only once, so repeated calls can return a sequence of DQRR entries, without + * requiring they be consumed immediately or in any particular order. + */ +static inline const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s) +{ + return qbman_swp_dqrr_next_ptr(s); +} + #endif /* __FSL_QBMAN_PORTAL_H */ From 3b2abda7d28c69f564c1157b9b9c21ef40092ee9 Mon Sep 17 00:00:00 2001 From: Youri Querry Date: Thu, 12 Dec 2019 17:01:18 +0000 Subject: [PATCH 0535/4444] soc: fsl: dpio: Replace QMAN array mode with ring mode enqueue This change of algorithm will enable faster bulk enqueue. This will greatly benefit XDP bulk enqueue. Signed-off-by: Youri Querry Acked-by: Roy Pledge Signed-off-by: Li Yang --- drivers/soc/fsl/dpio/qbman-portal.c | 410 +++++++++++++++++++++------- drivers/soc/fsl/dpio/qbman-portal.h | 13 + 2 files changed, 328 insertions(+), 95 deletions(-) diff --git a/drivers/soc/fsl/dpio/qbman-portal.c b/drivers/soc/fsl/dpio/qbman-portal.c index 0ffe018afb17..740ee0d19582 100644 --- a/drivers/soc/fsl/dpio/qbman-portal.c +++ b/drivers/soc/fsl/dpio/qbman-portal.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "qbman-portal.h" @@ -21,6 +22,7 @@ /* CINH register offsets */ #define QBMAN_CINH_SWP_EQCR_PI 0x800 +#define QBMAN_CINH_SWP_EQCR_CI 0x840 #define QBMAN_CINH_SWP_EQAR 0x8c0 #define QBMAN_CINH_SWP_CR_RT 0x900 #define QBMAN_CINH_SWP_VDQCR_RT 0x940 @@ -44,6 +46,8 @@ #define QBMAN_CENA_SWP_CR 0x600 #define QBMAN_CENA_SWP_RR(vb) (0x700 + ((u32)(vb) >> 1)) #define QBMAN_CENA_SWP_VDQCR 0x780 +#define QBMAN_CENA_SWP_EQCR_CI 0x840 +#define QBMAN_CENA_SWP_EQCR_CI_MEMBACK 0x1840 /* CENA register offsets in memory-backed mode */ #define QBMAN_CENA_SWP_DQRR_MEM(n) (0x800 + ((u32)(n) << 6)) @@ -71,6 +75,12 @@ /* opaque token for static dequeues */ #define QMAN_SDQCR_TOKEN 0xbb +#define QBMAN_EQCR_DCA_IDXMASK 0x0f +#define QBMAN_ENQUEUE_FLAG_DCA (1ULL << 31) + +#define EQ_DESC_SIZE_WITHOUT_FD 29 +#define EQ_DESC_SIZE_FD_START 32 + enum qbman_sdqcr_dct { qbman_sdqcr_dct_null = 0, qbman_sdqcr_dct_prio_ics, @@ -215,6 +225,15 @@ static inline u32 qbman_set_swp_cfg(u8 max_fill, u8 wn, u8 est, u8 rpm, u8 dcm, #define QMAN_RT_MODE 0x00000100 +static inline u8 qm_cyc_diff(u8 ringsize, u8 first, u8 last) +{ + /* 'first' is included, 'last' is excluded */ + if (first <= last) + return last - first; + else + return (2 * ringsize) - (first - last); +} + /** * qbman_swp_init() - Create a functional object representing the given * QBMan portal descriptor. @@ -227,6 +246,10 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) { struct qbman_swp *p = kzalloc(sizeof(*p), GFP_KERNEL); u32 reg; + u32 mask_size; + u32 eqcr_pi; + + spin_lock_init(&p->access_spinlock); if (!p) return NULL; @@ -255,25 +278,38 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) p->addr_cena = d->cena_bar; p->addr_cinh = d->cinh_bar; - if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000) - memset(p->addr_cena, 0, 64 * 1024); + if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) { - reg = qbman_set_swp_cfg(p->dqrr.dqrr_size, - 1, /* Writes Non-cacheable */ - 0, /* EQCR_CI stashing threshold */ - 3, /* RPM: Valid bit mode, RCR in array mode */ - 2, /* DCM: Discrete consumption ack mode */ - 3, /* EPM: Valid bit mode, EQCR in array mode */ - 1, /* mem stashing drop enable == TRUE */ - 1, /* mem stashing priority == TRUE */ - 1, /* mem stashing enable == TRUE */ - 1, /* dequeue stashing priority == TRUE */ - 0, /* dequeue stashing enable == FALSE */ - 0); /* EQCR_CI stashing priority == FALSE */ - if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000) + reg = qbman_set_swp_cfg(p->dqrr.dqrr_size, + 1, /* Writes Non-cacheable */ + 0, /* EQCR_CI stashing threshold */ + 3, /* RPM: RCR in array mode */ + 2, /* DCM: Discrete consumption ack */ + 2, /* EPM: EQCR in ring mode */ + 1, /* mem stashing drop enable enable */ + 1, /* mem stashing priority enable */ + 1, /* mem stashing enable */ + 1, /* dequeue stashing priority enable */ + 0, /* dequeue stashing enable enable */ + 0); /* EQCR_CI stashing priority enable */ + } else { + memset(p->addr_cena, 0, 64 * 1024); + reg = qbman_set_swp_cfg(p->dqrr.dqrr_size, + 1, /* Writes Non-cacheable */ + 1, /* EQCR_CI stashing threshold */ + 3, /* RPM: RCR in array mode */ + 2, /* DCM: Discrete consumption ack */ + 0, /* EPM: EQCR in ring mode */ + 1, /* mem stashing drop enable */ + 1, /* mem stashing priority enable */ + 1, /* mem stashing enable */ + 1, /* dequeue stashing priority enable */ + 0, /* dequeue stashing enable */ + 0); /* EQCR_CI stashing priority enable */ reg |= 1 << SWP_CFG_CPBS_SHIFT | /* memory-backed mode */ 1 << SWP_CFG_VPM_SHIFT | /* VDQCR read triggered mode */ 1 << SWP_CFG_CPM_SHIFT; /* CR read triggered mode */ + } qbman_write_register(p, QBMAN_CINH_SWP_CFG, reg); reg = qbman_read_register(p, QBMAN_CINH_SWP_CFG); @@ -295,7 +331,9 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) */ qbman_write_register(p, QBMAN_CINH_SWP_SDQCR, 0); + p->eqcr.pi_ring_size = 8; if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000) { + p->eqcr.pi_ring_size = 32; qbman_swp_enqueue_ptr = qbman_swp_enqueue_mem_back; qbman_swp_enqueue_multiple_ptr = @@ -307,6 +345,15 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) qbman_swp_release_ptr = qbman_swp_release_mem_back; } + for (mask_size = p->eqcr.pi_ring_size; mask_size > 0; mask_size >>= 1) + p->eqcr.pi_ci_mask = (p->eqcr.pi_ci_mask << 1) + 1; + eqcr_pi = qbman_read_register(p, QBMAN_CINH_SWP_EQCR_PI); + p->eqcr.pi = eqcr_pi & p->eqcr.pi_ci_mask; + p->eqcr.pi_vb = eqcr_pi & QB_VALID_BIT; + p->eqcr.ci = qbman_read_register(p, QBMAN_CINH_SWP_EQCR_CI) + & p->eqcr.pi_ci_mask; + p->eqcr.available = p->eqcr.pi_ring_size; + return p; } @@ -460,6 +507,7 @@ enum qb_enqueue_commands { #define QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT 2 #define QB_ENQUEUE_CMD_IRQ_ON_DISPATCH_SHIFT 3 #define QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT 4 +#define QB_ENQUEUE_CMD_DCA_EN_SHIFT 7 /** * qbman_eq_desc_clear() - Clear the contents of a descriptor to @@ -535,6 +583,7 @@ static inline void qbman_write_eqcr_am_rt_register(struct qbman_swp *p, QMAN_RT_MODE); } +#define QB_RT_BIT ((u32)0x100) /** * qbman_swp_enqueue_direct() - Issue an enqueue command * @s: the software portal used for enqueue @@ -546,34 +595,19 @@ static inline void qbman_write_eqcr_am_rt_register(struct qbman_swp *p, * * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready. */ -int qbman_swp_enqueue_direct(struct qbman_swp *s, const struct qbman_eq_desc *d, - const struct dpaa2_fd *fd) +static +int qbman_swp_enqueue_direct(struct qbman_swp *s, + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd) { - struct qbman_eq_desc_with_fd *p; - u32 eqar = qbman_read_register(s, QBMAN_CINH_SWP_EQAR); + int flags = 0; + int ret = qbman_swp_enqueue_multiple_direct(s, d, fd, &flags, 1); - if (!EQAR_SUCCESS(eqar)) - return -EBUSY; - - p = qbman_get_cmd(s, QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar))); - /* This is mapped as DEVICE type memory, writes are - * with address alignment: - * desc.dca address alignment = 1 - * desc.seqnum address alignment = 2 - * desc.orpid address alignment = 4 - * desc.tgtid address alignment = 8 - */ - p->desc.dca = d->dca; - p->desc.seqnum = d->seqnum; - p->desc.orpid = d->orpid; - memcpy(&p->desc.tgtid, &d->tgtid, 24); - memcpy(&p->fd, fd, sizeof(*fd)); - - /* Set the verb byte, have to substitute in the valid-bit */ - dma_wmb(); - p->desc.verb = d->verb | EQAR_VB(eqar); - - return 0; + if (ret >= 0) + ret = 0; + else + ret = -EBUSY; + return ret; } /** @@ -587,35 +621,19 @@ int qbman_swp_enqueue_direct(struct qbman_swp *s, const struct qbman_eq_desc *d, * * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready. */ +static int qbman_swp_enqueue_mem_back(struct qbman_swp *s, const struct qbman_eq_desc *d, const struct dpaa2_fd *fd) { - struct qbman_eq_desc_with_fd *p; - u32 eqar = qbman_read_register(s, QBMAN_CINH_SWP_EQAR); + int flags = 0; + int ret = qbman_swp_enqueue_multiple_mem_back(s, d, fd, &flags, 1); - if (!EQAR_SUCCESS(eqar)) - return -EBUSY; - - p = qbman_get_cmd(s, QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar))); - /* This is mapped as DEVICE type memory, writes are - * with address alignment: - * desc.dca address alignment = 1 - * desc.seqnum address alignment = 2 - * desc.orpid address alignment = 4 - * desc.tgtid address alignment = 8 - */ - p->desc.dca = d->dca; - p->desc.seqnum = d->seqnum; - p->desc.orpid = d->orpid; - memcpy(&p->desc.tgtid, &d->tgtid, 24); - memcpy(&p->fd, fd, sizeof(*fd)); - - p->desc.verb = d->verb | EQAR_VB(eqar); - dma_wmb(); - qbman_write_eqcr_am_rt_register(s, EQAR_IDX(eqar)); - - return 0; + if (ret >= 0) + ret = 0; + else + ret = -EBUSY; + return ret; } /** @@ -624,26 +642,82 @@ int qbman_swp_enqueue_mem_back(struct qbman_swp *s, * @s: the software portal used for enqueue * @d: the enqueue descriptor * @fd: table pointer of frame descriptor table to be enqueued - * @flags: table pointer of flags, not used for the moment + * @flags: table pointer of QBMAN_ENQUEUE_FLAG_DCA flags, not used if NULL * @num_frames: number of fd to be enqueued * * Return the number of fd enqueued, or a negative error number. */ +static int qbman_swp_enqueue_multiple_direct(struct qbman_swp *s, const struct qbman_eq_desc *d, const struct dpaa2_fd *fd, uint32_t *flags, int num_frames) { - int count = 0; + uint32_t *p = NULL; + const uint32_t *cl = (uint32_t *)d; + uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask; + int i, num_enqueued = 0; + uint64_t addr_cena; - while (count < num_frames) { - if (qbman_swp_enqueue_direct(s, d, fd) != 0) - break; - count++; + spin_lock(&s->access_spinlock); + half_mask = (s->eqcr.pi_ci_mask>>1); + full_mask = s->eqcr.pi_ci_mask; + + if (!s->eqcr.available) { + eqcr_ci = s->eqcr.ci; + p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI; + s->eqcr.ci = qbman_read_register(s, QBMAN_CINH_SWP_EQCR_CI); + + s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size, + eqcr_ci, s->eqcr.ci); + if (!s->eqcr.available) { + spin_unlock(&s->access_spinlock); + return 0; + } } - return count; + eqcr_pi = s->eqcr.pi; + num_enqueued = (s->eqcr.available < num_frames) ? + s->eqcr.available : num_frames; + s->eqcr.available -= num_enqueued; + /* Fill in the EQCR ring */ + for (i = 0; i < num_enqueued; i++) { + p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)); + /* Skip copying the verb */ + memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1); + memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)], + &fd[i], sizeof(*fd)); + eqcr_pi++; + } + + dma_wmb(); + + /* Set the verb byte, have to substitute in the valid-bit */ + eqcr_pi = s->eqcr.pi; + for (i = 0; i < num_enqueued; i++) { + p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)); + p[0] = cl[0] | s->eqcr.pi_vb; + if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) { + struct qbman_eq_desc *d = (struct qbman_eq_desc *)p; + + d->dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) | + ((flags[i]) & QBMAN_EQCR_DCA_IDXMASK); + } + eqcr_pi++; + if (!(eqcr_pi & half_mask)) + s->eqcr.pi_vb ^= QB_VALID_BIT; + } + + /* Flush all the cacheline without load/store in between */ + eqcr_pi = s->eqcr.pi; + addr_cena = (size_t)s->addr_cena; + for (i = 0; i < num_enqueued; i++) + eqcr_pi++; + s->eqcr.pi = eqcr_pi & full_mask; + spin_unlock(&s->access_spinlock); + + return num_enqueued; } /** @@ -652,26 +726,80 @@ int qbman_swp_enqueue_multiple_direct(struct qbman_swp *s, * @s: the software portal used for enqueue * @d: the enqueue descriptor * @fd: table pointer of frame descriptor table to be enqueued - * @flags: table pointer of flags, not used for the moment + * @flags: table pointer of QBMAN_ENQUEUE_FLAG_DCA flags, not used if NULL * @num_frames: number of fd to be enqueued * * Return the number of fd enqueued, or a negative error number. */ +static int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s, - const struct qbman_eq_desc *d, - const struct dpaa2_fd *fd, - uint32_t *flags, - int num_frames) + const struct qbman_eq_desc *d, + const struct dpaa2_fd *fd, + uint32_t *flags, + int num_frames) { - int count = 0; + uint32_t *p = NULL; + const uint32_t *cl = (uint32_t *)(d); + uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask; + int i, num_enqueued = 0; + unsigned long irq_flags; - while (count < num_frames) { - if (qbman_swp_enqueue_mem_back(s, d, fd) != 0) - break; - count++; + spin_lock(&s->access_spinlock); + local_irq_save(irq_flags); + + half_mask = (s->eqcr.pi_ci_mask>>1); + full_mask = s->eqcr.pi_ci_mask; + if (!s->eqcr.available) { + eqcr_ci = s->eqcr.ci; + p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI_MEMBACK; + s->eqcr.ci = __raw_readl(p) & full_mask; + s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size, + eqcr_ci, s->eqcr.ci); + if (!s->eqcr.available) { + local_irq_restore(irq_flags); + spin_unlock(&s->access_spinlock); + return 0; + } } - return count; + eqcr_pi = s->eqcr.pi; + num_enqueued = (s->eqcr.available < num_frames) ? + s->eqcr.available : num_frames; + s->eqcr.available -= num_enqueued; + /* Fill in the EQCR ring */ + for (i = 0; i < num_enqueued; i++) { + p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)); + /* Skip copying the verb */ + memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1); + memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)], + &fd[i], sizeof(*fd)); + eqcr_pi++; + } + + /* Set the verb byte, have to substitute in the valid-bit */ + eqcr_pi = s->eqcr.pi; + for (i = 0; i < num_enqueued; i++) { + p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)); + p[0] = cl[0] | s->eqcr.pi_vb; + if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) { + struct qbman_eq_desc *d = (struct qbman_eq_desc *)p; + + d->dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) | + ((flags[i]) & QBMAN_EQCR_DCA_IDXMASK); + } + eqcr_pi++; + if (!(eqcr_pi & half_mask)) + s->eqcr.pi_vb ^= QB_VALID_BIT; + } + s->eqcr.pi = eqcr_pi & full_mask; + + dma_wmb(); + qbman_write_register(s, QBMAN_CINH_SWP_EQCR_PI, + (QB_RT_BIT)|(s->eqcr.pi)|s->eqcr.pi_vb); + local_irq_restore(irq_flags); + spin_unlock(&s->access_spinlock); + + return num_enqueued; } /** @@ -684,20 +812,66 @@ int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s, * * Return the number of fd enqueued, or a negative error number. */ +static int qbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s, const struct qbman_eq_desc *d, const struct dpaa2_fd *fd, int num_frames) { - int count = 0; + uint32_t *p; + const uint32_t *cl; + uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask; + int i, num_enqueued = 0; + uint64_t addr_cena; - while (count < num_frames) { - if (qbman_swp_enqueue_direct(s, &(d[count]), fd) != 0) - break; - count++; + half_mask = (s->eqcr.pi_ci_mask>>1); + full_mask = s->eqcr.pi_ci_mask; + if (!s->eqcr.available) { + eqcr_ci = s->eqcr.ci; + p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI; + s->eqcr.ci = qbman_read_register(s, QBMAN_CINH_SWP_EQCR_CI); + s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size, + eqcr_ci, s->eqcr.ci); + if (!s->eqcr.available) + return 0; } - return count; + eqcr_pi = s->eqcr.pi; + num_enqueued = (s->eqcr.available < num_frames) ? + s->eqcr.available : num_frames; + s->eqcr.available -= num_enqueued; + /* Fill in the EQCR ring */ + for (i = 0; i < num_enqueued; i++) { + p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)); + cl = (uint32_t *)(&d[i]); + /* Skip copying the verb */ + memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1); + memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)], + &fd[i], sizeof(*fd)); + eqcr_pi++; + } + + dma_wmb(); + + /* Set the verb byte, have to substitute in the valid-bit */ + eqcr_pi = s->eqcr.pi; + for (i = 0; i < num_enqueued; i++) { + p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)); + cl = (uint32_t *)(&d[i]); + p[0] = cl[0] | s->eqcr.pi_vb; + eqcr_pi++; + if (!(eqcr_pi & half_mask)) + s->eqcr.pi_vb ^= QB_VALID_BIT; + } + + /* Flush all the cacheline without load/store in between */ + eqcr_pi = s->eqcr.pi; + addr_cena = (uint64_t)s->addr_cena; + for (i = 0; i < num_enqueued; i++) + eqcr_pi++; + s->eqcr.pi = eqcr_pi & full_mask; + + return num_enqueued; } /** @@ -710,20 +884,62 @@ int qbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s, * * Return the number of fd enqueued, or a negative error number. */ +static int qbman_swp_enqueue_multiple_desc_mem_back(struct qbman_swp *s, const struct qbman_eq_desc *d, const struct dpaa2_fd *fd, int num_frames) { - int count = 0; + uint32_t *p; + const uint32_t *cl; + uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask; + int i, num_enqueued = 0; - while (count < num_frames) { - if (qbman_swp_enqueue_mem_back(s, &(d[count]), fd) != 0) - break; - count++; + half_mask = (s->eqcr.pi_ci_mask>>1); + full_mask = s->eqcr.pi_ci_mask; + if (!s->eqcr.available) { + eqcr_ci = s->eqcr.ci; + p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI_MEMBACK; + s->eqcr.ci = __raw_readl(p) & full_mask; + s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size, + eqcr_ci, s->eqcr.ci); + if (!s->eqcr.available) + return 0; } - return count; + eqcr_pi = s->eqcr.pi; + num_enqueued = (s->eqcr.available < num_frames) ? + s->eqcr.available : num_frames; + s->eqcr.available -= num_enqueued; + /* Fill in the EQCR ring */ + for (i = 0; i < num_enqueued; i++) { + p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)); + cl = (uint32_t *)(&d[i]); + /* Skip copying the verb */ + memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1); + memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)], + &fd[i], sizeof(*fd)); + eqcr_pi++; + } + + /* Set the verb byte, have to substitute in the valid-bit */ + eqcr_pi = s->eqcr.pi; + for (i = 0; i < num_enqueued; i++) { + p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)); + cl = (uint32_t *)(&d[i]); + p[0] = cl[0] | s->eqcr.pi_vb; + eqcr_pi++; + if (!(eqcr_pi & half_mask)) + s->eqcr.pi_vb ^= QB_VALID_BIT; + } + + s->eqcr.pi = eqcr_pi & full_mask; + + dma_wmb(); + qbman_write_register(s, QBMAN_CINH_SWP_EQCR_PI, + (QB_RT_BIT)|(s->eqcr.pi)|s->eqcr.pi_vb); + + return num_enqueued; } /* Static (push) dequeue */ @@ -889,6 +1105,7 @@ void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid, * Return 0 for success, and -EBUSY if the software portal is not ready * to do pull dequeue. */ +static int qbman_swp_pull_direct(struct qbman_swp *s, struct qbman_pull_desc *d) { struct qbman_pull_desc *p; @@ -924,6 +1141,7 @@ int qbman_swp_pull_direct(struct qbman_swp *s, struct qbman_pull_desc *d) * Return 0 for success, and -EBUSY if the software portal is not ready * to do pull dequeue. */ +static int qbman_swp_pull_mem_back(struct qbman_swp *s, struct qbman_pull_desc *d) { struct qbman_pull_desc *p; @@ -942,6 +1160,8 @@ int qbman_swp_pull_mem_back(struct qbman_swp *s, struct qbman_pull_desc *d) p->dq_src = d->dq_src; p->rsp_addr = d->rsp_addr; p->rsp_addr_virt = d->rsp_addr_virt; + + /* Set the verb byte, have to substitute in the valid-bit */ p->verb = d->verb | s->vdq.valid_bit; s->vdq.valid_bit ^= QB_VALID_BIT; dma_wmb(); diff --git a/drivers/soc/fsl/dpio/qbman-portal.h b/drivers/soc/fsl/dpio/qbman-portal.h index 3b3fb86d180b..c7c2225b7d91 100644 --- a/drivers/soc/fsl/dpio/qbman-portal.h +++ b/drivers/soc/fsl/dpio/qbman-portal.h @@ -143,6 +143,19 @@ struct qbman_swp { u8 dqrr_size; int reset_bug; /* indicates dqrr reset workaround is needed */ } dqrr; + + struct { + u32 pi; + u32 pi_vb; + u32 pi_ring_size; + u32 pi_ci_mask; + u32 ci; + int available; + u32 pend; + u32 no_pfdr; + } eqcr; + + spinlock_t access_spinlock; }; /* Function pointers */ From a153182716c0dfbe6d929f32e89a3a2c3399c4b2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 10 Feb 2020 15:04:16 +0100 Subject: [PATCH 0536/4444] dt-bindings: usb: exynos-usb: Document clock names for DWC3 bindings The Exynos DWC3 driver expects certain clock names, depending on used compatible. Document this explicitly in the bindings. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/usb/exynos-usb.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/usb/exynos-usb.txt b/Documentation/devicetree/bindings/usb/exynos-usb.txt index 66c394f9e11f..6aae1544f240 100644 --- a/Documentation/devicetree/bindings/usb/exynos-usb.txt +++ b/Documentation/devicetree/bindings/usb/exynos-usb.txt @@ -78,7 +78,14 @@ Required properties: - ranges: allows valid 1:1 translation between child's address space and parent's address space - clocks: Clock IDs array as required by the controller. - - clock-names: names of clocks correseponding to IDs in the clock property + - clock-names: Names of clocks corresponding to IDs in the clock property. + Following clock names shall be provided for different + compatibles: + - samsung,exynos5250-dwusb3: "usbdrd30", + - samsung,exynos5433-dwusb3: "aclk", "susp_clk", "pipe_pclk", + "phyclk", + - samsung,exynos7-dwusb3: "usbdrd30", "usbdrd30_susp_clk", + "usbdrd30_axius_clk" - vdd10-supply: 1.0V powr supply - vdd33-supply: 3.0V/3.3V power supply From 94d57ebd233a39d4d28fcd4de13a092146da3f4f Mon Sep 17 00:00:00 2001 From: Alexey Minnekhanov Date: Wed, 12 Feb 2020 20:09:12 +0300 Subject: [PATCH 0537/4444] dt-bindings: Add vendor prefix for Xiaomi Xiaomi Corporation is a Chinese electronics company. Signed-off-by: Alexey Minnekhanov Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 9260980bc83a..a97601e0e537 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -1086,6 +1086,8 @@ patternProperties: description: X-Powers "^xes,.*": description: Extreme Engineering Solutions (X-ES) + "^xiaomi,.*": + description: Xiaomi Technology Co., Ltd. "^xillybus,.*": description: Xillybus Ltd. "^xinpeng,.*": From faf8e30acb219849725aa75302d36e0ffdb6a258 Mon Sep 17 00:00:00 2001 From: Alexey Minnekhanov Date: Wed, 12 Feb 2020 20:09:13 +0300 Subject: [PATCH 0538/4444] dt-bindings: arm: Add kryo260 compatible Kryo260 is found in SDM660, so add it in list of cpu compatibles Signed-off-by: Alexey Minnekhanov Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/arm/cpus.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/cpus.yaml b/Documentation/devicetree/bindings/arm/cpus.yaml index 7a9c3ce2dbef..765af3cbd11f 100644 --- a/Documentation/devicetree/bindings/arm/cpus.yaml +++ b/Documentation/devicetree/bindings/arm/cpus.yaml @@ -155,6 +155,7 @@ properties: - nvidia,tegra194-carmel - qcom,krait - qcom,kryo + - qcom,kryo260 - qcom,kryo385 - qcom,kryo485 - qcom,scorpion From b36368f685d66a53da73a05b63af32233e32cf36 Mon Sep 17 00:00:00 2001 From: Ashish Chavan Date: Sun, 9 Feb 2020 15:26:00 +0530 Subject: [PATCH 0539/4444] gpio: rcar: Fix typo in comment "Positive" is spelled incorrectly as "Postive" in comment fix this. Signed-off-by: Ashish Chavan Link: https://lore.kernel.org/r/20200209095600.16394-1-ashish.gschavan@gmail.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-rcar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index f800b250971c..7284473c9fe3 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -116,7 +116,7 @@ static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p, spin_lock_irqsave(&p->lock, flags); - /* Configure postive or negative logic in POSNEG */ + /* Configure positive or negative logic in POSNEG */ gpio_rcar_modify_bit(p, POSNEG, hwirq, !active_high_rising_edge); /* Configure edge or level trigger in EDGLEVEL */ @@ -228,7 +228,7 @@ static void gpio_rcar_config_general_input_output_mode(struct gpio_chip *chip, spin_lock_irqsave(&p->lock, flags); - /* Configure postive logic in POSNEG */ + /* Configure positive logic in POSNEG */ gpio_rcar_modify_bit(p, POSNEG, gpio, false); /* Select "General Input/Output Mode" in IOINTSEL */ From 9d6ee3656a9fbfe906be5ce6f828f1639da1ee7f Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 19 Feb 2020 12:50:48 +0100 Subject: [PATCH 0540/4444] ASoC: dpcm: remove confusing trace in dpcm_get_be() Now that dpcm_get_be() is used in dpcm_end_walk_at_be(), it is not a error if this function does not find a BE for the provided widget. Remove the related dev_err() trace which is confusing since things might be working as expected. When called from dpcm_add_paths(), it is an error if dpcm_get_be() fails to find a BE for the provided widget. The necessary error trace is already done in this case. Fixes: 027a48387183 ("ASoC: soc-pcm: use dpcm_get_be() at dpcm_end_walk_at_be()") Signed-off-by: Jerome Brunet Tested-by: Pierre-Louis Bossart Acked-by: Kuninori Morimoto Cc: Kuninori Morimoto Link: https://lore.kernel.org/r/20200219115048.934678-1-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 63f67eb7c077..aff27c8599ef 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1270,9 +1270,7 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, } } - /* dai link name and stream name set correctly ? */ - dev_err(card->dev, "ASoC: can't get %s BE for %s\n", - stream ? "capture" : "playback", widget->name); + /* Widget provided is not a BE */ return NULL; } From dc7f090d9ab2f36fc404f8d903f806a1b811739e Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 20 Feb 2020 12:56:54 +0000 Subject: [PATCH 0541/4444] ASoC: samsung: Update dependencies for Arizona machine drivers Currently it is possible to get the following bad config: WARNING: unmet direct dependencies detected for SND_SOC_WM5110 Depends on [n]: SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && MFD_WM5110 [=n] commit ea00d95200d0 ("ASoC: Use imply for SND_SOC_ALL_CODECS") commit d8dd3f92a6ba ("ASoC: Fix SND_SOC_ALL_CODECS imply misc fallout") After these two patches the machine drivers still selects the SND_SOC_WM5110 symbol which doesn't take account of the dependency added on the MFD_WM5110 symbol, fix this by also adding a dependency on MFD_WM5110 itself. Reported-by: Randy Dunlap Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20200220125654.7064-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 1a0b163ca47b..112911dc271b 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -151,7 +151,7 @@ config SND_SOC_TOBERMORY config SND_SOC_BELLS tristate "Audio support for Wolfson Bells" - depends on MFD_ARIZONA && I2C && SPI_MASTER + depends on MFD_ARIZONA && MFD_WM5102 && MFD_WM5110 && I2C && SPI_MASTER depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST select SND_SAMSUNG_I2S select SND_SOC_WM5102 @@ -204,7 +204,7 @@ config SND_SOC_ARNDALE config SND_SOC_SAMSUNG_TM2_WM5110 tristate "SoC I2S Audio support for WM5110 on TM2 board" - depends on SND_SOC_SAMSUNG && MFD_ARIZONA && I2C && SPI_MASTER + depends on SND_SOC_SAMSUNG && MFD_ARIZONA && MFD_WM5110 && I2C && SPI_MASTER depends on GPIOLIB || COMPILE_TEST select SND_SOC_MAX98504 select SND_SOC_WM5110 From f6e51bb331d51d4b08fe9b766c5ed442f889c853 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Feb 2020 16:50:59 +0100 Subject: [PATCH 0542/4444] gpio: mockup: coding-style fix The indentation is wrong in gpio_mockup_apply_pull(). This patch makes the code more readable. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20200210155059.29609-1-brgl@bgdev.pl Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mockup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index 7d343bea784a..3eb94f3740d1 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -171,7 +171,7 @@ static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip, /* Change the value unless we're actively driving the line. */ if (!test_bit(FLAG_REQUESTED, &desc->flags) || - !test_bit(FLAG_IS_OUT, &desc->flags)) + !test_bit(FLAG_IS_OUT, &desc->flags)) __gpio_mockup_set(chip, offset, value); out: From 86ecb7d6853c77711c14cb6600179196f179ee2d Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 18 Feb 2020 10:36:25 +0800 Subject: [PATCH 0543/4444] pinctrl: mediatek: remove set but not used variable 'e' drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c: In function mtk_hw_pin_field_lookup: drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c:70:39: warning: variable e set but not used [-Wunused-but-set-variable] Since commit 3de7deefce69 ("pinctrl: mediatek: Check gpio pin number and use binary search in mtk_hw_pin_field_lookup()"), it is not used any more, so remove it, also remove redundant assignment to variable c, it will be assigned a new value later before used. Reported-by: Hulk Robot Signed-off-by: YueHaibing Reviewed-by: Matthias Brugger Link: https://lore.kernel.org/r/20200218023625.14324-1-yuehaibing@huawei.com Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c index 1da942548ff4..d3169a87e1b3 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c @@ -67,7 +67,7 @@ static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, int field, struct mtk_pin_field *pfd) { - const struct mtk_pin_field_calc *c, *e; + const struct mtk_pin_field_calc *c; const struct mtk_pin_reg_calc *rc; int start = 0, end, check; bool found = false; @@ -82,8 +82,6 @@ static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw, } end = rc->nranges - 1; - c = rc->range; - e = c + rc->nranges; while (start <= end) { check = (start + end) >> 1; From 4ddfb4af07c82e7f63c28347e463046aa14c1837 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 11 Feb 2020 17:10:45 -0600 Subject: [PATCH 0544/4444] firmware: arm_scmi: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertenly introduced[3] to the codebase from now on. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Replace the zero-length member "msg_payload" in scmi_shared_mem structure with flexible-array. Link: https://lore.kernel.org/r/20200211231045.GA13956@embeddedor Signed-off-by: Gustavo A. R. Silva [ rebased the change as files are moved around ] Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/shmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/arm_scmi/shmem.c b/drivers/firmware/arm_scmi/shmem.c index ca0ffd302ea2..e1e816e0018c 100644 --- a/drivers/firmware/arm_scmi/shmem.c +++ b/drivers/firmware/arm_scmi/shmem.c @@ -26,7 +26,7 @@ struct scmi_shared_mem { #define SCMI_SHMEM_FLAG_INTR_ENABLED BIT(0) __le32 length; __le32 msg_header; - u8 msg_payload[0]; + u8 msg_payload[]; }; void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem, From 8694548ae1f245ad164d90d7aeafc7ab3bee71a4 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 11 Feb 2020 17:12:52 -0600 Subject: [PATCH 0545/4444] firmware: arm_scmi/perf: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertenly introduced[3] to the codebase from now on. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Replace the zero-length member "opp" in scmi_msg_resp_perf_describe_levels structure with flexible-array. Link: https://lore.kernel.org/r/20200211231252.GA14830@embeddedor Signed-off-by: Gustavo A. R. Silva Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/perf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c index ec81e6f7e7a4..34f3a917dd8d 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -89,7 +89,7 @@ struct scmi_msg_resp_perf_describe_levels { __le32 power; __le16 transition_latency_us; __le16 reserved; - } opp[0]; + } opp[]; }; struct scmi_perf_get_fc_info { From 539db76293cd2e73fe798ed0f21ac852351fedd8 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 11 Feb 2020 17:16:04 -0600 Subject: [PATCH 0546/4444] firmware: arm_scpi: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertenly introduced[3] to the codebase from now on. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Replace the zero-length member "payload" in {legacy_,}scpi_shared_mem structures with flexible-array. Link: https://lore.kernel.org/r/20200211231604.GA17274@embeddedor Signed-off-by: Gustavo A. R. Silva Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index a80c331c3a6e..d0dee37ad522 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -262,12 +262,12 @@ struct scpi_drvinfo { struct scpi_shared_mem { __le32 command; __le32 status; - u8 payload[0]; + u8 payload[]; } __packed; struct legacy_scpi_shared_mem { __le32 status; - u8 payload[0]; + u8 payload[]; } __packed; struct scp_capabilities { From 57c45d4d8a9d78c962e9ddfc4fb2d3210f34f966 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 11 Feb 2020 15:10:10 -0600 Subject: [PATCH 0547/4444] misc: vexpress: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertenly introduced[3] to the codebase from now on. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Replace the zero-length member "template" in vexpress_syscfg_func structure with flexible-array. Link: https://lore.kernel.org/r/20200211211010.GA32239@embeddedor Signed-off-by: Gustavo A. R. Silva Signed-off-by: Sudeep Holla --- drivers/misc/vexpress-syscfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/vexpress-syscfg.c b/drivers/misc/vexpress-syscfg.c index 058fcd7f9f01..a431787c0898 100644 --- a/drivers/misc/vexpress-syscfg.c +++ b/drivers/misc/vexpress-syscfg.c @@ -42,7 +42,7 @@ struct vexpress_syscfg_func { struct vexpress_syscfg *syscfg; struct regmap *regmap; int num_templates; - u32 template[0]; /* Keep it last! */ + u32 template[]; /* Keep it last! */ }; From 06f177c3daa0d419d900936407c367d2b0756eb1 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 10 Feb 2020 11:07:17 +0100 Subject: [PATCH 0548/4444] ARM: dts: sunxi: Remove redundant assigned-clocks The display backend nodes have an assigned clocks property, while the driver also enforces it. Since assigned-clocks is pretty fragile anyway, let's just remove it. Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i.dtsi | 3 --- arch/arm/boot/dts/sun6i-a31.dtsi | 6 ------ arch/arm/boot/dts/sun8i-a33.dtsi | 2 -- 3 files changed, 11 deletions(-) diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi index 0b526e6e5a95..7f5cf028ce1a 100644 --- a/arch/arm/boot/dts/sun5i.dtsi +++ b/arch/arm/boot/dts/sun5i.dtsi @@ -771,9 +771,6 @@ interconnect-names = "dma-mem"; status = "disabled"; - assigned-clocks = <&ccu CLK_DE_BE>; - assigned-clock-rates = <300000000>; - ports { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index 7762fbd9a133..f41440ecbdad 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -1139,9 +1139,6 @@ "ram"; resets = <&ccu RST_AHB1_BE1>; - assigned-clocks = <&ccu CLK_BE1>; - assigned-clock-rates = <300000000>; - ports { #address-cells = <1>; #size-cells = <0>; @@ -1231,9 +1228,6 @@ "ram"; resets = <&ccu RST_AHB1_BE0>; - assigned-clocks = <&ccu CLK_BE0>; - assigned-clock-rates = <300000000>; - ports { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/sun8i-a33.dtsi b/arch/arm/boot/dts/sun8i-a33.dtsi index 1532a0e59af4..d80c8a6856cf 100644 --- a/arch/arm/boot/dts/sun8i-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a33.dtsi @@ -372,8 +372,6 @@ "ram", "sat"; resets = <&ccu RST_BUS_DE_BE>, <&ccu RST_BUS_SAT>; reset-names = "be", "sat"; - assigned-clocks = <&ccu CLK_DE_BE>; - assigned-clock-rates = <300000000>; }; &ccu { From 692b4363c456ab237f95b414a2f439a6dbc9ab15 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 10 Feb 2020 11:07:18 +0100 Subject: [PATCH 0549/4444] ARM: dts: sunxi: Remove redundant assigned-clocks The display DRC nodes have an assigned clocks property, while the driver also enforces it. Since assigned-clocks is pretty fragile anyway, let's just remove it. Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31.dtsi | 6 ------ arch/arm/boot/dts/sun8i-a23-a33.dtsi | 3 --- 2 files changed, 9 deletions(-) diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index f41440ecbdad..f3425a66fc0a 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -1182,9 +1182,6 @@ "ram"; resets = <&ccu RST_AHB1_DRC1>; - assigned-clocks = <&ccu CLK_IEP_DRC1>; - assigned-clock-rates = <300000000>; - ports { #address-cells = <1>; #size-cells = <0>; @@ -1268,9 +1265,6 @@ "ram"; resets = <&ccu RST_AHB1_DRC0>; - assigned-clocks = <&ccu CLK_IEP_DRC0>; - assigned-clock-rates = <300000000>; - ports { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/sun8i-a23-a33.dtsi b/arch/arm/boot/dts/sun8i-a23-a33.dtsi index 48487f6d4ab9..c1362d0f0ff8 100644 --- a/arch/arm/boot/dts/sun8i-a23-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a23-a33.dtsi @@ -684,9 +684,6 @@ clock-names = "ahb", "mod", "ram"; resets = <&ccu RST_BUS_DRC>; - assigned-clocks = <&ccu CLK_DRC>; - assigned-clock-rates = <300000000>; - ports { #address-cells = <1>; #size-cells = <0>; From 564c4815074291c40a584b1b05da3732beac990c Mon Sep 17 00:00:00 2001 From: Andrey Lebedev Date: Wed, 19 Feb 2020 20:08:56 +0200 Subject: [PATCH 0550/4444] ARM: dts: sun7i: Add LVDS panel support on A20 Define pins for LVDS channels 0 and 1, configure reset line for tcon0 and provide sample LVDS panel, connected to tcon0. Signed-off-by: Andrey Lebedev Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20.dtsi | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 92b5be97085d..ffe1d10a1a84 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -47,6 +47,7 @@ #include #include #include +#include / { interrupt-parent = <&gic>; @@ -404,11 +405,12 @@ }; tcon0: lcd-controller@1c0c000 { - compatible = "allwinner,sun7i-a20-tcon"; + compatible = "allwinner,sun7i-a20-tcon0", + "allwinner,sun7i-a20-tcon"; reg = <0x01c0c000 0x1000>; interrupts = ; - resets = <&ccu RST_TCON0>; - reset-names = "lcd"; + resets = <&ccu RST_TCON0>, <&ccu RST_LVDS>; + reset-names = "lcd", "lvds"; clocks = <&ccu CLK_AHB_LCD0>, <&ccu CLK_TCON0_CH0>, <&ccu CLK_TCON0_CH1>; @@ -454,7 +456,8 @@ }; tcon1: lcd-controller@1c0d000 { - compatible = "allwinner,sun7i-a20-tcon"; + compatible = "allwinner,sun7i-a20-tcon1", + "allwinner,sun7i-a20-tcon"; reg = <0x01c0d000 0x1000>; interrupts = ; resets = <&ccu RST_TCON1>; @@ -931,6 +934,20 @@ function = "ir1"; }; + /omit-if-no-ref/ + lcd_lvds0_pins: lcd-lvds0-pins { + pins = "PD0", "PD1", "PD2", "PD3", "PD4", + "PD5", "PD6", "PD7", "PD8", "PD9"; + function = "lvds0"; + }; + + /omit-if-no-ref/ + lcd_lvds1_pins: lcd-lvds1-pins { + pins = "PD10", "PD11", "PD12", "PD13", "PD14", + "PD15", "PD16", "PD17", "PD18", "PD19"; + function = "lvds1"; + }; + /omit-if-no-ref/ mmc0_pins: mmc0-pins { pins = "PF0", "PF1", "PF2", From e4dcb4ab3b24150d99c9d94123d99f76095f1e3c Mon Sep 17 00:00:00 2001 From: Lukasz Luba Date: Thu, 20 Feb 2020 09:56:35 +0000 Subject: [PATCH 0551/4444] ARM: dts: exynos: Add dynamic-power-coefficient to Exynos5422 CPUs To use Energy Aware Scheduler (EAS) the Energy Model (EM) should be registered for CPUs. Add dynamic-power-coefficient into CPU nodes which let CPUFreq subsystem register the EM structures. This will increase energy efficiency of big.LITTLE platforms. The 'dynamic-power-coefficient' values have been obtained experimenting with different workloads. The power measurements taken from big CPU Cluster and LITTLE CPU Cluster has been compared with official documents and synthetic workloads estimations. The effective power ratio between Cortex-A7 and Cortex-A15 CPUs (~3x) is also aligned with documentation. Signed-off-by: Lukasz Luba Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos5422-cpus.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/exynos5422-cpus.dtsi b/arch/arm/boot/dts/exynos5422-cpus.dtsi index 1b8605cf2407..4b641b9b8179 100644 --- a/arch/arm/boot/dts/exynos5422-cpus.dtsi +++ b/arch/arm/boot/dts/exynos5422-cpus.dtsi @@ -31,6 +31,7 @@ operating-points-v2 = <&cluster_a7_opp_table>; #cooling-cells = <2>; /* min followed by max */ capacity-dmips-mhz = <539>; + dynamic-power-coefficient = <90>; }; cpu1: cpu@101 { @@ -43,6 +44,7 @@ operating-points-v2 = <&cluster_a7_opp_table>; #cooling-cells = <2>; /* min followed by max */ capacity-dmips-mhz = <539>; + dynamic-power-coefficient = <90>; }; cpu2: cpu@102 { @@ -55,6 +57,7 @@ operating-points-v2 = <&cluster_a7_opp_table>; #cooling-cells = <2>; /* min followed by max */ capacity-dmips-mhz = <539>; + dynamic-power-coefficient = <90>; }; cpu3: cpu@103 { @@ -67,6 +70,7 @@ operating-points-v2 = <&cluster_a7_opp_table>; #cooling-cells = <2>; /* min followed by max */ capacity-dmips-mhz = <539>; + dynamic-power-coefficient = <90>; }; cpu4: cpu@0 { @@ -79,6 +83,7 @@ operating-points-v2 = <&cluster_a15_opp_table>; #cooling-cells = <2>; /* min followed by max */ capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <310>; }; cpu5: cpu@1 { @@ -91,6 +96,7 @@ operating-points-v2 = <&cluster_a15_opp_table>; #cooling-cells = <2>; /* min followed by max */ capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <310>; }; cpu6: cpu@2 { @@ -103,6 +109,7 @@ operating-points-v2 = <&cluster_a15_opp_table>; #cooling-cells = <2>; /* min followed by max */ capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <310>; }; cpu7: cpu@3 { @@ -115,6 +122,7 @@ operating-points-v2 = <&cluster_a15_opp_table>; #cooling-cells = <2>; /* min followed by max */ capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <310>; }; }; }; From 834e34007eb20434620d988489389ad853f1293c Mon Sep 17 00:00:00 2001 From: Lukasz Luba Date: Thu, 20 Feb 2020 09:56:36 +0000 Subject: [PATCH 0552/4444] ARM: exynos_defconfig: Enable SCHED_MC and ENERGY_MODEL The Energy Model (EM) is needed to run Energy Aware Scheduler (EAS). Enable ENERGY_MODEL to make that happen. This will increase energy efficiency of the big.LITTLE platforms (e.g. Exynos5422) by smarter decisions in scheduling tasks in non-heavy workloads. Add SCHED_MC in order to create another level in scheduling domains: 'MC'. This improves scheduler's decisions on platforms with CPU clusters, such as big.LITTLE. Signed-off-by: Lukasz Luba Signed-off-by: Krzysztof Kozlowski --- arch/arm/configs/exynos_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig index 65c4daddefe3..439d37197959 100644 --- a/arch/arm/configs/exynos_defconfig +++ b/arch/arm/configs/exynos_defconfig @@ -8,6 +8,7 @@ CONFIG_PERF_EVENTS=y CONFIG_ARCH_EXYNOS=y CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND=y CONFIG_SMP=y +CONFIG_SCHED_MC=y CONFIG_BIG_LITTLE=y CONFIG_NR_CPUS=8 CONFIG_HIGHMEM=y @@ -17,6 +18,7 @@ CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_ARM_APPENDED_DTB=y CONFIG_ARM_ATAG_DTB_COMPAT=y CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc mem=256M" +CONFIG_ENERGY_MODEL=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y From d2ad9d6ca5b2435754a0fd811f57d30914c612ce Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 20 Feb 2020 19:10:27 +0200 Subject: [PATCH 0553/4444] ASoC: intel/skl/hda - add no-HDMI cases to generic HDA driver Extend the generic HDA driver to support systems where iDisp/HDMI audio codecs are disabled for some reason. Switch codecs to SoC dummy in the affected DAI links. This allows to reuse existing topologies for this case. Signed-off-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=206085 BugLink: https://bugzilla.opensuse.org/show_bug.cgi?id=1163677 BugLink: https://github.com/thesofproject/linux/issues/1658 Link: https://lore.kernel.org/r/20200220171028.22023-2-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/skl_hda_dsp_common.h | 4 ++++ sound/soc/intel/boards/skl_hda_dsp_generic.c | 25 ++++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.h b/sound/soc/intel/boards/skl_hda_dsp_common.h index d6150670ca05..e8545d13062f 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_common.h +++ b/sound/soc/intel/boards/skl_hda_dsp_common.h @@ -49,6 +49,10 @@ static inline int skl_hda_hdmi_build_controls(struct snd_soc_card *card) struct snd_soc_component *component; struct skl_hda_hdmi_pcm *pcm; + /* HDMI disabled, do not create controls */ + if (list_empty(&ctx->hdmi_pcm_list)) + return 0; + pcm = list_first_entry(&ctx->hdmi_pcm_list, struct skl_hda_hdmi_pcm, head); component = pcm->codec_dai->component; diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index 11eaee9ae41f..fe2d3a23a4ef 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -61,6 +61,9 @@ static const struct snd_soc_dapm_route skl_hda_map[] = { { "Alt Analog CPU Capture", NULL, "Alt Analog Codec Capture" }, }; +SND_SOC_DAILINK_DEF(dummy_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai"))); + static int skl_hda_card_late_probe(struct snd_soc_card *card) { return skl_hda_hdmi_jack_init(card); @@ -114,13 +117,19 @@ static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params) { struct snd_soc_card *card = &hda_soc_card; struct snd_soc_dai_link *dai_link; - u32 codec_count, codec_mask; + u32 codec_count, codec_mask, idisp_mask; int i, num_links, num_route; codec_mask = mach_params->codec_mask; codec_count = hweight_long(codec_mask); + idisp_mask = codec_mask & IDISP_CODEC_MASK; - if (codec_count == 1 && codec_mask & IDISP_CODEC_MASK) { + if (!codec_count || codec_count > 2 || + (codec_count == 2 && !idisp_mask)) + return -EINVAL; + + if (codec_mask == idisp_mask) { + /* topology with iDisp as the only HDA codec */ num_links = IDISP_DAI_COUNT + DMIC_DAI_COUNT; num_route = IDISP_ROUTE_COUNT; @@ -135,13 +144,19 @@ static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params) skl_hda_be_dai_links[IDISP_DAI_COUNT + HDAC_DAI_COUNT + i]; } - } else if (codec_count == 2 && codec_mask & IDISP_CODEC_MASK) { + } else { + /* topology with external and iDisp HDA codecs */ num_links = ARRAY_SIZE(skl_hda_be_dai_links); num_route = ARRAY_SIZE(skl_hda_map); card->dapm_widgets = skl_hda_widgets; card->num_dapm_widgets = ARRAY_SIZE(skl_hda_widgets); - } else { - return -EINVAL; + if (!idisp_mask) { + for (i = 0; i < IDISP_DAI_COUNT; i++) { + skl_hda_be_dai_links[i].codecs = dummy_codec; + skl_hda_be_dai_links[i].num_codecs = + ARRAY_SIZE(dummy_codec); + } + } } card->num_links = num_links; From 71cc8abb6ec705ce4efbb54e401004687d40a641 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 20 Feb 2020 19:10:28 +0200 Subject: [PATCH 0554/4444] ASoC: SOF: Intel: hda: allow operation without i915 gfx Add support to configure the HDA controller with an external HDA codec even if iDisp codec in i915 is not available. This can happen for multiple reasons: - internal graphics is disabled on the system - i915 driver is not enabled in kernel or it fails to init - i915 codec reports error in HDA codec probe - HDA codec driver probe fails Address all these scenarios, but keep using the existing topology. In case failures occur, HDMI PCM nodes are created, but they will report error if application tries to use them. No ALSA mixer controls are created. If the external HDA codec init fails as well, SOF probe will return error as before. Signed-off-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=206085 BugLink: https://bugzilla.opensuse.org/show_bug.cgi?id=1163677 BugLink: https://github.com/thesofproject/linux/issues/1658 Link: https://lore.kernel.org/r/20200220171028.22023-3-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-codec.c | 11 ++++++++++- sound/soc/sof/intel/hda.c | 22 ++++++++-------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index ff45075ef720..3041fbbb010a 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -113,8 +113,14 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, if (ret < 0) return ret; - if ((resp & 0xFFFF0000) == IDISP_VID_INTEL) + if ((resp & 0xFFFF0000) == IDISP_VID_INTEL) { + if (!hdev->bus->audio_component) { + dev_dbg(sdev->dev, + "iDisp hw present but no driver\n"); + return -ENOENT; + } hda_priv->need_display_power = true; + } /* * if common HDMI codec driver is not used, codec load @@ -203,6 +209,9 @@ int hda_codec_i915_exit(struct snd_sof_dev *sdev) struct hdac_bus *bus = sof_to_bus(sdev); int ret; + if (!bus->audio_component) + return 0; + /* power down unconditionally */ snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 726a9ef2d627..7ca887041a34 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -288,10 +288,8 @@ static int hda_init(struct snd_sof_dev *sdev) /* init i915 and HDMI codecs */ ret = hda_codec_i915_init(sdev); - if (ret < 0) { - dev_err(sdev->dev, "error: init i915 and HDMI codec failed\n"); - return ret; - } + if (ret < 0) + dev_warn(sdev->dev, "init of i915 and HDMI codec failed\n"); /* get controller capabilities */ ret = hda_dsp_ctrl_get_caps(sdev); @@ -365,9 +363,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev) if (ret < 0) { dev_err(bus->dev, "error: init chip failed with ret: %d\n", ret); -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - hda_codec_i915_exit(sdev); -#endif return ret; } @@ -379,7 +374,7 @@ static int hda_init_caps(struct snd_sof_dev *sdev) hda_codec_probe_bus(sdev, hda_codec_use_common_hdmi); if (!HDA_IDISP_CODEC(bus->codec_mask)) - hda_codec_i915_exit(sdev); + hda_codec_i915_display_power(sdev, false); /* * we are done probing so decrement link counts @@ -699,12 +694,11 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) /* * If no machine driver is found, then: * - * hda machine driver is used if : - * 1. there is one HDMI codec and one external HDAudio codec - * 2. only HDMI codec + * generic hda machine driver can handle: + * - one HDMI codec, and/or + * - one external HDAudio codec */ - if (!pdata->machine && codec_num <= 2 && - HDA_IDISP_CODEC(bus->codec_mask)) { + if (!pdata->machine && codec_num <= 2) { hda_mach = snd_soc_acpi_intel_hda_machines; /* topology: use the info from hda_machines */ @@ -714,7 +708,7 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) dev_info(bus->dev, "using HDA machine driver %s now\n", hda_mach->drv_name); - if (codec_num == 1) + if (codec_num == 1 && HDA_IDISP_CODEC(bus->codec_mask)) idisp_str = "-idisp"; else idisp_str = ""; From cc10317db0d5dc6d65211e58e1b90449db4da5f0 Mon Sep 17 00:00:00 2001 From: "michael.kao" Date: Fri, 3 Jan 2020 14:44:01 +0800 Subject: [PATCH 0555/4444] arm64: dts: mt8183: add/update dynamic power coefficients Add dynamic power coefficients for all cores. Signed-off-by: Michael Kao [mb: fix commit message] Signed-off-by: Matthias Brugger --- arch/arm64/boot/dts/mediatek/mt8183.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi index f1381e77918b..d5c916fb0cdc 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi @@ -75,6 +75,7 @@ enable-method = "psci"; capacity-dmips-mhz = <741>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + dynamic-power-coefficient = <84>; }; cpu1: cpu@1 { @@ -84,6 +85,7 @@ enable-method = "psci"; capacity-dmips-mhz = <741>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + dynamic-power-coefficient = <84>; }; cpu2: cpu@2 { @@ -93,6 +95,7 @@ enable-method = "psci"; capacity-dmips-mhz = <741>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + dynamic-power-coefficient = <84>; }; cpu3: cpu@3 { @@ -102,6 +105,7 @@ enable-method = "psci"; capacity-dmips-mhz = <741>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + dynamic-power-coefficient = <84>; }; cpu4: cpu@100 { @@ -111,6 +115,7 @@ enable-method = "psci"; capacity-dmips-mhz = <1024>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + dynamic-power-coefficient = <211>; }; cpu5: cpu@101 { @@ -120,6 +125,7 @@ enable-method = "psci"; capacity-dmips-mhz = <1024>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + dynamic-power-coefficient = <211>; }; cpu6: cpu@102 { @@ -129,6 +135,7 @@ enable-method = "psci"; capacity-dmips-mhz = <1024>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + dynamic-power-coefficient = <211>; }; cpu7: cpu@103 { @@ -138,6 +145,7 @@ enable-method = "psci"; capacity-dmips-mhz = <1024>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + dynamic-power-coefficient = <211>; }; idle-states { From 5323e0fa9394d3fc66166d5e8a761a9e24b076a6 Mon Sep 17 00:00:00 2001 From: "michael.kao" Date: Fri, 3 Jan 2020 14:44:02 +0800 Subject: [PATCH 0556/4444] arm64: dts: mt8183: Add #cooling-cells to CPU nodes The #cooling-cells property needs to be specified to allow a CPU to be used as cooling device. Signed-off-by: Michael Kao Signed-off-by: Matthias Brugger --- arch/arm64/boot/dts/mediatek/mt8183.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi index d5c916fb0cdc..97863adb7bc0 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi @@ -76,6 +76,7 @@ capacity-dmips-mhz = <741>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; dynamic-power-coefficient = <84>; + #cooling-cells = <2>; }; cpu1: cpu@1 { @@ -86,6 +87,7 @@ capacity-dmips-mhz = <741>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; dynamic-power-coefficient = <84>; + #cooling-cells = <2>; }; cpu2: cpu@2 { @@ -96,6 +98,7 @@ capacity-dmips-mhz = <741>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; dynamic-power-coefficient = <84>; + #cooling-cells = <2>; }; cpu3: cpu@3 { @@ -106,6 +109,7 @@ capacity-dmips-mhz = <741>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; dynamic-power-coefficient = <84>; + #cooling-cells = <2>; }; cpu4: cpu@100 { @@ -116,6 +120,7 @@ capacity-dmips-mhz = <1024>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; dynamic-power-coefficient = <211>; + #cooling-cells = <2>; }; cpu5: cpu@101 { @@ -126,6 +131,7 @@ capacity-dmips-mhz = <1024>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; dynamic-power-coefficient = <211>; + #cooling-cells = <2>; }; cpu6: cpu@102 { @@ -136,6 +142,7 @@ capacity-dmips-mhz = <1024>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; dynamic-power-coefficient = <211>; + #cooling-cells = <2>; }; cpu7: cpu@103 { @@ -146,6 +153,7 @@ capacity-dmips-mhz = <1024>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; dynamic-power-coefficient = <211>; + #cooling-cells = <2>; }; idle-states { From 4ee67cbd97668ab1b17d86d85348302c0b7490cd Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Thu, 20 Feb 2020 15:07:58 -0600 Subject: [PATCH 0557/4444] dt-bindings: sound: Add TLV320ADCx140 dt bindings Add dt bindings for the TLV320ADCx140 Burr-Brown ADC. The initial support is for the following: TLV320ADC3140 - http://www.ti.com/lit/gpn/tlv320adc3140 TLV320ADC5140 - http://www.ti.com/lit/gpn/tlv320adc5140 TLV320ADC6140 - http://www.ti.com/lit/gpn/tlv320adc6140 Signed-off-by: Dan Murphy Link: https://lore.kernel.org/r/20200220210759.31466-2-dmurphy@ti.com Signed-off-by: Mark Brown --- .../bindings/sound/tlv320adcx140.yaml | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/tlv320adcx140.yaml diff --git a/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml b/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml new file mode 100644 index 000000000000..1433ff62b14f --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause) +# Copyright (C) 2019 Texas Instruments Incorporated +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/tlv320adcx140.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments TLV320ADCX140 Quad Channel Analog-to-Digital Converter + +maintainers: + - Dan Murphy + +description: | + The TLV320ADCX140 are multichannel (4-ch analog recording or 8-ch digital + PDM microphones recording), high-performance audio, analog-to-digital + converter (ADC) with analog inputs supporting up to 2V RMS. The TLV320ADCX140 + family supports line and microphone Inputs, and offers a programmable + microphone bias or supply voltage generation. + + Specifications can be found at: + http://www.ti.com/lit/ds/symlink/tlv320adc3140.pdf + http://www.ti.com/lit/ds/symlink/tlv320adc5140.pdf + http://www.ti.com/lit/ds/symlink/tlv320adc6140.pdf + +properties: + compatible: + oneOf: + - const: ti,tlv320adc3140 + - const: ti,tlv320adc5140 + - const: ti,tlv320adc6140 + + reg: + maxItems: 1 + description: | + I2C addresss of the device can be one of these 0x4c, 0x4d, 0x4e or 0x4f + + reset-gpios: + description: | + GPIO used for hardware reset. + + areg-supply: + description: | + Regulator with AVDD at 3.3V. If not defined then the internal regulator + is enabled. + + ti,mic-bias-source: + description: | + Indicates the source for MIC Bias. + 0 - Mic bias is set to VREF + 1 - Mic bias is set to VREF × 1.096 + 6 - Mic bias is set to AVDD + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - enum: [0, 1, 6] + + ti,vref-source: + description: | + Indicates the source for MIC Bias. + 0 - Set VREF to 2.75V + 1 - Set VREF to 2.5V + 2 - Set VREF to 1.375V + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - enum: [0, 1, 2] + +required: + - compatible + - reg + +examples: + - | + #include + i2c0 { + #address-cells = <1>; + #size-cells = <0>; + codec: codec@4c { + compatible = "ti,tlv320adc5140"; + reg = <0x4c>; + ti,use-internal-areg; + ti,mic-bias-source = <6>; + reset-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; + }; + }; From 689c7655b50c5de2b6f0f42fecfb37bde5acf040 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Thu, 20 Feb 2020 15:07:59 -0600 Subject: [PATCH 0558/4444] ASoC: tlv320adcx140: Add the tlv320adcx140 codec driver family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the tlv320adcx140 codec driver family. The TLV320ADCx140 is a Burr-Brown™ highperformance, audio analog-to-digital converter (ADC) that supports simultaneous sampling of up to four analog channels or eight digital channels for the pulse density modulation (PDM) microphone input. The device supports line and microphone inputs, and allows for both single-ended and differential input configurations. Signed-off-by: Dan Murphy Link: https://lore.kernel.org/r/20200220210759.31466-3-dmurphy@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 9 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/tlv320adcx140.c | 849 +++++++++++++++++++++++++++++++ sound/soc/codecs/tlv320adcx140.h | 130 +++++ 4 files changed, 990 insertions(+) create mode 100644 sound/soc/codecs/tlv320adcx140.c create mode 100644 sound/soc/codecs/tlv320adcx140.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index d957fd6980b1..9e9d54e4576c 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -196,6 +196,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_TAS6424 imply SND_SOC_TDA7419 imply SND_SOC_TFA9879 + imply SND_SOC_TLV320ADCX140 imply SND_SOC_TLV320AIC23_I2C imply SND_SOC_TLV320AIC23_SPI imply SND_SOC_TLV320AIC26 @@ -1334,6 +1335,14 @@ config SND_SOC_TLV320DAC33 tristate depends on I2C +config SND_SOC_TLV320ADCX140 + tristate "Texas Instruments TLV320ADCX140 CODEC family" + depends on I2C + select REGMAP_I2C + help + Add support for Texas Instruments tlv320adc3140, tlv320adc5140 and + tlv320adc6140 quad channel ADCs. + config SND_SOC_TS3A227E tristate "TI Headset/Mic detect and keypress chip" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index ba1b4b3fa2da..943ebc93fbc1 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -218,6 +218,7 @@ snd-soc-tlv320aic32x4-i2c-objs := tlv320aic32x4-i2c.o snd-soc-tlv320aic32x4-spi-objs := tlv320aic32x4-spi.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320dac33-objs := tlv320dac33.o +snd-soc-tlv320adcx140-objs := tlv320adcx140.o snd-soc-tscs42xx-objs := tscs42xx.o snd-soc-tscs454-objs := tscs454.o snd-soc-ts3a227e-objs := ts3a227e.o @@ -516,6 +517,7 @@ obj-$(CONFIG_SND_SOC_TLV320AIC32X4_I2C) += snd-soc-tlv320aic32x4-i2c.o obj-$(CONFIG_SND_SOC_TLV320AIC32X4_SPI) += snd-soc-tlv320aic32x4-spi.o obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o +obj-$(CONFIG_SND_SOC_TLV320ADCX140) += snd-soc-tlv320adcx140.o obj-$(CONFIG_SND_SOC_TSCS42XX) += snd-soc-tscs42xx.o obj-$(CONFIG_SND_SOC_TSCS454) += snd-soc-tscs454.o obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c new file mode 100644 index 000000000000..8182c584de9c --- /dev/null +++ b/sound/soc/codecs/tlv320adcx140.c @@ -0,0 +1,849 @@ +// SPDX-License-Identifier: GPL-2.0 +// TLV320ADCX140 Sound driver +// Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tlv320adcx140.h" + +struct adcx140_priv { + struct snd_soc_component *component; + struct regulator *supply_areg; + struct gpio_desc *gpio_reset; + struct regmap *regmap; + struct device *dev; + + int micbias_vg; + + unsigned int dai_fmt; + unsigned int tdm_delay; + unsigned int slot_width; +}; + +static const struct reg_default adcx140_reg_defaults[] = { + { ADCX140_PAGE_SELECT, 0x00 }, + { ADCX140_SW_RESET, 0x00 }, + { ADCX140_SLEEP_CFG, 0x00 }, + { ADCX140_SHDN_CFG, 0x05 }, + { ADCX140_ASI_CFG0, 0x30 }, + { ADCX140_ASI_CFG1, 0x00 }, + { ADCX140_ASI_CFG2, 0x00 }, + { ADCX140_ASI_CH1, 0x00 }, + { ADCX140_ASI_CH2, 0x01 }, + { ADCX140_ASI_CH3, 0x02 }, + { ADCX140_ASI_CH4, 0x03 }, + { ADCX140_ASI_CH5, 0x04 }, + { ADCX140_ASI_CH6, 0x05 }, + { ADCX140_ASI_CH7, 0x06 }, + { ADCX140_ASI_CH8, 0x07 }, + { ADCX140_MST_CFG0, 0x02 }, + { ADCX140_MST_CFG1, 0x48 }, + { ADCX140_ASI_STS, 0xff }, + { ADCX140_CLK_SRC, 0x10 }, + { ADCX140_PDMCLK_CFG, 0x40 }, + { ADCX140_PDM_CFG, 0x00 }, + { ADCX140_GPIO_CFG0, 0x22 }, + { ADCX140_GPO_CFG1, 0x00 }, + { ADCX140_GPO_CFG2, 0x00 }, + { ADCX140_GPO_CFG3, 0x00 }, + { ADCX140_GPO_CFG4, 0x00 }, + { ADCX140_GPO_VAL, 0x00 }, + { ADCX140_GPIO_MON, 0x00 }, + { ADCX140_GPI_CFG0, 0x00 }, + { ADCX140_GPI_CFG1, 0x00 }, + { ADCX140_GPI_MON, 0x00 }, + { ADCX140_INT_CFG, 0x00 }, + { ADCX140_INT_MASK0, 0xff }, + { ADCX140_INT_LTCH0, 0x00 }, + { ADCX140_BIAS_CFG, 0x00 }, + { ADCX140_CH1_CFG0, 0x00 }, + { ADCX140_CH1_CFG1, 0x00 }, + { ADCX140_CH1_CFG2, 0xc9 }, + { ADCX140_CH1_CFG3, 0x80 }, + { ADCX140_CH1_CFG4, 0x00 }, + { ADCX140_CH2_CFG0, 0x00 }, + { ADCX140_CH2_CFG1, 0x00 }, + { ADCX140_CH2_CFG2, 0xc9 }, + { ADCX140_CH2_CFG3, 0x80 }, + { ADCX140_CH2_CFG4, 0x00 }, + { ADCX140_CH3_CFG0, 0x00 }, + { ADCX140_CH3_CFG1, 0x00 }, + { ADCX140_CH3_CFG2, 0xc9 }, + { ADCX140_CH3_CFG3, 0x80 }, + { ADCX140_CH3_CFG4, 0x00 }, + { ADCX140_CH4_CFG0, 0x00 }, + { ADCX140_CH4_CFG1, 0x00 }, + { ADCX140_CH4_CFG2, 0xc9 }, + { ADCX140_CH4_CFG3, 0x80 }, + { ADCX140_CH4_CFG4, 0x00 }, + { ADCX140_CH5_CFG2, 0xc9 }, + { ADCX140_CH5_CFG3, 0x80 }, + { ADCX140_CH5_CFG4, 0x00 }, + { ADCX140_CH6_CFG2, 0xc9 }, + { ADCX140_CH6_CFG3, 0x80 }, + { ADCX140_CH6_CFG4, 0x00 }, + { ADCX140_CH7_CFG2, 0xc9 }, + { ADCX140_CH7_CFG3, 0x80 }, + { ADCX140_CH7_CFG4, 0x00 }, + { ADCX140_CH8_CFG2, 0xc9 }, + { ADCX140_CH8_CFG3, 0x80 }, + { ADCX140_CH8_CFG4, 0x00 }, + { ADCX140_DSP_CFG0, 0x01 }, + { ADCX140_DSP_CFG1, 0x40 }, + { ADCX140_DRE_CFG0, 0x7b }, + { ADCX140_IN_CH_EN, 0xf0 }, + { ADCX140_ASI_OUT_CH_EN, 0x00 }, + { ADCX140_PWR_CFG, 0x00 }, + { ADCX140_DEV_STS0, 0x00 }, + { ADCX140_DEV_STS1, 0x80 }, +}; + +static const struct regmap_range_cfg adcx140_ranges[] = { + { + .range_min = 0, + .range_max = 12 * 128, + .selector_reg = ADCX140_PAGE_SELECT, + .selector_mask = 0xff, + .selector_shift = 0, + .window_start = 0, + .window_len = 128, + }, +}; + +static bool adcx140_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ADCX140_SW_RESET: + case ADCX140_DEV_STS0: + case ADCX140_DEV_STS1: + case ADCX140_ASI_STS: + return true; + default: + return false; + } +} + +static const struct regmap_config adcx140_i2c_regmap = { + .reg_bits = 8, + .val_bits = 8, + .reg_defaults = adcx140_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(adcx140_reg_defaults), + .cache_type = REGCACHE_FLAT, + .ranges = adcx140_ranges, + .num_ranges = ARRAY_SIZE(adcx140_ranges), + .max_register = 12 * 128, + .volatile_reg = adcx140_volatile, +}; + +/* Digital Volume control. From -100 to 27 dB in 0.5 dB steps */ +static DECLARE_TLV_DB_SCALE(dig_vol_tlv, -10000, 50, 0); + +/* ADC gain. From 0 to 42 dB in 1 dB steps */ +static DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0); + +static const char * const resistor_text[] = { + "2.5 kOhm", "10 kOhm", "20 kOhm" +}; + +static SOC_ENUM_SINGLE_DECL(in1_resistor_enum, ADCX140_CH1_CFG0, 2, + resistor_text); +static SOC_ENUM_SINGLE_DECL(in2_resistor_enum, ADCX140_CH2_CFG0, 2, + resistor_text); +static SOC_ENUM_SINGLE_DECL(in3_resistor_enum, ADCX140_CH3_CFG0, 2, + resistor_text); +static SOC_ENUM_SINGLE_DECL(in4_resistor_enum, ADCX140_CH4_CFG0, 2, + resistor_text); + +static const struct snd_kcontrol_new in1_resistor_controls[] = { + SOC_DAPM_ENUM("CH1 Resistor Select", in1_resistor_enum), +}; +static const struct snd_kcontrol_new in2_resistor_controls[] = { + SOC_DAPM_ENUM("CH2 Resistor Select", in2_resistor_enum), +}; +static const struct snd_kcontrol_new in3_resistor_controls[] = { + SOC_DAPM_ENUM("CH3 Resistor Select", in3_resistor_enum), +}; +static const struct snd_kcontrol_new in4_resistor_controls[] = { + SOC_DAPM_ENUM("CH4 Resistor Select", in4_resistor_enum), +}; + +/* Analog/Digital Selection */ +static const char *adcx140_mic_sel_text[] = {"Analog", "Line In", "Digital"}; +static const char *adcx140_analog_sel_text[] = {"Analog", "Line In"}; + +static SOC_ENUM_SINGLE_DECL(adcx140_mic1p_enum, + ADCX140_CH1_CFG0, 5, + adcx140_mic_sel_text); + +static const struct snd_kcontrol_new adcx140_dapm_mic1p_control = +SOC_DAPM_ENUM("MIC1P MUX", adcx140_mic1p_enum); + +static SOC_ENUM_SINGLE_DECL(adcx140_mic1_analog_enum, + ADCX140_CH1_CFG0, 7, + adcx140_analog_sel_text); + +static const struct snd_kcontrol_new adcx140_dapm_mic1_analog_control = +SOC_DAPM_ENUM("MIC1 Analog MUX", adcx140_mic1_analog_enum); + +static SOC_ENUM_SINGLE_DECL(adcx140_mic1m_enum, + ADCX140_CH1_CFG0, 5, + adcx140_mic_sel_text); + +static const struct snd_kcontrol_new adcx140_dapm_mic1m_control = +SOC_DAPM_ENUM("MIC1M MUX", adcx140_mic1m_enum); + +static SOC_ENUM_SINGLE_DECL(adcx140_mic2p_enum, + ADCX140_CH2_CFG0, 5, + adcx140_mic_sel_text); + +static const struct snd_kcontrol_new adcx140_dapm_mic2p_control = +SOC_DAPM_ENUM("MIC2P MUX", adcx140_mic2p_enum); + +static SOC_ENUM_SINGLE_DECL(adcx140_mic2_analog_enum, + ADCX140_CH2_CFG0, 7, + adcx140_analog_sel_text); + +static const struct snd_kcontrol_new adcx140_dapm_mic2_analog_control = +SOC_DAPM_ENUM("MIC2 Analog MUX", adcx140_mic2_analog_enum); + +static SOC_ENUM_SINGLE_DECL(adcx140_mic2m_enum, + ADCX140_CH2_CFG0, 5, + adcx140_mic_sel_text); + +static const struct snd_kcontrol_new adcx140_dapm_mic2m_control = +SOC_DAPM_ENUM("MIC2M MUX", adcx140_mic2m_enum); + +static SOC_ENUM_SINGLE_DECL(adcx140_mic3p_enum, + ADCX140_CH3_CFG0, 5, + adcx140_mic_sel_text); + +static const struct snd_kcontrol_new adcx140_dapm_mic3p_control = +SOC_DAPM_ENUM("MIC3P MUX", adcx140_mic3p_enum); + +static SOC_ENUM_SINGLE_DECL(adcx140_mic3_analog_enum, + ADCX140_CH3_CFG0, 7, + adcx140_analog_sel_text); + +static const struct snd_kcontrol_new adcx140_dapm_mic3_analog_control = +SOC_DAPM_ENUM("MIC3 Analog MUX", adcx140_mic3_analog_enum); + +static SOC_ENUM_SINGLE_DECL(adcx140_mic3m_enum, + ADCX140_CH3_CFG0, 5, + adcx140_mic_sel_text); + +static const struct snd_kcontrol_new adcx140_dapm_mic3m_control = +SOC_DAPM_ENUM("MIC3M MUX", adcx140_mic3m_enum); + +static SOC_ENUM_SINGLE_DECL(adcx140_mic4p_enum, + ADCX140_CH4_CFG0, 5, + adcx140_mic_sel_text); + +static const struct snd_kcontrol_new adcx140_dapm_mic4p_control = +SOC_DAPM_ENUM("MIC4P MUX", adcx140_mic4p_enum); + +static SOC_ENUM_SINGLE_DECL(adcx140_mic4_analog_enum, + ADCX140_CH4_CFG0, 7, + adcx140_analog_sel_text); + +static const struct snd_kcontrol_new adcx140_dapm_mic4_analog_control = +SOC_DAPM_ENUM("MIC4 Analog MUX", adcx140_mic4_analog_enum); + +static SOC_ENUM_SINGLE_DECL(adcx140_mic4m_enum, + ADCX140_CH4_CFG0, 5, + adcx140_mic_sel_text); + +static const struct snd_kcontrol_new adcx140_dapm_mic4m_control = +SOC_DAPM_ENUM("MIC4M MUX", adcx140_mic4m_enum); + +static const struct snd_kcontrol_new adcx140_dapm_ch1_en_switch = + SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 7, 1, 0); +static const struct snd_kcontrol_new adcx140_dapm_ch2_en_switch = + SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 6, 1, 0); +static const struct snd_kcontrol_new adcx140_dapm_ch3_en_switch = + SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 5, 1, 0); +static const struct snd_kcontrol_new adcx140_dapm_ch4_en_switch = + SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 4, 1, 0); + +/* Output Mixer */ +static const struct snd_kcontrol_new adcx140_output_mixer_controls[] = { + SOC_DAPM_SINGLE("Digital CH1 Switch", 0, 0, 0, 0), + SOC_DAPM_SINGLE("Digital CH2 Switch", 0, 0, 0, 0), + SOC_DAPM_SINGLE("Digital CH3 Switch", 0, 0, 0, 0), + SOC_DAPM_SINGLE("Digital CH4 Switch", 0, 0, 0, 0), +}; + +static const struct snd_soc_dapm_widget adcx140_dapm_widgets[] = { + /* Analog Differential Inputs */ + SND_SOC_DAPM_INPUT("MIC1P"), + SND_SOC_DAPM_INPUT("MIC1M"), + SND_SOC_DAPM_INPUT("MIC2P"), + SND_SOC_DAPM_INPUT("MIC2M"), + SND_SOC_DAPM_INPUT("MIC3P"), + SND_SOC_DAPM_INPUT("MIC3M"), + SND_SOC_DAPM_INPUT("MIC4P"), + SND_SOC_DAPM_INPUT("MIC4M"), + + SND_SOC_DAPM_OUTPUT("CH1_OUT"), + SND_SOC_DAPM_OUTPUT("CH2_OUT"), + SND_SOC_DAPM_OUTPUT("CH3_OUT"), + SND_SOC_DAPM_OUTPUT("CH4_OUT"), + SND_SOC_DAPM_OUTPUT("CH5_OUT"), + SND_SOC_DAPM_OUTPUT("CH6_OUT"), + SND_SOC_DAPM_OUTPUT("CH7_OUT"), + SND_SOC_DAPM_OUTPUT("CH8_OUT"), + + SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0, + &adcx140_output_mixer_controls[0], + ARRAY_SIZE(adcx140_output_mixer_controls)), + + /* Input Selection to MIC_PGA */ + SND_SOC_DAPM_MUX("MIC1P Input Mux", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_mic1p_control), + SND_SOC_DAPM_MUX("MIC2P Input Mux", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_mic2p_control), + SND_SOC_DAPM_MUX("MIC3P Input Mux", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_mic3p_control), + SND_SOC_DAPM_MUX("MIC4P Input Mux", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_mic4p_control), + + /* Input Selection to MIC_PGA */ + SND_SOC_DAPM_MUX("MIC1 Analog Mux", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_mic1_analog_control), + SND_SOC_DAPM_MUX("MIC2 Analog Mux", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_mic2_analog_control), + SND_SOC_DAPM_MUX("MIC3 Analog Mux", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_mic3_analog_control), + SND_SOC_DAPM_MUX("MIC4 Analog Mux", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_mic4_analog_control), + + SND_SOC_DAPM_MUX("MIC1M Input Mux", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_mic1m_control), + SND_SOC_DAPM_MUX("MIC2M Input Mux", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_mic2m_control), + SND_SOC_DAPM_MUX("MIC3M Input Mux", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_mic3m_control), + SND_SOC_DAPM_MUX("MIC4M Input Mux", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_mic4m_control), + + SND_SOC_DAPM_PGA("MIC_GAIN_CTL_CH1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("MIC_GAIN_CTL_CH2", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("MIC_GAIN_CTL_CH3", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("MIC_GAIN_CTL_CH4", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_ADC("CH1_ADC", "CH1 Capture", ADCX140_IN_CH_EN, 7, 0), + SND_SOC_DAPM_ADC("CH2_ADC", "CH2 Capture", ADCX140_IN_CH_EN, 6, 0), + SND_SOC_DAPM_ADC("CH3_ADC", "CH3 Capture", ADCX140_IN_CH_EN, 5, 0), + SND_SOC_DAPM_ADC("CH4_ADC", "CH4 Capture", ADCX140_IN_CH_EN, 4, 0), + + SND_SOC_DAPM_SWITCH("CH1_ASI_EN", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_ch1_en_switch), + SND_SOC_DAPM_SWITCH("CH2_ASI_EN", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_ch2_en_switch), + SND_SOC_DAPM_SWITCH("CH3_ASI_EN", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_ch3_en_switch), + SND_SOC_DAPM_SWITCH("CH4_ASI_EN", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_ch4_en_switch), + + SND_SOC_DAPM_MUX("IN1 Analog Mic Resistor", SND_SOC_NOPM, 0, 0, + in1_resistor_controls), + SND_SOC_DAPM_MUX("IN2 Analog Mic Resistor", SND_SOC_NOPM, 0, 0, + in2_resistor_controls), + SND_SOC_DAPM_MUX("IN3 Analog Mic Resistor", SND_SOC_NOPM, 0, 0, + in3_resistor_controls), + SND_SOC_DAPM_MUX("IN4 Analog Mic Resistor", SND_SOC_NOPM, 0, 0, + in4_resistor_controls), +}; + +static const struct snd_soc_dapm_route adcx140_audio_map[] = { + /* Outputs */ + {"CH1_OUT", NULL, "Output Mixer"}, + {"CH2_OUT", NULL, "Output Mixer"}, + {"CH3_OUT", NULL, "Output Mixer"}, + {"CH4_OUT", NULL, "Output Mixer"}, + + {"CH1_ASI_EN", "Switch", "CH1_ADC"}, + {"CH2_ASI_EN", "Switch", "CH2_ADC"}, + {"CH3_ASI_EN", "Switch", "CH3_ADC"}, + {"CH4_ASI_EN", "Switch", "CH4_ADC"}, + + /* Mic input */ + {"CH1_ADC", NULL, "MIC_GAIN_CTL_CH1"}, + {"CH2_ADC", NULL, "MIC_GAIN_CTL_CH2"}, + {"CH3_ADC", NULL, "MIC_GAIN_CTL_CH3"}, + {"CH4_ADC", NULL, "MIC_GAIN_CTL_CH4"}, + + {"MIC_GAIN_CTL_CH1", NULL, "IN1 Analog Mic Resistor"}, + {"MIC_GAIN_CTL_CH1", NULL, "IN1 Analog Mic Resistor"}, + {"MIC_GAIN_CTL_CH2", NULL, "IN2 Analog Mic Resistor"}, + {"MIC_GAIN_CTL_CH2", NULL, "IN2 Analog Mic Resistor"}, + {"MIC_GAIN_CTL_CH3", NULL, "IN3 Analog Mic Resistor"}, + {"MIC_GAIN_CTL_CH3", NULL, "IN3 Analog Mic Resistor"}, + {"MIC_GAIN_CTL_CH4", NULL, "IN4 Analog Mic Resistor"}, + {"MIC_GAIN_CTL_CH4", NULL, "IN4 Analog Mic Resistor"}, + + {"IN1 Analog Mic Resistor", "2.5 kOhm", "MIC1P Input Mux"}, + {"IN1 Analog Mic Resistor", "10 kOhm", "MIC1P Input Mux"}, + {"IN1 Analog Mic Resistor", "20 kOhm", "MIC1P Input Mux"}, + + {"IN1 Analog Mic Resistor", "2.5 kOhm", "MIC1M Input Mux"}, + {"IN1 Analog Mic Resistor", "10 kOhm", "MIC1M Input Mux"}, + {"IN1 Analog Mic Resistor", "20 kOhm", "MIC1M Input Mux"}, + + {"IN2 Analog Mic Resistor", "2.5 kOhm", "MIC2P Input Mux"}, + {"IN2 Analog Mic Resistor", "10 kOhm", "MIC2P Input Mux"}, + {"IN2 Analog Mic Resistor", "20 kOhm", "MIC2P Input Mux"}, + + {"IN2 Analog Mic Resistor", "2.5 kOhm", "MIC2M Input Mux"}, + {"IN2 Analog Mic Resistor", "10 kOhm", "MIC2M Input Mux"}, + {"IN2 Analog Mic Resistor", "20 kOhm", "MIC2M Input Mux"}, + + {"IN3 Analog Mic Resistor", "2.5 kOhm", "MIC3P Input Mux"}, + {"IN3 Analog Mic Resistor", "10 kOhm", "MIC3P Input Mux"}, + {"IN3 Analog Mic Resistor", "20 kOhm", "MIC3P Input Mux"}, + + {"IN3 Analog Mic Resistor", "2.5 kOhm", "MIC3M Input Mux"}, + {"IN3 Analog Mic Resistor", "10 kOhm", "MIC3M Input Mux"}, + {"IN3 Analog Mic Resistor", "20 kOhm", "MIC3M Input Mux"}, + + {"IN4 Analog Mic Resistor", "2.5 kOhm", "MIC4P Input Mux"}, + {"IN4 Analog Mic Resistor", "10 kOhm", "MIC4P Input Mux"}, + {"IN4 Analog Mic Resistor", "20 kOhm", "MIC4P Input Mux"}, + + {"IN4 Analog Mic Resistor", "2.5 kOhm", "MIC4M Input Mux"}, + {"IN4 Analog Mic Resistor", "10 kOhm", "MIC4M Input Mux"}, + {"IN4 Analog Mic Resistor", "20 kOhm", "MIC4M Input Mux"}, + + {"MIC1 Analog Mux", "Line In", "MIC1P"}, + {"MIC2 Analog Mux", "Line In", "MIC2P"}, + {"MIC3 Analog Mux", "Line In", "MIC3P"}, + {"MIC4 Analog Mux", "Line In", "MIC4P"}, + + {"MIC1P Input Mux", "Analog", "MIC1P"}, + {"MIC1M Input Mux", "Analog", "MIC1M"}, + {"MIC2P Input Mux", "Analog", "MIC2P"}, + {"MIC2M Input Mux", "Analog", "MIC2M"}, + {"MIC3P Input Mux", "Analog", "MIC3P"}, + {"MIC3M Input Mux", "Analog", "MIC3M"}, + {"MIC4P Input Mux", "Analog", "MIC4P"}, + {"MIC4M Input Mux", "Analog", "MIC4M"}, +}; + +static const struct snd_kcontrol_new adcx140_snd_controls[] = { + SOC_SINGLE_TLV("Analog CH1 Mic Gain Volume", ADCX140_CH1_CFG1, 2, 42, 0, + adc_tlv), + SOC_SINGLE_TLV("Analog CH2 Mic Gain Volume", ADCX140_CH1_CFG2, 2, 42, 0, + adc_tlv), + SOC_SINGLE_TLV("Analog CH3 Mic Gain Volume", ADCX140_CH1_CFG3, 2, 42, 0, + adc_tlv), + SOC_SINGLE_TLV("Analog CH4 Mic Gain Volume", ADCX140_CH1_CFG4, 2, 42, 0, + adc_tlv), + + SOC_SINGLE_TLV("Digital CH1 Out Volume", ADCX140_CH1_CFG2, + 0, 0xff, 0, dig_vol_tlv), + SOC_SINGLE_TLV("Digital CH2 Out Volume", ADCX140_CH2_CFG2, + 0, 0xff, 0, dig_vol_tlv), + SOC_SINGLE_TLV("Digital CH3 Out Volume", ADCX140_CH3_CFG2, + 0, 0xff, 0, dig_vol_tlv), + SOC_SINGLE_TLV("Digital CH4 Out Volume", ADCX140_CH4_CFG2, + 0, 0xff, 0, dig_vol_tlv), + SOC_SINGLE_TLV("Digital CH5 Out Volume", ADCX140_CH5_CFG2, + 0, 0xff, 0, dig_vol_tlv), + SOC_SINGLE_TLV("Digital CH6 Out Volume", ADCX140_CH6_CFG2, + 0, 0xff, 0, dig_vol_tlv), + SOC_SINGLE_TLV("Digital CH7 Out Volume", ADCX140_CH7_CFG2, + 0, 0xff, 0, dig_vol_tlv), + SOC_SINGLE_TLV("Digital CH8 Out Volume", ADCX140_CH8_CFG2, + 0, 0xff, 0, dig_vol_tlv), +}; + +static int adcx140_reset(struct adcx140_priv *adcx140) +{ + int ret = 0; + + if (adcx140->gpio_reset) { + gpiod_direction_output(adcx140->gpio_reset, 0); + /* 8.4.1: wait for hw shutdown (25ms) + >= 1ms */ + usleep_range(30000, 100000); + gpiod_direction_output(adcx140->gpio_reset, 1); + } else { + ret = regmap_write(adcx140->regmap, ADCX140_SW_RESET, + ADCX140_RESET); + } + + /* 8.4.2: wait >= 10 ms after entering sleep mode. */ + usleep_range(10000, 100000); + + return 0; +} + +static int adcx140_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + u8 data = 0; + + switch (params_width(params)) { + case 16: + data = ADCX140_16_BIT_WORD; + break; + case 20: + data = ADCX140_20_BIT_WORD; + break; + case 24: + data = ADCX140_24_BIT_WORD; + break; + case 32: + data = ADCX140_32_BIT_WORD; + break; + default: + dev_err(component->dev, "%s: Unsupported width %d\n", + __func__, params_width(params)); + return -EINVAL; + } + + snd_soc_component_update_bits(component, ADCX140_ASI_CFG0, + ADCX140_WORD_LEN_MSK, data); + + return 0; +} + +static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_component *component = codec_dai->component; + struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); + u8 iface_reg1 = 0; + u8 iface_reg2 = 0; + + /* set master/slave audio interface */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + iface_reg2 |= ADCX140_BCLK_FSYNC_MASTER; + break; + case SND_SOC_DAIFMT_CBS_CFS: + break; + case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBM_CFS: + default: + dev_err(component->dev, "Invalid DAI master/slave interface\n"); + return -EINVAL; + } + + /* signal polarity */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_IF: + iface_reg1 |= ADCX140_FSYNCINV_BIT; + break; + case SND_SOC_DAIFMT_IB_IF: + iface_reg1 |= ADCX140_BCLKINV_BIT | ADCX140_FSYNCINV_BIT; + break; + case SND_SOC_DAIFMT_IB_NF: + iface_reg1 |= ADCX140_BCLKINV_BIT; + break; + case SND_SOC_DAIFMT_NB_NF: + break; + default: + dev_err(component->dev, "Invalid DAI clock signal polarity\n"); + return -EINVAL; + } + + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + iface_reg1 |= ADCX140_I2S_MODE_BIT; + break; + case SND_SOC_DAIFMT_LEFT_J: + iface_reg1 |= ADCX140_LEFT_JUST_BIT; + break; + case SND_SOC_DAIFMT_DSP_A: + case SND_SOC_DAIFMT_DSP_B: + break; + default: + dev_err(component->dev, "Invalid DAI interface format\n"); + return -EINVAL; + } + + adcx140->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; + + snd_soc_component_update_bits(component, ADCX140_ASI_CFG0, + ADCX140_FSYNCINV_BIT | + ADCX140_BCLKINV_BIT | + ADCX140_ASI_FORMAT_MSK, + iface_reg1); + snd_soc_component_update_bits(component, ADCX140_MST_CFG0, + ADCX140_BCLK_FSYNC_MASTER, iface_reg2); + + return 0; +} + +static int adcx140_set_dai_tdm_slot(struct snd_soc_dai *codec_dai, + unsigned int tx_mask, unsigned int rx_mask, + int slots, int slot_width) +{ + struct snd_soc_component *component = codec_dai->component; + struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); + unsigned int lsb; + + if (tx_mask != rx_mask) { + dev_err(component->dev, "tx and rx masks must be symmetric\n"); + return -EINVAL; + } + + /* TDM based on DSP mode requires slots to be adjacent */ + lsb = __ffs(tx_mask); + if ((lsb + 1) != __fls(tx_mask)) { + dev_err(component->dev, "Invalid mask, slots must be adjacent\n"); + return -EINVAL; + } + + switch (slot_width) { + case 16: + case 20: + case 24: + case 32: + break; + default: + dev_err(component->dev, "Unsupported slot width %d\n", slot_width); + return -EINVAL; + } + + adcx140->tdm_delay = lsb; + adcx140->slot_width = slot_width; + + return 0; +} + +static int adcx140_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); + int offset = 0; + int width = adcx140->slot_width; + + if (!width) + width = substream->runtime->sample_bits; + + /* TDM slot selection only valid in DSP_A/_B mode */ + if (adcx140->dai_fmt == SND_SOC_DAIFMT_DSP_A) + offset += (adcx140->tdm_delay * width + 1); + else if (adcx140->dai_fmt == SND_SOC_DAIFMT_DSP_B) + offset += adcx140->tdm_delay * width; + + /* Configure data offset */ + snd_soc_component_update_bits(component, ADCX140_ASI_CFG1, + ADCX140_TX_OFFSET_MASK, offset); + + return 0; +} + +static const struct snd_soc_dai_ops adcx140_dai_ops = { + .hw_params = adcx140_hw_params, + .set_fmt = adcx140_set_dai_fmt, + .prepare = adcx140_prepare, + .set_tdm_slot = adcx140_set_dai_tdm_slot, +}; + +static int adcx140_codec_probe(struct snd_soc_component *component) +{ + struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); + int sleep_cfg_val = ADCX140_WAKE_DEV; + u8 bias_source; + u8 vref_source; + int ret; + + ret = device_property_read_u8(adcx140->dev, "ti,mic-bias-source", + &bias_source); + if (ret) + bias_source = ADCX140_MIC_BIAS_VAL_VREF; + + if (bias_source != ADCX140_MIC_BIAS_VAL_VREF && + bias_source != ADCX140_MIC_BIAS_VAL_VREF_1096 && + bias_source != ADCX140_MIC_BIAS_VAL_AVDD) { + dev_err(adcx140->dev, "Mic Bias source value is invalid\n"); + return -EINVAL; + } + + ret = device_property_read_u8(adcx140->dev, "ti,vref-source", + &vref_source); + if (ret) + vref_source = ADCX140_MIC_BIAS_VREF_275V; + + if (vref_source != ADCX140_MIC_BIAS_VREF_275V && + vref_source != ADCX140_MIC_BIAS_VREF_25V && + vref_source != ADCX140_MIC_BIAS_VREF_1375V) { + dev_err(adcx140->dev, "Mic Bias source value is invalid\n"); + return -EINVAL; + } + + bias_source |= vref_source; + + ret = adcx140_reset(adcx140); + if (ret) + goto out; + + if(adcx140->supply_areg == NULL) + sleep_cfg_val |= ADCX140_AREG_INTERNAL; + + ret = regmap_write(adcx140->regmap, ADCX140_SLEEP_CFG, sleep_cfg_val); + if (ret) { + dev_err(adcx140->dev, "setting sleep config failed %d\n", ret); + goto out; + } + + /* 8.4.3: Wait >= 1ms after entering active mode. */ + usleep_range(1000, 100000); + + ret = regmap_update_bits(adcx140->regmap, ADCX140_BIAS_CFG, + ADCX140_MIC_BIAS_VAL_MSK | + ADCX140_MIC_BIAS_VREF_MSK, bias_source); + if (ret) + dev_err(adcx140->dev, "setting MIC bias failed %d\n", ret); +out: + return ret; +} + +static int adcx140_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); + int pwr_cfg = 0; + + switch (level) { + case SND_SOC_BIAS_ON: + case SND_SOC_BIAS_PREPARE: + case SND_SOC_BIAS_STANDBY: + pwr_cfg = ADCX140_PWR_CFG_BIAS_PDZ | ADCX140_PWR_CFG_PLL_PDZ | + ADCX140_PWR_CFG_ADC_PDZ; + break; + case SND_SOC_BIAS_OFF: + pwr_cfg = 0x0; + break; + } + + return regmap_write(adcx140->regmap, ADCX140_PWR_CFG, pwr_cfg); +} + +static const struct snd_soc_component_driver soc_codec_driver_adcx140 = { + .probe = adcx140_codec_probe, + .set_bias_level = adcx140_set_bias_level, + .controls = adcx140_snd_controls, + .num_controls = ARRAY_SIZE(adcx140_snd_controls), + .dapm_widgets = adcx140_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adcx140_dapm_widgets), + .dapm_routes = adcx140_audio_map, + .num_dapm_routes = ARRAY_SIZE(adcx140_audio_map), + .suspend_bias_off = 1, + .idle_bias_on = 0, + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static struct snd_soc_dai_driver adcx140_dai_driver[] = { + { + .name = "tlv320adcx140-codec", + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = ADCX140_MAX_CHANNELS, + .rates = ADCX140_RATES, + .formats = ADCX140_FORMATS, + }, + .ops = &adcx140_dai_ops, + .symmetric_rates = 1, + } +}; + +static const struct of_device_id tlv320adcx140_of_match[] = { + { .compatible = "ti,tlv320adc3140" }, + { .compatible = "ti,tlv320adc5140" }, + { .compatible = "ti,tlv320adc6140" }, + {}, +}; +MODULE_DEVICE_TABLE(of, tlv320adcx140_of_match); + +static int adcx140_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct adcx140_priv *adcx140; + int ret; + + adcx140 = devm_kzalloc(&i2c->dev, sizeof(*adcx140), GFP_KERNEL); + if (!adcx140) + return -ENOMEM; + + adcx140->gpio_reset = devm_gpiod_get_optional(adcx140->dev, + "reset", GPIOD_OUT_LOW); + if (IS_ERR(adcx140->gpio_reset)) + dev_info(&i2c->dev, "Reset GPIO not defined\n"); + + adcx140->supply_areg = devm_regulator_get_optional(adcx140->dev, + "areg"); + if (IS_ERR(adcx140->supply_areg)) { + if (PTR_ERR(adcx140->supply_areg) == -EPROBE_DEFER) + return -EPROBE_DEFER; + else + adcx140->supply_areg = NULL; + } else { + ret = regulator_enable(adcx140->supply_areg); + if (ret) { + dev_err(adcx140->dev, "Failed to enable areg\n"); + return ret; + } + } + + adcx140->regmap = devm_regmap_init_i2c(i2c, &adcx140_i2c_regmap); + if (IS_ERR(adcx140->regmap)) { + ret = PTR_ERR(adcx140->regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + adcx140->dev = &i2c->dev; + i2c_set_clientdata(i2c, adcx140); + + return devm_snd_soc_register_component(&i2c->dev, + &soc_codec_driver_adcx140, + adcx140_dai_driver, 1); +} + +static const struct i2c_device_id adcx140_i2c_id[] = { + { "tlv320adc3140", 0 }, + { "tlv320adc5140", 1 }, + { "tlv320adc6140", 2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, adcx140_i2c_id); + +static struct i2c_driver adcx140_i2c_driver = { + .driver = { + .name = "tlv320adcx140-codec", + .of_match_table = of_match_ptr(tlv320adcx140_of_match), + }, + .probe = adcx140_i2c_probe, + .id_table = adcx140_i2c_id, +}; +module_i2c_driver(adcx140_i2c_driver); + +MODULE_AUTHOR("Dan Murphy "); +MODULE_DESCRIPTION("ASoC TLV320ADCX140 CODEC Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/tlv320adcx140.h b/sound/soc/codecs/tlv320adcx140.h new file mode 100644 index 000000000000..66b1c3b33f1e --- /dev/null +++ b/sound/soc/codecs/tlv320adcx140.h @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0 +// TLV320ADCX104 Sound driver +// Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ + +#ifndef _TLV320ADCX140_H +#define _TLV320ADCX140_H + +#define ADCX140_RATES (SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000) + +#define ADCX140_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +#define ADCX140_PAGE_SELECT 0x00 +#define ADCX140_SW_RESET 0x01 +#define ADCX140_SLEEP_CFG 0x02 +#define ADCX140_SHDN_CFG 0x05 +#define ADCX140_ASI_CFG0 0x07 +#define ADCX140_ASI_CFG1 0x08 +#define ADCX140_ASI_CFG2 0x09 +#define ADCX140_ASI_CH1 0x0b +#define ADCX140_ASI_CH2 0x0c +#define ADCX140_ASI_CH3 0x0d +#define ADCX140_ASI_CH4 0x0e +#define ADCX140_ASI_CH5 0x0f +#define ADCX140_ASI_CH6 0x10 +#define ADCX140_ASI_CH7 0x11 +#define ADCX140_ASI_CH8 0x12 +#define ADCX140_MST_CFG0 0x13 +#define ADCX140_MST_CFG1 0x14 +#define ADCX140_ASI_STS 0x15 +#define ADCX140_CLK_SRC 0x16 +#define ADCX140_PDMCLK_CFG 0x1f +#define ADCX140_PDM_CFG 0x20 +#define ADCX140_GPIO_CFG0 0x21 +#define ADCX140_GPO_CFG1 0x22 +#define ADCX140_GPO_CFG2 0x23 +#define ADCX140_GPO_CFG3 0x24 +#define ADCX140_GPO_CFG4 0x25 +#define ADCX140_GPO_VAL 0x29 +#define ADCX140_GPIO_MON 0x2a +#define ADCX140_GPI_CFG0 0x2b +#define ADCX140_GPI_CFG1 0x2c +#define ADCX140_GPI_MON 0x2f +#define ADCX140_INT_CFG 0x32 +#define ADCX140_INT_MASK0 0x33 +#define ADCX140_INT_LTCH0 0x36 +#define ADCX140_BIAS_CFG 0x3b +#define ADCX140_CH1_CFG0 0x3c +#define ADCX140_CH1_CFG1 0x3d +#define ADCX140_CH1_CFG2 0x3e +#define ADCX140_CH1_CFG3 0x3f +#define ADCX140_CH1_CFG4 0x40 +#define ADCX140_CH2_CFG0 0x41 +#define ADCX140_CH2_CFG1 0x42 +#define ADCX140_CH2_CFG2 0x43 +#define ADCX140_CH2_CFG3 0x44 +#define ADCX140_CH2_CFG4 0x45 +#define ADCX140_CH3_CFG0 0x46 +#define ADCX140_CH3_CFG1 0x47 +#define ADCX140_CH3_CFG2 0x48 +#define ADCX140_CH3_CFG3 0x49 +#define ADCX140_CH3_CFG4 0x4a +#define ADCX140_CH4_CFG0 0x4b +#define ADCX140_CH4_CFG1 0x4c +#define ADCX140_CH4_CFG2 0x4d +#define ADCX140_CH4_CFG3 0x4e +#define ADCX140_CH4_CFG4 0x4f +#define ADCX140_CH5_CFG2 0x52 +#define ADCX140_CH5_CFG3 0x53 +#define ADCX140_CH5_CFG4 0x54 +#define ADCX140_CH6_CFG2 0x57 +#define ADCX140_CH6_CFG3 0x58 +#define ADCX140_CH6_CFG4 0x59 +#define ADCX140_CH7_CFG2 0x5c +#define ADCX140_CH7_CFG3 0x5d +#define ADCX140_CH7_CFG4 0x5e +#define ADCX140_CH8_CFG2 0x61 +#define ADCX140_CH8_CFG3 0x62 +#define ADCX140_CH8_CFG4 0x63 +#define ADCX140_DSP_CFG0 0x6b +#define ADCX140_DSP_CFG1 0x6c +#define ADCX140_DRE_CFG0 0x6d +#define ADCX140_IN_CH_EN 0x73 +#define ADCX140_ASI_OUT_CH_EN 0x74 +#define ADCX140_PWR_CFG 0x75 +#define ADCX140_DEV_STS0 0x76 +#define ADCX140_DEV_STS1 0x77 + +#define ADCX140_RESET BIT(0) + +#define ADCX140_WAKE_DEV BIT(0) +#define ADCX140_AREG_INTERNAL BIT(7) + +#define ADCX140_BCLKINV_BIT BIT(2) +#define ADCX140_FSYNCINV_BIT BIT(3) +#define ADCX140_INV_MSK (ADCX140_BCLKINV_BIT | ADCX140_FSYNCINV_BIT) +#define ADCX140_BCLK_FSYNC_MASTER BIT(7) +#define ADCX140_I2S_MODE_BIT BIT(6) +#define ADCX140_LEFT_JUST_BIT BIT(7) +#define ADCX140_ASI_FORMAT_MSK (ADCX140_I2S_MODE_BIT | ADCX140_LEFT_JUST_BIT) + +#define ADCX140_16_BIT_WORD 0x0 +#define ADCX140_20_BIT_WORD BIT(4) +#define ADCX140_24_BIT_WORD BIT(5) +#define ADCX140_32_BIT_WORD (BIT(4) | BIT(5)) +#define ADCX140_WORD_LEN_MSK 0x30 + +#define ADCX140_MAX_CHANNELS 8 + +#define ADCX140_MIC_BIAS_VAL_VREF 0 +#define ADCX140_MIC_BIAS_VAL_VREF_1096 1 +#define ADCX140_MIC_BIAS_VAL_AVDD 6 +#define ADCX140_MIC_BIAS_VAL_MSK GENMASK(6, 4) + +#define ADCX140_MIC_BIAS_VREF_275V 0 +#define ADCX140_MIC_BIAS_VREF_25V 1 +#define ADCX140_MIC_BIAS_VREF_1375V 2 +#define ADCX140_MIC_BIAS_VREF_MSK GENMASK(1, 0) + +#define ADCX140_PWR_CFG_BIAS_PDZ BIT(7) +#define ADCX140_PWR_CFG_ADC_PDZ BIT(6) +#define ADCX140_PWR_CFG_PLL_PDZ BIT(5) + +#define ADCX140_TX_OFFSET_MASK GENMASK(4, 0) + +#endif /* _TLV320ADCX140_ */ From 9ffc1d19fc4a6dfcfe06c91c2861ad6d44fdd92d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 30 Jan 2020 12:06:07 -0800 Subject: [PATCH 0559/4444] mm/memremap_pages: Introduce memremap_compat_align() The "sub-section memory hotplug" facility allows memremap_pages() users like libnvdimm to compensate for hardware platforms like x86 that have a section size larger than their hardware memory mapping granularity. The compensation that sub-section support affords is being tolerant of physical memory resources shifting by units smaller (64MiB on x86) than the memory-hotplug section size (128 MiB). Where the platform physical-memory mapping granularity is limited by the number and capability of address-decode-registers in the memory controller. While the sub-section support allows memremap_pages() to operate on sub-section (2MiB) granularity, the Power architecture may still require 16MiB alignment on "!radix_enabled()" platforms. In order for libnvdimm to be able to detect and manage this per-arch limitation, introduce memremap_compat_align() as a common minimum alignment across all driver-facing memory-mapping interfaces, and let Power override it to 16MiB in the "!radix_enabled()" case. The assumption / requirement for 16MiB to be a viable memremap_compat_align() value is that Power does not have platforms where its equivalent of address-decode-registers never hardware remaps a persistent memory resource on smaller than 16MiB boundaries. Note that I tried my best to not add a new Kconfig symbol, but header include entanglements defeated the #ifndef memremap_compat_align design pattern and the need to export it defeats the __weak design pattern for arch overrides. Based on an initial patch by Aneesh. Link: http://lore.kernel.org/r/CAPcyv4gBGNP95APYaBcsocEa50tQj9b5h__83vgngjq3ouGX_Q@mail.gmail.com Reported-by: Aneesh Kumar K.V Reported-by: Jeff Moyer Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Reviewed-by: Aneesh Kumar K.V Acked-by: Michael Ellerman (powerpc) Signed-off-by: Dan Williams --- arch/powerpc/Kconfig | 1 + arch/powerpc/mm/ioremap.c | 21 +++++++++++++++++++++ drivers/nvdimm/pfn_devs.c | 2 +- include/linux/memremap.h | 8 ++++++++ include/linux/mmzone.h | 1 + lib/Kconfig | 3 +++ mm/memremap.c | 23 +++++++++++++++++++++++ 7 files changed, 58 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 497b7d0b2d7e..e6ffe905e2b9 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -122,6 +122,7 @@ config PPC select ARCH_HAS_GCOV_PROFILE_ALL select ARCH_HAS_KCOV select ARCH_HAS_HUGEPD if HUGETLB_PAGE + select ARCH_HAS_MEMREMAP_COMPAT_ALIGN select ARCH_HAS_MMIOWB if PPC64 select ARCH_HAS_PHYS_TO_DMA select ARCH_HAS_PMEM_API diff --git a/arch/powerpc/mm/ioremap.c b/arch/powerpc/mm/ioremap.c index fc669643ce6a..b1a0aebe8c48 100644 --- a/arch/powerpc/mm/ioremap.c +++ b/arch/powerpc/mm/ioremap.c @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -97,3 +98,23 @@ void __iomem *do_ioremap(phys_addr_t pa, phys_addr_t offset, unsigned long size, return NULL; } + +#ifdef CONFIG_ZONE_DEVICE +/* + * Override the generic version in mm/memremap.c. + * + * With hash translation, the direct-map range is mapped with just one + * page size selected by htab_init_page_sizes(). Consult + * mmu_psize_defs[] to determine the minimum page size alignment. +*/ +unsigned long memremap_compat_align(void) +{ + unsigned int shift = mmu_psize_defs[mmu_linear_psize].shift; + + if (radix_enabled()) + return SUBSECTION_SIZE; + return max(SUBSECTION_SIZE, 1UL << shift); + +} +EXPORT_SYMBOL_GPL(memremap_compat_align); +#endif diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c index b94f7a7e94b8..a5c25cb87116 100644 --- a/drivers/nvdimm/pfn_devs.c +++ b/drivers/nvdimm/pfn_devs.c @@ -750,7 +750,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) start = nsio->res.start; size = resource_size(&nsio->res); npfns = PHYS_PFN(size - SZ_8K); - align = max(nd_pfn->align, (1UL << SUBSECTION_SHIFT)); + align = max(nd_pfn->align, SUBSECTION_SIZE); end_trunc = start + size - ALIGN_DOWN(start + size, align); if (nd_pfn->mode == PFN_MODE_PMEM) { /* diff --git a/include/linux/memremap.h b/include/linux/memremap.h index 6fefb09af7c3..8af1cbd8f293 100644 --- a/include/linux/memremap.h +++ b/include/linux/memremap.h @@ -132,6 +132,7 @@ struct dev_pagemap *get_dev_pagemap(unsigned long pfn, unsigned long vmem_altmap_offset(struct vmem_altmap *altmap); void vmem_altmap_free(struct vmem_altmap *altmap, unsigned long nr_pfns); +unsigned long memremap_compat_align(void); #else static inline void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap) @@ -165,6 +166,12 @@ static inline void vmem_altmap_free(struct vmem_altmap *altmap, unsigned long nr_pfns) { } + +/* when memremap_pages() is disabled all archs can remap a single page */ +static inline unsigned long memremap_compat_align(void) +{ + return PAGE_SIZE; +} #endif /* CONFIG_ZONE_DEVICE */ static inline void put_dev_pagemap(struct dev_pagemap *pgmap) @@ -172,4 +179,5 @@ static inline void put_dev_pagemap(struct dev_pagemap *pgmap) if (pgmap) percpu_ref_put(pgmap->ref); } + #endif /* _LINUX_MEMREMAP_H_ */ diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 462f6873905a..6b77f7239af5 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -1170,6 +1170,7 @@ static inline unsigned long section_nr_to_pfn(unsigned long sec) #define SECTION_ALIGN_DOWN(pfn) ((pfn) & PAGE_SECTION_MASK) #define SUBSECTION_SHIFT 21 +#define SUBSECTION_SIZE (1UL << SUBSECTION_SHIFT) #define PFN_SUBSECTION_SHIFT (SUBSECTION_SHIFT - PAGE_SHIFT) #define PAGES_PER_SUBSECTION (1UL << PFN_SUBSECTION_SHIFT) diff --git a/lib/Kconfig b/lib/Kconfig index bc7e56370129..5d53f9609c25 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -615,6 +615,9 @@ config ARCH_HAS_PMEM_API config MEMREGION bool +config ARCH_HAS_MEMREMAP_COMPAT_ALIGN + bool + # use memcpy to implement user copies for nommu architectures config UACCESS_MEMCPY bool diff --git a/mm/memremap.c b/mm/memremap.c index 09b5b7adc773..3e7afaf05639 100644 --- a/mm/memremap.c +++ b/mm/memremap.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,28 @@ static DEFINE_XARRAY(pgmap_array); +/* + * The memremap() and memremap_pages() interfaces are alternately used + * to map persistent memory namespaces. These interfaces place different + * constraints on the alignment and size of the mapping (namespace). + * memremap() can map individual PAGE_SIZE pages. memremap_pages() can + * only map subsections (2MB), and at least one architecture (PowerPC) + * the minimum mapping granularity of memremap_pages() is 16MB. + * + * The role of memremap_compat_align() is to communicate the minimum + * arch supported alignment of a namespace such that it can freely + * switch modes without violating the arch constraint. Namely, do not + * allow a namespace to be PAGE_SIZE aligned since that namespace may be + * reconfigured into a mode that requires SUBSECTION_SIZE alignment. + */ +#ifndef CONFIG_ARCH_HAS_MEMREMAP_COMPAT_ALIGN +unsigned long memremap_compat_align(void) +{ + return SUBSECTION_SIZE; +} +EXPORT_SYMBOL_GPL(memremap_compat_align); +#endif + #ifdef CONFIG_DEV_PAGEMAP_OPS DEFINE_STATIC_KEY_FALSE(devmap_managed_key); EXPORT_SYMBOL(devmap_managed_key); From 202853595e53f981c86656c49fc1cc1e3620f558 Mon Sep 17 00:00:00 2001 From: Alexandru Gagniuc Date: Fri, 25 Oct 2019 15:00:45 -0400 Subject: [PATCH 0560/4444] PCI: pciehp: Disable in-band presence detect when possible The presence detect state (PDS) is normally a logical OR of in-band and out-of-band (OOB) presence detect. As of PCIe 4.0, there is the option to disable in-band presence so that the PDS bit always reflects the state of the out-of-band presence. The recommendation of the PCIe spec is to disable in-band presence whenever supported (PCIe r5.0, appendix I implementation note): Due to architectural issues, the in-band (Physical-Layer-based) portion of the PD mechanism is deprecated for use with async hot-plug. One issue is that in-band PD as architected does not detect adapter removal during certain LTSSM states, notably the L1 and Disabled States. Another issue is that when both in-band and OOB PD are being used together, the Presence Detect State bit and its associated interrupt mechanism always reflect the logical OR of the inband and OOB PD states, and with some hot-plug hardware configurations, it is important for software to detect and respond to in-band and OOB PD events independently. If OOB PD is being used and the associated DSP supports In-Band PD Disable, it is recommended that the In-Band PD Disable bit be Set, and the Presence Detect State bit and its associated interrupt mechanism be used exclusively for OOB PD. As a substitute for in-band PD with async hot-plug, the reference model uses either the DPC or the DLL Link Active mechanism. Link: https://lore.kernel.org/r/20191025190047.38130-2-stuart.w.hayes@gmail.com [bhelgaas: move PCI_EXP_SLTCAP2 read earlier & print PCI_EXP_SLTCAP2_IBPD value (suggested by Lukas)] Signed-off-by: Alexandru Gagniuc Signed-off-by: Bjorn Helgaas Reviewed-by: Andy Shevchenko Reviewed-by: Lukas Wunner --- drivers/pci/hotplug/pciehp.h | 1 + drivers/pci/hotplug/pciehp_hpc.c | 12 ++++++++++-- include/uapi/linux/pci_regs.h | 2 ++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index aa61d4c219d7..ae44f46d1bf3 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -84,6 +84,7 @@ struct controller { struct pcie_device *pcie; u32 slot_cap; /* capabilities and quirks */ + unsigned int inband_presence_disabled:1; u16 slot_ctrl; /* control register access */ struct mutex ctrl_lock; diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 8a2cb1764386..a573490289c3 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -848,7 +848,7 @@ static inline void dbg_ctrl(struct controller *ctrl) struct controller *pcie_init(struct pcie_device *dev) { struct controller *ctrl; - u32 slot_cap, link_cap; + u32 slot_cap, slot_cap2, link_cap; u8 poweron; struct pci_dev *pdev = dev->port; struct pci_bus *subordinate = pdev->subordinate; @@ -883,6 +883,13 @@ struct controller *pcie_init(struct pcie_device *dev) ctrl->state = list_empty(&subordinate->devices) ? OFF_STATE : ON_STATE; up_read(&pci_bus_sem); + pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP2, &slot_cap2); + if (slot_cap2 & PCI_EXP_SLTCAP2_IBPD) { + pcie_write_cmd_nowait(ctrl, PCI_EXP_SLTCTL_IBPD_DISABLE, + PCI_EXP_SLTCTL_IBPD_DISABLE); + ctrl->inband_presence_disabled = 1; + } + /* Check if Data Link Layer Link Active Reporting is implemented */ pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap); @@ -892,7 +899,7 @@ struct controller *pcie_init(struct pcie_device *dev) PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC | PCI_EXP_SLTSTA_PDC); - ctrl_info(ctrl, "Slot #%d AttnBtn%c PwrCtrl%c MRL%c AttnInd%c PwrInd%c HotPlug%c Surprise%c Interlock%c NoCompl%c LLActRep%c%s\n", + ctrl_info(ctrl, "Slot #%d AttnBtn%c PwrCtrl%c MRL%c AttnInd%c PwrInd%c HotPlug%c Surprise%c Interlock%c NoCompl%c IbPresDis%c LLActRep%c%s\n", (slot_cap & PCI_EXP_SLTCAP_PSN) >> 19, FLAG(slot_cap, PCI_EXP_SLTCAP_ABP), FLAG(slot_cap, PCI_EXP_SLTCAP_PCP), @@ -903,6 +910,7 @@ struct controller *pcie_init(struct pcie_device *dev) FLAG(slot_cap, PCI_EXP_SLTCAP_HPS), FLAG(slot_cap, PCI_EXP_SLTCAP_EIP), FLAG(slot_cap, PCI_EXP_SLTCAP_NCCS), + FLAG(slot_cap2, PCI_EXP_SLTCAP2_IBPD), FLAG(link_cap, PCI_EXP_LNKCAP_DLLLARC), pdev->broken_cmd_compl ? " (with Cmd Compl erratum)" : ""); diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index 5437690483cd..f9701410d3b5 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h @@ -605,6 +605,7 @@ #define PCI_EXP_SLTCTL_PWR_OFF 0x0400 /* Power Off */ #define PCI_EXP_SLTCTL_EIC 0x0800 /* Electromechanical Interlock Control */ #define PCI_EXP_SLTCTL_DLLSCE 0x1000 /* Data Link Layer State Changed Enable */ +#define PCI_EXP_SLTCTL_IBPD_DISABLE 0x4000 /* In-band PD disable */ #define PCI_EXP_SLTSTA 26 /* Slot Status */ #define PCI_EXP_SLTSTA_ABP 0x0001 /* Attention Button Pressed */ #define PCI_EXP_SLTSTA_PFD 0x0002 /* Power Fault Detected */ @@ -680,6 +681,7 @@ #define PCI_EXP_LNKSTA2 50 /* Link Status 2 */ #define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 52 /* v2 endpoints with link end here */ #define PCI_EXP_SLTCAP2 52 /* Slot Capabilities 2 */ +#define PCI_EXP_SLTCAP2_IBPD 0x00000001 /* In-band PD Disable Supported */ #define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */ #define PCI_EXP_SLTSTA2 58 /* Slot Status 2 */ From f496648b99f8f7f6711f7c30a6327381f37dd1e8 Mon Sep 17 00:00:00 2001 From: Alexandru Gagniuc Date: Fri, 25 Oct 2019 15:00:46 -0400 Subject: [PATCH 0561/4444] PCI: pciehp: Wait for PDS if in-band presence is disabled When in-band presence detect is disabled, PDS may come up at any time or not at all. PDS being low may indicate that the card is still mating, and we could expect contact bounce to bring down the link as well. It is reasonable to assume that most cards will mate in a hotplug slot in about a second. Thus, when we know PDS only reflects out-of-band presence detect, it's worthwhile to wait the extra second or so to make sure the card is properly mated before loading the driver and to prevent the hotplug code from disabling a device if the presence detect change goes active after the device is enabled. Link: https://lore.kernel.org/r/20191025190047.38130-3-stuart.w.hayes@gmail.com [bhelgaas: use ctrl_info() instead of pci_info()] Signed-off-by: Alexandru Gagniuc Signed-off-by: Stuart Hayes Signed-off-by: Bjorn Helgaas Reviewed-by: Andy Shevchenko Reviewed-by: Lukas Wunner --- drivers/pci/hotplug/pciehp_hpc.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index a573490289c3..bb9ad0032e6b 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -252,6 +252,22 @@ static bool pci_bus_check_dev(struct pci_bus *bus, int devfn) return found; } +static void pcie_wait_for_presence(struct pci_dev *pdev) +{ + int timeout = 1250; + u16 slot_status; + + do { + pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); + if (slot_status & PCI_EXP_SLTSTA_PDS) + return; + msleep(10); + timeout -= 10; + } while (timeout > 0); + + pci_info(pdev, "Timeout waiting for Presence Detect\n"); +} + int pciehp_check_link_status(struct controller *ctrl) { struct pci_dev *pdev = ctrl_dev(ctrl); @@ -261,6 +277,9 @@ int pciehp_check_link_status(struct controller *ctrl) if (!pcie_wait_for_link(pdev, true)) return -1; + if (ctrl->inband_presence_disabled) + pcie_wait_for_presence(pdev); + found = pci_bus_check_dev(ctrl->pcie->port->subordinate, PCI_DEVFN(0, 0)); From 0b382546d863f2f09eecaccda95a0b4bfd148f92 Mon Sep 17 00:00:00 2001 From: Stuart Hayes Date: Fri, 25 Oct 2019 15:00:47 -0400 Subject: [PATCH 0562/4444] PCI: pciehp: Add DMI table for in-band presence detection disabled Some systems have in-band presence detection disabled for hot-plug PCI slots but do not report this in the slot capabilities 2 (SLTCAP2) register. On these systems, presence detect can become active well after the link is reported to be active, which can cause the slots to be disabled after a device is connected. Add a DMI table to flag these systems as having in-band presence detect disabled. Link: https://lore.kernel.org/r/20191025190047.38130-4-stuart.w.hayes@gmail.com Signed-off-by: Stuart Hayes Signed-off-by: Bjorn Helgaas Reviewed-by: Andy Shevchenko Reviewed-by: Lukas Wunner --- drivers/pci/hotplug/pciehp_hpc.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index bb9ad0032e6b..e4627c68b30f 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -14,6 +14,7 @@ #define dev_fmt(fmt) "pciehp: " fmt +#include #include #include #include @@ -26,6 +27,24 @@ #include "../pci.h" #include "pciehp.h" +static const struct dmi_system_id inband_presence_disabled_dmi_table[] = { + /* + * Match all Dell systems, as some Dell systems have inband + * presence disabled on NVMe slots (but don't support the bit to + * report it). Setting inband presence disabled should have no + * negative effect, except on broken hotplug slots that never + * assert presence detect--and those will still work, they will + * just have a bit of extra delay before being probed. + */ + { + .ident = "Dell System", + .matches = { + DMI_MATCH(DMI_OEM_STRING, "Dell System"), + }, + }, + {} +}; + static inline struct pci_dev *ctrl_dev(struct controller *ctrl) { return ctrl->pcie->port; @@ -909,6 +928,9 @@ struct controller *pcie_init(struct pcie_device *dev) ctrl->inband_presence_disabled = 1; } + if (dmi_first_match(inband_presence_disabled_dmi_table)) + ctrl->inband_presence_disabled = 1; + /* Check if Data Link Layer Link Active Reporting is implemented */ pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap); From 71202c412478d6553281726a6772d0d5510c42fb Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Thu, 20 Feb 2020 21:44:33 +0100 Subject: [PATCH 0563/4444] clk: meson: meson8b: set audio output clock hierarchy The aiu devices peripheral clocks needs the aiu and aiu_glue clocks to operate. Reflect this hierarchy in the clock tree. Fixes: e31a1900c1ff73 ("meson: clk: Add support for clock gates") Suggested-by: Jerome Brunet Signed-off-by: Martin Blumenstingl Reviewed-by: Neil Armstrong Signed-off-by: Jerome Brunet --- drivers/clk/meson/meson8b.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index 9fd31f23b2a9..34a70c4b4899 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -2605,14 +2605,6 @@ static MESON_GATE(meson8b_spi, HHI_GCLK_MPEG0, 30); static MESON_GATE(meson8b_i2s_spdif, HHI_GCLK_MPEG1, 2); static MESON_GATE(meson8b_eth, HHI_GCLK_MPEG1, 3); static MESON_GATE(meson8b_demux, HHI_GCLK_MPEG1, 4); -static MESON_GATE(meson8b_aiu_glue, HHI_GCLK_MPEG1, 6); -static MESON_GATE(meson8b_iec958, HHI_GCLK_MPEG1, 7); -static MESON_GATE(meson8b_i2s_out, HHI_GCLK_MPEG1, 8); -static MESON_GATE(meson8b_amclk, HHI_GCLK_MPEG1, 9); -static MESON_GATE(meson8b_aififo2, HHI_GCLK_MPEG1, 10); -static MESON_GATE(meson8b_mixer, HHI_GCLK_MPEG1, 11); -static MESON_GATE(meson8b_mixer_iface, HHI_GCLK_MPEG1, 12); -static MESON_GATE(meson8b_adc, HHI_GCLK_MPEG1, 13); static MESON_GATE(meson8b_blkmv, HHI_GCLK_MPEG1, 14); static MESON_GATE(meson8b_aiu, HHI_GCLK_MPEG1, 15); static MESON_GATE(meson8b_uart1, HHI_GCLK_MPEG1, 16); @@ -2659,6 +2651,19 @@ static MESON_GATE(meson8b_vclk2_vencl, HHI_GCLK_OTHER, 25); static MESON_GATE(meson8b_vclk2_other, HHI_GCLK_OTHER, 26); static MESON_GATE(meson8b_edp, HHI_GCLK_OTHER, 31); +/* AIU gates */ +#define MESON_AIU_GLUE_GATE(_name, _reg, _bit) \ + MESON_PCLK(_name, _reg, _bit, &meson8b_aiu_glue.hw) + +static MESON_PCLK(meson8b_aiu_glue, HHI_GCLK_MPEG1, 6, &meson8b_aiu.hw); +static MESON_AIU_GLUE_GATE(meson8b_iec958, HHI_GCLK_MPEG1, 7); +static MESON_AIU_GLUE_GATE(meson8b_i2s_out, HHI_GCLK_MPEG1, 8); +static MESON_AIU_GLUE_GATE(meson8b_amclk, HHI_GCLK_MPEG1, 9); +static MESON_AIU_GLUE_GATE(meson8b_aififo2, HHI_GCLK_MPEG1, 10); +static MESON_AIU_GLUE_GATE(meson8b_mixer, HHI_GCLK_MPEG1, 11); +static MESON_AIU_GLUE_GATE(meson8b_mixer_iface, HHI_GCLK_MPEG1, 12); +static MESON_AIU_GLUE_GATE(meson8b_adc, HHI_GCLK_MPEG1, 13); + /* Always On (AO) domain gates */ static MESON_GATE(meson8b_ao_media_cpu, HHI_GCLK_AO, 0); From 1f442218d657b1a20900f09ae1fc269b69b3de70 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Thu, 13 Feb 2020 12:06:32 +0800 Subject: [PATCH 0564/4444] PCI: mobiveil: Introduce a new structure mobiveil_root_port The Mobiveil PCIe controller can work in either Root Complex mode or Endpoint mode. Introduce a new structure mobiveil_root_port and abstract the RC related members into it so that the code can be used by both modes. Signed-off-by: Hou Zhiqiang Signed-off-by: Lorenzo Pieralisi Reviewed-by: Andrew Murray --- drivers/pci/controller/pcie-mobiveil.c | 99 ++++++++++++++++---------- 1 file changed, 60 insertions(+), 39 deletions(-) diff --git a/drivers/pci/controller/pcie-mobiveil.c b/drivers/pci/controller/pcie-mobiveil.c index 3a696ca45bfa..a7c2354465a1 100644 --- a/drivers/pci/controller/pcie-mobiveil.c +++ b/drivers/pci/controller/pcie-mobiveil.c @@ -3,7 +3,10 @@ * PCIe host controller driver for Mobiveil PCIe Host controller * * Copyright (c) 2018 Mobiveil Inc. + * Copyright 2019-2020 NXP + * * Author: Subrahmanya Lingappa + * Hou Zhiqiang */ #include @@ -138,22 +141,27 @@ struct mobiveil_msi { /* MSI information */ DECLARE_BITMAP(msi_irq_in_use, PCI_NUM_MSI); }; +struct mobiveil_root_port { + char root_bus_nr; + void __iomem *config_axi_slave_base; /* endpoint config base */ + struct resource *ob_io_res; + int irq; + raw_spinlock_t intx_mask_lock; + struct irq_domain *intx_domain; + struct mobiveil_msi msi; + struct pci_host_bridge *bridge; +}; + struct mobiveil_pcie { struct platform_device *pdev; - void __iomem *config_axi_slave_base; /* endpoint config base */ void __iomem *csr_axi_slave_base; /* root port config base */ void __iomem *apb_csr_base; /* MSI register base */ phys_addr_t pcie_reg_base; /* Physical PCIe Controller Base */ - struct irq_domain *intx_domain; - raw_spinlock_t intx_mask_lock; - int irq; int apio_wins; int ppio_wins; int ob_wins_configured; /* configured outbound windows */ int ib_wins_configured; /* configured inbound windows */ - struct resource *ob_io_res; - char root_bus_nr; - struct mobiveil_msi msi; + struct mobiveil_root_port rp; }; /* @@ -281,16 +289,17 @@ static bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie) static bool mobiveil_pcie_valid_device(struct pci_bus *bus, unsigned int devfn) { struct mobiveil_pcie *pcie = bus->sysdata; + struct mobiveil_root_port *rp = &pcie->rp; /* Only one device down on each root port */ - if ((bus->number == pcie->root_bus_nr) && (devfn > 0)) + if ((bus->number == rp->root_bus_nr) && (devfn > 0)) return false; /* * Do not read more than one device on the bus directly * attached to RC */ - if ((bus->primary == pcie->root_bus_nr) && (PCI_SLOT(devfn) > 0)) + if ((bus->primary == rp->root_bus_nr) && (PCI_SLOT(devfn) > 0)) return false; return true; @@ -304,13 +313,14 @@ static void __iomem *mobiveil_pcie_map_bus(struct pci_bus *bus, unsigned int devfn, int where) { struct mobiveil_pcie *pcie = bus->sysdata; + struct mobiveil_root_port *rp = &pcie->rp; u32 value; if (!mobiveil_pcie_valid_device(bus, devfn)) return NULL; /* RC config access */ - if (bus->number == pcie->root_bus_nr) + if (bus->number == rp->root_bus_nr) return pcie->csr_axi_slave_base + where; /* @@ -325,7 +335,7 @@ static void __iomem *mobiveil_pcie_map_bus(struct pci_bus *bus, mobiveil_csr_writel(pcie, value, PAB_AXI_AMAP_PEX_WIN_L(WIN_NUM_0)); - return pcie->config_axi_slave_base + where; + return rp->config_axi_slave_base + where; } static struct pci_ops mobiveil_pcie_ops = { @@ -339,7 +349,8 @@ static void mobiveil_pcie_isr(struct irq_desc *desc) struct irq_chip *chip = irq_desc_get_chip(desc); struct mobiveil_pcie *pcie = irq_desc_get_handler_data(desc); struct device *dev = &pcie->pdev->dev; - struct mobiveil_msi *msi = &pcie->msi; + struct mobiveil_root_port *rp = &pcie->rp; + struct mobiveil_msi *msi = &rp->msi; u32 msi_data, msi_addr_lo, msi_addr_hi; u32 intr_status, msi_status; unsigned long shifted_status; @@ -365,7 +376,7 @@ static void mobiveil_pcie_isr(struct irq_desc *desc) shifted_status >>= PAB_INTX_START; do { for_each_set_bit(bit, &shifted_status, PCI_NUM_INTX) { - virq = irq_find_mapping(pcie->intx_domain, + virq = irq_find_mapping(rp->intx_domain, bit + 1); if (virq) generic_handle_irq(virq); @@ -424,15 +435,16 @@ static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie) struct device *dev = &pcie->pdev->dev; struct platform_device *pdev = pcie->pdev; struct device_node *node = dev->of_node; + struct mobiveil_root_port *rp = &pcie->rp; struct resource *res; /* map config resource */ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config_axi_slave"); - pcie->config_axi_slave_base = devm_pci_remap_cfg_resource(dev, res); - if (IS_ERR(pcie->config_axi_slave_base)) - return PTR_ERR(pcie->config_axi_slave_base); - pcie->ob_io_res = res; + rp->config_axi_slave_base = devm_pci_remap_cfg_resource(dev, res); + if (IS_ERR(rp->config_axi_slave_base)) + return PTR_ERR(rp->config_axi_slave_base); + rp->ob_io_res = res; /* map csr resource */ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, @@ -455,9 +467,9 @@ static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie) if (of_property_read_u32(node, "ppio-wins", &pcie->ppio_wins)) pcie->ppio_wins = MAX_PIO_WINDOWS; - pcie->irq = platform_get_irq(pdev, 0); - if (pcie->irq <= 0) { - dev_err(dev, "failed to map IRQ: %d\n", pcie->irq); + rp->irq = platform_get_irq(pdev, 0); + if (rp->irq <= 0) { + dev_err(dev, "failed to map IRQ: %d\n", rp->irq); return -ENODEV; } @@ -564,9 +576,9 @@ static int mobiveil_bringup_link(struct mobiveil_pcie *pcie) static void mobiveil_pcie_enable_msi(struct mobiveil_pcie *pcie) { phys_addr_t msg_addr = pcie->pcie_reg_base; - struct mobiveil_msi *msi = &pcie->msi; + struct mobiveil_msi *msi = &pcie->rp.msi; - pcie->msi.num_of_vectors = PCI_NUM_MSI; + msi->num_of_vectors = PCI_NUM_MSI; msi->msi_pages_phys = (phys_addr_t)msg_addr; writel_relaxed(lower_32_bits(msg_addr), @@ -579,7 +591,8 @@ static void mobiveil_pcie_enable_msi(struct mobiveil_pcie *pcie) static int mobiveil_host_init(struct mobiveil_pcie *pcie) { - struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); + struct mobiveil_root_port *rp = &pcie->rp; + struct pci_host_bridge *bridge = rp->bridge; u32 value, pab_ctrl, type; struct resource_entry *win; @@ -629,8 +642,8 @@ static int mobiveil_host_init(struct mobiveil_pcie *pcie) */ /* config outbound translation window */ - program_ob_windows(pcie, WIN_NUM_0, pcie->ob_io_res->start, 0, - CFG_WINDOW_TYPE, resource_size(pcie->ob_io_res)); + program_ob_windows(pcie, WIN_NUM_0, rp->ob_io_res->start, 0, + CFG_WINDOW_TYPE, resource_size(rp->ob_io_res)); /* memory inbound translation window */ program_ib_windows(pcie, WIN_NUM_0, 0, 0, MEM_WINDOW_TYPE, IB_WIN_SIZE); @@ -667,32 +680,36 @@ static void mobiveil_mask_intx_irq(struct irq_data *data) { struct irq_desc *desc = irq_to_desc(data->irq); struct mobiveil_pcie *pcie; + struct mobiveil_root_port *rp; unsigned long flags; u32 mask, shifted_val; pcie = irq_desc_get_chip_data(desc); + rp = &pcie->rp; mask = 1 << ((data->hwirq + PAB_INTX_START) - 1); - raw_spin_lock_irqsave(&pcie->intx_mask_lock, flags); + raw_spin_lock_irqsave(&rp->intx_mask_lock, flags); shifted_val = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB); shifted_val &= ~mask; mobiveil_csr_writel(pcie, shifted_val, PAB_INTP_AMBA_MISC_ENB); - raw_spin_unlock_irqrestore(&pcie->intx_mask_lock, flags); + raw_spin_unlock_irqrestore(&rp->intx_mask_lock, flags); } static void mobiveil_unmask_intx_irq(struct irq_data *data) { struct irq_desc *desc = irq_to_desc(data->irq); struct mobiveil_pcie *pcie; + struct mobiveil_root_port *rp; unsigned long flags; u32 shifted_val, mask; pcie = irq_desc_get_chip_data(desc); + rp = &pcie->rp; mask = 1 << ((data->hwirq + PAB_INTX_START) - 1); - raw_spin_lock_irqsave(&pcie->intx_mask_lock, flags); + raw_spin_lock_irqsave(&rp->intx_mask_lock, flags); shifted_val = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB); shifted_val |= mask; mobiveil_csr_writel(pcie, shifted_val, PAB_INTP_AMBA_MISC_ENB); - raw_spin_unlock_irqrestore(&pcie->intx_mask_lock, flags); + raw_spin_unlock_irqrestore(&rp->intx_mask_lock, flags); } static struct irq_chip intx_irq_chip = { @@ -760,7 +777,7 @@ static int mobiveil_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int nr_irqs, void *args) { struct mobiveil_pcie *pcie = domain->host_data; - struct mobiveil_msi *msi = &pcie->msi; + struct mobiveil_msi *msi = &pcie->rp.msi; unsigned long bit; WARN_ON(nr_irqs != 1); @@ -787,7 +804,7 @@ static void mobiveil_irq_msi_domain_free(struct irq_domain *domain, { struct irq_data *d = irq_domain_get_irq_data(domain, virq); struct mobiveil_pcie *pcie = irq_data_get_irq_chip_data(d); - struct mobiveil_msi *msi = &pcie->msi; + struct mobiveil_msi *msi = &pcie->rp.msi; mutex_lock(&msi->lock); @@ -808,9 +825,9 @@ static int mobiveil_allocate_msi_domains(struct mobiveil_pcie *pcie) { struct device *dev = &pcie->pdev->dev; struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node); - struct mobiveil_msi *msi = &pcie->msi; + struct mobiveil_msi *msi = &pcie->rp.msi; - mutex_init(&pcie->msi.lock); + mutex_init(&msi->lock); msi->dev_domain = irq_domain_add_linear(NULL, msi->num_of_vectors, &msi_domain_ops, pcie); if (!msi->dev_domain) { @@ -834,18 +851,19 @@ static int mobiveil_pcie_init_irq_domain(struct mobiveil_pcie *pcie) { struct device *dev = &pcie->pdev->dev; struct device_node *node = dev->of_node; + struct mobiveil_root_port *rp = &pcie->rp; int ret; /* setup INTx */ - pcie->intx_domain = irq_domain_add_linear(node, PCI_NUM_INTX, - &intx_domain_ops, pcie); + rp->intx_domain = irq_domain_add_linear(node, PCI_NUM_INTX, + &intx_domain_ops, pcie); - if (!pcie->intx_domain) { + if (!rp->intx_domain) { dev_err(dev, "Failed to get a INTx IRQ domain\n"); return -ENOMEM; } - raw_spin_lock_init(&pcie->intx_mask_lock); + raw_spin_lock_init(&rp->intx_mask_lock); /* setup MSI */ ret = mobiveil_allocate_msi_domains(pcie); @@ -862,6 +880,7 @@ static int mobiveil_pcie_probe(struct platform_device *pdev) struct pci_bus *child; struct pci_host_bridge *bridge; struct device *dev = &pdev->dev; + struct mobiveil_root_port *rp; int ret; /* allocate the PCIe port */ @@ -870,6 +889,8 @@ static int mobiveil_pcie_probe(struct platform_device *pdev) return -ENOMEM; pcie = pci_host_bridge_priv(bridge); + rp = &pcie->rp; + rp->bridge = bridge; pcie->pdev = pdev; @@ -904,12 +925,12 @@ static int mobiveil_pcie_probe(struct platform_device *pdev) return ret; } - irq_set_chained_handler_and_data(pcie->irq, mobiveil_pcie_isr, pcie); + irq_set_chained_handler_and_data(rp->irq, mobiveil_pcie_isr, pcie); /* Initialize bridge */ bridge->dev.parent = dev; bridge->sysdata = pcie; - bridge->busnr = pcie->root_bus_nr; + bridge->busnr = rp->root_bus_nr; bridge->ops = &mobiveil_pcie_ops; bridge->map_irq = of_irq_parse_and_map_pci; bridge->swizzle_irq = pci_common_swizzle; From 2ba24842d6b42453dbc9dfffdf5faf0cec2d7698 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Thu, 13 Feb 2020 12:06:33 +0800 Subject: [PATCH 0565/4444] PCI: mobiveil: Move the host initialization into a function Move the host initialization related operations into a new function so that it can be reused by other platform PCIe host drivers integrating the Mobiveil GPEX. Signed-off-by: Hou Zhiqiang [lorenzo.pieralisi@arm.com: updated commit log] Signed-off-by: Lorenzo Pieralisi Reviewed-by: Andrew Murray --- drivers/pci/controller/pcie-mobiveil.c | 39 +++++++++++++++----------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/drivers/pci/controller/pcie-mobiveil.c b/drivers/pci/controller/pcie-mobiveil.c index a7c2354465a1..d7ef0880edb2 100644 --- a/drivers/pci/controller/pcie-mobiveil.c +++ b/drivers/pci/controller/pcie-mobiveil.c @@ -873,27 +873,15 @@ static int mobiveil_pcie_init_irq_domain(struct mobiveil_pcie *pcie) return 0; } -static int mobiveil_pcie_probe(struct platform_device *pdev) +static int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie) { - struct mobiveil_pcie *pcie; + struct mobiveil_root_port *rp = &pcie->rp; + struct pci_host_bridge *bridge = rp->bridge; + struct device *dev = &pcie->pdev->dev; struct pci_bus *bus; struct pci_bus *child; - struct pci_host_bridge *bridge; - struct device *dev = &pdev->dev; - struct mobiveil_root_port *rp; int ret; - /* allocate the PCIe port */ - bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie)); - if (!bridge) - return -ENOMEM; - - pcie = pci_host_bridge_priv(bridge); - rp = &pcie->rp; - rp->bridge = bridge; - - pcie->pdev = pdev; - ret = mobiveil_pcie_parse_dt(pcie); if (ret) { dev_err(dev, "Parsing DT failed, ret: %x\n", ret); @@ -956,6 +944,25 @@ static int mobiveil_pcie_probe(struct platform_device *pdev) return 0; } +static int mobiveil_pcie_probe(struct platform_device *pdev) +{ + struct mobiveil_pcie *pcie; + struct pci_host_bridge *bridge; + struct device *dev = &pdev->dev; + + /* allocate the PCIe port */ + bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie)); + if (!bridge) + return -ENOMEM; + + pcie = pci_host_bridge_priv(bridge); + pcie->rp.bridge = bridge; + + pcie->pdev = pdev; + + return mobiveil_pcie_host_probe(pcie); +} + static const struct of_device_id mobiveil_pcie_of_match[] = { {.compatible = "mbvl,gpex40-pcie",}, {}, From 39e3a03eea5ba113f9ffe1cf39f0e0b4bc6a6713 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Thu, 13 Feb 2020 12:06:34 +0800 Subject: [PATCH 0566/4444] PCI: mobiveil: Collect the interrupt related operations into a function Collect the interrupt initialization related operations into a new function to make code more readable. Signed-off-by: Hou Zhiqiang Signed-off-by: Lorenzo Pieralisi Reviewed-by: Andrew Murray --- drivers/pci/controller/pcie-mobiveil.c | 65 +++++++++++++++++--------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/drivers/pci/controller/pcie-mobiveil.c b/drivers/pci/controller/pcie-mobiveil.c index d7ef0880edb2..04ad37906729 100644 --- a/drivers/pci/controller/pcie-mobiveil.c +++ b/drivers/pci/controller/pcie-mobiveil.c @@ -454,12 +454,6 @@ static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie) return PTR_ERR(pcie->csr_axi_slave_base); pcie->pcie_reg_base = res->start; - /* map MSI config resource */ - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apb_csr"); - pcie->apb_csr_base = devm_pci_remap_cfg_resource(dev, res); - if (IS_ERR(pcie->apb_csr_base)) - return PTR_ERR(pcie->apb_csr_base); - /* read the number of windows requested */ if (of_property_read_u32(node, "apio-wins", &pcie->apio_wins)) pcie->apio_wins = MAX_PIO_WINDOWS; @@ -467,12 +461,6 @@ static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie) if (of_property_read_u32(node, "ppio-wins", &pcie->ppio_wins)) pcie->ppio_wins = MAX_PIO_WINDOWS; - rp->irq = platform_get_irq(pdev, 0); - if (rp->irq <= 0) { - dev_err(dev, "failed to map IRQ: %d\n", rp->irq); - return -ENODEV; - } - return 0; } @@ -618,9 +606,6 @@ static int mobiveil_host_init(struct mobiveil_pcie *pcie) pab_ctrl |= (1 << AMBA_PIO_ENABLE_SHIFT) | (1 << PEX_PIO_ENABLE_SHIFT); mobiveil_csr_writel(pcie, pab_ctrl, PAB_CTRL); - mobiveil_csr_writel(pcie, (PAB_INTP_INTX_MASK | PAB_INTP_MSI_MASK), - PAB_INTP_AMBA_MISC_ENB); - /* * program PIO Enable Bit to 1 and Config Window Enable Bit to 1 in * PAB_AXI_PIO_CTRL Register @@ -670,9 +655,6 @@ static int mobiveil_host_init(struct mobiveil_pcie *pcie) value |= (PCI_CLASS_BRIDGE_PCI << 16); mobiveil_csr_writel(pcie, value, PAB_INTP_AXI_PIO_CLASS); - /* setup MSI hardware registers */ - mobiveil_pcie_enable_msi(pcie); - return 0; } @@ -873,6 +855,46 @@ static int mobiveil_pcie_init_irq_domain(struct mobiveil_pcie *pcie) return 0; } +static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie) +{ + struct platform_device *pdev = pcie->pdev; + struct device *dev = &pdev->dev; + struct mobiveil_root_port *rp = &pcie->rp; + struct resource *res; + int ret; + + /* map MSI config resource */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apb_csr"); + pcie->apb_csr_base = devm_pci_remap_cfg_resource(dev, res); + if (IS_ERR(pcie->apb_csr_base)) + return PTR_ERR(pcie->apb_csr_base); + + /* setup MSI hardware registers */ + mobiveil_pcie_enable_msi(pcie); + + rp->irq = platform_get_irq(pdev, 0); + if (rp->irq <= 0) { + dev_err(dev, "failed to map IRQ: %d\n", rp->irq); + return -ENODEV; + } + + /* initialize the IRQ domains */ + ret = mobiveil_pcie_init_irq_domain(pcie); + if (ret) { + dev_err(dev, "Failed creating IRQ Domain\n"); + return ret; + } + + irq_set_chained_handler_and_data(rp->irq, mobiveil_pcie_isr, pcie); + + /* Enable interrupts */ + mobiveil_csr_writel(pcie, (PAB_INTP_INTX_MASK | PAB_INTP_MSI_MASK), + PAB_INTP_AMBA_MISC_ENB); + + + return 0; +} + static int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie) { struct mobiveil_root_port *rp = &pcie->rp; @@ -906,15 +928,12 @@ static int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie) return ret; } - /* initialize the IRQ domains */ - ret = mobiveil_pcie_init_irq_domain(pcie); + ret = mobiveil_pcie_interrupt_init(pcie); if (ret) { - dev_err(dev, "Failed creating IRQ Domain\n"); + dev_err(dev, "Interrupt init failed\n"); return ret; } - irq_set_chained_handler_and_data(rp->irq, mobiveil_pcie_isr, pcie); - /* Initialize bridge */ bridge->dev.parent = dev; bridge->sysdata = pcie; From 03bdc3884019fb6463ac8163cc0e890920515f8b Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Thu, 13 Feb 2020 12:06:35 +0800 Subject: [PATCH 0567/4444] PCI: mobiveil: Modularize the Mobiveil PCIe Host Bridge IP driver Modularize the Mobiveil PCIe host driver according to the abstraction of Root Complex and Endpoint and move it into a new directory in order to make it easier to reuse the driver functions to add new host drivers for systems integrating the Mobiveil PCIe GPEX IP. Signed-off-by: Hou Zhiqiang [lorenzo.pieralisi@arm.com: updated commit log] Signed-off-by: Lorenzo Pieralisi Reviewed-by: Andrew Murray --- MAINTAINERS | 2 +- drivers/pci/controller/Kconfig | 11 +- drivers/pci/controller/Makefile | 2 +- drivers/pci/controller/mobiveil/Kconfig | 24 ++ drivers/pci/controller/mobiveil/Makefile | 4 + .../pcie-mobiveil-host.c} | 401 +----------------- .../controller/mobiveil/pcie-mobiveil-plat.c | 61 +++ .../pci/controller/mobiveil/pcie-mobiveil.c | 227 ++++++++++ .../pci/controller/mobiveil/pcie-mobiveil.h | 178 ++++++++ 9 files changed, 499 insertions(+), 411 deletions(-) create mode 100644 drivers/pci/controller/mobiveil/Kconfig create mode 100644 drivers/pci/controller/mobiveil/Makefile rename drivers/pci/controller/{pcie-mobiveil.c => mobiveil/pcie-mobiveil-host.c} (61%) create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil-plat.c create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil.c create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil.h diff --git a/MAINTAINERS b/MAINTAINERS index 38fe2f3f7b6f..f0b6fb59d598 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12794,7 +12794,7 @@ M: Hou Zhiqiang L: linux-pci@vger.kernel.org S: Supported F: Documentation/devicetree/bindings/pci/mobiveil-pcie.txt -F: drivers/pci/controller/pcie-mobiveil.c +F: drivers/pci/controller/mobiveil/pcie-mobiveil* PCI DRIVER FOR MVEBU (Marvell Armada 370 and Armada XP SOC support) M: Thomas Petazzoni diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig index 20bf00f587bd..91bfdb784829 100644 --- a/drivers/pci/controller/Kconfig +++ b/drivers/pci/controller/Kconfig @@ -213,16 +213,6 @@ config PCIE_MEDIATEK Say Y here if you want to enable PCIe controller support on MediaTek SoCs. -config PCIE_MOBIVEIL - bool "Mobiveil AXI PCIe controller" - depends on ARCH_ZYNQMP || COMPILE_TEST - depends on OF - depends on PCI_MSI_IRQ_DOMAIN - help - Say Y here if you want to enable support for the Mobiveil AXI PCIe - Soft IP. It has up to 8 outbound and inbound windows - for address translation and it is a PCIe Gen4 IP. - config PCIE_TANGO_SMP8759 bool "Tango SMP8759 PCIe controller (DANGEROUS)" depends on ARCH_TANGO && PCI_MSI && OF @@ -269,5 +259,6 @@ config PCI_HYPERV_INTERFACE have a common interface with the Hyper-V PCI frontend driver. source "drivers/pci/controller/dwc/Kconfig" +source "drivers/pci/controller/mobiveil/Kconfig" source "drivers/pci/controller/cadence/Kconfig" endmenu diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile index 01b2502a5323..158c59771824 100644 --- a/drivers/pci/controller/Makefile +++ b/drivers/pci/controller/Makefile @@ -25,12 +25,12 @@ obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o obj-$(CONFIG_PCIE_ROCKCHIP_EP) += pcie-rockchip-ep.o obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie-rockchip-host.o obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o -obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o obj-$(CONFIG_VMD) += vmd.o obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW obj-y += dwc/ +obj-y += mobiveil/ # The following drivers are for devices that use the generic ACPI diff --git a/drivers/pci/controller/mobiveil/Kconfig b/drivers/pci/controller/mobiveil/Kconfig new file mode 100644 index 000000000000..54161d4ddb11 --- /dev/null +++ b/drivers/pci/controller/mobiveil/Kconfig @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 + +menu "Mobiveil PCIe Core Support" + depends on PCI + +config PCIE_MOBIVEIL + bool + +config PCIE_MOBIVEIL_HOST + bool + depends on PCI_MSI_IRQ_DOMAIN + select PCIE_MOBIVEIL + +config PCIE_MOBIVEIL_PLAT + bool "Mobiveil AXI PCIe controller" + depends on ARCH_ZYNQMP || COMPILE_TEST + depends on OF + select PCIE_MOBIVEIL_HOST + help + Say Y here if you want to enable support for the Mobiveil AXI PCIe + Soft IP. It has up to 8 outbound and inbound windows + for address translation and it is a PCIe Gen4 IP. + +endmenu diff --git a/drivers/pci/controller/mobiveil/Makefile b/drivers/pci/controller/mobiveil/Makefile new file mode 100644 index 000000000000..9fb6d1c6504d --- /dev/null +++ b/drivers/pci/controller/mobiveil/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o +obj-$(CONFIG_PCIE_MOBIVEIL_HOST) += pcie-mobiveil-host.o +obj-$(CONFIG_PCIE_MOBIVEIL_PLAT) += pcie-mobiveil-plat.o diff --git a/drivers/pci/controller/pcie-mobiveil.c b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c similarity index 61% rename from drivers/pci/controller/pcie-mobiveil.c rename to drivers/pci/controller/mobiveil/pcie-mobiveil-host.c index 04ad37906729..432b019a4fcf 100644 --- a/drivers/pci/controller/pcie-mobiveil.c +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c @@ -9,7 +9,6 @@ * Hou Zhiqiang */ -#include #include #include #include @@ -26,265 +25,7 @@ #include #include -#include "../pci.h" - -/* register offsets and bit positions */ - -/* - * translation tables are grouped into windows, each window registers are - * grouped into blocks of 4 or 16 registers each - */ -#define PAB_REG_BLOCK_SIZE 16 -#define PAB_EXT_REG_BLOCK_SIZE 4 - -#define PAB_REG_ADDR(offset, win) \ - (offset + (win * PAB_REG_BLOCK_SIZE)) -#define PAB_EXT_REG_ADDR(offset, win) \ - (offset + (win * PAB_EXT_REG_BLOCK_SIZE)) - -#define LTSSM_STATUS 0x0404 -#define LTSSM_STATUS_L0_MASK 0x3f -#define LTSSM_STATUS_L0 0x2d - -#define PAB_CTRL 0x0808 -#define AMBA_PIO_ENABLE_SHIFT 0 -#define PEX_PIO_ENABLE_SHIFT 1 -#define PAGE_SEL_SHIFT 13 -#define PAGE_SEL_MASK 0x3f -#define PAGE_LO_MASK 0x3ff -#define PAGE_SEL_OFFSET_SHIFT 10 - -#define PAB_AXI_PIO_CTRL 0x0840 -#define APIO_EN_MASK 0xf - -#define PAB_PEX_PIO_CTRL 0x08c0 -#define PIO_ENABLE_SHIFT 0 - -#define PAB_INTP_AMBA_MISC_ENB 0x0b0c -#define PAB_INTP_AMBA_MISC_STAT 0x0b1c -#define PAB_INTP_INTX_MASK 0x01e0 -#define PAB_INTP_MSI_MASK 0x8 - -#define PAB_AXI_AMAP_CTRL(win) PAB_REG_ADDR(0x0ba0, win) -#define WIN_ENABLE_SHIFT 0 -#define WIN_TYPE_SHIFT 1 -#define WIN_TYPE_MASK 0x3 -#define WIN_SIZE_MASK 0xfffffc00 - -#define PAB_EXT_AXI_AMAP_SIZE(win) PAB_EXT_REG_ADDR(0xbaf0, win) - -#define PAB_EXT_AXI_AMAP_AXI_WIN(win) PAB_EXT_REG_ADDR(0x80a0, win) -#define PAB_AXI_AMAP_AXI_WIN(win) PAB_REG_ADDR(0x0ba4, win) -#define AXI_WINDOW_ALIGN_MASK 3 - -#define PAB_AXI_AMAP_PEX_WIN_L(win) PAB_REG_ADDR(0x0ba8, win) -#define PAB_BUS_SHIFT 24 -#define PAB_DEVICE_SHIFT 19 -#define PAB_FUNCTION_SHIFT 16 - -#define PAB_AXI_AMAP_PEX_WIN_H(win) PAB_REG_ADDR(0x0bac, win) -#define PAB_INTP_AXI_PIO_CLASS 0x474 - -#define PAB_PEX_AMAP_CTRL(win) PAB_REG_ADDR(0x4ba0, win) -#define AMAP_CTRL_EN_SHIFT 0 -#define AMAP_CTRL_TYPE_SHIFT 1 -#define AMAP_CTRL_TYPE_MASK 3 - -#define PAB_EXT_PEX_AMAP_SIZEN(win) PAB_EXT_REG_ADDR(0xbef0, win) -#define PAB_EXT_PEX_AMAP_AXI_WIN(win) PAB_EXT_REG_ADDR(0xb4a0, win) -#define PAB_PEX_AMAP_AXI_WIN(win) PAB_REG_ADDR(0x4ba4, win) -#define PAB_PEX_AMAP_PEX_WIN_L(win) PAB_REG_ADDR(0x4ba8, win) -#define PAB_PEX_AMAP_PEX_WIN_H(win) PAB_REG_ADDR(0x4bac, win) - -/* starting offset of INTX bits in status register */ -#define PAB_INTX_START 5 - -/* supported number of MSI interrupts */ -#define PCI_NUM_MSI 16 - -/* MSI registers */ -#define MSI_BASE_LO_OFFSET 0x04 -#define MSI_BASE_HI_OFFSET 0x08 -#define MSI_SIZE_OFFSET 0x0c -#define MSI_ENABLE_OFFSET 0x14 -#define MSI_STATUS_OFFSET 0x18 -#define MSI_DATA_OFFSET 0x20 -#define MSI_ADDR_L_OFFSET 0x24 -#define MSI_ADDR_H_OFFSET 0x28 - -/* outbound and inbound window definitions */ -#define WIN_NUM_0 0 -#define WIN_NUM_1 1 -#define CFG_WINDOW_TYPE 0 -#define IO_WINDOW_TYPE 1 -#define MEM_WINDOW_TYPE 2 -#define IB_WIN_SIZE ((u64)256 * 1024 * 1024 * 1024) -#define MAX_PIO_WINDOWS 8 - -/* Parameters for the waiting for link up routine */ -#define LINK_WAIT_MAX_RETRIES 10 -#define LINK_WAIT_MIN 90000 -#define LINK_WAIT_MAX 100000 - -#define PAGED_ADDR_BNDRY 0xc00 -#define OFFSET_TO_PAGE_ADDR(off) \ - ((off & PAGE_LO_MASK) | PAGED_ADDR_BNDRY) -#define OFFSET_TO_PAGE_IDX(off) \ - ((off >> PAGE_SEL_OFFSET_SHIFT) & PAGE_SEL_MASK) - -struct mobiveil_msi { /* MSI information */ - struct mutex lock; /* protect bitmap variable */ - struct irq_domain *msi_domain; - struct irq_domain *dev_domain; - phys_addr_t msi_pages_phys; - int num_of_vectors; - DECLARE_BITMAP(msi_irq_in_use, PCI_NUM_MSI); -}; - -struct mobiveil_root_port { - char root_bus_nr; - void __iomem *config_axi_slave_base; /* endpoint config base */ - struct resource *ob_io_res; - int irq; - raw_spinlock_t intx_mask_lock; - struct irq_domain *intx_domain; - struct mobiveil_msi msi; - struct pci_host_bridge *bridge; -}; - -struct mobiveil_pcie { - struct platform_device *pdev; - void __iomem *csr_axi_slave_base; /* root port config base */ - void __iomem *apb_csr_base; /* MSI register base */ - phys_addr_t pcie_reg_base; /* Physical PCIe Controller Base */ - int apio_wins; - int ppio_wins; - int ob_wins_configured; /* configured outbound windows */ - int ib_wins_configured; /* configured inbound windows */ - struct mobiveil_root_port rp; -}; - -/* - * mobiveil_pcie_sel_page - routine to access paged register - * - * Registers whose address greater than PAGED_ADDR_BNDRY (0xc00) are paged, - * for this scheme to work extracted higher 6 bits of the offset will be - * written to pg_sel field of PAB_CTRL register and rest of the lower 10 - * bits enabled with PAGED_ADDR_BNDRY are used as offset of the register. - */ -static void mobiveil_pcie_sel_page(struct mobiveil_pcie *pcie, u8 pg_idx) -{ - u32 val; - - val = readl(pcie->csr_axi_slave_base + PAB_CTRL); - val &= ~(PAGE_SEL_MASK << PAGE_SEL_SHIFT); - val |= (pg_idx & PAGE_SEL_MASK) << PAGE_SEL_SHIFT; - - writel(val, pcie->csr_axi_slave_base + PAB_CTRL); -} - -static void *mobiveil_pcie_comp_addr(struct mobiveil_pcie *pcie, u32 off) -{ - if (off < PAGED_ADDR_BNDRY) { - /* For directly accessed registers, clear the pg_sel field */ - mobiveil_pcie_sel_page(pcie, 0); - return pcie->csr_axi_slave_base + off; - } - - mobiveil_pcie_sel_page(pcie, OFFSET_TO_PAGE_IDX(off)); - return pcie->csr_axi_slave_base + OFFSET_TO_PAGE_ADDR(off); -} - -static int mobiveil_pcie_read(void __iomem *addr, int size, u32 *val) -{ - if ((uintptr_t)addr & (size - 1)) { - *val = 0; - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - switch (size) { - case 4: - *val = readl(addr); - break; - case 2: - *val = readw(addr); - break; - case 1: - *val = readb(addr); - break; - default: - *val = 0; - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - return PCIBIOS_SUCCESSFUL; -} - -static int mobiveil_pcie_write(void __iomem *addr, int size, u32 val) -{ - if ((uintptr_t)addr & (size - 1)) - return PCIBIOS_BAD_REGISTER_NUMBER; - - switch (size) { - case 4: - writel(val, addr); - break; - case 2: - writew(val, addr); - break; - case 1: - writeb(val, addr); - break; - default: - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - return PCIBIOS_SUCCESSFUL; -} - -static u32 mobiveil_csr_read(struct mobiveil_pcie *pcie, u32 off, size_t size) -{ - void *addr; - u32 val; - int ret; - - addr = mobiveil_pcie_comp_addr(pcie, off); - - ret = mobiveil_pcie_read(addr, size, &val); - if (ret) - dev_err(&pcie->pdev->dev, "read CSR address failed\n"); - - return val; -} - -static void mobiveil_csr_write(struct mobiveil_pcie *pcie, u32 val, u32 off, - size_t size) -{ - void *addr; - int ret; - - addr = mobiveil_pcie_comp_addr(pcie, off); - - ret = mobiveil_pcie_write(addr, size, val); - if (ret) - dev_err(&pcie->pdev->dev, "write CSR address failed\n"); -} - -static u32 mobiveil_csr_readl(struct mobiveil_pcie *pcie, u32 off) -{ - return mobiveil_csr_read(pcie, off, 0x4); -} - -static void mobiveil_csr_writel(struct mobiveil_pcie *pcie, u32 val, u32 off) -{ - mobiveil_csr_write(pcie, val, off, 0x4); -} - -static bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie) -{ - return (mobiveil_csr_readl(pcie, LTSSM_STATUS) & - LTSSM_STATUS_L0_MASK) == LTSSM_STATUS_L0; -} +#include "pcie-mobiveil.h" static bool mobiveil_pcie_valid_device(struct pci_bus *bus, unsigned int devfn) { @@ -464,103 +205,6 @@ static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie) return 0; } -static void program_ib_windows(struct mobiveil_pcie *pcie, int win_num, - u64 cpu_addr, u64 pci_addr, u32 type, u64 size) -{ - u32 value; - u64 size64 = ~(size - 1); - - if (win_num >= pcie->ppio_wins) { - dev_err(&pcie->pdev->dev, - "ERROR: max inbound windows reached !\n"); - return; - } - - value = mobiveil_csr_readl(pcie, PAB_PEX_AMAP_CTRL(win_num)); - value &= ~(AMAP_CTRL_TYPE_MASK << AMAP_CTRL_TYPE_SHIFT | WIN_SIZE_MASK); - value |= type << AMAP_CTRL_TYPE_SHIFT | 1 << AMAP_CTRL_EN_SHIFT | - (lower_32_bits(size64) & WIN_SIZE_MASK); - mobiveil_csr_writel(pcie, value, PAB_PEX_AMAP_CTRL(win_num)); - - mobiveil_csr_writel(pcie, upper_32_bits(size64), - PAB_EXT_PEX_AMAP_SIZEN(win_num)); - - mobiveil_csr_writel(pcie, lower_32_bits(cpu_addr), - PAB_PEX_AMAP_AXI_WIN(win_num)); - mobiveil_csr_writel(pcie, upper_32_bits(cpu_addr), - PAB_EXT_PEX_AMAP_AXI_WIN(win_num)); - - mobiveil_csr_writel(pcie, lower_32_bits(pci_addr), - PAB_PEX_AMAP_PEX_WIN_L(win_num)); - mobiveil_csr_writel(pcie, upper_32_bits(pci_addr), - PAB_PEX_AMAP_PEX_WIN_H(win_num)); - - pcie->ib_wins_configured++; -} - -/* - * routine to program the outbound windows - */ -static void program_ob_windows(struct mobiveil_pcie *pcie, int win_num, - u64 cpu_addr, u64 pci_addr, u32 type, u64 size) -{ - u32 value; - u64 size64 = ~(size - 1); - - if (win_num >= pcie->apio_wins) { - dev_err(&pcie->pdev->dev, - "ERROR: max outbound windows reached !\n"); - return; - } - - /* - * program Enable Bit to 1, Type Bit to (00) base 2, AXI Window Size Bit - * to 4 KB in PAB_AXI_AMAP_CTRL register - */ - value = mobiveil_csr_readl(pcie, PAB_AXI_AMAP_CTRL(win_num)); - value &= ~(WIN_TYPE_MASK << WIN_TYPE_SHIFT | WIN_SIZE_MASK); - value |= 1 << WIN_ENABLE_SHIFT | type << WIN_TYPE_SHIFT | - (lower_32_bits(size64) & WIN_SIZE_MASK); - mobiveil_csr_writel(pcie, value, PAB_AXI_AMAP_CTRL(win_num)); - - mobiveil_csr_writel(pcie, upper_32_bits(size64), - PAB_EXT_AXI_AMAP_SIZE(win_num)); - - /* - * program AXI window base with appropriate value in - * PAB_AXI_AMAP_AXI_WIN0 register - */ - mobiveil_csr_writel(pcie, - lower_32_bits(cpu_addr) & (~AXI_WINDOW_ALIGN_MASK), - PAB_AXI_AMAP_AXI_WIN(win_num)); - mobiveil_csr_writel(pcie, upper_32_bits(cpu_addr), - PAB_EXT_AXI_AMAP_AXI_WIN(win_num)); - - mobiveil_csr_writel(pcie, lower_32_bits(pci_addr), - PAB_AXI_AMAP_PEX_WIN_L(win_num)); - mobiveil_csr_writel(pcie, upper_32_bits(pci_addr), - PAB_AXI_AMAP_PEX_WIN_H(win_num)); - - pcie->ob_wins_configured++; -} - -static int mobiveil_bringup_link(struct mobiveil_pcie *pcie) -{ - int retries; - - /* check if the link is up or not */ - for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) { - if (mobiveil_pcie_link_up(pcie)) - return 0; - - usleep_range(LINK_WAIT_MIN, LINK_WAIT_MAX); - } - - dev_err(&pcie->pdev->dev, "link never came up\n"); - - return -ETIMEDOUT; -} - static void mobiveil_pcie_enable_msi(struct mobiveil_pcie *pcie) { phys_addr_t msg_addr = pcie->pcie_reg_base; @@ -895,7 +539,7 @@ static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie) return 0; } -static int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie) +int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie) { struct mobiveil_root_port *rp = &pcie->rp; struct pci_host_bridge *bridge = rp->bridge; @@ -962,44 +606,3 @@ static int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie) return 0; } - -static int mobiveil_pcie_probe(struct platform_device *pdev) -{ - struct mobiveil_pcie *pcie; - struct pci_host_bridge *bridge; - struct device *dev = &pdev->dev; - - /* allocate the PCIe port */ - bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie)); - if (!bridge) - return -ENOMEM; - - pcie = pci_host_bridge_priv(bridge); - pcie->rp.bridge = bridge; - - pcie->pdev = pdev; - - return mobiveil_pcie_host_probe(pcie); -} - -static const struct of_device_id mobiveil_pcie_of_match[] = { - {.compatible = "mbvl,gpex40-pcie",}, - {}, -}; - -MODULE_DEVICE_TABLE(of, mobiveil_pcie_of_match); - -static struct platform_driver mobiveil_pcie_driver = { - .probe = mobiveil_pcie_probe, - .driver = { - .name = "mobiveil-pcie", - .of_match_table = mobiveil_pcie_of_match, - .suppress_bind_attrs = true, - }, -}; - -builtin_platform_driver(mobiveil_pcie_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Mobiveil PCIe host controller driver"); -MODULE_AUTHOR("Subrahmanya Lingappa "); diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil-plat.c b/drivers/pci/controller/mobiveil/pcie-mobiveil-plat.c new file mode 100644 index 000000000000..f6fcd95c2bf5 --- /dev/null +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-plat.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PCIe host controller driver for Mobiveil PCIe Host controller + * + * Copyright (c) 2018 Mobiveil Inc. + * Copyright 2019 NXP + * + * Author: Subrahmanya Lingappa + * Hou Zhiqiang + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pcie-mobiveil.h" + +static int mobiveil_pcie_probe(struct platform_device *pdev) +{ + struct mobiveil_pcie *pcie; + struct pci_host_bridge *bridge; + struct device *dev = &pdev->dev; + + /* allocate the PCIe port */ + bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie)); + if (!bridge) + return -ENOMEM; + + pcie = pci_host_bridge_priv(bridge); + pcie->rp.bridge = bridge; + + pcie->pdev = pdev; + + return mobiveil_pcie_host_probe(pcie); +} + +static const struct of_device_id mobiveil_pcie_of_match[] = { + {.compatible = "mbvl,gpex40-pcie",}, + {}, +}; + +MODULE_DEVICE_TABLE(of, mobiveil_pcie_of_match); + +static struct platform_driver mobiveil_pcie_driver = { + .probe = mobiveil_pcie_probe, + .driver = { + .name = "mobiveil-pcie", + .of_match_table = mobiveil_pcie_of_match, + .suppress_bind_attrs = true, + }, +}; + +builtin_platform_driver(mobiveil_pcie_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Mobiveil PCIe host controller driver"); +MODULE_AUTHOR("Subrahmanya Lingappa "); diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.c b/drivers/pci/controller/mobiveil/pcie-mobiveil.c new file mode 100644 index 000000000000..8215d7eeff4e --- /dev/null +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.c @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PCIe host controller driver for Mobiveil PCIe Host controller + * + * Copyright (c) 2018 Mobiveil Inc. + * Copyright 2019 NXP + * + * Author: Subrahmanya Lingappa + * Hou Zhiqiang + */ + +#include +#include +#include +#include +#include + +#include "pcie-mobiveil.h" + +/* + * mobiveil_pcie_sel_page - routine to access paged register + * + * Registers whose address greater than PAGED_ADDR_BNDRY (0xc00) are paged, + * for this scheme to work extracted higher 6 bits of the offset will be + * written to pg_sel field of PAB_CTRL register and rest of the lower 10 + * bits enabled with PAGED_ADDR_BNDRY are used as offset of the register. + */ +static void mobiveil_pcie_sel_page(struct mobiveil_pcie *pcie, u8 pg_idx) +{ + u32 val; + + val = readl(pcie->csr_axi_slave_base + PAB_CTRL); + val &= ~(PAGE_SEL_MASK << PAGE_SEL_SHIFT); + val |= (pg_idx & PAGE_SEL_MASK) << PAGE_SEL_SHIFT; + + writel(val, pcie->csr_axi_slave_base + PAB_CTRL); +} + +static void *mobiveil_pcie_comp_addr(struct mobiveil_pcie *pcie, u32 off) +{ + if (off < PAGED_ADDR_BNDRY) { + /* For directly accessed registers, clear the pg_sel field */ + mobiveil_pcie_sel_page(pcie, 0); + return pcie->csr_axi_slave_base + off; + } + + mobiveil_pcie_sel_page(pcie, OFFSET_TO_PAGE_IDX(off)); + return pcie->csr_axi_slave_base + OFFSET_TO_PAGE_ADDR(off); +} + +static int mobiveil_pcie_read(void __iomem *addr, int size, u32 *val) +{ + if ((uintptr_t)addr & (size - 1)) { + *val = 0; + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + switch (size) { + case 4: + *val = readl(addr); + break; + case 2: + *val = readw(addr); + break; + case 1: + *val = readb(addr); + break; + default: + *val = 0; + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int mobiveil_pcie_write(void __iomem *addr, int size, u32 val) +{ + if ((uintptr_t)addr & (size - 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + switch (size) { + case 4: + writel(val, addr); + break; + case 2: + writew(val, addr); + break; + case 1: + writeb(val, addr); + break; + default: + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + return PCIBIOS_SUCCESSFUL; +} + +u32 mobiveil_csr_read(struct mobiveil_pcie *pcie, u32 off, size_t size) +{ + void *addr; + u32 val; + int ret; + + addr = mobiveil_pcie_comp_addr(pcie, off); + + ret = mobiveil_pcie_read(addr, size, &val); + if (ret) + dev_err(&pcie->pdev->dev, "read CSR address failed\n"); + + return val; +} + +void mobiveil_csr_write(struct mobiveil_pcie *pcie, u32 val, u32 off, + size_t size) +{ + void *addr; + int ret; + + addr = mobiveil_pcie_comp_addr(pcie, off); + + ret = mobiveil_pcie_write(addr, size, val); + if (ret) + dev_err(&pcie->pdev->dev, "write CSR address failed\n"); +} + +bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie) +{ + return (mobiveil_csr_readl(pcie, LTSSM_STATUS) & + LTSSM_STATUS_L0_MASK) == LTSSM_STATUS_L0; +} + +void program_ib_windows(struct mobiveil_pcie *pcie, int win_num, + u64 cpu_addr, u64 pci_addr, u32 type, u64 size) +{ + u32 value; + u64 size64 = ~(size - 1); + + if (win_num >= pcie->ppio_wins) { + dev_err(&pcie->pdev->dev, + "ERROR: max inbound windows reached !\n"); + return; + } + + value = mobiveil_csr_readl(pcie, PAB_PEX_AMAP_CTRL(win_num)); + value &= ~(AMAP_CTRL_TYPE_MASK << AMAP_CTRL_TYPE_SHIFT | WIN_SIZE_MASK); + value |= type << AMAP_CTRL_TYPE_SHIFT | 1 << AMAP_CTRL_EN_SHIFT | + (lower_32_bits(size64) & WIN_SIZE_MASK); + mobiveil_csr_writel(pcie, value, PAB_PEX_AMAP_CTRL(win_num)); + + mobiveil_csr_writel(pcie, upper_32_bits(size64), + PAB_EXT_PEX_AMAP_SIZEN(win_num)); + + mobiveil_csr_writel(pcie, lower_32_bits(cpu_addr), + PAB_PEX_AMAP_AXI_WIN(win_num)); + mobiveil_csr_writel(pcie, upper_32_bits(cpu_addr), + PAB_EXT_PEX_AMAP_AXI_WIN(win_num)); + + mobiveil_csr_writel(pcie, lower_32_bits(pci_addr), + PAB_PEX_AMAP_PEX_WIN_L(win_num)); + mobiveil_csr_writel(pcie, upper_32_bits(pci_addr), + PAB_PEX_AMAP_PEX_WIN_H(win_num)); + + pcie->ib_wins_configured++; +} + +/* + * routine to program the outbound windows + */ +void program_ob_windows(struct mobiveil_pcie *pcie, int win_num, + u64 cpu_addr, u64 pci_addr, u32 type, u64 size) +{ + u32 value; + u64 size64 = ~(size - 1); + + if (win_num >= pcie->apio_wins) { + dev_err(&pcie->pdev->dev, + "ERROR: max outbound windows reached !\n"); + return; + } + + /* + * program Enable Bit to 1, Type Bit to (00) base 2, AXI Window Size Bit + * to 4 KB in PAB_AXI_AMAP_CTRL register + */ + value = mobiveil_csr_readl(pcie, PAB_AXI_AMAP_CTRL(win_num)); + value &= ~(WIN_TYPE_MASK << WIN_TYPE_SHIFT | WIN_SIZE_MASK); + value |= 1 << WIN_ENABLE_SHIFT | type << WIN_TYPE_SHIFT | + (lower_32_bits(size64) & WIN_SIZE_MASK); + mobiveil_csr_writel(pcie, value, PAB_AXI_AMAP_CTRL(win_num)); + + mobiveil_csr_writel(pcie, upper_32_bits(size64), + PAB_EXT_AXI_AMAP_SIZE(win_num)); + + /* + * program AXI window base with appropriate value in + * PAB_AXI_AMAP_AXI_WIN0 register + */ + mobiveil_csr_writel(pcie, + lower_32_bits(cpu_addr) & (~AXI_WINDOW_ALIGN_MASK), + PAB_AXI_AMAP_AXI_WIN(win_num)); + mobiveil_csr_writel(pcie, upper_32_bits(cpu_addr), + PAB_EXT_AXI_AMAP_AXI_WIN(win_num)); + + mobiveil_csr_writel(pcie, lower_32_bits(pci_addr), + PAB_AXI_AMAP_PEX_WIN_L(win_num)); + mobiveil_csr_writel(pcie, upper_32_bits(pci_addr), + PAB_AXI_AMAP_PEX_WIN_H(win_num)); + + pcie->ob_wins_configured++; +} + +int mobiveil_bringup_link(struct mobiveil_pcie *pcie) +{ + int retries; + + /* check if the link is up or not */ + for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) { + if (mobiveil_pcie_link_up(pcie)) + return 0; + + usleep_range(LINK_WAIT_MIN, LINK_WAIT_MAX); + } + + dev_err(&pcie->pdev->dev, "link never came up\n"); + + return -ETIMEDOUT; +} diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h new file mode 100644 index 000000000000..98ad7227b022 --- /dev/null +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * PCIe host controller driver for Mobiveil PCIe Host controller + * + * Copyright (c) 2018 Mobiveil Inc. + * Copyright 2019 NXP + * + * Author: Subrahmanya Lingappa + * Hou Zhiqiang + */ + +#ifndef _PCIE_MOBIVEIL_H +#define _PCIE_MOBIVEIL_H + +#include +#include +#include +#include "../../pci.h" + +/* register offsets and bit positions */ + +/* + * translation tables are grouped into windows, each window registers are + * grouped into blocks of 4 or 16 registers each + */ +#define PAB_REG_BLOCK_SIZE 16 +#define PAB_EXT_REG_BLOCK_SIZE 4 + +#define PAB_REG_ADDR(offset, win) \ + (offset + (win * PAB_REG_BLOCK_SIZE)) +#define PAB_EXT_REG_ADDR(offset, win) \ + (offset + (win * PAB_EXT_REG_BLOCK_SIZE)) + +#define LTSSM_STATUS 0x0404 +#define LTSSM_STATUS_L0_MASK 0x3f +#define LTSSM_STATUS_L0 0x2d + +#define PAB_CTRL 0x0808 +#define AMBA_PIO_ENABLE_SHIFT 0 +#define PEX_PIO_ENABLE_SHIFT 1 +#define PAGE_SEL_SHIFT 13 +#define PAGE_SEL_MASK 0x3f +#define PAGE_LO_MASK 0x3ff +#define PAGE_SEL_OFFSET_SHIFT 10 + +#define PAB_AXI_PIO_CTRL 0x0840 +#define APIO_EN_MASK 0xf + +#define PAB_PEX_PIO_CTRL 0x08c0 +#define PIO_ENABLE_SHIFT 0 + +#define PAB_INTP_AMBA_MISC_ENB 0x0b0c +#define PAB_INTP_AMBA_MISC_STAT 0x0b1c +#define PAB_INTP_INTX_MASK 0x01e0 +#define PAB_INTP_MSI_MASK 0x8 + +#define PAB_AXI_AMAP_CTRL(win) PAB_REG_ADDR(0x0ba0, win) +#define WIN_ENABLE_SHIFT 0 +#define WIN_TYPE_SHIFT 1 +#define WIN_TYPE_MASK 0x3 +#define WIN_SIZE_MASK 0xfffffc00 + +#define PAB_EXT_AXI_AMAP_SIZE(win) PAB_EXT_REG_ADDR(0xbaf0, win) + +#define PAB_EXT_AXI_AMAP_AXI_WIN(win) PAB_EXT_REG_ADDR(0x80a0, win) +#define PAB_AXI_AMAP_AXI_WIN(win) PAB_REG_ADDR(0x0ba4, win) +#define AXI_WINDOW_ALIGN_MASK 3 + +#define PAB_AXI_AMAP_PEX_WIN_L(win) PAB_REG_ADDR(0x0ba8, win) +#define PAB_BUS_SHIFT 24 +#define PAB_DEVICE_SHIFT 19 +#define PAB_FUNCTION_SHIFT 16 + +#define PAB_AXI_AMAP_PEX_WIN_H(win) PAB_REG_ADDR(0x0bac, win) +#define PAB_INTP_AXI_PIO_CLASS 0x474 + +#define PAB_PEX_AMAP_CTRL(win) PAB_REG_ADDR(0x4ba0, win) +#define AMAP_CTRL_EN_SHIFT 0 +#define AMAP_CTRL_TYPE_SHIFT 1 +#define AMAP_CTRL_TYPE_MASK 3 + +#define PAB_EXT_PEX_AMAP_SIZEN(win) PAB_EXT_REG_ADDR(0xbef0, win) +#define PAB_EXT_PEX_AMAP_AXI_WIN(win) PAB_EXT_REG_ADDR(0xb4a0, win) +#define PAB_PEX_AMAP_AXI_WIN(win) PAB_REG_ADDR(0x4ba4, win) +#define PAB_PEX_AMAP_PEX_WIN_L(win) PAB_REG_ADDR(0x4ba8, win) +#define PAB_PEX_AMAP_PEX_WIN_H(win) PAB_REG_ADDR(0x4bac, win) + +/* starting offset of INTX bits in status register */ +#define PAB_INTX_START 5 + +/* supported number of MSI interrupts */ +#define PCI_NUM_MSI 16 + +/* MSI registers */ +#define MSI_BASE_LO_OFFSET 0x04 +#define MSI_BASE_HI_OFFSET 0x08 +#define MSI_SIZE_OFFSET 0x0c +#define MSI_ENABLE_OFFSET 0x14 +#define MSI_STATUS_OFFSET 0x18 +#define MSI_DATA_OFFSET 0x20 +#define MSI_ADDR_L_OFFSET 0x24 +#define MSI_ADDR_H_OFFSET 0x28 + +/* outbound and inbound window definitions */ +#define WIN_NUM_0 0 +#define WIN_NUM_1 1 +#define CFG_WINDOW_TYPE 0 +#define IO_WINDOW_TYPE 1 +#define MEM_WINDOW_TYPE 2 +#define IB_WIN_SIZE ((u64)256 * 1024 * 1024 * 1024) +#define MAX_PIO_WINDOWS 8 + +/* Parameters for the waiting for link up routine */ +#define LINK_WAIT_MAX_RETRIES 10 +#define LINK_WAIT_MIN 90000 +#define LINK_WAIT_MAX 100000 + +#define PAGED_ADDR_BNDRY 0xc00 +#define OFFSET_TO_PAGE_ADDR(off) \ + ((off & PAGE_LO_MASK) | PAGED_ADDR_BNDRY) +#define OFFSET_TO_PAGE_IDX(off) \ + ((off >> PAGE_SEL_OFFSET_SHIFT) & PAGE_SEL_MASK) + +struct mobiveil_msi { /* MSI information */ + struct mutex lock; /* protect bitmap variable */ + struct irq_domain *msi_domain; + struct irq_domain *dev_domain; + phys_addr_t msi_pages_phys; + int num_of_vectors; + DECLARE_BITMAP(msi_irq_in_use, PCI_NUM_MSI); +}; + +struct mobiveil_root_port { + char root_bus_nr; + void __iomem *config_axi_slave_base; /* endpoint config base */ + struct resource *ob_io_res; + int irq; + raw_spinlock_t intx_mask_lock; + struct irq_domain *intx_domain; + struct mobiveil_msi msi; + struct pci_host_bridge *bridge; +}; + +struct mobiveil_pcie { + struct platform_device *pdev; + void __iomem *csr_axi_slave_base; /* root port config base */ + void __iomem *apb_csr_base; /* MSI register base */ + phys_addr_t pcie_reg_base; /* Physical PCIe Controller Base */ + int apio_wins; + int ppio_wins; + int ob_wins_configured; /* configured outbound windows */ + int ib_wins_configured; /* configured inbound windows */ + struct mobiveil_root_port rp; +}; + +int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie); +bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie); +int mobiveil_bringup_link(struct mobiveil_pcie *pcie); +void program_ob_windows(struct mobiveil_pcie *pcie, int win_num, u64 cpu_addr, + u64 pci_addr, u32 type, u64 size); +void program_ib_windows(struct mobiveil_pcie *pcie, int win_num, u64 cpu_addr, + u64 pci_addr, u32 type, u64 size); +u32 mobiveil_csr_read(struct mobiveil_pcie *pcie, u32 off, size_t size); +void mobiveil_csr_write(struct mobiveil_pcie *pcie, u32 val, u32 off, + size_t size); + +static inline u32 mobiveil_csr_readl(struct mobiveil_pcie *pcie, u32 off) +{ + return mobiveil_csr_read(pcie, off, 0x4); +} + +static inline void mobiveil_csr_writel(struct mobiveil_pcie *pcie, u32 val, + u32 off) +{ + mobiveil_csr_write(pcie, val, off, 0x4); +} + +#endif /* _PCIE_MOBIVEIL_H */ From ed620e96541f3248ad7cfe069f98d43177ae0435 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Thu, 13 Feb 2020 12:06:36 +0800 Subject: [PATCH 0568/4444] PCI: mobiveil: Add callback function for interrupt initialization The Mobiveil GPEX internal MSI/INTx controller is not implemented in all platforms in which the Mobiveil GPEX is integrated. Allow platforms to implement their specific interrupt initialization. Signed-off-by: Hou Zhiqiang Signed-off-by: Lorenzo Pieralisi Reviewed-by: Andrew Murray --- drivers/pci/controller/mobiveil/pcie-mobiveil-host.c | 12 +++++++++++- drivers/pci/controller/mobiveil/pcie-mobiveil.h | 7 +++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c index 432b019a4fcf..8d12682e8346 100644 --- a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c @@ -499,7 +499,7 @@ static int mobiveil_pcie_init_irq_domain(struct mobiveil_pcie *pcie) return 0; } -static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie) +static int mobiveil_pcie_integrated_interrupt_init(struct mobiveil_pcie *pcie) { struct platform_device *pdev = pcie->pdev; struct device *dev = &pdev->dev; @@ -539,6 +539,16 @@ static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie) return 0; } +static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie) +{ + struct mobiveil_root_port *rp = &pcie->rp; + + if (rp->ops->interrupt_init) + return rp->ops->interrupt_init(pcie); + + return mobiveil_pcie_integrated_interrupt_init(pcie); +} + int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie) { struct mobiveil_root_port *rp = &pcie->rp; diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h index 98ad7227b022..1f7d9da76542 100644 --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h @@ -130,10 +130,17 @@ struct mobiveil_msi { /* MSI information */ DECLARE_BITMAP(msi_irq_in_use, PCI_NUM_MSI); }; +struct mobiveil_pcie; + +struct mobiveil_rp_ops { + int (*interrupt_init)(struct mobiveil_pcie *pcie); +}; + struct mobiveil_root_port { char root_bus_nr; void __iomem *config_axi_slave_base; /* endpoint config base */ struct resource *ob_io_res; + struct mobiveil_rp_ops *ops; int irq; raw_spinlock_t intx_mask_lock; struct irq_domain *intx_domain; From fc99b3311af7125c46b56e753dc1a65c27b0d7e2 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Thu, 13 Feb 2020 12:06:37 +0800 Subject: [PATCH 0569/4444] PCI: mobiveil: Add callback function for link up check Platforms integrating the Mobiveil GPEX can implement a specific mechanism to check the link status. Add a callback to enable platform specific link status functions. Signed-off-by: Hou Zhiqiang [lorenzo.pieralisi@arm.com: updated log] Signed-off-by: Lorenzo Pieralisi Reviewed-by: Andrew Murray --- drivers/pci/controller/mobiveil/pcie-mobiveil.c | 3 +++ drivers/pci/controller/mobiveil/pcie-mobiveil.h | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.c b/drivers/pci/controller/mobiveil/pcie-mobiveil.c index 8215d7eeff4e..23ab904989ea 100644 --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.c +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.c @@ -125,6 +125,9 @@ void mobiveil_csr_write(struct mobiveil_pcie *pcie, u32 val, u32 off, bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie) { + if (pcie->ops->link_up) + return pcie->ops->link_up(pcie); + return (mobiveil_csr_readl(pcie, LTSSM_STATUS) & LTSSM_STATUS_L0_MASK) == LTSSM_STATUS_L0; } diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h index 1f7d9da76542..63eec5618af2 100644 --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h @@ -148,6 +148,10 @@ struct mobiveil_root_port { struct pci_host_bridge *bridge; }; +struct mobiveil_pab_ops { + int (*link_up)(struct mobiveil_pcie *pcie); +}; + struct mobiveil_pcie { struct platform_device *pdev; void __iomem *csr_axi_slave_base; /* root port config base */ @@ -157,6 +161,7 @@ struct mobiveil_pcie { int ppio_wins; int ob_wins_configured; /* configured outbound windows */ int ib_wins_configured; /* configured inbound windows */ + const struct mobiveil_pab_ops *ops; struct mobiveil_root_port rp; }; From 52cae4c7082f5f479f1692ba3f5ee6292d0aa4f9 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Thu, 13 Feb 2020 12:06:38 +0800 Subject: [PATCH 0570/4444] PCI: mobiveil: Allow mobiveil_host_init() to be used to re-init host Allow the mobiveil_host_init() function to be used to re-init host controller's PAB and GPEX CSR register block, since the NXP integrated Mobiveil IP has to reset and then re-init the PAB and GPEX CSR registers upon hot-reset. Signed-off-by: Hou Zhiqiang Signed-off-by: Lorenzo Pieralisi Reviewed-by: Subrahmanya Lingappa Reviewed-by: Andrew Murray --- .../controller/mobiveil/pcie-mobiveil-host.c | 19 ++++++++++++------- .../pci/controller/mobiveil/pcie-mobiveil.h | 1 + 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c index 8d12682e8346..209e75d24e3b 100644 --- a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c @@ -221,18 +221,23 @@ static void mobiveil_pcie_enable_msi(struct mobiveil_pcie *pcie) writel_relaxed(1, pcie->apb_csr_base + MSI_ENABLE_OFFSET); } -static int mobiveil_host_init(struct mobiveil_pcie *pcie) +int mobiveil_host_init(struct mobiveil_pcie *pcie, bool reinit) { struct mobiveil_root_port *rp = &pcie->rp; struct pci_host_bridge *bridge = rp->bridge; u32 value, pab_ctrl, type; struct resource_entry *win; - /* setup bus numbers */ - value = mobiveil_csr_readl(pcie, PCI_PRIMARY_BUS); - value &= 0xff000000; - value |= 0x00ff0100; - mobiveil_csr_writel(pcie, value, PCI_PRIMARY_BUS); + pcie->ib_wins_configured = 0; + pcie->ob_wins_configured = 0; + + if (!reinit) { + /* setup bus numbers */ + value = mobiveil_csr_readl(pcie, PCI_PRIMARY_BUS); + value &= 0xff000000; + value |= 0x00ff0100; + mobiveil_csr_writel(pcie, value, PCI_PRIMARY_BUS); + } /* * program Bus Master Enable Bit in Command Register in PAB Config @@ -576,7 +581,7 @@ int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie) * configure all inbound and outbound windows and prepare the RC for * config access */ - ret = mobiveil_host_init(pcie); + ret = mobiveil_host_init(pcie, false); if (ret) { dev_err(dev, "Failed to initialize host\n"); return ret; diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h index 63eec5618af2..f395fa661a1c 100644 --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h @@ -166,6 +166,7 @@ struct mobiveil_pcie { }; int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie); +int mobiveil_host_init(struct mobiveil_pcie *pcie, bool reinit); bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie); int mobiveil_bringup_link(struct mobiveil_pcie *pcie); void program_ob_windows(struct mobiveil_pcie *pcie, int win_num, u64 cpu_addr, From 029dea3cdc67690736e35b78c9d8ed6da1c9ec98 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Thu, 13 Feb 2020 12:06:39 +0800 Subject: [PATCH 0571/4444] PCI: mobiveil: Add 8-bit and 16-bit CSR register accessors There are some 8-bit and 16-bit registers in PCIe configuration space, so add these accessors accordingly. Signed-off-by: Hou Zhiqiang Signed-off-by: Lorenzo Pieralisi Reviewed-by: Minghuan Lian Reviewed-by: Subrahmanya Lingappa Reviewed-by: Andrew Murray --- .../pci/controller/mobiveil/pcie-mobiveil.h | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h index f395fa661a1c..ac76cf5d1007 100644 --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h @@ -182,10 +182,33 @@ static inline u32 mobiveil_csr_readl(struct mobiveil_pcie *pcie, u32 off) return mobiveil_csr_read(pcie, off, 0x4); } +static inline u16 mobiveil_csr_readw(struct mobiveil_pcie *pcie, u32 off) +{ + return mobiveil_csr_read(pcie, off, 0x2); +} + +static inline u8 mobiveil_csr_readb(struct mobiveil_pcie *pcie, u32 off) +{ + return mobiveil_csr_read(pcie, off, 0x1); +} + + static inline void mobiveil_csr_writel(struct mobiveil_pcie *pcie, u32 val, u32 off) { mobiveil_csr_write(pcie, val, off, 0x4); } +static inline void mobiveil_csr_writew(struct mobiveil_pcie *pcie, u16 val, + u32 off) +{ + mobiveil_csr_write(pcie, val, off, 0x2); +} + +static inline void mobiveil_csr_writeb(struct mobiveil_pcie *pcie, u8 val, + u32 off) +{ + mobiveil_csr_write(pcie, val, off, 0x1); +} + #endif /* _PCIE_MOBIVEIL_H */ From 11d22cc395ca1b9ff78255edaee3bf258515ad72 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Thu, 13 Feb 2020 12:06:40 +0800 Subject: [PATCH 0572/4444] PCI: mobiveil: Add Header Type field check Check the Header Type and exit from the host driver initialization if it is not in host mode. Signed-off-by: Hou Zhiqiang Signed-off-by: Lorenzo Pieralisi Reviewed-by: Andrew Murray --- .../pci/controller/mobiveil/pcie-mobiveil-host.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c index 209e75d24e3b..a94be264240f 100644 --- a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c @@ -554,6 +554,16 @@ static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie) return mobiveil_pcie_integrated_interrupt_init(pcie); } +static bool mobiveil_pcie_is_bridge(struct mobiveil_pcie *pcie) +{ + u32 header_type; + + header_type = mobiveil_csr_readb(pcie, PCI_HEADER_TYPE); + header_type &= 0x7f; + + return header_type == PCI_HEADER_TYPE_BRIDGE; +} + int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie) { struct mobiveil_root_port *rp = &pcie->rp; @@ -569,6 +579,9 @@ int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie) return ret; } + if (!mobiveil_pcie_is_bridge(pcie)) + return -ENODEV; + /* parse the host bridge base addresses from the device tree file */ ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows, &bridge->dma_ranges, NULL); From 3edeb49525bbe34441618fdc5912b1ec37b2a61c Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Thu, 13 Feb 2020 12:06:41 +0800 Subject: [PATCH 0573/4444] dt-bindings: PCI: Add NXP Layerscape SoCs PCIe Gen4 controller Add PCIe Gen4 controller DT bindings of NXP Layerscape SoCs. Signed-off-by: Hou Zhiqiang Signed-off-by: Lorenzo Pieralisi Reviewed-by: Rob Herring --- .../bindings/pci/layerscape-pcie-gen4.txt | 52 +++++++++++++++++++ MAINTAINERS | 8 +++ 2 files changed, 60 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt diff --git a/Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt b/Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt new file mode 100644 index 000000000000..b40fb5d15d3d --- /dev/null +++ b/Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt @@ -0,0 +1,52 @@ +NXP Layerscape PCIe Gen4 controller + +This PCIe controller is based on the Mobiveil PCIe IP and thus inherits all +the common properties defined in mobiveil-pcie.txt. + +Required properties: +- compatible: should contain the platform identifier such as: + "fsl,lx2160a-pcie" +- reg: base addresses and lengths of the PCIe controller register blocks. + "csr_axi_slave": Bridge config registers + "config_axi_slave": PCIe controller registers +- interrupts: A list of interrupt outputs of the controller. Must contain an + entry for each entry in the interrupt-names property. +- interrupt-names: It could include the following entries: + "intr": The interrupt that is asserted for controller interrupts + "aer": Asserted for aer interrupt when chip support the aer interrupt with + none MSI/MSI-X/INTx mode,but there is interrupt line for aer. + "pme": Asserted for pme interrupt when chip support the pme interrupt with + none MSI/MSI-X/INTx mode,but there is interrupt line for pme. +- dma-coherent: Indicates that the hardware IP block can ensure the coherency + of the data transferred from/to the IP block. This can avoid the software + cache flush/invalid actions, and improve the performance significantly. +- msi-parent : See the generic MSI binding described in + Documentation/devicetree/bindings/interrupt-controller/msi.txt. + +Example: + + pcie@3400000 { + compatible = "fsl,lx2160a-pcie"; + reg = <0x00 0x03400000 0x0 0x00100000 /* controller registers */ + 0x80 0x00000000 0x0 0x00001000>; /* configuration space */ + reg-names = "csr_axi_slave", "config_axi_slave"; + interrupts = , /* AER interrupt */ + , /* PME interrupt */ + ; /* controller interrupt */ + interrupt-names = "aer", "pme", "intr"; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + apio-wins = <8>; + ppio-wins = <8>; + dma-coherent; + bus-range = <0x0 0xff>; + msi-parent = <&its>; + ranges = <0x82000000 0x0 0x40000000 0x80 0x40000000 0x0 0x40000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 2 &gic 0 0 GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 3 &gic 0 0 GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 4 &gic 0 0 GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>; + }; diff --git a/MAINTAINERS b/MAINTAINERS index f0b6fb59d598..0d39b3745356 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12752,6 +12752,14 @@ L: linux-arm-kernel@lists.infradead.org S: Maintained F: drivers/pci/controller/dwc/*layerscape* +PCI DRIVER FOR NXP LAYERSCAPE GEN4 CONTROLLER +M: Hou Zhiqiang +L: linux-pci@vger.kernel.org +L: linux-arm-kernel@lists.infradead.org +S: Maintained +F: Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt +F: drivers/pci/controller/mobibeil/pcie-layerscape-gen4.c + PCI DRIVER FOR GENERIC OF HOSTS M: Will Deacon L: linux-pci@vger.kernel.org From d29ad70a813b0daa424b70950d432c34a1a95865 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Thu, 13 Feb 2020 12:06:42 +0800 Subject: [PATCH 0574/4444] PCI: mobiveil: Add PCIe Gen4 RC driver for Layerscape SoCs Add a PCI host controller driver for Layerscape SoCs integrating the Mobiveil GPEX IP. Signed-off-by: Hou Zhiqiang [lorenzo.pieralisi@arm.com: updated commit log] Signed-off-by: Lorenzo Pieralisi Reviewed-by: Minghuan Lian Reviewed-by: Andrew Murray --- drivers/pci/controller/mobiveil/Kconfig | 9 + drivers/pci/controller/mobiveil/Makefile | 1 + .../mobiveil/pcie-layerscape-gen4.c | 267 ++++++++++++++++++ .../pci/controller/mobiveil/pcie-mobiveil.h | 16 +- 4 files changed, 291 insertions(+), 2 deletions(-) create mode 100644 drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c diff --git a/drivers/pci/controller/mobiveil/Kconfig b/drivers/pci/controller/mobiveil/Kconfig index 54161d4ddb11..7439991ee82c 100644 --- a/drivers/pci/controller/mobiveil/Kconfig +++ b/drivers/pci/controller/mobiveil/Kconfig @@ -21,4 +21,13 @@ config PCIE_MOBIVEIL_PLAT Soft IP. It has up to 8 outbound and inbound windows for address translation and it is a PCIe Gen4 IP. +config PCIE_LAYERSCAPE_GEN4 + bool "Freescale Layerscape PCIe Gen4 controller" + depends on PCI + depends on OF && (ARM64 || ARCH_LAYERSCAPE) + depends on PCI_MSI_IRQ_DOMAIN + select PCIE_MOBIVEIL_HOST + help + Say Y here if you want PCIe Gen4 controller support on + Layerscape SoCs. endmenu diff --git a/drivers/pci/controller/mobiveil/Makefile b/drivers/pci/controller/mobiveil/Makefile index 9fb6d1c6504d..99d879de32d6 100644 --- a/drivers/pci/controller/mobiveil/Makefile +++ b/drivers/pci/controller/mobiveil/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o obj-$(CONFIG_PCIE_MOBIVEIL_HOST) += pcie-mobiveil-host.o obj-$(CONFIG_PCIE_MOBIVEIL_PLAT) += pcie-mobiveil-plat.o +obj-$(CONFIG_PCIE_LAYERSCAPE_GEN4) += pcie-layerscape-gen4.o diff --git a/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c new file mode 100644 index 000000000000..a6d2190a6753 --- /dev/null +++ b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c @@ -0,0 +1,267 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PCIe Gen4 host controller driver for NXP Layerscape SoCs + * + * Copyright 2019-2020 NXP + * + * Author: Zhiqiang Hou + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pcie-mobiveil.h" + +/* LUT and PF control registers */ +#define PCIE_LUT_OFF 0x80000 +#define PCIE_PF_OFF 0xc0000 +#define PCIE_PF_INT_STAT 0x18 +#define PF_INT_STAT_PABRST BIT(31) + +#define PCIE_PF_DBG 0x7fc +#define PF_DBG_LTSSM_MASK 0x3f +#define PF_DBG_LTSSM_L0 0x2d /* L0 state */ +#define PF_DBG_WE BIT(31) +#define PF_DBG_PABR BIT(27) + +#define to_ls_pcie_g4(x) platform_get_drvdata((x)->pdev) + +struct ls_pcie_g4 { + struct mobiveil_pcie pci; + struct delayed_work dwork; + int irq; +}; + +static inline u32 ls_pcie_g4_lut_readl(struct ls_pcie_g4 *pcie, u32 off) +{ + return ioread32(pcie->pci.csr_axi_slave_base + PCIE_LUT_OFF + off); +} + +static inline void ls_pcie_g4_lut_writel(struct ls_pcie_g4 *pcie, + u32 off, u32 val) +{ + iowrite32(val, pcie->pci.csr_axi_slave_base + PCIE_LUT_OFF + off); +} + +static inline u32 ls_pcie_g4_pf_readl(struct ls_pcie_g4 *pcie, u32 off) +{ + return ioread32(pcie->pci.csr_axi_slave_base + PCIE_PF_OFF + off); +} + +static inline void ls_pcie_g4_pf_writel(struct ls_pcie_g4 *pcie, + u32 off, u32 val) +{ + iowrite32(val, pcie->pci.csr_axi_slave_base + PCIE_PF_OFF + off); +} + +static int ls_pcie_g4_link_up(struct mobiveil_pcie *pci) +{ + struct ls_pcie_g4 *pcie = to_ls_pcie_g4(pci); + u32 state; + + state = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG); + state = state & PF_DBG_LTSSM_MASK; + + if (state == PF_DBG_LTSSM_L0) + return 1; + + return 0; +} + +static void ls_pcie_g4_disable_interrupt(struct ls_pcie_g4 *pcie) +{ + struct mobiveil_pcie *mv_pci = &pcie->pci; + + mobiveil_csr_writel(mv_pci, 0, PAB_INTP_AMBA_MISC_ENB); +} + +static void ls_pcie_g4_enable_interrupt(struct ls_pcie_g4 *pcie) +{ + struct mobiveil_pcie *mv_pci = &pcie->pci; + u32 val; + + /* Clear the interrupt status */ + mobiveil_csr_writel(mv_pci, 0xffffffff, PAB_INTP_AMBA_MISC_STAT); + + val = PAB_INTP_INTX_MASK | PAB_INTP_MSI | PAB_INTP_RESET | + PAB_INTP_PCIE_UE | PAB_INTP_IE_PMREDI | PAB_INTP_IE_EC; + mobiveil_csr_writel(mv_pci, val, PAB_INTP_AMBA_MISC_ENB); +} + +static int ls_pcie_g4_reinit_hw(struct ls_pcie_g4 *pcie) +{ + struct mobiveil_pcie *mv_pci = &pcie->pci; + struct device *dev = &mv_pci->pdev->dev; + u32 val, act_stat; + int to = 100; + + /* Poll for pab_csb_reset to set and PAB activity to clear */ + do { + usleep_range(10, 15); + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_INT_STAT); + act_stat = mobiveil_csr_readl(mv_pci, PAB_ACTIVITY_STAT); + } while (((val & PF_INT_STAT_PABRST) == 0 || act_stat) && to--); + if (to < 0) { + dev_err(dev, "Poll PABRST&PABACT timeout\n"); + return -EIO; + } + + /* clear PEX_RESET bit in PEX_PF0_DBG register */ + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG); + val |= PF_DBG_WE; + ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val); + + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG); + val |= PF_DBG_PABR; + ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val); + + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG); + val &= ~PF_DBG_WE; + ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val); + + mobiveil_host_init(mv_pci, true); + + to = 100; + while (!ls_pcie_g4_link_up(mv_pci) && to--) + usleep_range(200, 250); + if (to < 0) { + dev_err(dev, "PCIe link training timeout\n"); + return -EIO; + } + + return 0; +} + +static irqreturn_t ls_pcie_g4_isr(int irq, void *dev_id) +{ + struct ls_pcie_g4 *pcie = (struct ls_pcie_g4 *)dev_id; + struct mobiveil_pcie *mv_pci = &pcie->pci; + u32 val; + + val = mobiveil_csr_readl(mv_pci, PAB_INTP_AMBA_MISC_STAT); + if (!val) + return IRQ_NONE; + + if (val & PAB_INTP_RESET) { + ls_pcie_g4_disable_interrupt(pcie); + schedule_delayed_work(&pcie->dwork, msecs_to_jiffies(1)); + } + + mobiveil_csr_writel(mv_pci, val, PAB_INTP_AMBA_MISC_STAT); + + return IRQ_HANDLED; +} + +static int ls_pcie_g4_interrupt_init(struct mobiveil_pcie *mv_pci) +{ + struct ls_pcie_g4 *pcie = to_ls_pcie_g4(mv_pci); + struct platform_device *pdev = mv_pci->pdev; + struct device *dev = &pdev->dev; + int ret; + + pcie->irq = platform_get_irq_byname(pdev, "intr"); + if (pcie->irq < 0) { + dev_err(dev, "Can't get 'intr' IRQ, errno = %d\n", pcie->irq); + return pcie->irq; + } + ret = devm_request_irq(dev, pcie->irq, ls_pcie_g4_isr, + IRQF_SHARED, pdev->name, pcie); + if (ret) { + dev_err(dev, "Can't register PCIe IRQ, errno = %d\n", ret); + return ret; + } + + return 0; +} + +static void ls_pcie_g4_reset(struct work_struct *work) +{ + struct delayed_work *dwork = container_of(work, struct delayed_work, + work); + struct ls_pcie_g4 *pcie = container_of(dwork, struct ls_pcie_g4, dwork); + struct mobiveil_pcie *mv_pci = &pcie->pci; + u16 ctrl; + + ctrl = mobiveil_csr_readw(mv_pci, PCI_BRIDGE_CONTROL); + ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET; + mobiveil_csr_writew(mv_pci, ctrl, PCI_BRIDGE_CONTROL); + + if (!ls_pcie_g4_reinit_hw(pcie)) + return; + + ls_pcie_g4_enable_interrupt(pcie); +} + +static struct mobiveil_rp_ops ls_pcie_g4_rp_ops = { + .interrupt_init = ls_pcie_g4_interrupt_init, +}; + +static const struct mobiveil_pab_ops ls_pcie_g4_pab_ops = { + .link_up = ls_pcie_g4_link_up, +}; + +static int __init ls_pcie_g4_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct pci_host_bridge *bridge; + struct mobiveil_pcie *mv_pci; + struct ls_pcie_g4 *pcie; + struct device_node *np = dev->of_node; + int ret; + + if (!of_parse_phandle(np, "msi-parent", 0)) { + dev_err(dev, "Failed to find msi-parent\n"); + return -EINVAL; + } + + bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie)); + if (!bridge) + return -ENOMEM; + + pcie = pci_host_bridge_priv(bridge); + mv_pci = &pcie->pci; + + mv_pci->pdev = pdev; + mv_pci->ops = &ls_pcie_g4_pab_ops; + mv_pci->rp.ops = &ls_pcie_g4_rp_ops; + mv_pci->rp.bridge = bridge; + + platform_set_drvdata(pdev, pcie); + + INIT_DELAYED_WORK(&pcie->dwork, ls_pcie_g4_reset); + + ret = mobiveil_pcie_host_probe(mv_pci); + if (ret) { + dev_err(dev, "Fail to probe\n"); + return ret; + } + + ls_pcie_g4_enable_interrupt(pcie); + + return 0; +} + +static const struct of_device_id ls_pcie_g4_of_match[] = { + { .compatible = "fsl,lx2160a-pcie", }, + { }, +}; + +static struct platform_driver ls_pcie_g4_driver = { + .driver = { + .name = "layerscape-pcie-gen4", + .of_match_table = ls_pcie_g4_of_match, + .suppress_bind_attrs = true, + }, +}; + +builtin_platform_driver_probe(ls_pcie_g4_driver, ls_pcie_g4_probe); diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h index ac76cf5d1007..767e36a8522d 100644 --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h @@ -43,6 +43,8 @@ #define PAGE_LO_MASK 0x3ff #define PAGE_SEL_OFFSET_SHIFT 10 +#define PAB_ACTIVITY_STAT 0x81c + #define PAB_AXI_PIO_CTRL 0x0840 #define APIO_EN_MASK 0xf @@ -51,8 +53,18 @@ #define PAB_INTP_AMBA_MISC_ENB 0x0b0c #define PAB_INTP_AMBA_MISC_STAT 0x0b1c -#define PAB_INTP_INTX_MASK 0x01e0 -#define PAB_INTP_MSI_MASK 0x8 +#define PAB_INTP_RESET BIT(1) +#define PAB_INTP_MSI BIT(3) +#define PAB_INTP_INTA BIT(5) +#define PAB_INTP_INTB BIT(6) +#define PAB_INTP_INTC BIT(7) +#define PAB_INTP_INTD BIT(8) +#define PAB_INTP_PCIE_UE BIT(9) +#define PAB_INTP_IE_PMREDI BIT(29) +#define PAB_INTP_IE_EC BIT(30) +#define PAB_INTP_MSI_MASK PAB_INTP_MSI +#define PAB_INTP_INTX_MASK (PAB_INTP_INTA | PAB_INTP_INTB |\ + PAB_INTP_INTC | PAB_INTP_INTD) #define PAB_AXI_AMAP_CTRL(win) PAB_REG_ADDR(0x0ba0, win) #define WIN_ENABLE_SHIFT 0 From 8e66f52288c18db46f4cdcf417cefaaafc6b8608 Mon Sep 17 00:00:00 2001 From: Kieran Bingham Date: Thu, 12 Sep 2019 11:37:34 +0100 Subject: [PATCH 0575/4444] arm: dts: renesas: r8a77980: Remove r8a77970 DU compatible The r8a77970 was added with a compatible string for a different device rather than adding the correct compatible to the driver. Remove the unnecessary compatible which is for a different platform. Signed-off-by: Kieran Bingham Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20190912103734.1879-1-kieran.bingham+renesas@ideasonboard.com Signed-off-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a77980.dtsi | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi index b340fb469999..878ecbb7d63d 100644 --- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi @@ -1484,8 +1484,7 @@ }; du: display@feb00000 { - compatible = "renesas,du-r8a77980", - "renesas,du-r8a77970"; + compatible = "renesas,du-r8a77980"; reg = <0 0xfeb00000 0 0x80000>; interrupts = ; clocks = <&cpg CPG_MOD 724>; From 03abfdd31c66f0ecd629a1d1362e87551ce6c027 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 5 Nov 2019 19:35:04 +0100 Subject: [PATCH 0576/4444] arm64: dts: renesas: rcar-gen3: Replace "vsps" by "renesas,vsps" The Renesas-specific "vsps" property lacks a vendor prefix. Add a "renesas," prefix to comply with DT best practises. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Link: https://lore.kernel.org/r/20191105183504.21447-4-geert+renesas@glider.be --- arch/arm64/boot/dts/renesas/r8a774a1.dtsi | 2 +- arch/arm64/boot/dts/renesas/r8a774b1.dtsi | 2 +- arch/arm64/boot/dts/renesas/r8a774c0.dtsi | 3 ++- arch/arm64/boot/dts/renesas/r8a77950.dtsi | 2 +- arch/arm64/boot/dts/renesas/r8a77951.dtsi | 3 ++- arch/arm64/boot/dts/renesas/r8a77960.dtsi | 2 +- arch/arm64/boot/dts/renesas/r8a77965.dtsi | 2 +- arch/arm64/boot/dts/renesas/r8a77970.dtsi | 3 ++- arch/arm64/boot/dts/renesas/r8a77980.dtsi | 3 ++- arch/arm64/boot/dts/renesas/r8a77990.dtsi | 2 +- arch/arm64/boot/dts/renesas/r8a77995.dtsi | 2 +- 11 files changed, 15 insertions(+), 11 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi index 8f950dabca54..507e78ebaab5 100644 --- a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi @@ -2640,7 +2640,7 @@ clock-names = "du.0", "du.1", "du.2"; status = "disabled"; - vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>; + renesas,vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>; ports { #address-cells = <1>; diff --git a/arch/arm64/boot/dts/renesas/r8a774b1.dtsi b/arch/arm64/boot/dts/renesas/r8a774b1.dtsi index c40ea300968e..93dd10b5d6d0 100644 --- a/arch/arm64/boot/dts/renesas/r8a774b1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774b1.dtsi @@ -2486,7 +2486,7 @@ clock-names = "du.0", "du.1", "du.3"; status = "disabled"; - vsps = <&vspd0 0>, <&vspd1 0>, <&vspd0 1>; + renesas,vsps = <&vspd0 0>, <&vspd1 0>, <&vspd0 1>; ports { #address-cells = <1>; diff --git a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi index a53cd5fcc401..d4eee8fef35d 100644 --- a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi @@ -1813,7 +1813,8 @@ clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>; clock-names = "du.0", "du.1"; - vsps = <&vspd0 0>, <&vspd1 0>; + renesas,vsps = <&vspd0 0>, <&vspd1 0>; + status = "disabled"; ports { diff --git a/arch/arm64/boot/dts/renesas/r8a77950.dtsi b/arch/arm64/boot/dts/renesas/r8a77950.dtsi index 15216495e1c8..3975eecd50c4 100644 --- a/arch/arm64/boot/dts/renesas/r8a77950.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77950.dtsi @@ -30,7 +30,7 @@ }; &du { - vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd3 0>; + renesas,vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd3 0>; }; &fcpvb1 { diff --git a/arch/arm64/boot/dts/renesas/r8a77951.dtsi b/arch/arm64/boot/dts/renesas/r8a77951.dtsi index a8729eb744db..27cbe697490c 100644 --- a/arch/arm64/boot/dts/renesas/r8a77951.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77951.dtsi @@ -3184,7 +3184,8 @@ clock-names = "du.0", "du.1", "du.2", "du.3"; renesas,cmms = <&cmm0>, <&cmm1>, <&cmm2>, <&cmm3>; - vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd0 1>; + renesas,vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, + <&vspd0 1>; status = "disabled"; diff --git a/arch/arm64/boot/dts/renesas/r8a77960.dtsi b/arch/arm64/boot/dts/renesas/r8a77960.dtsi index 60f156cfd2d6..988b83fe62d4 100644 --- a/arch/arm64/boot/dts/renesas/r8a77960.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77960.dtsi @@ -2824,7 +2824,7 @@ clock-names = "du.0", "du.1", "du.2"; renesas,cmms = <&cmm0>, <&cmm1>, <&cmm2>; - vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>; + renesas,vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>; status = "disabled"; diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi index c17d90bd160e..7d2b283b7f55 100644 --- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi @@ -2500,7 +2500,7 @@ clock-names = "du.0", "du.1", "du.3"; renesas,cmms = <&cmm0>, <&cmm1>, <&cmm3>; - vsps = <&vspd0 0>, <&vspd1 0>, <&vspd0 1>; + renesas,vsps = <&vspd0 0>, <&vspd1 0>, <&vspd0 1>; status = "disabled"; diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi index 664a73a2cc69..dbf1c677dbc6 100644 --- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi @@ -1121,7 +1121,8 @@ clock-names = "du.0"; power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; resets = <&cpg 724>; - vsps = <&vspd0 0>; + renesas,vsps = <&vspd0 0>; + status = "disabled"; ports { diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi index 878ecbb7d63d..9444347e61eb 100644 --- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi @@ -1491,7 +1491,8 @@ clock-names = "du.0"; power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; resets = <&cpg 724>; - vsps = <&vspd0 0>; + renesas,vsps = <&vspd0 0>; + status = "disabled"; ports { diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi index 32d91f210246..80e8ef3007c5 100644 --- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi @@ -1791,7 +1791,7 @@ reset-names = "du.0"; renesas,cmms = <&cmm0>, <&cmm1>; - vsps = <&vspd0 0>, <&vspd1 0>; + renesas,vsps = <&vspd0 0>, <&vspd1 0>; status = "disabled"; diff --git a/arch/arm64/boot/dts/renesas/r8a77995.dtsi b/arch/arm64/boot/dts/renesas/r8a77995.dtsi index 9503007c34c0..2b5c39bd8685 100644 --- a/arch/arm64/boot/dts/renesas/r8a77995.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77995.dtsi @@ -1024,7 +1024,7 @@ reset-names = "du.0"; renesas,cmms = <&cmm0>, <&cmm1>; - vsps = <&vspd0 0>, <&vspd1 0>; + renesas,vsps = <&vspd0 0>, <&vspd1 0>; status = "disabled"; From a582013b7b1a6fbe9e896b5686887bc804800fe0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 24 Jan 2020 14:33:30 +0100 Subject: [PATCH 0577/4444] arm64: dts: renesas: rcar-gen3: Add CCREE nodes Add device nodes for the CryptoCell instances on the various Renesas R-Car Gen3 SoCs that do not have support for them yet in their device trees (M3-W, M3-W+, M3-N, E3, D3). The R-Car H3 device tree already supports this device. Signed-off-by: Geert Uytterhoeven Reviewed-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20200124133330.16121-1-geert+renesas@glider.be --- arch/arm64/boot/dts/renesas/r8a77960.dtsi | 9 +++++++++ arch/arm64/boot/dts/renesas/r8a77961.dtsi | 9 +++++++++ arch/arm64/boot/dts/renesas/r8a77965.dtsi | 9 +++++++++ arch/arm64/boot/dts/renesas/r8a77990.dtsi | 9 +++++++++ arch/arm64/boot/dts/renesas/r8a77995.dtsi | 9 +++++++++ 5 files changed, 45 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a77960.dtsi b/arch/arm64/boot/dts/renesas/r8a77960.dtsi index 988b83fe62d4..ea03b91bdf9d 100644 --- a/arch/arm64/boot/dts/renesas/r8a77960.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77960.dtsi @@ -862,6 +862,15 @@ status = "disabled"; }; + arm_cc630p: crypto@e6601000 { + compatible = "arm,cryptocell-630p-ree"; + interrupts = ; + reg = <0x0 0xe6601000 0 0x1000>; + clocks = <&cpg CPG_MOD 229>; + resets = <&cpg 229>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + }; + dmac0: dma-controller@e6700000 { compatible = "renesas,dmac-r8a7796", "renesas,rcar-dmac"; diff --git a/arch/arm64/boot/dts/renesas/r8a77961.dtsi b/arch/arm64/boot/dts/renesas/r8a77961.dtsi index be3824bda632..b6915319a61c 100644 --- a/arch/arm64/boot/dts/renesas/r8a77961.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77961.dtsi @@ -629,6 +629,15 @@ /* placeholder */ }; + arm_cc630p: crypto@e6601000 { + compatible = "arm,cryptocell-630p-ree"; + interrupts = ; + reg = <0x0 0xe6601000 0 0x1000>; + clocks = <&cpg CPG_MOD 229>; + resets = <&cpg 229>; + power-domains = <&sysc R8A77961_PD_ALWAYS_ON>; + }; + dmac0: dma-controller@e6700000 { compatible = "renesas,dmac-r8a77961", "renesas,rcar-dmac"; diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi index 7d2b283b7f55..1a20ebe9ea5b 100644 --- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi @@ -717,6 +717,15 @@ status = "disabled"; }; + arm_cc630p: crypto@e6601000 { + compatible = "arm,cryptocell-630p-ree"; + interrupts = ; + reg = <0x0 0xe6601000 0 0x1000>; + clocks = <&cpg CPG_MOD 229>; + resets = <&cpg 229>; + power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; + }; + dmac0: dma-controller@e6700000 { compatible = "renesas,dmac-r8a77965", "renesas,rcar-dmac"; diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi index 80e8ef3007c5..c05ee98043b2 100644 --- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi @@ -667,6 +667,15 @@ dma-channels = <2>; }; + arm_cc630p: crypto@e6601000 { + compatible = "arm,cryptocell-630p-ree"; + interrupts = ; + reg = <0x0 0xe6601000 0 0x1000>; + clocks = <&cpg CPG_MOD 229>; + resets = <&cpg 229>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + }; + dmac0: dma-controller@e6700000 { compatible = "renesas,dmac-r8a77990", "renesas,rcar-dmac"; diff --git a/arch/arm64/boot/dts/renesas/r8a77995.dtsi b/arch/arm64/boot/dts/renesas/r8a77995.dtsi index 2b5c39bd8685..7d3102dccac9 100644 --- a/arch/arm64/boot/dts/renesas/r8a77995.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77995.dtsi @@ -389,6 +389,15 @@ dma-channels = <2>; }; + arm_cc630p: crypto@e6601000 { + compatible = "arm,cryptocell-630p-ree"; + interrupts = ; + reg = <0x0 0xe6601000 0 0x1000>; + clocks = <&cpg CPG_MOD 229>; + resets = <&cpg 229>; + power-domains = <&sysc R8A77995_PD_ALWAYS_ON>; + }; + canfd: can@e66c0000 { compatible = "renesas,r8a77995-canfd", "renesas,rcar-gen3-canfd"; From c3f8dcee7a0cfe2a94103c6213d74eac99122f01 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 10 Jan 2020 14:19:16 +0100 Subject: [PATCH 0578/4444] pinctrl: sh-pfc: checker: Add helpers for reporting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add helpers to report errors and warnings, and to increase the corresponding counters. This simplifies callers. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20200110131927.1029-3-geert+renesas@glider.be --- drivers/pinctrl/sh-pfc/core.c | 96 ++++++++++++++++------------------- 1 file changed, 44 insertions(+), 52 deletions(-) diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index a565effbff12..d0b87a024516 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -729,6 +729,17 @@ static int sh_pfc_suspend_init(struct sh_pfc *pfc) { return 0; } static unsigned int sh_pfc_errors __initdata = 0; static unsigned int sh_pfc_warnings __initdata = 0; +#define sh_pfc_err(fmt, ...) \ + do { \ + pr_err("%s: " fmt, drvname, ##__VA_ARGS__); \ + sh_pfc_errors++; \ + } while (0) +#define sh_pfc_warn(fmt, ...) \ + do { \ + pr_warn("%s: " fmt, drvname, ##__VA_ARGS__); \ + sh_pfc_warnings++; \ + } while (0) + static bool __init is0s(const u16 *enum_ids, unsigned int n) { unsigned int i; @@ -751,26 +762,20 @@ static void __init sh_pfc_check_cfg_reg(const char *drvname, } for (i = 0, n = 0, rw = 0; (fw = cfg_reg->var_field_width[i]); i++) { - if (fw > 3 && is0s(&cfg_reg->enum_ids[n], 1 << fw)) { - pr_warn("%s: reg 0x%x: reserved field [%u:%u] can be split to reduce table size\n", - drvname, cfg_reg->reg, rw, rw + fw - 1); - sh_pfc_warnings++; - } + if (fw > 3 && is0s(&cfg_reg->enum_ids[n], 1 << fw)) + sh_pfc_warn("reg 0x%x: reserved field [%u:%u] can be split to reduce table size\n", + cfg_reg->reg, rw, rw + fw - 1); n += 1 << fw; rw += fw; } - if (rw != cfg_reg->reg_width) { - pr_err("%s: reg 0x%x: var_field_width declares %u instead of %u bits\n", - drvname, cfg_reg->reg, rw, cfg_reg->reg_width); - sh_pfc_errors++; - } + if (rw != cfg_reg->reg_width) + sh_pfc_err("reg 0x%x: var_field_width declares %u instead of %u bits\n", + cfg_reg->reg, rw, cfg_reg->reg_width); - if (n != cfg_reg->nr_enum_ids) { - pr_err("%s: reg 0x%x: enum_ids[] has %u instead of %u values\n", - drvname, cfg_reg->reg, cfg_reg->nr_enum_ids, n); - sh_pfc_errors++; - } + if (n != cfg_reg->nr_enum_ids) + sh_pfc_err("reg 0x%x: enum_ids[] has %u instead of %u values\n", + cfg_reg->reg, cfg_reg->nr_enum_ids, n); } static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) @@ -785,29 +790,24 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) /* Check pins */ for (i = 0; i < info->nr_pins; i++) { for (j = 0; j < i; j++) { - if (!strcmp(info->pins[i].name, info->pins[j].name)) { - pr_err("%s: pin %s/%s: name conflict\n", - drvname, info->pins[i].name, - info->pins[j].name); - sh_pfc_errors++; - } + if (!strcmp(info->pins[i].name, info->pins[j].name)) + sh_pfc_err("pin %s/%s: name conflict\n", + info->pins[i].name, + info->pins[j].name); if (info->pins[i].pin != (u16)-1 && - info->pins[i].pin == info->pins[j].pin) { - pr_err("%s: pin %s/%s: pin %u conflict\n", - drvname, info->pins[i].name, - info->pins[j].name, info->pins[i].pin); - sh_pfc_errors++; - } + info->pins[i].pin == info->pins[j].pin) + sh_pfc_err("pin %s/%s: pin %u conflict\n", + info->pins[i].name, + info->pins[j].name, + info->pins[i].pin); if (info->pins[i].enum_id && - info->pins[i].enum_id == info->pins[j].enum_id) { - pr_err("%s: pin %s/%s: enum_id %u conflict\n", - drvname, info->pins[i].name, - info->pins[j].name, - info->pins[i].enum_id); - sh_pfc_errors++; - } + info->pins[i].enum_id == info->pins[j].enum_id) + sh_pfc_err("pin %s/%s: enum_id %u conflict\n", + info->pins[i].name, + info->pins[j].name, + info->pins[i].enum_id); } } @@ -819,8 +819,7 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) for (i = 0; i < info->nr_functions; i++) { func = &info->functions[i]; if (!func->name) { - pr_err("%s: empty function %u\n", drvname, i); - sh_pfc_errors++; + sh_pfc_err("empty function %u\n", i); continue; } for (j = 0; j < func->nr_groups; j++) { @@ -833,29 +832,22 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) } } - if (k == info->nr_groups) { - pr_err("%s: function %s: group %s not found\n", - drvname, func->name, func->groups[j]); - sh_pfc_errors++; - } + if (k == info->nr_groups) + sh_pfc_err("function %s: group %s not found\n", + func->name, func->groups[j]); } } for (i = 0; i < info->nr_groups; i++) { if (!info->groups[i].name) { - pr_err("%s: empty group %u\n", drvname, i); - sh_pfc_errors++; + sh_pfc_err("empty group %u\n", i); continue; } - if (!refcnts[i]) { - pr_err("%s: orphan group %s\n", drvname, - info->groups[i].name); - sh_pfc_errors++; - } else if (refcnts[i] > 1) { - pr_warn("%s: group %s referenced by %u functions\n", - drvname, info->groups[i].name, refcnts[i]); - sh_pfc_warnings++; - } + if (!refcnts[i]) + sh_pfc_err("orphan group %s\n", info->groups[i].name); + else if (refcnts[i] > 1) + sh_pfc_warn("group %s referenced by %u functions\n", + info->groups[i].name, refcnts[i]); } kfree(refcnts); From 1251887c0c78fe7fee1eb1e13546c86a75368cef Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 10 Jan 2020 14:19:17 +0100 Subject: [PATCH 0579/4444] pinctrl: sh-pfc: checker: Add helper for safe name comparison MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a helper to check if two strings are identical, skipping NULL pointers. This simplifies callers. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20200110131927.1029-4-geert+renesas@glider.be --- drivers/pinctrl/sh-pfc/core.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index d0b87a024516..aad3f62c583f 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -751,6 +751,14 @@ static bool __init is0s(const u16 *enum_ids, unsigned int n) return true; } +static bool __init same_name(const char *a, const char *b) +{ + if (!a || !b) + return false; + + return !strcmp(a, b); +} + static void __init sh_pfc_check_cfg_reg(const char *drvname, const struct pinmux_cfg_reg *cfg_reg) { @@ -790,7 +798,7 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) /* Check pins */ for (i = 0; i < info->nr_pins; i++) { for (j = 0; j < i; j++) { - if (!strcmp(info->pins[i].name, info->pins[j].name)) + if (same_name(info->pins[i].name, info->pins[j].name)) sh_pfc_err("pin %s/%s: name conflict\n", info->pins[i].name, info->pins[j].name); @@ -824,9 +832,8 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) } for (j = 0; j < func->nr_groups; j++) { for (k = 0; k < info->nr_groups; k++) { - if (info->groups[k].name && - !strcmp(func->groups[j], - info->groups[k].name)) { + if (same_name(func->groups[j], + info->groups[k].name)) { refcnts[k]++; break; } From 3c26186472726fd22234fa63a6bc7c08112a4152 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 10 Jan 2020 14:19:18 +0100 Subject: [PATCH 0580/4444] pinctrl: sh-pfc: checker: Add check for config register conflicts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a helper to verify that register addresses are unique, and use it to validate config register descriptors. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20200110131927.1029-5-geert+renesas@glider.be --- drivers/pinctrl/sh-pfc/core.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index aad3f62c583f..69a6ec6aa334 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -726,8 +726,12 @@ static int sh_pfc_suspend_init(struct sh_pfc *pfc) { return 0; } #endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */ #ifdef DEBUG +#define SH_PFC_MAX_REGS 300 + static unsigned int sh_pfc_errors __initdata = 0; static unsigned int sh_pfc_warnings __initdata = 0; +static u32 *sh_pfc_regs __initdata = NULL; +static u32 sh_pfc_num_regs __initdata = 0; #define sh_pfc_err(fmt, ...) \ do { \ @@ -759,11 +763,31 @@ static bool __init same_name(const char *a, const char *b) return !strcmp(a, b); } +static void __init sh_pfc_check_reg(const char *drvname, u32 reg) +{ + unsigned int i; + + for (i = 0; i < sh_pfc_num_regs; i++) + if (reg == sh_pfc_regs[i]) { + sh_pfc_err("reg 0x%x conflict\n", reg); + return; + } + + if (sh_pfc_num_regs == SH_PFC_MAX_REGS) { + pr_warn_once("%s: Please increase SH_PFC_MAX_REGS\n", drvname); + return; + } + + sh_pfc_regs[sh_pfc_num_regs++] = reg; +} + static void __init sh_pfc_check_cfg_reg(const char *drvname, const struct pinmux_cfg_reg *cfg_reg) { unsigned int i, n, rw, fw; + sh_pfc_check_reg(drvname, cfg_reg->reg); + if (cfg_reg->field_width) { /* Checked at build time */ return; @@ -794,6 +818,7 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) unsigned int i, j, k; pr_info("Checking %s\n", drvname); + sh_pfc_num_regs = 0; /* Check pins */ for (i = 0; i < info->nr_pins; i++) { @@ -868,6 +893,11 @@ static void __init sh_pfc_check_driver(const struct platform_driver *pdrv) { unsigned int i; + sh_pfc_regs = kcalloc(SH_PFC_MAX_REGS, sizeof(*sh_pfc_regs), + GFP_KERNEL); + if (!sh_pfc_regs) + return; + pr_warn("Checking builtin pinmux tables\n"); for (i = 0; pdrv->id_table[i].name[0]; i++) @@ -880,6 +910,8 @@ static void __init sh_pfc_check_driver(const struct platform_driver *pdrv) pr_warn("Detected %u errors and %u warnings\n", sh_pfc_errors, sh_pfc_warnings); + + kfree(sh_pfc_regs); } #else /* !DEBUG */ From 12d057bad683b1c60476681ecc835c858018df60 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 10 Jan 2020 14:19:19 +0100 Subject: [PATCH 0581/4444] pinctrl: sh-pfc: checker: Add check for enum ID conflicts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a helper to verify that enum IDs are unique, and use it to validate the enum ID arrays in config register descriptors. This exposes bugs like those fixed in: - commit 805f635703b2562b ("pinctrl: sh-pfc: r8a7778: Fix duplicate SDSELF_B and SD1_CLK_B"), - commit 884caadad128efad ("pinctrl: sh-pfc: sh7734: Fix duplicate TCLK1_B"), - commit 2a069a92811fb35b ("pinctrl: sh-pfc: sh7264: Fix Port K I/O Register 0 definition"). Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20200110131927.1029-6-geert+renesas@glider.be --- drivers/pinctrl/sh-pfc/core.c | 49 +++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index 69a6ec6aa334..6c6eb791f145 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -727,11 +727,14 @@ static int sh_pfc_suspend_init(struct sh_pfc *pfc) { return 0; } #ifdef DEBUG #define SH_PFC_MAX_REGS 300 +#define SH_PFC_MAX_ENUMS 3000 static unsigned int sh_pfc_errors __initdata = 0; static unsigned int sh_pfc_warnings __initdata = 0; static u32 *sh_pfc_regs __initdata = NULL; static u32 sh_pfc_num_regs __initdata = 0; +static u16 *sh_pfc_enums __initdata = NULL; +static u32 sh_pfc_num_enums __initdata = 0; #define sh_pfc_err(fmt, ...) \ do { \ @@ -781,6 +784,36 @@ static void __init sh_pfc_check_reg(const char *drvname, u32 reg) sh_pfc_regs[sh_pfc_num_regs++] = reg; } +static int __init sh_pfc_check_enum(const char *drvname, u16 enum_id) +{ + unsigned int i; + + for (i = 0; i < sh_pfc_num_enums; i++) { + if (enum_id == sh_pfc_enums[i]) + return -EINVAL; + } + + if (sh_pfc_num_enums == SH_PFC_MAX_ENUMS) { + pr_warn_once("%s: Please increase SH_PFC_MAX_ENUMS\n", drvname); + return 0; + } + + sh_pfc_enums[sh_pfc_num_enums++] = enum_id; + return 0; +} + +static void __init sh_pfc_check_reg_enums(const char *drvname, u32 reg, + const u16 *enums, unsigned int n) +{ + unsigned int i; + + for (i = 0; i < n; i++) { + if (enums[i] && sh_pfc_check_enum(drvname, enums[i])) + sh_pfc_err("reg 0x%x enum_id %u conflict\n", reg, + enums[i]); + } +} + static void __init sh_pfc_check_cfg_reg(const char *drvname, const struct pinmux_cfg_reg *cfg_reg) { @@ -789,8 +822,9 @@ static void __init sh_pfc_check_cfg_reg(const char *drvname, sh_pfc_check_reg(drvname, cfg_reg->reg); if (cfg_reg->field_width) { - /* Checked at build time */ - return; + n = cfg_reg->reg_width / cfg_reg->field_width; + /* Skip field checks (done at build time) */ + goto check_enum_ids; } for (i = 0, n = 0, rw = 0; (fw = cfg_reg->var_field_width[i]); i++) { @@ -808,6 +842,9 @@ static void __init sh_pfc_check_cfg_reg(const char *drvname, if (n != cfg_reg->nr_enum_ids) sh_pfc_err("reg 0x%x: enum_ids[] has %u instead of %u values\n", cfg_reg->reg, cfg_reg->nr_enum_ids, n); + +check_enum_ids: + sh_pfc_check_reg_enums(drvname, cfg_reg->reg, cfg_reg->enum_ids, n); } static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) @@ -819,6 +856,7 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) pr_info("Checking %s\n", drvname); sh_pfc_num_regs = 0; + sh_pfc_num_enums = 0; /* Check pins */ for (i = 0; i < info->nr_pins; i++) { @@ -898,6 +936,11 @@ static void __init sh_pfc_check_driver(const struct platform_driver *pdrv) if (!sh_pfc_regs) return; + sh_pfc_enums = kcalloc(SH_PFC_MAX_ENUMS, sizeof(*sh_pfc_enums), + GFP_KERNEL); + if (!sh_pfc_enums) + goto free_regs; + pr_warn("Checking builtin pinmux tables\n"); for (i = 0; pdrv->id_table[i].name[0]; i++) @@ -911,6 +954,8 @@ static void __init sh_pfc_check_driver(const struct platform_driver *pdrv) pr_warn("Detected %u errors and %u warnings\n", sh_pfc_errors, sh_pfc_warnings); + kfree(sh_pfc_enums); +free_regs: kfree(sh_pfc_regs); } From 4ef30dc72d0a3b3087078379b8e6d666a3c24270 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 10 Jan 2020 14:19:20 +0100 Subject: [PATCH 0582/4444] pinctrl: sh-pfc: checker: Improve pin checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Improve the checks for pin descriptors: 1. Introduce local variables for the current pin, to make the checks easier to read, 2. Pins must have a name, 3. Fix double printing of identical pin names. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20200110131927.1029-7-geert+renesas@glider.be --- drivers/pinctrl/sh-pfc/core.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index 6c6eb791f145..be7afc48703d 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -860,25 +860,27 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) /* Check pins */ for (i = 0; i < info->nr_pins; i++) { + const struct sh_pfc_pin *pin = &info->pins[i]; + + if (!pin->name) { + sh_pfc_err("empty pin %u\n", i); + continue; + } for (j = 0; j < i; j++) { - if (same_name(info->pins[i].name, info->pins[j].name)) - sh_pfc_err("pin %s/%s: name conflict\n", - info->pins[i].name, - info->pins[j].name); + const struct sh_pfc_pin *pin2 = &info->pins[j]; - if (info->pins[i].pin != (u16)-1 && - info->pins[i].pin == info->pins[j].pin) + if (same_name(pin->name, pin2->name)) + sh_pfc_err("pin %s: name conflict\n", + pin->name); + + if (pin->pin != (u16)-1 && pin->pin == pin2->pin) sh_pfc_err("pin %s/%s: pin %u conflict\n", - info->pins[i].name, - info->pins[j].name, - info->pins[i].pin); + pin->name, pin2->name, pin->pin); - if (info->pins[i].enum_id && - info->pins[i].enum_id == info->pins[j].enum_id) + if (pin->enum_id && pin->enum_id == pin2->enum_id) sh_pfc_err("pin %s/%s: enum_id %u conflict\n", - info->pins[i].name, - info->pins[j].name, - info->pins[i].enum_id); + pin->name, pin2->name, + pin->enum_id); } } From a95b077db4fcf5aeeaf74372e31d684df29cb033 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 10 Jan 2020 14:19:21 +0100 Subject: [PATCH 0583/4444] pinctrl: sh-pfc: checker: Improve pin function checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Improve the checks for pin function descriptors: 1. Merge declaration and assignment of the local variable for the current pin function, 2. Pin function names must be unique. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20200110131927.1029-8-geert+renesas@glider.be --- drivers/pinctrl/sh-pfc/core.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index be7afc48703d..fd649ab8ad1a 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -849,7 +849,6 @@ check_enum_ids: static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) { - const struct sh_pfc_function *func; const char *drvname = info->name; unsigned int *refcnts; unsigned int i, j, k; @@ -890,11 +889,17 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) return; for (i = 0; i < info->nr_functions; i++) { - func = &info->functions[i]; + const struct sh_pfc_function *func = &info->functions[i]; + if (!func->name) { sh_pfc_err("empty function %u\n", i); continue; } + for (j = 0; j < i; j++) { + if (same_name(func->name, info->functions[j].name)) + sh_pfc_err("function %s: name conflict\n", + func->name); + } for (j = 0; j < func->nr_groups; j++) { for (k = 0; k < info->nr_groups; k++) { if (same_name(func->groups[j], From 40c8e4aad4e1575e101576aab1313f99ed3df49d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 10 Jan 2020 14:19:22 +0100 Subject: [PATCH 0584/4444] pinctrl: sh-pfc: checker: Improve pin group checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Improve the checks for pin group descriptors: 1. Introduce a local variable for the current group, to make the checks easier to read, 2. Pin group names must be unique. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20200110131927.1029-9-geert+renesas@glider.be --- drivers/pinctrl/sh-pfc/core.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index fd649ab8ad1a..b67584d65ecc 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -916,15 +916,22 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) } for (i = 0; i < info->nr_groups; i++) { - if (!info->groups[i].name) { + const struct sh_pfc_pin_group *group = &info->groups[i]; + + if (!group->name) { sh_pfc_err("empty group %u\n", i); continue; } + for (j = 0; j < i; j++) { + if (same_name(group->name, info->groups[j].name)) + sh_pfc_err("group %s: name conflict\n", + group->name); + } if (!refcnts[i]) - sh_pfc_err("orphan group %s\n", info->groups[i].name); + sh_pfc_err("orphan group %s\n", group->name); else if (refcnts[i] > 1) sh_pfc_warn("group %s referenced by %u functions\n", - info->groups[i].name, refcnts[i]); + group->name, refcnts[i]); } kfree(refcnts); From 08df16e07ad0a1ec0ccf9a154014cb80e82c773e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 10 Jan 2020 14:19:23 +0100 Subject: [PATCH 0585/4444] pinctrl: sh-pfc: checker: Add drive strength register checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add checks for drive strength register descriptors: 1. Register addresses must be unique, 2. Register fields must be non-overlapping, 3. Referred pins must exist. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20200110131927.1029-10-geert+renesas@glider.be --- drivers/pinctrl/sh-pfc/core.c | 45 +++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index b67584d65ecc..8304832e7c39 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -814,6 +814,23 @@ static void __init sh_pfc_check_reg_enums(const char *drvname, u32 reg, } } +static void __init sh_pfc_check_pin(const struct sh_pfc_soc_info *info, + u32 reg, unsigned int pin) +{ + const char *drvname = info->name; + unsigned int i; + + if (pin == SH_PFC_PIN_NONE) + return; + + for (i = 0; i < info->nr_pins; i++) { + if (pin == info->pins[i].pin) + return; + } + + sh_pfc_err("reg 0x%x: pin %u not found\n", reg, pin); +} + static void __init sh_pfc_check_cfg_reg(const char *drvname, const struct pinmux_cfg_reg *cfg_reg) { @@ -847,6 +864,30 @@ check_enum_ids: sh_pfc_check_reg_enums(drvname, cfg_reg->reg, cfg_reg->enum_ids, n); } +static void __init sh_pfc_check_drive_reg(const struct sh_pfc_soc_info *info, + const struct pinmux_drive_reg *drive) +{ + const char *drvname = info->name; + unsigned long seen = 0, mask; + unsigned int i; + + sh_pfc_check_reg(info->name, drive->reg); + for (i = 0; i < ARRAY_SIZE(drive->fields); i++) { + const struct pinmux_drive_reg_field *field = &drive->fields[i]; + + if (!field->pin && !field->offset && !field->size) + continue; + + mask = GENMASK(field->offset + field->size, field->offset); + if (mask & seen) + sh_pfc_err("drive_reg 0x%x: field %u overlap\n", + drive->reg, i); + seen |= mask; + + sh_pfc_check_pin(info, drive->reg, field->pin); + } +} + static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) { const char *drvname = info->name; @@ -939,6 +980,10 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) /* Check config register descriptions */ for (i = 0; info->cfg_regs && info->cfg_regs[i].reg; i++) sh_pfc_check_cfg_reg(drvname, &info->cfg_regs[i]); + + /* Check drive strength registers */ + for (i = 0; info->drive_regs && info->drive_regs[i].reg; i++) + sh_pfc_check_drive_reg(info, &info->drive_regs[i]); } static void __init sh_pfc_check_driver(const struct platform_driver *pdrv) From 8990cd297f1508904d3773f6a2c5af531e8649ca Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 10 Jan 2020 14:19:24 +0100 Subject: [PATCH 0586/4444] pinctrl: sh-pfc: checker: Add bias register checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add checks for bias register descriptors: 1. Pull-up and optional pull-down register addresses must be unique, 2. Referred pins must exist. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20200110131927.1029-11-geert+renesas@glider.be --- drivers/pinctrl/sh-pfc/core.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index 8304832e7c39..fcd11d83ee41 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -888,6 +888,18 @@ static void __init sh_pfc_check_drive_reg(const struct sh_pfc_soc_info *info, } } +static void __init sh_pfc_check_bias_reg(const struct sh_pfc_soc_info *info, + const struct pinmux_bias_reg *bias) +{ + unsigned int i; + + sh_pfc_check_reg(info->name, bias->puen); + if (bias->pud) + sh_pfc_check_reg(info->name, bias->pud); + for (i = 0; i < ARRAY_SIZE(bias->pins); i++) + sh_pfc_check_pin(info, bias->puen, bias->pins[i]); +} + static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) { const char *drvname = info->name; @@ -984,6 +996,10 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) /* Check drive strength registers */ for (i = 0; info->drive_regs && info->drive_regs[i].reg; i++) sh_pfc_check_drive_reg(info, &info->drive_regs[i]); + + /* Check bias registers */ + for (i = 0; info->bias_regs && info->bias_regs[i].puen; i++) + sh_pfc_check_bias_reg(info, &info->bias_regs[i]); } static void __init sh_pfc_check_driver(const struct platform_driver *pdrv) From 4bd7d16a309e034ec92b13840bae5668918ddd5b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 10 Jan 2020 14:19:25 +0100 Subject: [PATCH 0587/4444] pinctrl: sh-pfc: checker: Add ioctrl register checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add checks for generic control register descriptors: 1. Register addresses must be unique. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20200110131927.1029-12-geert+renesas@glider.be --- drivers/pinctrl/sh-pfc/core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index fcd11d83ee41..42432db4fc0b 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -1000,6 +1000,10 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) /* Check bias registers */ for (i = 0; info->bias_regs && info->bias_regs[i].puen; i++) sh_pfc_check_bias_reg(info, &info->bias_regs[i]); + + /* Check ioctrl registers */ + for (i = 0; info->ioctrl_regs && info->ioctrl_regs[i].reg; i++) + sh_pfc_check_reg(drvname, info->ioctrl_regs[i].reg); } static void __init sh_pfc_check_driver(const struct platform_driver *pdrv) From 0e6cd847a420e21f6e0d476c355127a7cbcb4a5d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 10 Jan 2020 14:19:26 +0100 Subject: [PATCH 0588/4444] pinctrl: sh-pfc: checker: Add data register checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add checks for data register descriptors: 1. Register addresses must be unique. 2. Enum ID values must be unique. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20200110131927.1029-13-geert+renesas@glider.be --- drivers/pinctrl/sh-pfc/core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index 42432db4fc0b..da2baa9446ce 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -1004,6 +1004,14 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) /* Check ioctrl registers */ for (i = 0; info->ioctrl_regs && info->ioctrl_regs[i].reg; i++) sh_pfc_check_reg(drvname, info->ioctrl_regs[i].reg); + + /* Check data registers */ + for (i = 0; info->data_regs && info->data_regs[i].reg; i++) { + sh_pfc_check_reg(drvname, info->data_regs[i].reg); + sh_pfc_check_reg_enums(drvname, info->data_regs[i].reg, + info->data_regs[i].enum_ids, + info->data_regs[i].reg_width); + } } static void __init sh_pfc_check_driver(const struct platform_driver *pdrv) From 92c44680c5c6f1342288f6626da4008d416d8e40 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 10 Jan 2020 14:19:27 +0100 Subject: [PATCH 0589/4444] pinctrl: sh-pfc: checker: Add function GPIO checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add checks for legacy function GPIO descriptors: 1. Function GPIOs must have a name, 2. Names must be unique, 3. Enum ID values must be unique. This exposes bugs like those fixed in - commit 884caadad128efad ("pinctrl: sh-pfc: sh7734: Fix duplicate TCLK1_B"), - commit 55b1cb1f03ad5eea ("pinctrl: sh-pfc: sh7264: Fix CAN function GPIOs"), - commit 02aeb2f21530c98f ("pinctrl: sh-pfc: sh7269: Fix CAN function GPIOs"), - commit db9c07272c8245a2 ("sh: sh7264: Remove bogus SSU GPIO function definitions"), - commit b4fba344a2930769 ("sh: sh7269: Remove bogus SSU GPIO function definitions"). Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20200110131927.1029-14-geert+renesas@glider.be --- drivers/pinctrl/sh-pfc/core.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index da2baa9446ce..a2e19efa26e3 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -1012,6 +1012,26 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) info->data_regs[i].enum_ids, info->data_regs[i].reg_width); } + +#ifdef CONFIG_PINCTRL_SH_FUNC_GPIO + /* Check function GPIOs */ + for (i = 0; i < info->nr_func_gpios; i++) { + const struct pinmux_func *func = &info->func_gpios[i]; + + if (!func->name) { + sh_pfc_err("empty function gpio %u\n", i); + continue; + } + for (j = 0; j < i; j++) { + if (same_name(func->name, info->func_gpios[j].name)) + sh_pfc_err("func_gpio %s: name conflict\n", + func->name); + } + if (sh_pfc_check_enum(drvname, func->enum_id)) + sh_pfc_err("%s enum_id %u conflict\n", func->name, + func->enum_id); + } +#endif } static void __init sh_pfc_check_driver(const struct platform_driver *pdrv) From 6793baa31d684f2cace0e2ee4af4bdbc993dbed8 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 12 Feb 2020 10:02:00 +0100 Subject: [PATCH 0590/4444] pinctrl: sh-pfc: gpio: Return early in gpio_pin_to_irq() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As of commit 4adeabd042422cee ("pinctrl: sh-pfc: Remove hardcoded IRQ numbers"), only a single operation needs to be performed after finding the wanted pin. Hence decrease the needed attention span of the casual reader by replacing the goto by a direct return. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20200212090200.11106-1-geert+renesas@glider.be --- drivers/pinctrl/sh-pfc/gpio.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c index 8213e118aa40..9c6e931ae766 100644 --- a/drivers/pinctrl/sh-pfc/gpio.c +++ b/drivers/pinctrl/sh-pfc/gpio.c @@ -205,14 +205,11 @@ static int gpio_pin_to_irq(struct gpio_chip *gc, unsigned offset) for (k = 0; gpios[k] >= 0; k++) { if (gpios[k] == offset) - goto found; + return pfc->irqs[i]; } } return 0; - -found: - return pfc->irqs[i]; } static int gpio_pin_setup(struct sh_pfc_chip *chip) From ffe9f9b0515600fc5ccf121315939c2ab2cd1486 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 18 Feb 2020 12:25:57 +0100 Subject: [PATCH 0591/4444] pinctrl: sh-pfc: Remove use of ARCH_R8A7795 CONFIG_ARCH_R8A7795 was split in CONFIG_ARCH_R8A77950 and CONFIG_ARCH_R8A77951 in commit b925adfceb529389 ("soc: renesas: Add ARCH_R8A7795[01] for existing R-Car H3"), so its users can be removed. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200218112557.5924-1-geert+renesas@glider.be --- drivers/pinctrl/sh-pfc/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/sh-pfc/Kconfig b/drivers/pinctrl/sh-pfc/Kconfig index cf0e0dc42b84..9552851b96f1 100644 --- a/drivers/pinctrl/sh-pfc/Kconfig +++ b/drivers/pinctrl/sh-pfc/Kconfig @@ -26,8 +26,8 @@ config PINCTRL_SH_PFC select PINCTRL_PFC_R8A7792 if ARCH_R8A7792 select PINCTRL_PFC_R8A7793 if ARCH_R8A7793 select PINCTRL_PFC_R8A7794 if ARCH_R8A7794 - select PINCTRL_PFC_R8A77950 if ARCH_R8A77950 || ARCH_R8A7795 - select PINCTRL_PFC_R8A77951 if ARCH_R8A77951 || ARCH_R8A7795 + select PINCTRL_PFC_R8A77950 if ARCH_R8A77950 + select PINCTRL_PFC_R8A77951 if ARCH_R8A77951 select PINCTRL_PFC_R8A77960 if ARCH_R8A77960 select PINCTRL_PFC_R8A77961 if ARCH_R8A77961 select PINCTRL_PFC_R8A77965 if ARCH_R8A77965 From 068e7f85234c0b56f55cc0259ad9c05f2c64b8fb Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 18 Feb 2020 12:25:25 +0100 Subject: [PATCH 0592/4444] clk: renesas: Remove use of ARCH_R8A7795 CONFIG_ARCH_R8A7795 was split in CONFIG_ARCH_R8A77950 and CONFIG_ARCH_R8A77951 in commit b925adfceb529389 ("soc: renesas: Add ARCH_R8A7795[01] for existing R-Car H3"), so its users can be removed. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200218112525.5834-1-geert+renesas@glider.be --- drivers/clk/renesas/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 250d8165167a..879d96ead06b 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -20,7 +20,7 @@ config CLK_RENESAS select CLK_R8A7791 if ARCH_R8A7791 || ARCH_R8A7793 select CLK_R8A7792 if ARCH_R8A7792 select CLK_R8A7794 if ARCH_R8A7794 - select CLK_R8A7795 if ARCH_R8A77950 || ARCH_R8A77951 || ARCH_R8A7795 + select CLK_R8A7795 if ARCH_R8A77950 || ARCH_R8A77951 select CLK_R8A77960 if ARCH_R8A77960 select CLK_R8A77961 if ARCH_R8A77961 select CLK_R8A77965 if ARCH_R8A77965 From 62209c9ad2ac29431e91392afb0bd6332ae4c33e Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Thu, 20 Feb 2020 21:57:09 +0100 Subject: [PATCH 0593/4444] ASoC: meson: aiu: Document Meson8 and Meson8b support in the dt-bindings The AIU audio output controller on the Meson8 and Meson8b SoC families is compatible with the one found in the GXBB family. Document the compatible string for these two older SoCs. Signed-off-by: Martin Blumenstingl Reviewed-by: Jerome Brunet Link: https://lore.kernel.org/r/20200220205711.77953-2-martin.blumenstingl@googlemail.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/amlogic,aiu.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/amlogic,aiu.yaml b/Documentation/devicetree/bindings/sound/amlogic,aiu.yaml index 3ef7632dcb59..a61bccf915d8 100644 --- a/Documentation/devicetree/bindings/sound/amlogic,aiu.yaml +++ b/Documentation/devicetree/bindings/sound/amlogic,aiu.yaml @@ -21,6 +21,8 @@ properties: - enum: - amlogic,aiu-gxbb - amlogic,aiu-gxl + - amlogic,aiu-meson8 + - amlogic,aiu-meson8b - const: amlogic,aiu From edc761805302db6d63916694d0cdb7468864a47a Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Thu, 20 Feb 2020 21:57:10 +0100 Subject: [PATCH 0594/4444] ASoC: meson: aiu: introduce a struct for platform specific information Introduce a struct aiu_platform_data to make the driver aware of platform specific information. Convert the existing check for the internal stereo audio codec (only available on GXL) to this new struct. Support for the 32-bit SoCs will need this as well because the AIU_CLK_CTRL_MORE register doesn't have the I2S divider bits (and we need to use the I2S divider from AIU_CLK_CTRL instead). Signed-off-by: Martin Blumenstingl Reviewed-by: Jerome Brunet Link: https://lore.kernel.org/r/20200220205711.77953-3-martin.blumenstingl@googlemail.com Signed-off-by: Mark Brown --- sound/soc/meson/aiu.c | 19 ++++++++++++++++--- sound/soc/meson/aiu.h | 5 +++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/sound/soc/meson/aiu.c b/sound/soc/meson/aiu.c index d3e2d40e9562..38209312a8c3 100644 --- a/sound/soc/meson/aiu.c +++ b/sound/soc/meson/aiu.c @@ -273,6 +273,11 @@ static int aiu_probe(struct platform_device *pdev) aiu = devm_kzalloc(dev, sizeof(*aiu), GFP_KERNEL); if (!aiu) return -ENOMEM; + + aiu->platform = device_get_match_data(dev); + if (!aiu->platform) + return -ENODEV; + platform_set_drvdata(pdev, aiu); ret = device_reset(dev); @@ -322,7 +327,7 @@ static int aiu_probe(struct platform_device *pdev) } /* Register the internal dac control component on gxl */ - if (of_device_is_compatible(dev->of_node, "amlogic,aiu-gxl")) { + if (aiu->platform->has_acodec) { ret = aiu_acodec_ctrl_register_component(dev); if (ret) { dev_err(dev, @@ -344,9 +349,17 @@ static int aiu_remove(struct platform_device *pdev) return 0; } +static const struct aiu_platform_data aiu_gxbb_pdata = { + .has_acodec = false, +}; + +static const struct aiu_platform_data aiu_gxl_pdata = { + .has_acodec = true, +}; + static const struct of_device_id aiu_of_match[] = { - { .compatible = "amlogic,aiu-gxbb", }, - { .compatible = "amlogic,aiu-gxl", }, + { .compatible = "amlogic,aiu-gxbb", .data = &aiu_gxbb_pdata }, + { .compatible = "amlogic,aiu-gxl", .data = &aiu_gxl_pdata }, {} }; MODULE_DEVICE_TABLE(of, aiu_of_match); diff --git a/sound/soc/meson/aiu.h b/sound/soc/meson/aiu.h index 06a968c55728..ab003638d5e5 100644 --- a/sound/soc/meson/aiu.h +++ b/sound/soc/meson/aiu.h @@ -27,11 +27,16 @@ struct aiu_interface { int irq; }; +struct aiu_platform_data { + bool has_acodec; +}; + struct aiu { struct clk *pclk; struct clk *spdif_mclk; struct aiu_interface i2s; struct aiu_interface spdif; + const struct aiu_platform_data *platform; }; #define AIU_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ From 3e25c44598aa44134207ad7b3c5ad6b586135777 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Thu, 20 Feb 2020 21:57:11 +0100 Subject: [PATCH 0595/4444] ASoC: meson: aiu: add support for the Meson8 and Meson8b SoC families The AIU audio controller on the Meson8 and Meson8b SoC families is compatible with the one found in the later GXBB family. Add compatible strings for these two older SoC families so the driver can be loaded for them. Instead of using the I2S divider from the AIU_CLK_CTRL_MORE register we need to use the I2S divider from the AIU_CLK_CTRL register. This older register is less flexible because it only supports four divider settings (1, 2, 4, 8) compared to the AIU_CLK_CTRL_MORE register (which supports dividers in the range 0..64). Signed-off-by: Martin Blumenstingl Reviewed-by: Jerome Brunet Link: https://lore.kernel.org/r/20200220205711.77953-4-martin.blumenstingl@googlemail.com Signed-off-by: Mark Brown --- sound/soc/meson/Kconfig | 2 +- sound/soc/meson/aiu-encoder-i2s.c | 94 +++++++++++++++++++++++-------- sound/soc/meson/aiu.c | 9 +++ sound/soc/meson/aiu.h | 1 + 4 files changed, 82 insertions(+), 24 deletions(-) diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index 897a706dcda0..d27e9180b453 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -10,7 +10,7 @@ config SND_MESON_AIU imply SND_SOC_HDMI_CODEC if DRM_MESON_DW_HDMI help Select Y or M to add support for the Audio output subsystem found - in the Amlogic GX SoC family + in the Amlogic Meson8, Meson8b and GX SoC families config SND_MESON_AXG_FIFO tristate diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encoder-i2s.c index 4900e38e7e49..cc73b5d5c2b7 100644 --- a/sound/soc/meson/aiu-encoder-i2s.c +++ b/sound/soc/meson/aiu-encoder-i2s.c @@ -111,12 +111,76 @@ static int aiu_encoder_i2s_setup_desc(struct snd_soc_component *component, return 0; } +static int aiu_encoder_i2s_set_legacy_div(struct snd_soc_component *component, + struct snd_pcm_hw_params *params, + unsigned int bs) +{ + switch (bs) { + case 1: + case 2: + case 4: + case 8: + /* These are the only valid legacy dividers */ + break; + + default: + dev_err(component->dev, "Unsupported i2s divider: %u\n", bs); + return -EINVAL; + }; + + snd_soc_component_update_bits(component, AIU_CLK_CTRL, + AIU_CLK_CTRL_I2S_DIV, + FIELD_PREP(AIU_CLK_CTRL_I2S_DIV, + __ffs(bs))); + + snd_soc_component_update_bits(component, AIU_CLK_CTRL_MORE, + AIU_CLK_CTRL_MORE_I2S_DIV, + FIELD_PREP(AIU_CLK_CTRL_MORE_I2S_DIV, + 0)); + + return 0; +} + +static int aiu_encoder_i2s_set_more_div(struct snd_soc_component *component, + struct snd_pcm_hw_params *params, + unsigned int bs) +{ + /* + * NOTE: this HW is odd. + * In most configuration, the i2s divider is 'mclk / blck'. + * However, in 16 bits - 8ch mode, this factor needs to be + * increased by 50% to get the correct output rate. + * No idea why ! + */ + if (params_width(params) == 16 && params_channels(params) == 8) { + if (bs % 2) { + dev_err(component->dev, + "Cannot increase i2s divider by 50%%\n"); + return -EINVAL; + } + bs += bs / 2; + } + + /* Use CLK_MORE for mclk to bclk divider */ + snd_soc_component_update_bits(component, AIU_CLK_CTRL, + AIU_CLK_CTRL_I2S_DIV, + FIELD_PREP(AIU_CLK_CTRL_I2S_DIV, 0)); + + snd_soc_component_update_bits(component, AIU_CLK_CTRL_MORE, + AIU_CLK_CTRL_MORE_I2S_DIV, + FIELD_PREP(AIU_CLK_CTRL_MORE_I2S_DIV, + bs - 1)); + + return 0; +} + static int aiu_encoder_i2s_set_clocks(struct snd_soc_component *component, struct snd_pcm_hw_params *params) { struct aiu *aiu = snd_soc_component_get_drvdata(component); unsigned int srate = params_rate(params); unsigned int fs, bs; + int ret; /* Get the oversampling factor */ fs = DIV_ROUND_CLOSEST(clk_get_rate(aiu->i2s.clks[MCLK].clk), srate); @@ -135,31 +199,15 @@ static int aiu_encoder_i2s_set_clocks(struct snd_soc_component *component, FIELD_PREP(AIU_CODEC_DAC_LRCLK_CTRL_DIV, 64 - 1)); - /* Use CLK_MORE for mclk to bclk divider */ - snd_soc_component_update_bits(component, AIU_CLK_CTRL, - AIU_CLK_CTRL_I2S_DIV, 0); - - /* - * NOTE: this HW is odd. - * In most configuration, the i2s divider is 'mclk / blck'. - * However, in 16 bits - 8ch mode, this factor needs to be - * increased by 50% to get the correct output rate. - * No idea why ! - */ bs = fs / 64; - if (params_width(params) == 16 && params_channels(params) == 8) { - if (bs % 2) { - dev_err(component->dev, - "Cannot increase i2s divider by 50%%\n"); - return -EINVAL; - } - bs += bs / 2; - } - snd_soc_component_update_bits(component, AIU_CLK_CTRL_MORE, - AIU_CLK_CTRL_MORE_I2S_DIV, - FIELD_PREP(AIU_CLK_CTRL_MORE_I2S_DIV, - bs - 1)); + if (aiu->platform->has_clk_ctrl_more_i2s_div) + ret = aiu_encoder_i2s_set_more_div(component, params, bs); + else + ret = aiu_encoder_i2s_set_legacy_div(component, params, bs); + + if (ret) + return ret; /* Make sure amclk is used for HDMI i2s as well */ snd_soc_component_update_bits(component, AIU_CLK_CTRL_MORE, diff --git a/sound/soc/meson/aiu.c b/sound/soc/meson/aiu.c index 38209312a8c3..dc35ca79021c 100644 --- a/sound/soc/meson/aiu.c +++ b/sound/soc/meson/aiu.c @@ -351,15 +351,24 @@ static int aiu_remove(struct platform_device *pdev) static const struct aiu_platform_data aiu_gxbb_pdata = { .has_acodec = false, + .has_clk_ctrl_more_i2s_div = true, }; static const struct aiu_platform_data aiu_gxl_pdata = { .has_acodec = true, + .has_clk_ctrl_more_i2s_div = true, +}; + +static const struct aiu_platform_data aiu_meson8_pdata = { + .has_acodec = false, + .has_clk_ctrl_more_i2s_div = false, }; static const struct of_device_id aiu_of_match[] = { { .compatible = "amlogic,aiu-gxbb", .data = &aiu_gxbb_pdata }, { .compatible = "amlogic,aiu-gxl", .data = &aiu_gxl_pdata }, + { .compatible = "amlogic,aiu-meson8", .data = &aiu_meson8_pdata }, + { .compatible = "amlogic,aiu-meson8b", .data = &aiu_meson8_pdata }, {} }; MODULE_DEVICE_TABLE(of, aiu_of_match); diff --git a/sound/soc/meson/aiu.h b/sound/soc/meson/aiu.h index ab003638d5e5..87aa19ac4af3 100644 --- a/sound/soc/meson/aiu.h +++ b/sound/soc/meson/aiu.h @@ -29,6 +29,7 @@ struct aiu_interface { struct aiu_platform_data { bool has_acodec; + bool has_clk_ctrl_more_i2s_div; }; struct aiu { From 4ff27112282e5482d618ea93837fe416af671bc2 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 18 Feb 2020 12:24:49 +0100 Subject: [PATCH 0596/4444] soc: renesas: Remove ARCH_R8A7795 Replace the final user of CONFIG_ARCH_R8A7795 by CONFIG_ARCH_R8A77950 || CONFIG_ARCH_R8A77951, and remove the now unused CONFIG_ARCH_R8A7795 symbol definition. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200218112449.5723-1-geert+renesas@glider.be --- drivers/soc/renesas/Kconfig | 20 ++++++++++---------- drivers/soc/renesas/renesas-soc.c | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index ba2b8b51d2d9..7f154517b91c 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -193,19 +193,19 @@ config ARCH_R8A774C0 This enables support for the Renesas RZ/G2E SoC. config ARCH_R8A77950 - bool - -config ARCH_R8A77951 - bool - -config ARCH_R8A7795 - bool "Renesas R-Car H3 SoC Platform" - select ARCH_R8A77950 - select ARCH_R8A77951 + bool "Renesas R-Car H3 ES1.x SoC Platform" select ARCH_RCAR_GEN3 select SYSC_R8A7795 help - This enables support for the Renesas R-Car H3 SoC. + This enables support for the Renesas R-Car H3 SoC (revision 1.x). + +config ARCH_R8A77951 + bool "Renesas R-Car H3 ES2.0+ SoC Platform" + select ARCH_RCAR_GEN3 + select SYSC_R8A7795 + help + This enables support for the Renesas R-Car H3 SoC (revisions 2.0 and + later). config ARCH_R8A77960 bool "Renesas R-Car M3-W SoC Platform" diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c index 850f5733dc88..35dba8b8814e 100644 --- a/drivers/soc/renesas/renesas-soc.c +++ b/drivers/soc/renesas/renesas-soc.c @@ -259,7 +259,7 @@ static const struct of_device_id renesas_socs[] __initconst = { #ifdef CONFIG_ARCH_R8A7794 { .compatible = "renesas,r8a7794", .data = &soc_rcar_e2 }, #endif -#ifdef CONFIG_ARCH_R8A7795 +#if defined(CONFIG_ARCH_R8A77950) || defined(CONFIG_ARCH_R8A77951) { .compatible = "renesas,r8a7795", .data = &soc_rcar_h3 }, #endif #ifdef CONFIG_ARCH_R8A77960 From 361c5dbb446eedcb1367f1bf50f32ed4d8d4cc3b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 18 Feb 2020 12:24:14 +0100 Subject: [PATCH 0597/4444] arm64: dts: renesas: Remove use of ARCH_R8A7795 CONFIG_ARCH_R8A7795 was split in CONFIG_ARCH_R8A77950 and CONFIG_ARCH_R8A77951 in commit b925adfceb529389 ("soc: renesas: Add ARCH_R8A7795[01] for existing R-Car H3"), so its users can be removed. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200218112414.5591-1-geert+renesas@glider.be --- arch/arm64/boot/dts/renesas/Makefile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile index 2153842321ce..94d5ad03197d 100644 --- a/arch/arm64/boot/dts/renesas/Makefile +++ b/arch/arm64/boot/dts/renesas/Makefile @@ -5,10 +5,6 @@ dtb-$(CONFIG_ARCH_R8A774B1) += r8a774b1-hihope-rzg2n.dtb dtb-$(CONFIG_ARCH_R8A774B1) += r8a774b1-hihope-rzg2n-ex.dtb dtb-$(CONFIG_ARCH_R8A774C0) += r8a774c0-cat874.dtb r8a774c0-ek874.dtb \ r8a774c0-ek874-idk-2121wr.dtb -dtb-$(CONFIG_ARCH_R8A7795) += r8a77950-salvator-x.dtb -dtb-$(CONFIG_ARCH_R8A7795) += r8a77950-ulcb.dtb r8a77950-ulcb-kf.dtb -dtb-$(CONFIG_ARCH_R8A7795) += r8a77951-salvator-x.dtb r8a77951-salvator-xs.dtb -dtb-$(CONFIG_ARCH_R8A7795) += r8a77951-ulcb.dtb r8a77951-ulcb-kf.dtb dtb-$(CONFIG_ARCH_R8A77950) += r8a77950-salvator-x.dtb dtb-$(CONFIG_ARCH_R8A77950) += r8a77950-ulcb.dtb r8a77950-ulcb-kf.dtb dtb-$(CONFIG_ARCH_R8A77951) += r8a77951-salvator-x.dtb r8a77951-salvator-xs.dtb From d745c72da921acdf38d68681d5fc2ff113b78f55 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 18 Feb 2020 14:30:18 +0100 Subject: [PATCH 0598/4444] arm64: dts: renesas: rcar-gen3: Add reset control properties for display Add reset control properties to the device nodes for the Display Units on all supported R-Car Gen3 SoCs. Note that on these SoCs, there is only a single reset for each pair of DU channels. The display nodes on R-Car V3M and V3H already had "resets" properties, but lacked the corresponding "reset-names" properties. Join the clocks lines while at it, to increase uniformity. Signed-off-by: Geert Uytterhoeven Reviewed-by: Ulrich Hecht Reviewed-by: Laurent Pinchart Link: https://lore.kernel.org/r/20200218133019.22299-4-geert+renesas@glider.be --- arch/arm64/boot/dts/renesas/r8a77951.dtsi | 8 ++++---- arch/arm64/boot/dts/renesas/r8a77960.dtsi | 5 +++-- arch/arm64/boot/dts/renesas/r8a77965.dtsi | 5 +++-- arch/arm64/boot/dts/renesas/r8a77970.dtsi | 1 + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 1 + arch/arm64/boot/dts/renesas/r8a77990.dtsi | 3 +-- arch/arm64/boot/dts/renesas/r8a77995.dtsi | 3 +-- 7 files changed, 14 insertions(+), 12 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a77951.dtsi b/arch/arm64/boot/dts/renesas/r8a77951.dtsi index 27cbe697490c..52229546454c 100644 --- a/arch/arm64/boot/dts/renesas/r8a77951.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77951.dtsi @@ -3177,11 +3177,11 @@ , , ; - clocks = <&cpg CPG_MOD 724>, - <&cpg CPG_MOD 723>, - <&cpg CPG_MOD 722>, - <&cpg CPG_MOD 721>; + clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>, + <&cpg CPG_MOD 722>, <&cpg CPG_MOD 721>; clock-names = "du.0", "du.1", "du.2", "du.3"; + resets = <&cpg 724>, <&cpg 722>; + reset-names = "du.0", "du.2"; renesas,cmms = <&cmm0>, <&cmm1>, <&cmm2>, <&cmm3>; renesas,vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, diff --git a/arch/arm64/boot/dts/renesas/r8a77960.dtsi b/arch/arm64/boot/dts/renesas/r8a77960.dtsi index ea03b91bdf9d..31282367d3ac 100644 --- a/arch/arm64/boot/dts/renesas/r8a77960.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77960.dtsi @@ -2827,10 +2827,11 @@ interrupts = , , ; - clocks = <&cpg CPG_MOD 724>, - <&cpg CPG_MOD 723>, + clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>, <&cpg CPG_MOD 722>; clock-names = "du.0", "du.1", "du.2"; + resets = <&cpg 724>, <&cpg 722>; + reset-names = "du.0", "du.2"; renesas,cmms = <&cmm0>, <&cmm1>, <&cmm2>; renesas,vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>; diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi index 1a20ebe9ea5b..f7468822e81e 100644 --- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi @@ -2503,10 +2503,11 @@ interrupts = , , ; - clocks = <&cpg CPG_MOD 724>, - <&cpg CPG_MOD 723>, + clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>, <&cpg CPG_MOD 721>; clock-names = "du.0", "du.1", "du.3"; + resets = <&cpg 724>, <&cpg 722>; + reset-names = "du.0", "du.3"; renesas,cmms = <&cmm0>, <&cmm1>, <&cmm3>; renesas,vsps = <&vspd0 0>, <&vspd1 0>, <&vspd0 1>; diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi index dbf1c677dbc6..a009c0ebc8b4 100644 --- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi @@ -1121,6 +1121,7 @@ clock-names = "du.0"; power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; resets = <&cpg 724>; + reset-names = "du.0"; renesas,vsps = <&vspd0 0>; status = "disabled"; diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi index 9444347e61eb..e01b0508a18f 100644 --- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi @@ -1491,6 +1491,7 @@ clock-names = "du.0"; power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; resets = <&cpg 724>; + reset-names = "du.0"; renesas,vsps = <&vspd0 0>; status = "disabled"; diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi index c05ee98043b2..0ad20b78e6eb 100644 --- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi @@ -1793,8 +1793,7 @@ reg = <0 0xfeb00000 0 0x40000>; interrupts = , ; - clocks = <&cpg CPG_MOD 724>, - <&cpg CPG_MOD 723>; + clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>; clock-names = "du.0", "du.1"; resets = <&cpg 724>; reset-names = "du.0"; diff --git a/arch/arm64/boot/dts/renesas/r8a77995.dtsi b/arch/arm64/boot/dts/renesas/r8a77995.dtsi index 7d3102dccac9..e8d2290fe79d 100644 --- a/arch/arm64/boot/dts/renesas/r8a77995.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77995.dtsi @@ -1026,8 +1026,7 @@ reg = <0 0xfeb00000 0 0x40000>; interrupts = , ; - clocks = <&cpg CPG_MOD 724>, - <&cpg CPG_MOD 723>; + clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>; clock-names = "du.0", "du.1"; resets = <&cpg 724>; reset-names = "du.0"; From 721b76195b31467e56851fbab3855e700f281270 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 18 Feb 2020 14:30:19 +0100 Subject: [PATCH 0599/4444] arm64: dts: renesas: rzg2: Add reset control properties for display Add reset control properties to the device nodes for the Display Units on all supported RZ/G2 SoCs. Note that on these SoCs, there is only a single reset for each pair of DU channels. Join the clocks lines while at it, to increase uniformity. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Link: https://lore.kernel.org/r/20200218133019.22299-5-geert+renesas@glider.be --- arch/arm64/boot/dts/renesas/r8a774a1.dtsi | 5 +++-- arch/arm64/boot/dts/renesas/r8a774b1.dtsi | 5 +++-- arch/arm64/boot/dts/renesas/r8a774c0.dtsi | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi index 507e78ebaab5..79023433a740 100644 --- a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi @@ -2634,10 +2634,11 @@ interrupts = , , ; - clocks = <&cpg CPG_MOD 724>, - <&cpg CPG_MOD 723>, + clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>, <&cpg CPG_MOD 722>; clock-names = "du.0", "du.1", "du.2"; + resets = <&cpg 724>, <&cpg 722>; + reset-names = "du.0", "du.2"; status = "disabled"; renesas,vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>; diff --git a/arch/arm64/boot/dts/renesas/r8a774b1.dtsi b/arch/arm64/boot/dts/renesas/r8a774b1.dtsi index 93dd10b5d6d0..3137f735974b 100644 --- a/arch/arm64/boot/dts/renesas/r8a774b1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774b1.dtsi @@ -2480,10 +2480,11 @@ interrupts = , , ; - clocks = <&cpg CPG_MOD 724>, - <&cpg CPG_MOD 723>, + clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>, <&cpg CPG_MOD 721>; clock-names = "du.0", "du.1", "du.3"; + resets = <&cpg 724>, <&cpg 722>; + reset-names = "du.0", "du.3"; status = "disabled"; renesas,vsps = <&vspd0 0>, <&vspd1 0>, <&vspd0 1>; diff --git a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi index d4eee8fef35d..22785cbddff5 100644 --- a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi @@ -1810,9 +1810,10 @@ reg = <0 0xfeb00000 0 0x40000>; interrupts = , ; - clocks = <&cpg CPG_MOD 724>, - <&cpg CPG_MOD 723>; + clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>; clock-names = "du.0", "du.1"; + resets = <&cpg 724>; + reset-names = "du.0"; renesas,vsps = <&vspd0 0>, <&vspd1 0>; status = "disabled"; From 150cbf8e66ec86966c13fd7a0e3de8813bca03d8 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 17 Feb 2020 00:42:20 -0600 Subject: [PATCH 0600/4444] ASoC: sun8i-codec: Remove unused dev from codec struct This field is not used anywhere in the driver, so remove it. Fixes: 36c684936fae ("ASoC: Add sun8i digital audio codec") Signed-off-by: Samuel Holland Acked-by: Chen-Yu Tsai Link: https://lore.kernel.org/r/20200217064250.15516-5-samuel@sholland.org Signed-off-by: Mark Brown --- sound/soc/sunxi/sun8i-codec.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 55798bc8eae2..41471bd01042 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -85,7 +85,6 @@ #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK GENMASK(12, 9) struct sun8i_codec { - struct device *dev; struct regmap *regmap; struct clk *clk_module; struct clk *clk_bus; @@ -541,8 +540,6 @@ static int sun8i_codec_probe(struct platform_device *pdev) if (!scodec) return -ENOMEM; - scodec->dev = &pdev->dev; - scodec->clk_module = devm_clk_get(&pdev->dev, "mod"); if (IS_ERR(scodec->clk_module)) { dev_err(&pdev->dev, "Failed to get the module clock\n"); From bf9e333ec0d54f7428d9192ad403c3cb523584c7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 17 Feb 2020 11:32:51 +0100 Subject: [PATCH 0601/4444] arm64: defconfig: Enable additional support for Renesas platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Increase build and test coverage by enabling support for more hardware present on Renesas SoCs and boards: - R-Car CAN and CAN-FD controllers, - MSIOF SPI controllers, - ROHM BD9571 GPIO support, - R-Car MIPI CSI-2 receivers, - R-Car Video Input, - Renesas Fine Display Processors, - Renesas Digital Radio Interfaces, - R-Car Gen3 internal HDMI encoders, - Generic LVDS panel support, - Dumb VGA DAC Bridge support, - Thine THC63LVD1024 LVDS decoder bridges, - Synopsys Designware AHB Audio and CEC interfaces, - Renesas USBHS HCD support, - IDT VersaClock 5,6 devices, - Maxim max9611/max9612 ADCs, - ARM TrustZone CryptoCell security processors. All of the above are modular, except for the VC5 clock driver, and the SDR config gatekeepers. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund (VIN, CSI-2) Link: https://lore.kernel.org/r/20200217103251.5205-1-geert+renesas@glider.be --- arch/arm64/configs/defconfig | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 51b8b8555a6e..49053323323f 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -161,6 +161,9 @@ CONFIG_QRTR=m CONFIG_QRTR_SMD=m CONFIG_QRTR_TUN=m CONFIG_BPF_JIT=y +CONFIG_CAN=m +CONFIG_CAN_RCAR=m +CONFIG_CAN_RCAR_CANFD=m CONFIG_BT=m CONFIG_BT_HIDP=m # CONFIG_BT_HS is not set @@ -399,6 +402,7 @@ CONFIG_SPI_QCOM_QSPI=m CONFIG_SPI_QUP=y CONFIG_SPI_QCOM_GENI=m CONFIG_SPI_S3C64XX=y +CONFIG_SPI_SH_MSIOF=m CONFIG_SPI_SUN6I=y CONFIG_SPI_SPIDEV=m CONFIG_SPMI=y @@ -432,6 +436,7 @@ CONFIG_GPIO_XGENE_SB=y CONFIG_GPIO_MAX732X=y CONFIG_GPIO_PCA953X=y CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_GPIO_BD9571MWV=m CONFIG_GPIO_MAX77620=y CONFIG_POWER_AVS=y CONFIG_QCOM_CPR=y @@ -516,19 +521,25 @@ CONFIG_MEDIA_SUPPORT=m CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_ANALOG_TV_SUPPORT=y CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +CONFIG_MEDIA_SDR_SUPPORT=y CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_V4L2_SUBDEV_API=y # CONFIG_DVB_NET is not set CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=m CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_VIDEO_RCAR_CSI2=m +CONFIG_VIDEO_RCAR_VIN=m CONFIG_VIDEO_SUN6I_CSI=m CONFIG_V4L_MEM2MEM_DRIVERS=y CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m CONFIG_VIDEO_SAMSUNG_S5P_MFC=m CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=m +CONFIG_VIDEO_RENESAS_FDP1=m CONFIG_VIDEO_RENESAS_FCP=m CONFIG_VIDEO_RENESAS_VSP1=m +CONFIG_SDR_PLATFORM_DRIVERS=y +CONFIG_VIDEO_RCAR_DRIF=m CONFIG_DRM=m CONFIG_DRM_I2C_NXP_TDA998X=m CONFIG_DRM_NOUVEAU=m @@ -546,15 +557,21 @@ CONFIG_ROCKCHIP_DW_HDMI=y CONFIG_ROCKCHIP_DW_MIPI_DSI=y CONFIG_ROCKCHIP_INNO_HDMI=y CONFIG_DRM_RCAR_DU=m +CONFIG_DRM_RCAR_DW_HDMI=m CONFIG_DRM_SUN4I=m CONFIG_DRM_SUN8I_DW_HDMI=m CONFIG_DRM_SUN8I_MIXER=m CONFIG_DRM_MSM=m CONFIG_DRM_TEGRA=m +CONFIG_DRM_PANEL_LVDS=m CONFIG_DRM_PANEL_SIMPLE=m +CONFIG_DRM_DUMB_VGA_DAC=m CONFIG_DRM_SII902X=m +CONFIG_DRM_THINE_THC63LVD1024=m CONFIG_DRM_TI_SN65DSI86=m CONFIG_DRM_I2C_ADV7511=m +CONFIG_DRM_DW_HDMI_AHB_AUDIO=m +CONFIG_DRM_DW_HDMI_CEC=m CONFIG_DRM_VC4=m CONFIG_DRM_ETNAVIV=m CONFIG_DRM_HISI_HIBMC=m @@ -605,6 +622,7 @@ CONFIG_USB_EHCI_HCD_PLATFORM=y CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_EXYNOS=y CONFIG_USB_OHCI_HCD_PLATFORM=y +CONFIG_USB_RENESAS_USBHS_HCD=m CONFIG_USB_RENESAS_USBHS=m CONFIG_USB_STORAGE=y CONFIG_USB_MUSB_HDRC=y @@ -712,6 +730,7 @@ CONFIG_COMMON_CLK_CS2000_CP=y CONFIG_COMMON_CLK_S2MPS11=y CONFIG_CLK_QORIQ=y CONFIG_COMMON_CLK_PWM=y +CONFIG_COMMON_CLK_VC5=y CONFIG_CLK_RASPBERRYPI=m CONFIG_CLK_IMX8MM=y CONFIG_CLK_IMX8MN=y @@ -792,6 +811,7 @@ CONFIG_EXTCON_USBC_CROS_EC=y CONFIG_MEMORY=y CONFIG_IIO=y CONFIG_EXYNOS_ADC=y +CONFIG_MAX9611=m CONFIG_QCOM_SPMI_ADC5=m CONFIG_ROCKCHIP_SARADC=m CONFIG_IIO_CROS_EC_SENSORS_CORE=m @@ -885,6 +905,7 @@ CONFIG_CRYPTO_DEV_FSL_CAAM=m CONFIG_CRYPTO_DEV_HISI_ZIP=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_DEV_QCOM_RNG=m +CONFIG_CRYPTO_DEV_CCREE=m CONFIG_CMA_SIZE_MBYTES=32 CONFIG_PRINTK_TIME=y CONFIG_DEBUG_INFO=y From 023892ec80f0efcffe22045e92bb89f3f1480f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 11 Feb 2020 14:51:21 +0100 Subject: [PATCH 0602/4444] gpio: siox: use raw spinlock for irq related locking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the irq related callbacks are called with the (raw) spinlock desc->lock being held. So the lock here must be raw as well. Also irqs were already disabled by the caller for the irq chip callbacks, so the non-irq variants of spin_lock must be used there. Fixes: be8c8facc707 ("gpio: new driver to work with a 8x12 siox") Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20200211135121.15752-1-uwe@kleine-koenig.org Signed-off-by: Linus Walleij --- drivers/gpio/gpio-siox.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/gpio-siox.c b/drivers/gpio/gpio-siox.c index 311f66757b92..26e1fe092304 100644 --- a/drivers/gpio/gpio-siox.c +++ b/drivers/gpio/gpio-siox.c @@ -15,7 +15,7 @@ struct gpio_siox_ddata { u8 setdata[1]; u8 getdata[3]; - spinlock_t irqlock; + raw_spinlock_t irqlock; u32 irq_enable; u32 irq_status; u32 irq_type[20]; @@ -44,7 +44,7 @@ static int gpio_siox_get_data(struct siox_device *sdevice, const u8 buf[]) mutex_lock(&ddata->lock); - spin_lock_irq(&ddata->irqlock); + raw_spin_lock_irq(&ddata->irqlock); for (offset = 0; offset < 12; ++offset) { unsigned int bitpos = 11 - offset; @@ -66,7 +66,7 @@ static int gpio_siox_get_data(struct siox_device *sdevice, const u8 buf[]) trigger = ddata->irq_status & ddata->irq_enable; - spin_unlock_irq(&ddata->irqlock); + raw_spin_unlock_irq(&ddata->irqlock); ddata->getdata[0] = buf[0]; ddata->getdata[1] = buf[1]; @@ -84,9 +84,9 @@ static int gpio_siox_get_data(struct siox_device *sdevice, const u8 buf[]) * handler of the irq chip. But it doesn't, so we have * to clean the irq_status here. */ - spin_lock_irq(&ddata->irqlock); + raw_spin_lock_irq(&ddata->irqlock); ddata->irq_status &= ~(1 << offset); - spin_unlock_irq(&ddata->irqlock); + raw_spin_unlock_irq(&ddata->irqlock); handle_nested_irq(irq); } @@ -101,9 +101,9 @@ static void gpio_siox_irq_ack(struct irq_data *d) struct gpio_siox_ddata *ddata = container_of(ic, struct gpio_siox_ddata, ichip); - spin_lock_irq(&ddata->irqlock); + raw_spin_lock(&ddata->irqlock); ddata->irq_status &= ~(1 << d->hwirq); - spin_unlock_irq(&ddata->irqlock); + raw_spin_unlock(&ddata->irqlock); } static void gpio_siox_irq_mask(struct irq_data *d) @@ -112,9 +112,9 @@ static void gpio_siox_irq_mask(struct irq_data *d) struct gpio_siox_ddata *ddata = container_of(ic, struct gpio_siox_ddata, ichip); - spin_lock_irq(&ddata->irqlock); + raw_spin_lock(&ddata->irqlock); ddata->irq_enable &= ~(1 << d->hwirq); - spin_unlock_irq(&ddata->irqlock); + raw_spin_unlock(&ddata->irqlock); } static void gpio_siox_irq_unmask(struct irq_data *d) @@ -123,9 +123,9 @@ static void gpio_siox_irq_unmask(struct irq_data *d) struct gpio_siox_ddata *ddata = container_of(ic, struct gpio_siox_ddata, ichip); - spin_lock_irq(&ddata->irqlock); + raw_spin_lock(&ddata->irqlock); ddata->irq_enable |= 1 << d->hwirq; - spin_unlock_irq(&ddata->irqlock); + raw_spin_unlock(&ddata->irqlock); } static int gpio_siox_irq_set_type(struct irq_data *d, u32 type) @@ -134,9 +134,9 @@ static int gpio_siox_irq_set_type(struct irq_data *d, u32 type) struct gpio_siox_ddata *ddata = container_of(ic, struct gpio_siox_ddata, ichip); - spin_lock_irq(&ddata->irqlock); + raw_spin_lock(&ddata->irqlock); ddata->irq_type[d->hwirq] = type; - spin_unlock_irq(&ddata->irqlock); + raw_spin_unlock(&ddata->irqlock); return 0; } @@ -222,7 +222,7 @@ static int gpio_siox_probe(struct siox_device *sdevice) dev_set_drvdata(dev, ddata); mutex_init(&ddata->lock); - spin_lock_init(&ddata->irqlock); + raw_spin_lock_init(&ddata->irqlock); ddata->gchip.base = -1; ddata->gchip.can_sleep = 1; From a59c99d9eaf90e6426d9bfe3b0a5e5b78010c72e Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 17 Jan 2020 15:33:39 -0600 Subject: [PATCH 0603/4444] pinctrl: sunxi: Forward calls to irq_set_irq_wake The pinctrl irqchip may be connected to an irqchip that implements the .irq_set_wake callback, such as the R_INTC on A31 and newer sunxi SoCs. In order for GPIOs to be able to trigger wakeup, the IRQ from the pinctrl to the upper irqchip must also be enabled for wakeup. Since the kernel's IRQ core already manages the "wake_depth" of each IRQ, no additional accounting is needed in the pinctrl driver. Signed-off-by: Samuel Holland Link: https://lore.kernel.org/r/20200117213340.47714-1-samuel@sholland.org Acked-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index b35c3245ab3f..9ede17ab6638 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -1058,6 +1059,14 @@ static void sunxi_pinctrl_irq_ack_unmask(struct irq_data *d) sunxi_pinctrl_irq_unmask(d); } +static int sunxi_pinctrl_irq_set_wake(struct irq_data *d, unsigned int on) +{ + struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); + u8 bank = d->hwirq / IRQ_PER_BANK; + + return irq_set_irq_wake(pctl->irq[bank], on); +} + static struct irq_chip sunxi_pinctrl_edge_irq_chip = { .name = "sunxi_pio_edge", .irq_ack = sunxi_pinctrl_irq_ack, @@ -1066,7 +1075,7 @@ static struct irq_chip sunxi_pinctrl_edge_irq_chip = { .irq_request_resources = sunxi_pinctrl_irq_request_resources, .irq_release_resources = sunxi_pinctrl_irq_release_resources, .irq_set_type = sunxi_pinctrl_irq_set_type, - .flags = IRQCHIP_SKIP_SET_WAKE, + .irq_set_wake = sunxi_pinctrl_irq_set_wake, }; static struct irq_chip sunxi_pinctrl_level_irq_chip = { @@ -1081,7 +1090,8 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip = { .irq_request_resources = sunxi_pinctrl_irq_request_resources, .irq_release_resources = sunxi_pinctrl_irq_release_resources, .irq_set_type = sunxi_pinctrl_irq_set_type, - .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_EOI_THREADED | + .irq_set_wake = sunxi_pinctrl_irq_set_wake, + .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED, }; From 8587b21c599e2874233cc5bbea7d0b18f4b62963 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 17 Jan 2020 15:33:40 -0600 Subject: [PATCH 0604/4444] pinctrl: sunxi: Mask non-wakeup IRQs on suspend The pin controller hardware does not distinguish IRQs intended for wakeup from other IRQs, so we must mask non-wakeup IRQs in software to prevent inadvertent wakeups. This is accomplished at the irqchip level via the IRQCHIP_MASK_ON_SUSPEND flag. Signed-off-by: Samuel Holland Link: https://lore.kernel.org/r/20200117213340.47714-2-samuel@sholland.org Acked-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 9ede17ab6638..8e792f8e2dc9 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -1076,6 +1076,7 @@ static struct irq_chip sunxi_pinctrl_edge_irq_chip = { .irq_release_resources = sunxi_pinctrl_irq_release_resources, .irq_set_type = sunxi_pinctrl_irq_set_type, .irq_set_wake = sunxi_pinctrl_irq_set_wake, + .flags = IRQCHIP_MASK_ON_SUSPEND, }; static struct irq_chip sunxi_pinctrl_level_irq_chip = { @@ -1092,6 +1093,7 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip = { .irq_set_type = sunxi_pinctrl_irq_set_type, .irq_set_wake = sunxi_pinctrl_irq_set_wake, .flags = IRQCHIP_EOI_THREADED | + IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_EOI_IF_HANDLED, }; From 3c827873590c3f49c76d540c1e646135a11e0b4e Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Fri, 14 Feb 2020 15:57:12 +0200 Subject: [PATCH 0605/4444] pinctrl: Use new GPIO_LINE_DIRECTION Use newly added GPIO defines GPIO_LINE_DIRECTION_IN and GPIO_LINE_DIRECTION_OUT instead of using hard-coded 1 and 0. Main benefit is to make it easier to see which values mean IN and which OUT. As a side effect this helps GPIO framework to change the direction defines to something else if ever needed. Please note that return value from get_direction call on pinctrl-axp209 driver was changed. Previously pinctrl-axp209 might have returned value 2 for direction INPUT. Signed-off-by: Matti Vaittinen Reported-by: kbuild test robot Reviewed-by: Geert Uytterhoeven Acked-by: Geert Uytterhoeven Reviewed-by: Bjorn Andersson Reviewed-by: Jacopo Mondi Link: https://lore.kernel.org/r/20200214135712.GA14557@localhost.localdomain Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 5 ++++- drivers/pinctrl/bcm/pinctrl-iproc-gpio.c | 5 ++++- drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 5 ++++- drivers/pinctrl/mediatek/pinctrl-paris.c | 5 ++++- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 5 ++++- drivers/pinctrl/nomadik/pinctrl-nomadik.c | 7 +++++-- drivers/pinctrl/pinctrl-amd.c | 5 ++++- drivers/pinctrl/pinctrl-at91.c | 5 ++++- drivers/pinctrl/pinctrl-axp209.c | 7 +++++-- drivers/pinctrl/pinctrl-ingenic.c | 14 ++++++++++---- drivers/pinctrl/pinctrl-ocelot.c | 5 ++++- drivers/pinctrl/pinctrl-oxnas.c | 5 ++++- drivers/pinctrl/pinctrl-pic32.c | 5 ++++- drivers/pinctrl/pinctrl-pistachio.c | 5 ++++- drivers/pinctrl/pinctrl-rk805.c | 7 +++++-- drivers/pinctrl/pinctrl-rockchip.c | 5 ++++- drivers/pinctrl/pinctrl-rza1.c | 5 ++++- drivers/pinctrl/pinctrl-rza2.c | 6 +++--- drivers/pinctrl/pinctrl-st.c | 14 +++++++++++--- drivers/pinctrl/pinctrl-stmfx.c | 17 ++++++++++++++--- drivers/pinctrl/pinctrl-sx150x.c | 9 ++++++--- drivers/pinctrl/qcom/pinctrl-msm.c | 4 ++-- drivers/pinctrl/stm32/pinctrl-stm32.c | 4 ++-- drivers/pinctrl/vt8500/pinctrl-wmt.c | 6 ++++-- 24 files changed, 119 insertions(+), 41 deletions(-) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 061e70ed17a7..06bd2b70af3c 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -329,7 +329,10 @@ static int bcm2835_gpio_get_direction(struct gpio_chip *chip, unsigned int offse if (fsel > BCM2835_FSEL_GPIO_OUT) return -EINVAL; - return (fsel == BCM2835_FSEL_GPIO_IN); + if (fsel == BCM2835_FSEL_GPIO_IN) + return GPIO_LINE_DIRECTION_IN; + + return GPIO_LINE_DIRECTION_OUT; } static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value) diff --git a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c index 25166217c3e0..a38f0d5f47ce 100644 --- a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c +++ b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c @@ -363,7 +363,10 @@ static int iproc_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio) unsigned int offset = IPROC_GPIO_REG(gpio, IPROC_GPIO_OUT_EN_OFFSET); unsigned int shift = IPROC_GPIO_SHIFT(gpio); - return !(readl(chip->base + offset) & BIT(shift)); + if (readl(chip->base + offset) & BIT(shift)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static void iproc_gpio_set(struct gpio_chip *gc, unsigned gpio, int val) diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index 67f8444f7a0c..a02ad10ec6fa 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -804,7 +804,10 @@ static int mtk_gpio_get_direction(struct gpio_chip *chip, unsigned offset) pctl->devdata->spec_dir_set(®_addr, offset); regmap_read(pctl->regmap1, reg_addr, &read_val); - return !(read_val & bit); + if (read_val & bit) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int mtk_gpio_get(struct gpio_chip *chip, unsigned offset) diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c index 83bf29c7ce7e..2e2ee4dba13c 100644 --- a/drivers/pinctrl/mediatek/pinctrl-paris.c +++ b/drivers/pinctrl/mediatek/pinctrl-paris.c @@ -775,7 +775,10 @@ static int mtk_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio) if (err) return err; - return !value; + if (value) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio) diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index 243fba254175..32f12a388b3c 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c @@ -402,7 +402,10 @@ static int armada_37xx_gpio_get_direction(struct gpio_chip *chip, mask = BIT(offset); regmap_read(info->regmap, reg, &val); - return !(val & mask); + if (val & mask) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int armada_37xx_gpio_direction_output(struct gpio_chip *chip, diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c index 95f864dfdef4..ca7bbe4164c0 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c @@ -831,11 +831,14 @@ static int nmk_gpio_get_dir(struct gpio_chip *chip, unsigned offset) clk_enable(nmk_chip->clk); - dir = !(readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset)); + dir = readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset); clk_disable(nmk_chip->clk); - return dir; + if (dir) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset) diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index 73aff6591de2..1fe62a35bb12 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -46,7 +46,10 @@ static int amd_gpio_get_direction(struct gpio_chip *gc, unsigned offset) pin_reg = readl(gpio_dev->base + offset * 4); raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); - return !(pin_reg & BIT(OUTPUT_ENABLE_OFF)); + if (pin_reg & BIT(OUTPUT_ENABLE_OFF)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int amd_gpio_direction_input(struct gpio_chip *gc, unsigned offset) diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 207f266e9cf2..52386ad29f28 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -1414,7 +1414,10 @@ static int at91_gpio_get_direction(struct gpio_chip *chip, unsigned offset) u32 osr; osr = readl_relaxed(pio + PIO_OSR); - return !(osr & mask); + if (osr & mask) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int at91_gpio_direction_input(struct gpio_chip *chip, unsigned offset) diff --git a/drivers/pinctrl/pinctrl-axp209.c b/drivers/pinctrl/pinctrl-axp209.c index be5b645815e5..207cbae3a7bf 100644 --- a/drivers/pinctrl/pinctrl-axp209.c +++ b/drivers/pinctrl/pinctrl-axp209.c @@ -149,13 +149,16 @@ static int axp20x_gpio_get_direction(struct gpio_chip *chip, * going to change the value soon anyway. Default to output. */ if ((val & AXP20X_GPIO_FUNCTIONS) > 2) - return 0; + return GPIO_LINE_DIRECTION_OUT; /* * The GPIO directions are the three lowest values. * 2 is input, 0 and 1 are output */ - return val & 2; + if (val & 2) + return GPIO_LINE_DIRECTION_IN; + + return GPIO_LINE_DIRECTION_OUT; } static int axp20x_gpio_output(struct gpio_chip *chip, unsigned int offset, diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c index 96f04d121ebd..5328a6232d65 100644 --- a/drivers/pinctrl/pinctrl-ingenic.c +++ b/drivers/pinctrl/pinctrl-ingenic.c @@ -1916,13 +1916,19 @@ static int ingenic_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) struct ingenic_pinctrl *jzpc = jzgc->jzpc; unsigned int pin = gc->base + offset; - if (jzpc->info->version >= ID_JZ4760) - return ingenic_get_pin_config(jzpc, pin, JZ4760_GPIO_PAT1); + if (jzpc->info->version >= ID_JZ4760) { + if (ingenic_get_pin_config(jzpc, pin, JZ4760_GPIO_PAT1)) + return GPIO_LINE_DIRECTION_IN; + return GPIO_LINE_DIRECTION_OUT; + } if (ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_SELECT)) - return true; + return GPIO_LINE_DIRECTION_IN; - return !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_DIR); + if (ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_DIR)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static const struct pinctrl_ops ingenic_pctlops = { diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c index eb3dd0d46d6c..ed8eac6c1494 100644 --- a/drivers/pinctrl/pinctrl-ocelot.c +++ b/drivers/pinctrl/pinctrl-ocelot.c @@ -604,7 +604,10 @@ static int ocelot_gpio_get_direction(struct gpio_chip *chip, regmap_read(info->map, REG(OCELOT_GPIO_OE, info, offset), &val); - return !(val & BIT(offset % 32)); + if (val & BIT(offset % 32)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int ocelot_gpio_direction_input(struct gpio_chip *chip, diff --git a/drivers/pinctrl/pinctrl-oxnas.c b/drivers/pinctrl/pinctrl-oxnas.c index 674b7b5919df..5a312279b3c7 100644 --- a/drivers/pinctrl/pinctrl-oxnas.c +++ b/drivers/pinctrl/pinctrl-oxnas.c @@ -756,7 +756,10 @@ static int oxnas_gpio_get_direction(struct gpio_chip *chip, struct oxnas_gpio_bank *bank = gpiochip_get_data(chip); u32 mask = BIT(offset); - return !(readl_relaxed(bank->reg_base + OUTPUT_EN) & mask); + if (readl_relaxed(bank->reg_base + OUTPUT_EN) & mask) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int oxnas_gpio_direction_input(struct gpio_chip *chip, diff --git a/drivers/pinctrl/pinctrl-pic32.c b/drivers/pinctrl/pinctrl-pic32.c index e5d6d3f9753e..a6e2a4a4ca95 100644 --- a/drivers/pinctrl/pinctrl-pic32.c +++ b/drivers/pinctrl/pinctrl-pic32.c @@ -1990,7 +1990,10 @@ static int pic32_gpio_get_direction(struct gpio_chip *chip, unsigned offset) { struct pic32_gpio_bank *bank = gpiochip_get_data(chip); - return !!(readl(bank->reg_base + TRIS_REG) & BIT(offset)); + if (readl(bank->reg_base + TRIS_REG) & BIT(offset)) + return GPIO_LINE_DIRECTION_IN; + + return GPIO_LINE_DIRECTION_OUT; } static void pic32_gpio_irq_ack(struct irq_data *data) diff --git a/drivers/pinctrl/pinctrl-pistachio.c b/drivers/pinctrl/pinctrl-pistachio.c index fa370c171cad..ec761ba2a2da 100644 --- a/drivers/pinctrl/pinctrl-pistachio.c +++ b/drivers/pinctrl/pinctrl-pistachio.c @@ -1166,7 +1166,10 @@ static int pistachio_gpio_get_direction(struct gpio_chip *chip, unsigned offset) { struct pistachio_gpio_bank *bank = gpiochip_get_data(chip); - return !(gpio_readl(bank, GPIO_OUTPUT_EN) & BIT(offset)); + if (gpio_readl(bank, GPIO_OUTPUT_EN) & BIT(offset)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int pistachio_gpio_get(struct gpio_chip *chip, unsigned offset) diff --git a/drivers/pinctrl/pinctrl-rk805.c b/drivers/pinctrl/pinctrl-rk805.c index 26adbe9d6d42..cccbe072274e 100644 --- a/drivers/pinctrl/pinctrl-rk805.c +++ b/drivers/pinctrl/pinctrl-rk805.c @@ -184,7 +184,7 @@ static int rk805_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) /* default output*/ if (!pci->pin_cfg[offset].dir_msk) - return 0; + return GPIO_LINE_DIRECTION_OUT; ret = regmap_read(pci->rk808->regmap, pci->pin_cfg[offset].reg, @@ -194,7 +194,10 @@ static int rk805_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) return ret; } - return !(val & pci->pin_cfg[offset].dir_msk); + if (val & pci->pin_cfg[offset].dir_msk) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static const struct gpio_chip rk805_gpio_chip = { diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index fc9a2a9959d9..098951346339 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -2549,7 +2549,10 @@ static int rockchip_gpio_get_direction(struct gpio_chip *chip, unsigned offset) data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); clk_disable(bank->clk); - return !(data & BIT(offset)); + if (data & BIT(offset)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } /* diff --git a/drivers/pinctrl/pinctrl-rza1.c b/drivers/pinctrl/pinctrl-rza1.c index 617585be6a7d..da2d8365c690 100644 --- a/drivers/pinctrl/pinctrl-rza1.c +++ b/drivers/pinctrl/pinctrl-rza1.c @@ -777,7 +777,10 @@ static int rza1_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio) { struct rza1_port *port = gpiochip_get_data(chip); - return !!rza1_get_bit(port, RZA1_PM_REG, gpio); + if (rza1_get_bit(port, RZA1_PM_REG, gpio)) + return GPIO_LINE_DIRECTION_IN; + + return GPIO_LINE_DIRECTION_OUT; } static int rza1_gpio_direction_input(struct gpio_chip *chip, diff --git a/drivers/pinctrl/pinctrl-rza2.c b/drivers/pinctrl/pinctrl-rza2.c index a205964e839b..c5bf98c86b2b 100644 --- a/drivers/pinctrl/pinctrl-rza2.c +++ b/drivers/pinctrl/pinctrl-rza2.c @@ -135,10 +135,10 @@ static int rza2_chip_get_direction(struct gpio_chip *chip, unsigned int offset) reg16 = (reg16 >> (pin * 2)) & RZA2_PDR_MASK; if (reg16 == RZA2_PDR_OUTPUT) - return 0; + return GPIO_LINE_DIRECTION_OUT; if (reg16 == RZA2_PDR_INPUT) - return 1; + return GPIO_LINE_DIRECTION_IN; /* * This GPIO controller has a default Hi-Z state that is not input or @@ -146,7 +146,7 @@ static int rza2_chip_get_direction(struct gpio_chip *chip, unsigned int offset) */ rza2_pin_to_gpio(priv->base, offset, 1); - return 1; + return GPIO_LINE_DIRECTION_IN; } static int rza2_chip_direction_input(struct gpio_chip *chip, diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c index 4f39a7945d01..7b8c7a0b13de 100644 --- a/drivers/pinctrl/pinctrl-st.c +++ b/drivers/pinctrl/pinctrl-st.c @@ -746,7 +746,10 @@ static int st_gpio_get_direction(struct gpio_chip *chip, unsigned offset) function = st_pctl_get_pin_function(&pc, offset); if (function) { st_pinconf_get_direction(&pc, offset, &config); - return !ST_PINCONF_UNPACK_OE(config); + if (ST_PINCONF_UNPACK_OE(config)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } /* @@ -758,7 +761,10 @@ static int st_gpio_get_direction(struct gpio_chip *chip, unsigned offset) direction |= ((value >> offset) & 0x1) << i; } - return (direction == ST_GPIO_DIRECTION_IN); + if (direction == ST_GPIO_DIRECTION_IN) + return GPIO_LINE_DIRECTION_IN; + + return GPIO_LINE_DIRECTION_OUT; } /* Pinctrl Groups */ @@ -996,6 +1002,7 @@ static void st_pinconf_dbg_show(struct pinctrl_dev *pctldev, unsigned int function; int offset = st_gpio_pin(pin_id); char f[16]; + int oe; mutex_unlock(&pctldev->mutex); pc = st_get_pio_control(pctldev, pin_id); @@ -1008,10 +1015,11 @@ static void st_pinconf_dbg_show(struct pinctrl_dev *pctldev, else snprintf(f, 5, "GPIO"); + oe = st_gpio_get_direction(&pc_to_bank(pc)->gpio_chip, offset); seq_printf(s, "[OE:%d,PU:%ld,OD:%ld]\t%s\n" "\t\t[retime:%ld,invclk:%ld,clknotdat:%ld," "de:%ld,rt-clk:%ld,rt-delay:%ld]", - !st_gpio_get_direction(&pc_to_bank(pc)->gpio_chip, offset), + (oe == GPIO_LINE_DIRECTION_OUT), ST_PINCONF_UNPACK_PU(config), ST_PINCONF_UNPACK_OD(config), f, diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c index 16723797fa7c..60100b45f5e5 100644 --- a/drivers/pinctrl/pinctrl-stmfx.c +++ b/drivers/pinctrl/pinctrl-stmfx.c @@ -134,10 +134,14 @@ static int stmfx_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) ret = regmap_read(pctl->stmfx->map, reg, &val); /* * On stmfx, gpio pins direction is (0)input, (1)output. - * .get_direction returns 0=out, 1=in */ + if (ret) + return ret; - return ret ? ret : !(val & mask); + if (val & mask) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int stmfx_gpio_direction_input(struct gpio_chip *gc, unsigned int offset) @@ -223,6 +227,13 @@ static int stmfx_pinconf_get(struct pinctrl_dev *pctldev, dir = stmfx_gpio_get_direction(&pctl->gpio_chip, pin); if (dir < 0) return dir; + + /* + * Currently the gpiolib IN is 1 and OUT is 0 but let's not count + * on it just to be on the safe side also in the future :) + */ + dir = (dir == GPIO_LINE_DIRECTION_IN) ? 1 : 0; + type = stmfx_pinconf_get_type(pctl, pin); if (type < 0) return type; @@ -360,7 +371,7 @@ static void stmfx_pinconf_dbg_show(struct pinctrl_dev *pctldev, if (val < 0) return; - if (!dir) { + if (dir == GPIO_LINE_DIRECTION_OUT) { seq_printf(s, "output %s ", val ? "high" : "low"); if (type) seq_printf(s, "open drain %s internal pull-up ", diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 566665931a04..6e74bd87d959 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -391,13 +391,16 @@ static int sx150x_gpio_get_direction(struct gpio_chip *chip, int ret; if (sx150x_pin_is_oscio(pctl, offset)) - return false; + return GPIO_LINE_DIRECTION_OUT; ret = regmap_read(pctl->regmap, pctl->data->reg_dir, &value); if (ret < 0) return ret; - return !!(value & BIT(offset)); + if (value & BIT(offset)) + return GPIO_LINE_DIRECTION_IN; + + return GPIO_LINE_DIRECTION_OUT; } static int sx150x_gpio_get(struct gpio_chip *chip, unsigned int offset) @@ -687,7 +690,7 @@ static int sx150x_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, if (ret < 0) return ret; - if (ret) + if (ret == GPIO_LINE_DIRECTION_IN) return -EINVAL; ret = sx150x_gpio_get(&pctl->gpio, pin); diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 9a8daa256a32..173be7d4f00c 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -489,8 +489,8 @@ static int msm_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) val = msm_readl_ctl(pctrl, g); - /* 0 = output, 1 = input */ - return val & BIT(g->oe_bit) ? 0 : 1; + return val & BIT(g->oe_bit) ? GPIO_LINE_DIRECTION_OUT : + GPIO_LINE_DIRECTION_IN; } static int msm_gpio_get(struct gpio_chip *chip, unsigned offset) diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index 2d5e0435af0a..72e0669ca7c8 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -283,9 +283,9 @@ static int stm32_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) stm32_pmx_get_mode(bank, pin, &mode, &alt); if ((alt == 0) && (mode == 0)) - ret = 1; + ret = GPIO_LINE_DIRECTION_IN; else if ((alt == 0) && (mode == 1)) - ret = 0; + ret = GPIO_LINE_DIRECTION_OUT; else ret = -EINVAL; diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c index ea910a18b4d7..65b97e240196 100644 --- a/drivers/pinctrl/vt8500/pinctrl-wmt.c +++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c @@ -486,8 +486,10 @@ static int wmt_gpio_get_direction(struct gpio_chip *chip, unsigned offset) u32 val; val = readl_relaxed(data->base + reg_dir); - /* Return 0 == output, 1 == input */ - return !(val & BIT(bit)); + if (val & BIT(bit)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int wmt_gpio_get_value(struct gpio_chip *chip, unsigned offset) From b295474360619f71cc6e99c8080ff7d9f66a3c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E7=90=B0=E6=9D=B0=20=28Zhou=20Yanjie=29?= Date: Sun, 16 Feb 2020 19:17:08 +0800 Subject: [PATCH 0606/4444] pinctrl: Ingenic: Add missing parts for X1830. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add lcd pinctrl driver for X1830. Signed-off-by: 周琰杰 (Zhou Yanjie) Link: https://lore.kernel.org/r/1581851828-3493-3-git-send-email-zhouyanjie@wanyeetech.com Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-ingenic.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c index 5328a6232d65..cb9576bc20db 100644 --- a/drivers/pinctrl/pinctrl-ingenic.c +++ b/drivers/pinctrl/pinctrl-ingenic.c @@ -1437,6 +1437,19 @@ static int x1830_mmc1_4bit_pins[] = { 0x45, 0x46, 0x47, }; static int x1830_i2c0_pins[] = { 0x0c, 0x0d, }; static int x1830_i2c1_pins[] = { 0x39, 0x3a, }; static int x1830_i2c2_pins[] = { 0x5b, 0x5c, }; +static int x1830_lcd_rgb_18bit_pins[] = { + 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, +}; +static int x1830_lcd_slcd_8bit_pins[] = { + 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x6c, 0x6d, + 0x69, 0x72, 0x73, 0x7b, 0x7a, +}; +static int x1830_lcd_slcd_16bit_pins[] = { + 0x6e, 0x6f, 0x70, 0x71, 0x76, 0x77, 0x78, 0x79, +}; static int x1830_pwm_pwm0_b_pins[] = { 0x31, }; static int x1830_pwm_pwm0_c_pins[] = { 0x4b, }; static int x1830_pwm_pwm1_b_pins[] = { 0x32, }; @@ -1486,6 +1499,16 @@ static int x1830_mmc1_4bit_funcs[] = { 0, 0, 0, }; static int x1830_i2c0_funcs[] = { 1, 1, }; static int x1830_i2c1_funcs[] = { 0, 0, }; static int x1830_i2c2_funcs[] = { 1, 1, }; +static int x1830_lcd_rgb_18bit_funcs[] = { + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, +}; +static int x1830_lcd_slcd_8bit_funcs[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +}; +static int x1830_lcd_slcd_16bit_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, }; static int x1830_pwm_pwm0_b_funcs[] = { 0, }; static int x1830_pwm_pwm0_c_funcs[] = { 1, }; static int x1830_pwm_pwm1_b_funcs[] = { 0, }; @@ -1534,6 +1557,10 @@ static const struct group_desc x1830_groups[] = { INGENIC_PIN_GROUP("i2c0-data", x1830_i2c0), INGENIC_PIN_GROUP("i2c1-data", x1830_i2c1), INGENIC_PIN_GROUP("i2c2-data", x1830_i2c2), + INGENIC_PIN_GROUP("lcd-rgb-18bit", x1830_lcd_rgb_18bit), + INGENIC_PIN_GROUP("lcd-slcd-8bit", x1830_lcd_slcd_8bit), + INGENIC_PIN_GROUP("lcd-slcd-16bit", x1830_lcd_slcd_16bit), + { "lcd-no-pins", }, INGENIC_PIN_GROUP("pwm0-b", x1830_pwm_pwm0_b), INGENIC_PIN_GROUP("pwm0-c", x1830_pwm_pwm0_c), INGENIC_PIN_GROUP("pwm1-b", x1830_pwm_pwm1_b), @@ -1572,6 +1599,9 @@ static const char *x1830_mmc1_groups[] = { "mmc1-1bit", "mmc1-4bit", }; static const char *x1830_i2c0_groups[] = { "i2c0-data", }; static const char *x1830_i2c1_groups[] = { "i2c1-data", }; static const char *x1830_i2c2_groups[] = { "i2c2-data", }; +static const char *x1830_lcd_groups[] = { + "lcd-rgb-18bit", "lcd-slcd-8bit", "lcd-slcd-16bit", "lcd-no-pins", +}; static const char *x1830_pwm0_groups[] = { "pwm0-b", "pwm0-c", }; static const char *x1830_pwm1_groups[] = { "pwm1-b", "pwm1-c", }; static const char *x1830_pwm2_groups[] = { "pwm2-c-8", "pwm2-c-13", }; @@ -1593,6 +1623,7 @@ static const struct function_desc x1830_functions[] = { { "i2c0", x1830_i2c0_groups, ARRAY_SIZE(x1830_i2c0_groups), }, { "i2c1", x1830_i2c1_groups, ARRAY_SIZE(x1830_i2c1_groups), }, { "i2c2", x1830_i2c2_groups, ARRAY_SIZE(x1830_i2c2_groups), }, + { "lcd", x1830_lcd_groups, ARRAY_SIZE(x1830_lcd_groups), }, { "pwm0", x1830_pwm0_groups, ARRAY_SIZE(x1830_pwm0_groups), }, { "pwm1", x1830_pwm1_groups, ARRAY_SIZE(x1830_pwm1_groups), }, { "pwm2", x1830_pwm2_groups, ARRAY_SIZE(x1830_pwm2_groups), }, From bf726b1c86f2caab70ad614cdf7da3b81ad08e69 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Fri, 21 Feb 2020 06:41:51 -0600 Subject: [PATCH 0607/4444] ASoC: tas2562: Add support for digital volume control Add support for digital volume control. There is no dedicated register for volume control but instead there are 4. The values of the registers are determined with exponential floating point math. So a table was created with register values for 2dB step increments from -110dB to 0dB. Signed-off-by: Dan Murphy Link: https://lore.kernel.org/r/20200221124151.8774-1-dmurphy@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2562.c | 78 ++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/tas2562.h | 6 ++- 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c index b517ada7e809..561ac0ac0795 100644 --- a/sound/soc/codecs/tas2562.c +++ b/sound/soc/codecs/tas2562.c @@ -26,6 +26,24 @@ #define TAS2562_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\ SNDRV_PCM_FORMAT_S32_LE) +/* DVC equation involves floating point math + * round(10^(volume in dB/20)*2^30) + * so create a lookup table for 2dB step + */ +static const unsigned int float_vol_db_lookup[] = { +0x00000d43, 0x000010b2, 0x00001505, 0x00001a67, 0x00002151, +0x000029f1, 0x000034cd, 0x00004279, 0x000053af, 0x0000695b, +0x0000695b, 0x0000a6fa, 0x0000d236, 0x000108a4, 0x00014d2a, +0x0001a36e, 0x00021008, 0x000298c0, 0x000344df, 0x00041d8f, +0x00052e5a, 0x000685c8, 0x00083621, 0x000a566d, 0x000d03a7, +0x0010624d, 0x0014a050, 0x0019f786, 0x0020b0bc, 0x0029279d, +0x0033cf8d, 0x004139d3, 0x00521d50, 0x00676044, 0x0082248a, +0x00a3d70a, 0x00ce4328, 0x0103ab3d, 0x0146e75d, 0x019b8c27, +0x02061b89, 0x028c423f, 0x03352529, 0x0409c2b0, 0x05156d68, +0x080e9f96, 0x0a24b062, 0x0cc509ab, 0x10137987, 0x143d1362, +0x197a967f, 0x2013739e, 0x28619ae9, 0x32d64617, 0x40000000 +}; + struct tas2562_data { struct snd_soc_component *component; struct gpio_desc *sdz_gpio; @@ -34,6 +52,7 @@ struct tas2562_data { struct i2c_client *client; int v_sense_slot; int i_sense_slot; + int volume_lvl; }; static int tas2562_set_bias_level(struct snd_soc_component *component, @@ -413,6 +432,50 @@ end: return 0; } +static int tas2562_volume_control_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = tas2562->volume_lvl; + return 0; +} + +static int tas2562_volume_control_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); + int ret; + u32 reg_val; + + reg_val = float_vol_db_lookup[ucontrol->value.integer.value[0]/2]; + ret = snd_soc_component_write(component, TAS2562_DVC_CFG4, + (reg_val & 0xff)); + if (ret) + return ret; + ret = snd_soc_component_write(component, TAS2562_DVC_CFG3, + ((reg_val >> 8) & 0xff)); + if (ret) + return ret; + ret = snd_soc_component_write(component, TAS2562_DVC_CFG2, + ((reg_val >> 16) & 0xff)); + if (ret) + return ret; + ret = snd_soc_component_write(component, TAS2562_DVC_CFG1, + ((reg_val >> 24) & 0xff)); + if (ret) + return ret; + + tas2562->volume_lvl = ucontrol->value.integer.value[0]; + + return ret; +} + +/* Digital Volume Control. From 0 dB to -110 dB in 1 dB steps */ +static const DECLARE_TLV_DB_SCALE(dvc_tlv, -11000, 100, 0); + static DECLARE_TLV_DB_SCALE(tas2562_dac_tlv, 850, 50, 0); static const struct snd_kcontrol_new isense_switch = @@ -426,6 +489,17 @@ static const struct snd_kcontrol_new vsense_switch = static const struct snd_kcontrol_new tas2562_snd_controls[] = { SOC_SINGLE_TLV("Amp Gain Volume", TAS2562_PB_CFG1, 0, 0x1c, 0, tas2562_dac_tlv), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Digital Volume Control", + .index = 0, + .tlv.p = dvc_tlv, + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = snd_soc_info_volsw, + .get = tas2562_volume_control_get, + .put = tas2562_volume_control_put, + .private_value = SOC_SINGLE_VALUE(TAS2562_DVC_CFG1, 0, 110, 0, 0) , + }, }; static const struct snd_soc_dapm_widget tas2562_dapm_widgets[] = { @@ -516,6 +590,10 @@ static const struct reg_default tas2562_reg_defaults[] = { { TAS2562_PB_CFG1, 0x20 }, { TAS2562_TDM_CFG0, 0x09 }, { TAS2562_TDM_CFG1, 0x02 }, + { TAS2562_DVC_CFG1, 0x40 }, + { TAS2562_DVC_CFG2, 0x40 }, + { TAS2562_DVC_CFG3, 0x00 }, + { TAS2562_DVC_CFG4, 0x00 }, }; static const struct regmap_config tas2562_regmap_config = { diff --git a/sound/soc/codecs/tas2562.h b/sound/soc/codecs/tas2562.h index 6f55ebcf19ea..28e75fc431d0 100644 --- a/sound/soc/codecs/tas2562.h +++ b/sound/soc/codecs/tas2562.h @@ -35,8 +35,10 @@ #define TAS2562_REV_ID TAS2562_REG(0, 0x7d) /* Page 2 */ -#define TAS2562_DVC_CFG1 TAS2562_REG(2, 0x01) -#define TAS2562_DVC_CFG2 TAS2562_REG(2, 0x02) +#define TAS2562_DVC_CFG1 TAS2562_REG(2, 0x0c) +#define TAS2562_DVC_CFG2 TAS2562_REG(2, 0x0d) +#define TAS2562_DVC_CFG3 TAS2562_REG(2, 0x0e) +#define TAS2562_DVC_CFG4 TAS2562_REG(2, 0x0f) #define TAS2562_RESET BIT(0) From aa0ed0d00f1d33d179cb531766176cf6b2a03934 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 17 Feb 2020 12:54:37 -0600 Subject: [PATCH 0608/4444] pinctrl: uniphier: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200217185437.GA20901@embeddedor Acked-by: Masahiro Yamada Signed-off-by: Linus Walleij --- drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c index 57babf31e320..ade348b49b31 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c @@ -29,7 +29,7 @@ struct uniphier_pinctrl_reg_region { struct list_head node; unsigned int base; unsigned int nregs; - u32 vals[0]; + u32 vals[]; }; struct uniphier_pinctrl_priv { From b3a3740c35d6072e66eaa3a3bebaa9b70f566fda Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 18 Feb 2020 15:51:37 +0800 Subject: [PATCH 0609/4444] dt-bindings: pinctrl: Convert i.MX8MQ to json-schema Convert the i.MX8MQ pinctrl binding to DT schema format using json-schema Signed-off-by: Anson Huang Link: https://lore.kernel.org/r/1582012300-30260-1-git-send-email-Anson.Huang@nxp.com Reviewed-by: Rob Herring Signed-off-by: Linus Walleij --- .../bindings/pinctrl/fsl,imx8mq-pinctrl.txt | 36 -------- .../bindings/pinctrl/fsl,imx8mq-pinctrl.yaml | 82 +++++++++++++++++++ 2 files changed, 82 insertions(+), 36 deletions(-) delete mode 100644 Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt create mode 100644 Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt deleted file mode 100644 index 66de75090458..000000000000 --- a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt +++ /dev/null @@ -1,36 +0,0 @@ -* Freescale IMX8MQ IOMUX Controller - -Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory -for common binding part and usage. - -Required properties: -- compatible: "fsl,imx8mq-iomuxc" -- reg: should contain the base physical address and size of the iomuxc - registers. - -Required properties in sub-nodes: -- fsl,pins: each entry consists of 6 integers and represents the mux and config - setting for one pin. The first 5 integers are specified using a PIN_FUNC_ID macro, which can be found in - imx8mq-pinfunc.h under device tree source folder. The last integer CONFIG is - the pad setting value like pull-up on this pin. Please refer to i.MX8M Quad - Reference Manual for detailed CONFIG settings. - -Examples: - -&uart1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart1>; -}; - -iomuxc: pinctrl@30330000 { - compatible = "fsl,imx8mq-iomuxc"; - reg = <0x0 0x30330000 0x0 0x10000>; - - pinctrl_uart1: uart1grp { - fsl,pins = < - MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX 0x49 - MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX 0x49 - >; - }; -}; diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.yaml new file mode 100644 index 000000000000..b30c704fcfa1 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.yaml @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/fsl,imx8mq-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale IMX8MQ IOMUX Controller + +maintainers: + - Anson Huang + +description: + Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory + for common binding part and usage. + +properties: + compatible: + const: fsl,imx8mq-iomuxc + + reg: + maxItems: 1 + +# Client device subnode's properties +patternProperties: + 'grp$': + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + + properties: + fsl,pins: + description: + each entry consists of 6 integers and represents the mux and config + setting for one pin. The first 5 integers are specified using a PIN_FUNC_ID macro, which can + be found in . The last + integer CONFIG is the pad setting value like pull-up on this pin. Please + refer to i.MX8M Quad Reference Manual for detailed CONFIG settings. + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32-matrix + - items: + items: + - description: | + "mux_reg" indicates the offset of mux register. + - description: | + "conf_reg" indicates the offset of pad configuration register. + - description: | + "input_reg" indicates the offset of select input register. + - description: | + "mux_val" indicates the mux value to be applied. + - description: | + "input_val" indicates the select input value to be applied. + - description: | + "pad_setting" indicates the pad configuration value to be applied. + + required: + - fsl,pins + + additionalProperties: false + +required: + - compatible + - reg + +additionalProperties: false + +examples: + # Pinmux controller node + - | + iomuxc: pinctrl@30330000 { + compatible = "fsl,imx8mq-iomuxc"; + reg = <0x30330000 0x10000>; + + pinctrl_uart1: uart1grp { + fsl,pins = + <0x234 0x49C 0x4F4 0x0 0x0 0x49>, + <0x238 0x4A0 0x4F4 0x0 0x0 0x49>; + }; + }; + +... From 03b4154183a2dbecfb6db8ba0bb684a42c7bec6b Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 18 Feb 2020 15:51:38 +0800 Subject: [PATCH 0610/4444] dt-bindings: pinctrl: Convert i.MX8MM to json-schema Convert the i.MX8MM pinctrl binding to DT schema format using json-schema Signed-off-by: Anson Huang Link: https://lore.kernel.org/r/1582012300-30260-2-git-send-email-Anson.Huang@nxp.com Reviewed-by: Rob Herring Signed-off-by: Linus Walleij --- .../bindings/pinctrl/fsl,imx8mm-pinctrl.txt | 36 -------- .../bindings/pinctrl/fsl,imx8mm-pinctrl.yaml | 82 +++++++++++++++++++ 2 files changed, 82 insertions(+), 36 deletions(-) delete mode 100644 Documentation/devicetree/bindings/pinctrl/fsl,imx8mm-pinctrl.txt create mode 100644 Documentation/devicetree/bindings/pinctrl/fsl,imx8mm-pinctrl.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mm-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mm-pinctrl.txt deleted file mode 100644 index e4e01c05cf83..000000000000 --- a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mm-pinctrl.txt +++ /dev/null @@ -1,36 +0,0 @@ -* Freescale IMX8MM IOMUX Controller - -Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory -for common binding part and usage. - -Required properties: -- compatible: "fsl,imx8mm-iomuxc" -- reg: should contain the base physical address and size of the iomuxc - registers. - -Required properties in sub-nodes: -- fsl,pins: each entry consists of 6 integers and represents the mux and config - setting for one pin. The first 5 integers are specified using a PIN_FUNC_ID macro, which can be found in - . The last integer CONFIG is - the pad setting value like pull-up on this pin. Please refer to i.MX8M Mini - Reference Manual for detailed CONFIG settings. - -Examples: - -&uart1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart1>; -}; - -iomuxc: pinctrl@30330000 { - compatible = "fsl,imx8mm-iomuxc"; - reg = <0x0 0x30330000 0x0 0x10000>; - - pinctrl_uart1: uart1grp { - fsl,pins = < - MX8MM_IOMUXC_UART1_RXD_UART1_DCE_RX 0x140 - MX8MM_IOMUXC_UART1_TXD_UART1_DCE_TX 0x140 - >; - }; -}; diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mm-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mm-pinctrl.yaml new file mode 100644 index 000000000000..d98a3866add8 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mm-pinctrl.yaml @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/fsl,imx8mm-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale IMX8MM IOMUX Controller + +maintainers: + - Anson Huang + +description: + Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory + for common binding part and usage. + +properties: + compatible: + const: fsl,imx8mm-iomuxc + + reg: + maxItems: 1 + +# Client device subnode's properties +patternProperties: + 'grp$': + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + + properties: + fsl,pins: + description: + each entry consists of 6 integers and represents the mux and config + setting for one pin. The first 5 integers are specified using a PIN_FUNC_ID macro, which can + be found in . The last + integer CONFIG is the pad setting value like pull-up on this pin. Please + refer to i.MX8M Mini Reference Manual for detailed CONFIG settings. + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32-matrix + - items: + items: + - description: | + "mux_reg" indicates the offset of mux register. + - description: | + "conf_reg" indicates the offset of pad configuration register. + - description: | + "input_reg" indicates the offset of select input register. + - description: | + "mux_val" indicates the mux value to be applied. + - description: | + "input_val" indicates the select input value to be applied. + - description: | + "pad_setting" indicates the pad configuration value to be applied. + + required: + - fsl,pins + + additionalProperties: false + +required: + - compatible + - reg + +additionalProperties: false + +examples: + # Pinmux controller node + - | + iomuxc: pinctrl@30330000 { + compatible = "fsl,imx8mm-iomuxc"; + reg = <0x30330000 0x10000>; + + pinctrl_uart2: uart2grp { + fsl,pins = + <0x23C 0x4A4 0x4FC 0x0 0x0 0x140>, + <0x240 0x4A8 0x000 0x0 0x0 0x140>; + }; + }; + +... From f4a776f752669af78bf80f4bbc57285b0ae732b6 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 18 Feb 2020 15:51:39 +0800 Subject: [PATCH 0611/4444] dt-bindings: pinctrl: Convert i.MX8MN to json-schema Convert the i.MX8MN pinctrl binding to DT schema format using json-schema Signed-off-by: Anson Huang Link: https://lore.kernel.org/r/1582012300-30260-3-git-send-email-Anson.Huang@nxp.com Reviewed-by: Rob Herring Signed-off-by: Linus Walleij --- .../bindings/pinctrl/fsl,imx8mn-pinctrl.txt | 39 --------- .../bindings/pinctrl/fsl,imx8mn-pinctrl.yaml | 82 +++++++++++++++++++ 2 files changed, 82 insertions(+), 39 deletions(-) delete mode 100644 Documentation/devicetree/bindings/pinctrl/fsl,imx8mn-pinctrl.txt create mode 100644 Documentation/devicetree/bindings/pinctrl/fsl,imx8mn-pinctrl.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mn-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mn-pinctrl.txt deleted file mode 100644 index 330716c971b9..000000000000 --- a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mn-pinctrl.txt +++ /dev/null @@ -1,39 +0,0 @@ -* Freescale IMX8MN IOMUX Controller - -Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory -for common binding part and usage. - -Required properties: -- compatible: "fsl,imx8mn-iomuxc" -- reg: should contain the base physical address and size of the iomuxc - registers. - -Required properties in sub-nodes: -- fsl,pins: each entry consists of 6 integers and represents the mux and config - setting for one pin. The first 5 integers are specified using a PIN_FUNC_ID macro, which can be found in - . The last integer CONFIG is - the pad setting value like pull-up on this pin. Please refer to i.MX8M Nano - Reference Manual for detailed CONFIG settings. - -Examples: - -&uart1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart1>; -}; - -iomuxc: pinctrl@30330000 { - compatible = "fsl,imx8mn-iomuxc"; - reg = <0x0 0x30330000 0x0 0x10000>; - - pinctrl_uart1: uart1grp { - fsl,pins = < - MX8MN_IOMUXC_UART1_RXD_UART1_DCE_RX 0x140 - MX8MN_IOMUXC_UART1_TXD_UART1_DCE_TX 0x140 - MX8MN_IOMUXC_UART3_RXD_UART1_DCE_CTS_B 0x140 - MX8MN_IOMUXC_UART3_TXD_UART1_DCE_RTS_B 0x140 - MX8MN_IOMUXC_SD1_DATA4_GPIO2_IO6 0x19 - >; - }; -}; diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mn-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mn-pinctrl.yaml new file mode 100644 index 000000000000..b9aa180e07e4 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mn-pinctrl.yaml @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/fsl,imx8mn-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale IMX8MN IOMUX Controller + +maintainers: + - Anson Huang + +description: + Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory + for common binding part and usage. + +properties: + compatible: + const: fsl,imx8mn-iomuxc + + reg: + maxItems: 1 + +# Client device subnode's properties +patternProperties: + 'grp$': + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + + properties: + fsl,pins: + description: + each entry consists of 6 integers and represents the mux and config + setting for one pin. The first 5 integers are specified using a PIN_FUNC_ID macro, which can + be found in . The last + integer CONFIG is the pad setting value like pull-up on this pin. Please + refer to i.MX8M Nano Reference Manual for detailed CONFIG settings. + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32-matrix + - items: + items: + - description: | + "mux_reg" indicates the offset of mux register. + - description: | + "conf_reg" indicates the offset of pad configuration register. + - description: | + "input_reg" indicates the offset of select input register. + - description: | + "mux_val" indicates the mux value to be applied. + - description: | + "input_val" indicates the select input value to be applied. + - description: | + "pad_setting" indicates the pad configuration value to be applied. + + required: + - fsl,pins + + additionalProperties: false + +required: + - compatible + - reg + +additionalProperties: false + +examples: + # Pinmux controller node + - | + iomuxc: pinctrl@30330000 { + compatible = "fsl,imx8mn-iomuxc"; + reg = <0x30330000 0x10000>; + + pinctrl_uart2: uart2grp { + fsl,pins = + <0x23C 0x4A4 0x4FC 0x0 0x0 0x140>, + <0x240 0x4A8 0x000 0x0 0x0 0x140>; + }; + }; + +... From 61bccd918c83f275d24c4f2eaab1830ad3a1c583 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 18 Feb 2020 15:51:40 +0800 Subject: [PATCH 0612/4444] dt-bindings: pinctrl: imx8mp: Replace the uint32-array with uint32-matrix The items of mux_reg/conf_reg/input_reg/mux_val/input_val/pad_setting should be uint32-matrix instead of uint32-array, fix it and improve the schema and example. Signed-off-by: Anson Huang Link: https://lore.kernel.org/r/1582012300-30260-4-git-send-email-Anson.Huang@nxp.com Reviewed-by: Rob Herring Signed-off-by: Linus Walleij --- .../bindings/pinctrl/fsl,imx8mp-pinctrl.yaml | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mp-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mp-pinctrl.yaml index 2e31e120395e..6297e78418cf 100644 --- a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mp-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mp-pinctrl.yaml @@ -30,8 +30,6 @@ patternProperties: properties: fsl,pins: - allOf: - - $ref: /schemas/types.yaml#/definitions/uint32-array description: each entry consists of 6 integers and represents the mux and config setting for one pin. The first 5 integers . The last integer CONFIG is the pad setting value like pull-up on this pin. Please refer to i.MX8M Plus Reference Manual for detailed CONFIG settings. + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32-matrix + - items: + items: + - description: | + "mux_reg" indicates the offset of mux register. + - description: | + "conf_reg" indicates the offset of pad configuration register. + - description: | + "input_reg" indicates the offset of select input register. + - description: | + "mux_val" indicates the mux value to be applied. + - description: | + "input_val" indicates the select input value to be applied. + - description: | + "pad_setting" indicates the pad configuration value to be applied. required: - fsl,pins @@ -59,10 +73,9 @@ examples: reg = <0x30330000 0x10000>; pinctrl_uart2: uart2grp { - fsl,pins = < - 0x228 0x488 0x5F0 0x0 0x6 0x49 - 0x228 0x488 0x000 0x0 0x0 0x49 - >; + fsl,pins = + <0x228 0x488 0x5F0 0x0 0x6 0x49>, + <0x228 0x488 0x000 0x0 0x0 0x49>; }; }; From 1739a2d852265977836152be43073ead5c64d1ea Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 19 Feb 2020 10:47:02 +0100 Subject: [PATCH 0613/4444] gpiolib: use gpiochip_get_desc() where applicable Whenever retrieving a descriptor from a gpiochip: use the provided helper which checks for errors. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20200219094702.6463-1-brgl@bgdev.pl Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f73077f26eff..611709fd560f 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3143,7 +3143,9 @@ const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset) if (offset >= chip->ngpio) return NULL; - desc = &chip->gpiodev->descs[offset]; + desc = gpiochip_get_desc(chip, offset); + if (IS_ERR(desc)) + return NULL; if (test_bit(FLAG_REQUESTED, &desc->flags) == 0) return NULL; From 8d8cec9bf6e9260397872785f249dfb59a417d08 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Wed, 19 Feb 2020 18:59:39 +0100 Subject: [PATCH 0614/4444] ipq8064: pinctrl: Fixed missing RGMII pincontrol definitions Add missing gpio definition for mdio and rgmii2. Signed-off-by: Ram Chandra Jangir Signed-off-by: Ansuel Smith Link: https://lore.kernel.org/r/20200219175940.744-1-ansuelsmth@gmail.com Acked-by: Bjorn Andersson Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-ipq8064.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8064.c b/drivers/pinctrl/qcom/pinctrl-ipq8064.c index c2fb1ddf2f22..ac717ee38416 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq8064.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq8064.c @@ -299,7 +299,7 @@ static const char * const gpio_groups[] = { }; static const char * const mdio_groups[] = { - "gpio0", "gpio1", "gpio10", "gpio11", + "gpio0", "gpio1", "gpio2", "gpio10", "gpio11", "gpio66", }; static const char * const mi2s_groups[] = { @@ -403,8 +403,8 @@ static const char * const usb2_hsic_groups[] = { }; static const char * const rgmii2_groups[] = { - "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", - "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62", + "gpio2", "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", + "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62", "gpio66", }; static const char * const sata_groups[] = { @@ -539,7 +539,7 @@ static const struct msm_function ipq8064_functions[] = { static const struct msm_pingroup ipq8064_groups[] = { PINGROUP(0, mdio, NA, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(1, mdio, NA, NA, NA, NA, NA, NA, NA, NA, NA), - PINGROUP(2, gsbi5_spi_cs3, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(2, gsbi5_spi_cs3, rgmii2, mdio, NA, NA, NA, NA, NA, NA, NA), PINGROUP(3, pcie1_rst, pcie1_prsnt, pdm, NA, NA, NA, NA, NA, NA, NA), PINGROUP(4, pcie1_pwren_n, pcie1_pwren, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(5, pcie1_clk_req, pcie1_pwrflt, NA, NA, NA, NA, NA, NA, NA, NA), @@ -603,7 +603,7 @@ static const struct msm_pingroup ipq8064_groups[] = { PINGROUP(63, pcie3_rst, NA, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(64, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(65, pcie3_clk_req, NA, NA, NA, NA, NA, NA, NA, NA, NA), - PINGROUP(66, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(66, rgmii2, mdio, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(67, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(68, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA), SDC_PINGROUP(sdc3_clk, 0x204a, 14, 6), From f8850206e160bfe35de9ca2e726ab6d6b8cb77dd Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 20 Feb 2020 15:56:24 +0100 Subject: [PATCH 0615/4444] gpio: Switch timestamps to ktime_get_ns() The existing use of ktime_get_real_ns() in the timestamps from the GPIO events is dubious. We have had several discussions about this timestamp, and it is unclear whether userspace has ever taken into account that a timestamp from ktime_get_real_ns() can actually move backwards in time relative the previous timetamp, and userspace is more likely to expect a monotonic counter. Background: https://lore.kernel.org/linux-gpio/CAK8P3a1Skvm48sje8FNDPLYqyz9Lf8q0qX1QETWtyZTxuX4k1g@mail.gmail.com/ https://marc.info/?l=linux-gpio&m=151661955709074&w=2 The change is ABI incompatible, but incompatible in a way that is IMO more likely to fix future bugs rather than break current userspace. To the best of my knowledge all userspace expects a monotonic timestamp and users are just lucky that they very seldom move backwards in time. Cc: Arnd Bergmann Acked-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 611709fd560f..2c3a9c1c76be 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -954,7 +954,7 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p) * we didn't get the timestamp from lineevent_irq_handler(). */ if (!le->timestamp) - ge.timestamp = ktime_get_real_ns(); + ge.timestamp = ktime_get_ns(); else ge.timestamp = le->timestamp; @@ -995,7 +995,7 @@ static irqreturn_t lineevent_irq_handler(int irq, void *p) * Just store the timestamp in hardirq context so we get it as * close in time as possible to the actual event. */ - le->timestamp = ktime_get_real_ns(); + le->timestamp = ktime_get_ns(); return IRQ_WAKE_THREAD; } From d6d43a92172085a2681e06a0d06aac53c7bcdd12 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Thu, 20 Feb 2020 09:35:09 -0600 Subject: [PATCH 0616/4444] pinctrl: ingenic: Improve unreachable code generation In the second loop of ingenic_pinconf_set(), it annotates the switch default case as unreachable(). The annotation is technically correct, because that same case would have resulted in an early function return in the previous loop. However, the compiled code is suboptimal. GCC seems to work extra hard to ensure that the unreachable code path triggers undefined behavior. The function would fall through to start executing whatever function happens to be next in the compilation unit. This is problematic because: a) it adds unnecessary 'ensure undefined behavior' logic, and corresponding i-cache footprint; and b) it's less robust -- if a bug were to be introduced, falling through to the next function would be catastrophic. Yet another issue is that, while objtool normally understands unreachable() annotations, there's one special case where it doesn't: when the annotation occurs immediately after a 'ret' instruction. That happens to be the case here because unreachable() is immediately before the return. Remove the unreachable() annotation and replace it with a comment. This simplifies the code generation and changes the unreachable error path to just silently return instead of corrupting execution. This fixes the following objtool warning: drivers/pinctrl/pinctrl-ingenic.o: warning: objtool: ingenic_pinconf_set() falls through to next function ingenic_pinconf_group_set() Reported-by: Randy Dunlap Signed-off-by: Josh Poimboeuf Link: https://lore.kernel.org/r/bc20fdbcb826512cf76b7dfd0972740875931b19.1582212881.git.jpoimboe@redhat.com Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-ingenic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c index cb9576bc20db..34870f934563 100644 --- a/drivers/pinctrl/pinctrl-ingenic.c +++ b/drivers/pinctrl/pinctrl-ingenic.c @@ -2195,7 +2195,8 @@ static int ingenic_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, break; default: - unreachable(); + /* unreachable */ + break; } } From bc21077e084b80c22072a40d32beb24ea33938ec Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Feb 2020 14:01:48 +0100 Subject: [PATCH 0617/4444] gpio: of: Extract of_gpiochip_add_hog() Extract the code to add all GPIO hogs of a gpio-hog node into its own function, so it can be reused. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200220130149.26283-2-geert+renesas@glider.be Reviewed-by: Frank Rowand Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 49 ++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index c6d30f73df07..2b47f9388607 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -604,6 +604,35 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np, return desc; } +/** + * of_gpiochip_add_hog - Add all hogs in a hog device node + * @chip: gpio chip to act on + * @hog: device node describing the hogs + * + * Returns error if it fails otherwise 0 on success. + */ +static int of_gpiochip_add_hog(struct gpio_chip *chip, struct device_node *hog) +{ + enum gpiod_flags dflags; + struct gpio_desc *desc; + unsigned long lflags; + const char *name; + unsigned int i; + int ret; + + for (i = 0;; i++) { + desc = of_parse_own_gpio(hog, chip, i, &name, &lflags, &dflags); + if (IS_ERR(desc)) + break; + + ret = gpiod_hog(desc, name, lflags, dflags); + if (ret < 0) + return ret; + } + + return 0; +} + /** * of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions * @chip: gpio chip to act on @@ -614,29 +643,17 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np, */ static int of_gpiochip_scan_gpios(struct gpio_chip *chip) { - struct gpio_desc *desc = NULL; struct device_node *np; - const char *name; - unsigned long lflags; - enum gpiod_flags dflags; - unsigned int i; int ret; for_each_available_child_of_node(chip->of_node, np) { if (!of_property_read_bool(np, "gpio-hog")) continue; - for (i = 0;; i++) { - desc = of_parse_own_gpio(np, chip, i, &name, &lflags, - &dflags); - if (IS_ERR(desc)) - break; - - ret = gpiod_hog(desc, name, lflags, dflags); - if (ret < 0) { - of_node_put(np); - return ret; - } + ret = of_gpiochip_add_hog(chip, np); + if (ret < 0) { + of_node_put(np); + return ret; } } From 63636d956c455c0fbe2118078a03f563ddd6bf6e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Feb 2020 14:01:49 +0100 Subject: [PATCH 0618/4444] gpio: of: Add DT overlay support for GPIO hogs As GPIO hogs are configured at GPIO controller initialization time, adding/removing GPIO hogs in DT overlays does not work. Add support for GPIO hogs described in DT overlays by registering an OF reconfiguration notifier, to handle the addition and removal of GPIO hog subnodes to/from a GPIO controller device node. Note that when a GPIO hog device node is being removed, its "gpios" properties is no longer available, so we have to keep track of which node a hog belongs to, which is done by adding a pointer to the hog's device node to struct gpio_desc. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200220130149.26283-3-geert+renesas@glider.be Reviewed-by: Frank Rowand Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 90 +++++++++++++++++++++++++++++++++++++++ drivers/gpio/gpiolib-of.h | 2 + drivers/gpio/gpiolib.c | 14 ++++-- drivers/gpio/gpiolib.h | 3 ++ 4 files changed, 106 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 2b47f9388607..ccc449df3792 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -628,6 +628,10 @@ static int of_gpiochip_add_hog(struct gpio_chip *chip, struct device_node *hog) ret = gpiod_hog(desc, name, lflags, dflags); if (ret < 0) return ret; + +#ifdef CONFIG_OF_DYNAMIC + desc->hog = hog; +#endif } return 0; @@ -655,11 +659,97 @@ static int of_gpiochip_scan_gpios(struct gpio_chip *chip) of_node_put(np); return ret; } + + of_node_set_flag(np, OF_POPULATED); } return 0; } +#ifdef CONFIG_OF_DYNAMIC +/** + * of_gpiochip_remove_hog - Remove all hogs in a hog device node + * @chip: gpio chip to act on + * @hog: device node describing the hogs + */ +static void of_gpiochip_remove_hog(struct gpio_chip *chip, + struct device_node *hog) +{ + struct gpio_desc *descs = chip->gpiodev->descs; + unsigned int i; + + for (i = 0; i < chip->ngpio; i++) { + if (test_bit(FLAG_IS_HOGGED, &descs[i].flags) && + descs[i].hog == hog) + gpiochip_free_own_desc(&descs[i]); + } +} + +static int of_gpiochip_match_node(struct gpio_chip *chip, void *data) +{ + return chip->gpiodev->dev.of_node == data; +} + +static struct gpio_chip *of_find_gpiochip_by_node(struct device_node *np) +{ + return gpiochip_find(np, of_gpiochip_match_node); +} + +static int of_gpio_notify(struct notifier_block *nb, unsigned long action, + void *arg) +{ + struct of_reconfig_data *rd = arg; + struct gpio_chip *chip; + int ret; + + /* + * This only supports adding and removing complete gpio-hog nodes. + * Modifying an existing gpio-hog node is not supported (except for + * changing its "status" property, which is treated the same as + * addition/removal). + */ + switch (of_reconfig_get_state_change(action, arg)) { + case OF_RECONFIG_CHANGE_ADD: + if (!of_property_read_bool(rd->dn, "gpio-hog")) + return NOTIFY_OK; /* not for us */ + + if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) + return NOTIFY_OK; + + chip = of_find_gpiochip_by_node(rd->dn->parent); + if (chip == NULL) + return NOTIFY_OK; /* not for us */ + + ret = of_gpiochip_add_hog(chip, rd->dn); + if (ret < 0) { + pr_err("%s: failed to add hogs for %pOF\n", __func__, + rd->dn); + of_node_clear_flag(rd->dn, OF_POPULATED); + return notifier_from_errno(ret); + } + break; + + case OF_RECONFIG_CHANGE_REMOVE: + if (!of_node_check_flag(rd->dn, OF_POPULATED)) + return NOTIFY_OK; /* already depopulated */ + + chip = of_find_gpiochip_by_node(rd->dn->parent); + if (chip == NULL) + return NOTIFY_OK; /* not for us */ + + of_gpiochip_remove_hog(chip, rd->dn); + of_node_clear_flag(rd->dn, OF_POPULATED); + break; + } + + return NOTIFY_OK; +} + +struct notifier_block gpio_of_notifier = { + .notifier_call = of_gpio_notify, +}; +#endif /* CONFIG_OF_DYNAMIC */ + /** * of_gpio_simple_xlate - translate gpiospec to the GPIO number and flags * @gc: pointer to the gpio_chip structure diff --git a/drivers/gpio/gpiolib-of.h b/drivers/gpio/gpiolib-of.h index 9768831b1fe2..ed26664f1537 100644 --- a/drivers/gpio/gpiolib-of.h +++ b/drivers/gpio/gpiolib-of.h @@ -35,4 +35,6 @@ static inline bool of_gpio_need_valid_mask(const struct gpio_chip *gc) } #endif /* CONFIG_OF_GPIO */ +extern struct notifier_block gpio_of_notifier; + #endif /* GPIOLIB_OF_H */ diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 2c3a9c1c76be..9ad86477af9c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3103,6 +3103,9 @@ static bool gpiod_free_commit(struct gpio_desc *desc) clear_bit(FLAG_PULL_DOWN, &desc->flags); clear_bit(FLAG_BIAS_DISABLE, &desc->flags); clear_bit(FLAG_IS_HOGGED, &desc->flags); +#ifdef CONFIG_OF_DYNAMIC + desc->hog = NULL; +#endif ret = true; } @@ -5281,10 +5284,15 @@ static int __init gpiolib_dev_init(void) if (ret < 0) { pr_err("gpiolib: failed to allocate char dev region\n"); bus_unregister(&gpio_bus_type); - } else { - gpiolib_initialized = true; - gpiochip_setup_devs(); + return ret; } + + gpiolib_initialized = true; + gpiochip_setup_devs(); + + if (IS_ENABLED(CONFIG_OF_DYNAMIC)) + WARN_ON(of_reconfig_notifier_register(&gpio_of_notifier)); + return ret; } core_initcall(gpiolib_dev_init); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 5ab90746b519..853ce681b4a4 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -120,6 +120,9 @@ struct gpio_desc { const char *label; /* Name of the GPIO */ const char *name; +#ifdef CONFIG_OF_DYNAMIC + struct device_node *hog; +#endif }; int gpiod_request(struct gpio_desc *desc, const char *label); From 3385ab72d995fc0b876818a36203bf2429445686 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 18 Feb 2020 08:52:47 +0300 Subject: [PATCH 0619/4444] pinctrl: mediatek: Fix some off by one bugs These comparisons should be >= instead of > to prevent accessing one element beyond the end of the hw->soc->pins[] array. Fixes: 3de7deefce69 ("pinctrl: mediatek: Check gpio pin number and use binary search in mtk_hw_pin_field_lookup()") Fixes: 184d8e13f9b1 ("pinctrl: mediatek: Add support for pin configuration dump via debugfs.") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/20200218055247.74s2xa7veqx2do34@kili.mountain Reviewed-by: Matthias Brugger Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-paris.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c index 2e2ee4dba13c..3ee8086f5e55 100644 --- a/drivers/pinctrl/mediatek/pinctrl-paris.c +++ b/drivers/pinctrl/mediatek/pinctrl-paris.c @@ -544,7 +544,7 @@ static int mtk_hw_get_value_wrap(struct mtk_pinctrl *hw, unsigned int gpio, int const struct mtk_pin_desc *desc; int value, err; - if (gpio > hw->soc->npins) + if (gpio >= hw->soc->npins) return -EINVAL; desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; @@ -583,7 +583,7 @@ ssize_t mtk_pctrl_show_one_pin(struct mtk_pinctrl *hw, int pinmux, pullup, pullen, len = 0, r1 = -1, r0 = -1; const struct mtk_pin_desc *desc; - if (gpio > hw->soc->npins) + if (gpio >= hw->soc->npins) return -EINVAL; desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; @@ -766,7 +766,7 @@ static int mtk_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio) const struct mtk_pin_desc *desc; int value, err; - if (gpio > hw->soc->npins) + if (gpio >= hw->soc->npins) return -EINVAL; desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; @@ -787,7 +787,7 @@ static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio) const struct mtk_pin_desc *desc; int value, err; - if (gpio > hw->soc->npins) + if (gpio >= hw->soc->npins) return -EINVAL; desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; @@ -804,7 +804,7 @@ static void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value) struct mtk_pinctrl *hw = gpiochip_get_data(chip); const struct mtk_pin_desc *desc; - if (gpio > hw->soc->npins) + if (gpio >= hw->soc->npins) return; desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; @@ -816,7 +816,7 @@ static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio) { struct mtk_pinctrl *hw = gpiochip_get_data(chip); - if (gpio > hw->soc->npins) + if (gpio >= hw->soc->npins) return -EINVAL; return pinctrl_gpio_direction_input(chip->base + gpio); @@ -827,7 +827,7 @@ static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio, { struct mtk_pinctrl *hw = gpiochip_get_data(chip); - if (gpio > hw->soc->npins) + if (gpio >= hw->soc->npins) return -EINVAL; mtk_gpio_set(chip, gpio, value); From bd56e593da19de22284951c33ce5c419258171bf Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 21 Feb 2020 16:36:05 +0100 Subject: [PATCH 0620/4444] ASoC: meson: g12a: add toacodec dt-binding documentation Add the DT bindings and documentation of the internal audio DAC glue found on Amlogic g12a and sm1 SoC families Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200221153607.1585499-2-jbrunet@baylibre.com Signed-off-by: Mark Brown --- .../bindings/sound/amlogic,g12a-toacodec.yaml | 51 +++++++++++++++++++ .../dt-bindings/sound/meson-g12a-toacodec.h | 10 ++++ 2 files changed, 61 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml create mode 100644 include/dt-bindings/sound/meson-g12a-toacodec.h diff --git a/Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml b/Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml new file mode 100644 index 000000000000..f778d3371fde --- /dev/null +++ b/Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/amlogic,g12a-toacodec.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic G12a Internal DAC Control Glue + +maintainers: + - Jerome Brunet + +properties: + $nodename: + pattern: "^audio-controller@.*" + + "#sound-dai-cells": + const: 1 + + compatible: + oneOf: + - items: + - const: + amlogic,g12a-toacodec + - items: + - enum: + - amlogic,sm1-toacodec + - const: + amlogic,g12a-toacodec + + reg: + maxItems: 1 + + resets: + maxItems: 1 + +required: + - "#sound-dai-cells" + - compatible + - reg + - resets + +examples: + - | + #include + + toacodec: audio-controller@740 { + compatible = "amlogic,g12a-toacodec"; + reg = <0x0 0x740 0x0 0x4>; + #sound-dai-cells = <1>; + resets = <&clkc_audio AUD_RESET_TOACODEC>; + }; diff --git a/include/dt-bindings/sound/meson-g12a-toacodec.h b/include/dt-bindings/sound/meson-g12a-toacodec.h new file mode 100644 index 000000000000..69d7a75592a2 --- /dev/null +++ b/include/dt-bindings/sound/meson-g12a-toacodec.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __DT_MESON_G12A_TOACODEC_H +#define __DT_MESON_G12A_TOACODEC_H + +#define TOACODEC_IN_A 0 +#define TOACODEC_IN_B 1 +#define TOACODEC_IN_C 2 +#define TOACODEC_OUT 3 + +#endif /* __DT_MESON_G12A_TOACODEC_H */ From af2618a2eee8531e134c42194143c2f4faef94ba Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 21 Feb 2020 16:36:06 +0100 Subject: [PATCH 0621/4444] ASoC: meson: g12a: add internal DAC glue driver Add support for the internal audio DAC glue found on the Amlogic g12a and sm1 SoC families. This allows to connect the TDM outputs of the SoC to the internal t9015 audio DAC. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200221153607.1585499-3-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/Kconfig | 9 ++ sound/soc/meson/Makefile | 2 + sound/soc/meson/g12a-toacodec.c | 252 ++++++++++++++++++++++++++++++++ 3 files changed, 263 insertions(+) create mode 100644 sound/soc/meson/g12a-toacodec.c diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index d27e9180b453..8b6295283989 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -109,6 +109,15 @@ config SND_MESON_GX_SOUND_CARD help Select Y or M to add support for the GXBB/GXL SoC sound card +config SND_MESON_G12A_TOACODEC + tristate "Amlogic G12A To Internal DAC Control Support" + select SND_MESON_CODEC_GLUE + select REGMAP_MMIO + imply SND_SOC_MESON_T9015 + help + Select Y or M to add support for the internal audio DAC on the + g12a SoC family + config SND_MESON_G12A_TOHDMITX tristate "Amlogic G12A To HDMI TX Control Support" select REGMAP_MMIO diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index 3c9d48846816..e446bc980481 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -22,6 +22,7 @@ snd-soc-meson-axg-pdm-objs := axg-pdm.o snd-soc-meson-card-utils-objs := meson-card-utils.o snd-soc-meson-codec-glue-objs := meson-codec-glue.o snd-soc-meson-gx-sound-card-objs := gx-card.o +snd-soc-meson-g12a-toacodec-objs := g12a-toacodec.o snd-soc-meson-g12a-tohdmitx-objs := g12a-tohdmitx.o snd-soc-meson-t9015-objs := t9015.o @@ -40,5 +41,6 @@ obj-$(CONFIG_SND_MESON_AXG_PDM) += snd-soc-meson-axg-pdm.o obj-$(CONFIG_SND_MESON_CARD_UTILS) += snd-soc-meson-card-utils.o obj-$(CONFIG_SND_MESON_CODEC_GLUE) += snd-soc-meson-codec-glue.o obj-$(CONFIG_SND_MESON_GX_SOUND_CARD) += snd-soc-meson-gx-sound-card.o +obj-$(CONFIG_SND_MESON_G12A_TOACODEC) += snd-soc-meson-g12a-toacodec.o obj-$(CONFIG_SND_MESON_G12A_TOHDMITX) += snd-soc-meson-g12a-tohdmitx.o obj-$(CONFIG_SND_SOC_MESON_T9015) += snd-soc-meson-t9015.o diff --git a/sound/soc/meson/g12a-toacodec.c b/sound/soc/meson/g12a-toacodec.c new file mode 100644 index 000000000000..9339fabccb79 --- /dev/null +++ b/sound/soc/meson/g12a-toacodec.c @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2020 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "axg-tdm.h" +#include "meson-codec-glue.h" + +#define G12A_TOACODEC_DRV_NAME "g12a-toacodec" + +#define TOACODEC_CTRL0 0x0 +#define CTRL0_ENABLE_SHIFT 31 +#define CTRL0_DAT_SEL_SHIFT 14 +#define CTRL0_DAT_SEL (0x3 << CTRL0_DAT_SEL_SHIFT) +#define CTRL0_LANE_SEL 12 +#define CTRL0_LRCLK_SEL GENMASK(9, 8) +#define CTRL0_BLK_CAP_INV BIT(7) +#define CTRL0_BCLK_O_INV BIT(6) +#define CTRL0_BCLK_SEL GENMASK(5, 4) +#define CTRL0_MCLK_SEL GENMASK(2, 0) + +#define TOACODEC_OUT_CHMAX 2 + +static const char * const g12a_toacodec_mux_texts[] = { + "I2S A", "I2S B", "I2S C", +}; + +static int g12a_toacodec_mux_put_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int mux, changed; + + mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]); + changed = snd_soc_component_test_bits(component, e->reg, + CTRL0_DAT_SEL, + FIELD_PREP(CTRL0_DAT_SEL, mux)); + + if (!changed) + return 0; + + /* Force disconnect of the mux while updating */ + snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL); + + snd_soc_component_update_bits(component, e->reg, + CTRL0_DAT_SEL | + CTRL0_LRCLK_SEL | + CTRL0_BCLK_SEL, + FIELD_PREP(CTRL0_DAT_SEL, mux) | + FIELD_PREP(CTRL0_LRCLK_SEL, mux) | + FIELD_PREP(CTRL0_BCLK_SEL, mux)); + + /* + * FIXME: + * On this soc, the glue gets the MCLK directly from the clock + * controller instead of going the through the TDM interface. + * + * Here we assume interface A uses clock A, etc ... While it is + * true for now, it could be different. Instead the glue should + * find out the clock used by the interface and select the same + * source. For that, we will need regmap backed clock mux which + * is a work in progress + */ + snd_soc_component_update_bits(component, e->reg, + CTRL0_MCLK_SEL, + FIELD_PREP(CTRL0_MCLK_SEL, mux)); + + snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL); + + return 0; +} + +static SOC_ENUM_SINGLE_DECL(g12a_toacodec_mux_enum, TOACODEC_CTRL0, + CTRL0_DAT_SEL_SHIFT, + g12a_toacodec_mux_texts); + +static const struct snd_kcontrol_new g12a_toacodec_mux = + SOC_DAPM_ENUM_EXT("Source", g12a_toacodec_mux_enum, + snd_soc_dapm_get_enum_double, + g12a_toacodec_mux_put_enum); + +static const struct snd_kcontrol_new g12a_toacodec_out_enable = + SOC_DAPM_SINGLE_AUTODISABLE("Switch", TOACODEC_CTRL0, + CTRL0_ENABLE_SHIFT, 1, 0); + +static const struct snd_soc_dapm_widget g12a_toacodec_widgets[] = { + SND_SOC_DAPM_MUX("SRC", SND_SOC_NOPM, 0, 0, + &g12a_toacodec_mux), + SND_SOC_DAPM_SWITCH("OUT EN", SND_SOC_NOPM, 0, 0, + &g12a_toacodec_out_enable), +}; + +static int g12a_toacodec_input_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct meson_codec_glue_input *data; + int ret; + + ret = meson_codec_glue_input_hw_params(substream, params, dai); + if (ret) + return ret; + + /* The glue will provide 1 lane out of the 4 to the output */ + data = meson_codec_glue_input_get_data(dai); + data->params.channels_min = min_t(unsigned int, TOACODEC_OUT_CHMAX, + data->params.channels_min); + data->params.channels_max = min_t(unsigned int, TOACODEC_OUT_CHMAX, + data->params.channels_max); + + return 0; +} + +static const struct snd_soc_dai_ops g12a_toacodec_input_ops = { + .hw_params = g12a_toacodec_input_hw_params, + .set_fmt = meson_codec_glue_input_set_fmt, +}; + +static const struct snd_soc_dai_ops g12a_toacodec_output_ops = { + .startup = meson_codec_glue_output_startup, +}; + +#define TOACODEC_STREAM(xname, xsuffix, xchmax) \ +{ \ + .stream_name = xname " " xsuffix, \ + .channels_min = 1, \ + .channels_max = (xchmax), \ + .rate_min = 5512, \ + .rate_max = 192000, \ + .formats = AXG_TDM_FORMATS, \ +} + +#define TOACODEC_INPUT(xname, xid) { \ + .name = xname, \ + .id = (xid), \ + .playback = TOACODEC_STREAM(xname, "Playback", 8), \ + .ops = &g12a_toacodec_input_ops, \ + .probe = meson_codec_glue_input_dai_probe, \ + .remove = meson_codec_glue_input_dai_remove, \ +} + +#define TOACODEC_OUTPUT(xname, xid) { \ + .name = xname, \ + .id = (xid), \ + .capture = TOACODEC_STREAM(xname, "Capture", TOACODEC_OUT_CHMAX), \ + .ops = &g12a_toacodec_output_ops, \ +} + +static struct snd_soc_dai_driver g12a_toacodec_dai_drv[] = { + TOACODEC_INPUT("IN A", TOACODEC_IN_A), + TOACODEC_INPUT("IN B", TOACODEC_IN_B), + TOACODEC_INPUT("IN C", TOACODEC_IN_C), + TOACODEC_OUTPUT("OUT", TOACODEC_OUT), +}; + +static int g12a_toacodec_component_probe(struct snd_soc_component *c) +{ + /* Initialize the static clock parameters */ + return snd_soc_component_write(c, TOACODEC_CTRL0, + CTRL0_BLK_CAP_INV); +} + +static const struct snd_soc_dapm_route g12a_toacodec_routes[] = { + { "SRC", "I2S A", "IN A Playback" }, + { "SRC", "I2S B", "IN B Playback" }, + { "SRC", "I2S C", "IN C Playback" }, + { "OUT EN", "Switch", "SRC" }, + { "OUT Capture", NULL, "OUT EN" }, +}; + +static const struct snd_kcontrol_new g12a_toacodec_controls[] = { + SOC_SINGLE("Lane Select", TOACODEC_CTRL0, CTRL0_LANE_SEL, 3, 0), +}; + +static const struct snd_soc_component_driver g12a_toacodec_component_drv = { + .probe = g12a_toacodec_component_probe, + .controls = g12a_toacodec_controls, + .num_controls = ARRAY_SIZE(g12a_toacodec_controls), + .dapm_widgets = g12a_toacodec_widgets, + .num_dapm_widgets = ARRAY_SIZE(g12a_toacodec_widgets), + .dapm_routes = g12a_toacodec_routes, + .num_dapm_routes = ARRAY_SIZE(g12a_toacodec_routes), + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static const struct regmap_config g12a_toacodec_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static const struct of_device_id g12a_toacodec_of_match[] = { + { .compatible = "amlogic,g12a-toacodec", }, + {} +}; +MODULE_DEVICE_TABLE(of, g12a_toacodec_of_match); + +static int g12a_toacodec_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + void __iomem *regs; + struct regmap *map; + int ret; + + ret = device_reset(dev); + if (ret) + return ret; + + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + map = devm_regmap_init_mmio(dev, regs, &g12a_toacodec_regmap_cfg); + if (IS_ERR(map)) { + dev_err(dev, "failed to init regmap: %ld\n", + PTR_ERR(map)); + return PTR_ERR(map); + } + + return devm_snd_soc_register_component(dev, + &g12a_toacodec_component_drv, g12a_toacodec_dai_drv, + ARRAY_SIZE(g12a_toacodec_dai_drv)); +} + +static struct platform_driver g12a_toacodec_pdrv = { + .driver = { + .name = G12A_TOACODEC_DRV_NAME, + .of_match_table = g12a_toacodec_of_match, + }, + .probe = g12a_toacodec_probe, +}; +module_platform_driver(g12a_toacodec_pdrv); + +MODULE_AUTHOR("Jerome Brunet "); +MODULE_DESCRIPTION("Amlogic G12a To Internal DAC Codec Driver"); +MODULE_LICENSE("GPL v2"); From b38c4a8a0291c31a660cd77761202ebb18332fb7 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 21 Feb 2020 16:36:07 +0100 Subject: [PATCH 0622/4444] ASoC: meson: axg-card: add toacodec support Make sure the axg audio card driver recognise the dai_link as a codec-to-codec link if the cpu dai is the internal dac glue. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200221153607.1585499-4-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-card.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index 372dc696cc8e..48651631bdcf 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c @@ -303,7 +303,8 @@ static int axg_card_cpu_is_tdm_iface(struct device_node *np) static int axg_card_cpu_is_codec(struct device_node *np) { - return of_device_is_compatible(np, DT_PREFIX "g12a-tohdmitx"); + return of_device_is_compatible(np, DT_PREFIX "g12a-tohdmitx") || + of_device_is_compatible(np, DT_PREFIX "g12a-toacodec"); } static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np, From 8d54a27593896895f6166a1ac69eac99c8a6a71a Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 22 Dec 2019 16:39:40 +0000 Subject: [PATCH 0623/4444] ARM: allow unwinder to unwind recursive functions Allow the unwinder to unwind recursive functions if the stack makes progress, even if the PC is the same. This allows tracing through recursive __switchdev_handle_port_attr_set() and similar. Signed-off-by: Russell King --- arch/arm/kernel/unwind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index 4574e6aea0a5..11a964fd66f4 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -444,7 +444,7 @@ int unwind_frame(struct stackframe *frame) ctrl.vrs[PC] = ctrl.vrs[LR]; /* check for infinite loop */ - if (frame->pc == ctrl.vrs[PC]) + if (frame->pc == ctrl.vrs[PC] && frame->sp == ctrl.vrs[SP]) return -URC_FAILURE; frame->fp = ctrl.vrs[FP]; From 3c14fe70be3ed2224f8bbd70506dbf0c8a17de02 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 10 Feb 2020 02:06:06 +0100 Subject: [PATCH 0624/4444] ARM: 8959/1: Remove unused .fixup section in boot stub The boot stub does not emit a .fixup section at all anymore, so remove it. Link: https://lore.kernel.org/lkml/202002080058.FD1DDB1@keescook/ Suggested-by: Nick Desaulniers Signed-off-by: Kees Cook Reviewed-by: Ard Biesheuvel Reviewed-by: Nick Desaulniers Signed-off-by: Russell King --- arch/arm/boot/compressed/vmlinux.lds.S | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S index fc7ed03d8b93..b247f399de71 100644 --- a/arch/arm/boot/compressed/vmlinux.lds.S +++ b/arch/arm/boot/compressed/vmlinux.lds.S @@ -36,7 +36,6 @@ SECTIONS *(.start) *(.text) *(.text.*) - *(.fixup) *(.gnu.warning) *(.glue_7t) *(.glue_7) From f4a5ac7bd96f13b67e0f554c3c7f1b6740e3dbdf Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 21 Feb 2020 10:57:17 -0800 Subject: [PATCH 0625/4444] ARM: OMAP2+: Improve handling of ti-sysc related sysc_fields We can currently get a cryptic warning sysc_fields (ptrval) != (ptrval) if the legacy platform data has no sysc_fields defined while the newer dts data has them. This warning appears only when booting still with legacy "ti,hwmods" custom property set. This can happen at least with DSS related modules where we may not have sysc_fields defined in the in the legacy data. Let's not error out on missing legacy data sysc_fields, and show a more descriptive warning for other cases. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_hwmod.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 17d337ed18be..82706af307de 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -3148,15 +3148,14 @@ static int omap_hwmod_check_sysc(struct device *dev, /** * omap_hwmod_init_regbits - init sysconfig specific register bits * @dev: struct device + * @oh: module * @data: module data * @sysc_fields: new sysc configuration */ -static int omap_hwmod_init_regbits(struct device *dev, +static int omap_hwmod_init_regbits(struct device *dev, struct omap_hwmod *oh, const struct ti_sysc_module_data *data, struct sysc_regbits **sysc_fields) { - *sysc_fields = NULL; - switch (data->cap->type) { case TI_SYSC_OMAP2: case TI_SYSC_OMAP2_TIMER: @@ -3191,6 +3190,12 @@ static int omap_hwmod_init_regbits(struct device *dev, *sysc_fields = &omap_hwmod_sysc_type_usb_host_fs; break; default: + *sysc_fields = NULL; + if (!oh->class->sysc->sysc_fields) + return 0; + + dev_err(dev, "sysc_fields not found\n"); + return -EINVAL; } @@ -3356,9 +3361,9 @@ static int omap_hwmod_check_module(struct device *dev, if (!oh->class->sysc) return -ENODEV; - if (sysc_fields != oh->class->sysc->sysc_fields) - dev_warn(dev, "sysc_fields %p != %p\n", sysc_fields, - oh->class->sysc->sysc_fields); + if (oh->class->sysc->sysc_fields && + sysc_fields != oh->class->sysc->sysc_fields) + dev_warn(dev, "sysc_fields mismatch\n"); if (rev_offs != oh->class->sysc->rev_offs) dev_warn(dev, "rev_offs %08x != %08x\n", rev_offs, @@ -3574,7 +3579,7 @@ int omap_hwmod_init_module(struct device *dev, cookie->data = oh; - error = omap_hwmod_init_regbits(dev, data, &sysc_fields); + error = omap_hwmod_init_regbits(dev, oh, data, &sysc_fields); if (error) return error; From 8a329dbd4a02dc4e4ff78b006c33676f867f2726 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Fri, 21 Feb 2020 12:13:57 -0600 Subject: [PATCH 0626/4444] ASoC: tlv320adcx140: Add DRE and AGC support The TLV320ADCx140 parts support Dynamic Range Enhancer (DRE) as defined in Section 8.3.2 of the data sheets. The DRE achieves a complete-channel dynamic range as high as 120 dB. At a system level, the DRE scheme enables far-field, high-fidelity recording of audio signals in very quiet environments and low-distortion recording in loud environments. There are 2 enables for DRE. The first is a global setting that enables the DRE engine in the device and the other enable is per channel. If the DRE is enabled globally then either DRE or AGC can be used per each configured channel. If global DRE is disabled then even setting the DRE enable bit in the channel config register will have no effect. Signed-off-by: Dan Murphy Link: https://lore.kernel.org/r/20200221181358.22526-1-dmurphy@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320adcx140.c | 55 ++++++++++++++++++++++++++++++++ sound/soc/codecs/tlv320adcx140.h | 1 + 2 files changed, 56 insertions(+) diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c index 8182c584de9c..105e51be6fe6 100644 --- a/sound/soc/codecs/tlv320adcx140.c +++ b/sound/soc/codecs/tlv320adcx140.c @@ -108,6 +108,7 @@ static const struct reg_default adcx140_reg_defaults[] = { { ADCX140_DSP_CFG0, 0x01 }, { ADCX140_DSP_CFG1, 0x40 }, { ADCX140_DRE_CFG0, 0x7b }, + { ADCX140_AGC_CFG0, 0xe7 }, { ADCX140_IN_CH_EN, 0xf0 }, { ADCX140_ASI_OUT_CH_EN, 0x00 }, { ADCX140_PWR_CFG, 0x00 }, @@ -158,6 +159,16 @@ static DECLARE_TLV_DB_SCALE(dig_vol_tlv, -10000, 50, 0); /* ADC gain. From 0 to 42 dB in 1 dB steps */ static DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0); +/* DRE Level. From -12 dB to -66 dB in 1 dB steps */ +static DECLARE_TLV_DB_SCALE(dre_thresh_tlv, -6600, 100, 0); +/* DRE Max Gain. From 2 dB to 26 dB in 2 dB steps */ +static DECLARE_TLV_DB_SCALE(dre_gain_tlv, 200, 200, 0); + +/* AGC Level. From -6 dB to -36 dB in 2 dB steps */ +static DECLARE_TLV_DB_SCALE(agc_thresh_tlv, -3600, 200, 0); +/* AGC Max Gain. From 3 dB to 42 dB in 3 dB steps */ +static DECLARE_TLV_DB_SCALE(agc_gain_tlv, 300, 300, 0); + static const char * const resistor_text[] = { "2.5 kOhm", "10 kOhm", "20 kOhm" }; @@ -281,6 +292,18 @@ static const struct snd_kcontrol_new adcx140_dapm_ch3_en_switch = static const struct snd_kcontrol_new adcx140_dapm_ch4_en_switch = SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 4, 1, 0); +static const struct snd_kcontrol_new adcx140_dapm_ch1_dre_en_switch = + SOC_DAPM_SINGLE("Switch", ADCX140_CH1_CFG0, 0, 1, 0); +static const struct snd_kcontrol_new adcx140_dapm_ch2_dre_en_switch = + SOC_DAPM_SINGLE("Switch", ADCX140_CH2_CFG0, 0, 1, 0); +static const struct snd_kcontrol_new adcx140_dapm_ch3_dre_en_switch = + SOC_DAPM_SINGLE("Switch", ADCX140_CH3_CFG0, 0, 1, 0); +static const struct snd_kcontrol_new adcx140_dapm_ch4_dre_en_switch = + SOC_DAPM_SINGLE("Switch", ADCX140_CH4_CFG0, 0, 1, 0); + +static const struct snd_kcontrol_new adcx140_dapm_dre_en_switch = + SOC_DAPM_SINGLE("Switch", ADCX140_DSP_CFG1, 3, 1, 0); + /* Output Mixer */ static const struct snd_kcontrol_new adcx140_output_mixer_controls[] = { SOC_DAPM_SINGLE("Digital CH1 Switch", 0, 0, 0, 0), @@ -361,6 +384,18 @@ static const struct snd_soc_dapm_widget adcx140_dapm_widgets[] = { SND_SOC_DAPM_SWITCH("CH4_ASI_EN", SND_SOC_NOPM, 0, 0, &adcx140_dapm_ch4_en_switch), + SND_SOC_DAPM_SWITCH("DRE_ENABLE", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_dre_en_switch), + + SND_SOC_DAPM_SWITCH("CH1_DRE_EN", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_ch1_dre_en_switch), + SND_SOC_DAPM_SWITCH("CH2_DRE_EN", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_ch2_dre_en_switch), + SND_SOC_DAPM_SWITCH("CH3_DRE_EN", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_ch3_dre_en_switch), + SND_SOC_DAPM_SWITCH("CH4_DRE_EN", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_ch4_dre_en_switch), + SND_SOC_DAPM_MUX("IN1 Analog Mic Resistor", SND_SOC_NOPM, 0, 0, in1_resistor_controls), SND_SOC_DAPM_MUX("IN2 Analog Mic Resistor", SND_SOC_NOPM, 0, 0, @@ -383,6 +418,16 @@ static const struct snd_soc_dapm_route adcx140_audio_map[] = { {"CH3_ASI_EN", "Switch", "CH3_ADC"}, {"CH4_ASI_EN", "Switch", "CH4_ADC"}, + {"DRE_ENABLE", "Switch", "CH1_DRE_EN"}, + {"DRE_ENABLE", "Switch", "CH2_DRE_EN"}, + {"DRE_ENABLE", "Switch", "CH3_DRE_EN"}, + {"DRE_ENABLE", "Switch", "CH4_DRE_EN"}, + + {"CH1_DRE_EN", "Switch", "CH1_ADC"}, + {"CH2_DRE_EN", "Switch", "CH2_ADC"}, + {"CH3_DRE_EN", "Switch", "CH3_ADC"}, + {"CH4_DRE_EN", "Switch", "CH4_ADC"}, + /* Mic input */ {"CH1_ADC", NULL, "MIC_GAIN_CTL_CH1"}, {"CH2_ADC", NULL, "MIC_GAIN_CTL_CH2"}, @@ -455,6 +500,16 @@ static const struct snd_kcontrol_new adcx140_snd_controls[] = { SOC_SINGLE_TLV("Analog CH4 Mic Gain Volume", ADCX140_CH1_CFG4, 2, 42, 0, adc_tlv), + SOC_SINGLE_TLV("DRE Threshold", ADCX140_DRE_CFG0, 4, 9, 0, + dre_thresh_tlv), + SOC_SINGLE_TLV("DRE Max Gain", ADCX140_DRE_CFG0, 0, 12, 0, + dre_gain_tlv), + + SOC_SINGLE_TLV("AGC Threshold", ADCX140_AGC_CFG0, 4, 15, 0, + agc_thresh_tlv), + SOC_SINGLE_TLV("AGC Max Gain", ADCX140_AGC_CFG0, 0, 13, 0, + agc_gain_tlv), + SOC_SINGLE_TLV("Digital CH1 Out Volume", ADCX140_CH1_CFG2, 0, 0xff, 0, dig_vol_tlv), SOC_SINGLE_TLV("Digital CH2 Out Volume", ADCX140_CH2_CFG2, diff --git a/sound/soc/codecs/tlv320adcx140.h b/sound/soc/codecs/tlv320adcx140.h index 66b1c3b33f1e..6d055e55909e 100644 --- a/sound/soc/codecs/tlv320adcx140.h +++ b/sound/soc/codecs/tlv320adcx140.h @@ -84,6 +84,7 @@ #define ADCX140_DSP_CFG0 0x6b #define ADCX140_DSP_CFG1 0x6c #define ADCX140_DRE_CFG0 0x6d +#define ADCX140_AGC_CFG0 0x70 #define ADCX140_IN_CH_EN 0x73 #define ADCX140_ASI_OUT_CH_EN 0x74 #define ADCX140_PWR_CFG 0x75 From 8101d76253f6d1032ca79e937e45b837cb4bf0e0 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Fri, 21 Feb 2020 12:13:58 -0600 Subject: [PATCH 0627/4444] ASoC: tlv320adcx140: Add decimation filter support Add decimation filter selection support. Per Section 8.3.6.7 the Digital Decimation Filter is selectable between a Linear Phase, Low Latency, and Ultra Low Latency filer. Signed-off-by: Dan Murphy Link: https://lore.kernel.org/r/20200221181358.22526-2-dmurphy@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320adcx140.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c index 105e51be6fe6..93a0cb8e662c 100644 --- a/sound/soc/codecs/tlv320adcx140.c +++ b/sound/soc/codecs/tlv320adcx140.c @@ -169,6 +169,17 @@ static DECLARE_TLV_DB_SCALE(agc_thresh_tlv, -3600, 200, 0); /* AGC Max Gain. From 3 dB to 42 dB in 3 dB steps */ static DECLARE_TLV_DB_SCALE(agc_gain_tlv, 300, 300, 0); +static const char * const decimation_filter_text[] = { + "Linear Phase", "Low Latency", "Ultra-low Latency" +}; + +static SOC_ENUM_SINGLE_DECL(decimation_filter_enum, ADCX140_DSP_CFG0, 4, + decimation_filter_text); + +static const struct snd_kcontrol_new decimation_filter_controls[] = { + SOC_DAPM_ENUM("Decimation Filter", decimation_filter_enum), +}; + static const char * const resistor_text[] = { "2.5 kOhm", "10 kOhm", "20 kOhm" }; @@ -404,6 +415,9 @@ static const struct snd_soc_dapm_widget adcx140_dapm_widgets[] = { in3_resistor_controls), SND_SOC_DAPM_MUX("IN4 Analog Mic Resistor", SND_SOC_NOPM, 0, 0, in4_resistor_controls), + + SND_SOC_DAPM_MUX("Decimation Filter", SND_SOC_NOPM, 0, 0, + decimation_filter_controls), }; static const struct snd_soc_dapm_route adcx140_audio_map[] = { @@ -418,6 +432,10 @@ static const struct snd_soc_dapm_route adcx140_audio_map[] = { {"CH3_ASI_EN", "Switch", "CH3_ADC"}, {"CH4_ASI_EN", "Switch", "CH4_ADC"}, + {"Decimation Filter", "Linear Phase", "DRE_ENABLE"}, + {"Decimation Filter", "Low Latency", "DRE_ENABLE"}, + {"Decimation Filter", "Ultra-low Latency", "DRE_ENABLE"}, + {"DRE_ENABLE", "Switch", "CH1_DRE_EN"}, {"DRE_ENABLE", "Switch", "CH2_DRE_EN"}, {"DRE_ENABLE", "Switch", "CH3_DRE_EN"}, From 738981bd74e89d5de012c56a20427e34c6937334 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Wed, 19 Feb 2020 14:01:35 +0100 Subject: [PATCH 0628/4444] scsi: target: fix unmap_zeroes_data boolean initialisation The LIO unmap_zeroes_data device attribute is mapped to the LBPRZ flag in the READ CAPACITY(16) and Thin Provisioning VPD INQUIRY responses. The unmap_zeroes_data attribute is exposed via configfs, where any write value is correctly validated via strtobool(). However, when initialised via target_configure_unmap_from_queue() it takes the value of the device's max_write_zeroes_sectors queue limit, which is non-boolean. A non-boolean value can be read from configfs, but attempting to write the same value back results in -EINVAL, causing problems for configuration utilities such as targetcli. Link: https://marc.info/?l=target-devel&m=158213354011309 Fixes: 2237498f0b5c ("target/iblock: Convert WRITE_SAME to blkdev_issue_zeroout") Reviewed-by: Bart Van Assche Signed-off-by: David Disseldorp Signed-off-by: Martin K. Petersen --- drivers/target/target_core_device.c | 2 +- include/target/target_core_base.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 2d19f0e332b0..2c7ba2f7e13c 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -829,7 +829,7 @@ bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib, attrib->unmap_granularity = q->limits.discard_granularity / block_size; attrib->unmap_granularity_alignment = q->limits.discard_alignment / block_size; - attrib->unmap_zeroes_data = (q->limits.max_write_zeroes_sectors); + attrib->unmap_zeroes_data = !!(q->limits.max_write_zeroes_sectors); return true; } EXPORT_SYMBOL(target_configure_unmap_from_queue); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 1728e883b7b2..35188e64239e 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -682,7 +682,7 @@ struct se_dev_attrib { int force_pr_aptpl; int is_nonrot; int emulate_rest_reord; - int unmap_zeroes_data; + bool unmap_zeroes_data; u32 hw_block_size; u32 block_size; u32 hw_max_sectors; From 87310c9fb502868798c26c6720837718e94dd479 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Wed, 19 Feb 2020 14:01:36 +0100 Subject: [PATCH 0629/4444] scsi: target: convert boolean se_dev_attrib types to bool This should harden us against configfs API regressions similar to the one fixed by the previous commit. Link: https://marc.info/?l=target-devel&m=158211731505174 Signed-off-by: David Disseldorp Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/target/target_core_tmr.c | 6 +++--- include/target/target_core_base.h | 32 +++++++++++++++---------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index feeba3966617..afbd492c76a9 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -78,7 +78,7 @@ static int target_check_cdb_and_preempt(struct list_head *list, } static bool __target_check_io_state(struct se_cmd *se_cmd, - struct se_session *tmr_sess, int tas) + struct se_session *tmr_sess, bool tas) { struct se_session *sess = se_cmd->se_sess; @@ -251,7 +251,7 @@ static void core_tmr_drain_state_list( struct se_device *dev, struct se_cmd *prout_cmd, struct se_session *tmr_sess, - int tas, + bool tas, struct list_head *preempt_and_abort_list) { LIST_HEAD(drain_task_list); @@ -334,7 +334,7 @@ int core_tmr_lun_reset( struct se_node_acl *tmr_nacl = NULL; struct se_portal_group *tmr_tpg = NULL; struct se_session *tmr_sess = NULL; - int tas; + bool tas; /* * TASK_ABORTED status bit, this is configurable via ConfigFS * struct se_device attributes. spc4r17 section 7.4.6 Control mode page diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 35188e64239e..bbac0f1c3ba1 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -663,25 +663,25 @@ struct se_dev_entry { }; struct se_dev_attrib { - int emulate_model_alias; - int emulate_dpo; - int emulate_fua_write; - int emulate_fua_read; - int emulate_write_cache; + bool emulate_model_alias; + bool emulate_dpo; /* deprecated */ + bool emulate_fua_write; + bool emulate_fua_read; /* deprecated */ + bool emulate_write_cache; int emulate_ua_intlck_ctrl; - int emulate_tas; - int emulate_tpu; - int emulate_tpws; - int emulate_caw; - int emulate_3pc; - int emulate_pr; + bool emulate_tas; + bool emulate_tpu; + bool emulate_tpws; + bool emulate_caw; + bool emulate_3pc; + bool emulate_pr; enum target_prot_type pi_prot_type; enum target_prot_type hw_pi_prot_type; - int pi_prot_verify; - int enforce_pr_isids; - int force_pr_aptpl; - int is_nonrot; - int emulate_rest_reord; + bool pi_prot_verify; + bool enforce_pr_isids; + bool force_pr_aptpl; + bool is_nonrot; + bool emulate_rest_reord; bool unmap_zeroes_data; u32 hw_block_size; u32 block_size; From 1bf630fddd505e4d3e1c7e857eb54f8da787fe9a Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Fri, 21 Feb 2020 10:44:01 +0100 Subject: [PATCH 0630/4444] scsi: target: use an enum to track emulate_ua_intlck_ctrl The emulate_ua_intlck_ctrl device attribute accepts values of 0, 1 or 2 via ConfigFS, which map to unit attention interlocks control codes in the MODE SENSE control Mode Page. Use an enum to track these values so that it's clear that, unlike the remaining emulate_X attributes, emulate_ua_intlck_ctrl isn't boolean. Link: https://marc.info/?l=target-devel&m=158227825428798 Suggested-by: Bart Van Assche Signed-off-by: David Disseldorp Signed-off-by: Martin K. Petersen --- drivers/target/target_core_configfs.c | 4 +++- drivers/target/target_core_device.c | 2 +- drivers/target/target_core_spc.c | 13 +++++++++++-- drivers/target/target_core_transport.c | 3 ++- drivers/target/target_core_ua.c | 8 +++++--- include/target/target_core_base.h | 11 ++++++++--- 6 files changed, 30 insertions(+), 11 deletions(-) diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index e6e175597860..ff82b21fdcce 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -684,7 +684,9 @@ static ssize_t emulate_ua_intlck_ctrl_store(struct config_item *item, if (ret < 0) return ret; - if (val != 0 && val != 1 && val != 2) { + if (val != TARGET_UA_INTLCK_CTRL_CLEAR + && val != TARGET_UA_INTLCK_CTRL_NO_CLEAR + && val != TARGET_UA_INTLCK_CTRL_ESTABLISH_UA) { pr_err("Illegal value %d\n", val); return -EINVAL; } diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 2c7ba2f7e13c..4cee1138284b 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -767,7 +767,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) dev->dev_attrib.emulate_fua_write = 1; dev->dev_attrib.emulate_fua_read = 1; dev->dev_attrib.emulate_write_cache = DA_EMULATE_WRITE_CACHE; - dev->dev_attrib.emulate_ua_intlck_ctrl = DA_EMULATE_UA_INTLLCK_CTRL; + dev->dev_attrib.emulate_ua_intlck_ctrl = TARGET_UA_INTLCK_CTRL_CLEAR; dev->dev_attrib.emulate_tas = DA_EMULATE_TAS; dev->dev_attrib.emulate_tpu = DA_EMULATE_TPU; dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS; diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 6d4cf2643c0a..ca5579ebc81d 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -847,8 +847,17 @@ static int spc_modesense_control(struct se_cmd *cmd, u8 pc, u8 *p) * for a BUSY, TASK SET FULL, or RESERVATION CONFLICT status regardless * to the number of commands completed with one of those status codes. */ - p[4] = (dev->dev_attrib.emulate_ua_intlck_ctrl == 2) ? 0x30 : - (dev->dev_attrib.emulate_ua_intlck_ctrl == 1) ? 0x20 : 0x00; + switch (dev->dev_attrib.emulate_ua_intlck_ctrl) { + case TARGET_UA_INTLCK_CTRL_ESTABLISH_UA: + p[4] = 0x30; + break; + case TARGET_UA_INTLCK_CTRL_NO_CLEAR: + p[4] = 0x20; + break; + default: /* TARGET_UA_INTLCK_CTRL_CLEAR */ + p[4] = 0x00; + break; + } /* * From spc4r17, section 7.4.6 Control mode Page * diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index ea482d4b1f00..9681d4ba02d7 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1879,7 +1879,8 @@ void transport_generic_request_failure(struct se_cmd *cmd, * See spc4r17, section 7.4.6 Control Mode Page, Table 349 */ if (cmd->se_sess && - cmd->se_dev->dev_attrib.emulate_ua_intlck_ctrl == 2) { + cmd->se_dev->dev_attrib.emulate_ua_intlck_ctrl + == TARGET_UA_INTLCK_CTRL_ESTABLISH_UA) { target_ua_allocate_lun(cmd->se_sess->se_node_acl, cmd->orig_fe_lun, 0x2C, ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS); diff --git a/drivers/target/target_core_ua.c b/drivers/target/target_core_ua.c index 151b56002da5..4276690fb6cb 100644 --- a/drivers/target/target_core_ua.c +++ b/drivers/target/target_core_ua.c @@ -199,6 +199,8 @@ bool core_scsi3_ua_for_check_condition(struct se_cmd *cmd, u8 *key, u8 *asc, struct se_node_acl *nacl; struct se_ua *ua = NULL, *ua_p; int head = 1; + bool dev_ua_intlck_clear = (dev->dev_attrib.emulate_ua_intlck_ctrl + == TARGET_UA_INTLCK_CTRL_CLEAR); if (WARN_ON_ONCE(!sess)) return false; @@ -229,7 +231,7 @@ bool core_scsi3_ua_for_check_condition(struct se_cmd *cmd, u8 *key, u8 *asc, * highest priority UNIT_ATTENTION and ASC/ASCQ without * clearing it. */ - if (dev->dev_attrib.emulate_ua_intlck_ctrl != 0) { + if (!dev_ua_intlck_clear) { *asc = ua->ua_asc; *ascq = ua->ua_ascq; break; @@ -254,8 +256,8 @@ bool core_scsi3_ua_for_check_condition(struct se_cmd *cmd, u8 *key, u8 *asc, " INTLCK_CTRL: %d, mapped LUN: %llu, got CDB: 0x%02x" " reported ASC: 0x%02x, ASCQ: 0x%02x\n", nacl->se_tpg->se_tpg_tfo->fabric_name, - (dev->dev_attrib.emulate_ua_intlck_ctrl != 0) ? "Reporting" : - "Releasing", dev->dev_attrib.emulate_ua_intlck_ctrl, + dev_ua_intlck_clear ? "Releasing" : "Reporting", + dev->dev_attrib.emulate_ua_intlck_ctrl, cmd->orig_fe_lun, cmd->t_task_cdb[0], *asc, *ascq); return head == 0; diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index bbac0f1c3ba1..6d4a694f6ea7 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -74,8 +74,6 @@ #define DA_EMULATE_MODEL_ALIAS 0 /* Emulation for WriteCache and SYNCHRONIZE_CACHE */ #define DA_EMULATE_WRITE_CACHE 0 -/* Emulation for UNIT ATTENTION Interlock Control */ -#define DA_EMULATE_UA_INTLLCK_CTRL 0 /* Emulation for TASK_ABORTED status (TAS) by default */ #define DA_EMULATE_TAS 1 /* Emulation for Thin Provisioning UNMAP using block/blk-lib.c:blkdev_issue_discard() */ @@ -433,6 +431,13 @@ enum target_prot_type { TARGET_DIF_TYPE3_PROT, }; +/* Emulation for UNIT ATTENTION Interlock Control */ +enum target_ua_intlck_ctrl { + TARGET_UA_INTLCK_CTRL_CLEAR = 0, + TARGET_UA_INTLCK_CTRL_NO_CLEAR = 1, + TARGET_UA_INTLCK_CTRL_ESTABLISH_UA = 2, +}; + enum target_core_dif_check { TARGET_DIF_CHECK_GUARD = 0x1 << 0, TARGET_DIF_CHECK_APPTAG = 0x1 << 1, @@ -668,7 +673,7 @@ struct se_dev_attrib { bool emulate_fua_write; bool emulate_fua_read; /* deprecated */ bool emulate_write_cache; - int emulate_ua_intlck_ctrl; + enum target_ua_intlck_ctrl emulate_ua_intlck_ctrl; bool emulate_tas; bool emulate_tpu; bool emulate_tpws; From 6a7f10c795743a7f81e89df99866d7532811c324 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 21 Feb 2020 23:11:43 +0000 Subject: [PATCH 0631/4444] soc: fsl: dpio: fix dereference of pointer p before null check Pointer p is currently being dereferenced before it is null checked on a memory allocation failure check. Fix this by checking if p is null before dereferencing it. Addresses-Coverity: ("Dereference before null check") Fixes: 3b2abda7d28c ("soc: fsl: dpio: Replace QMAN array mode with ring mode enqueue") Signed-off-by: Colin Ian King Signed-off-by: Li Yang --- drivers/soc/fsl/dpio/qbman-portal.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/soc/fsl/dpio/qbman-portal.c b/drivers/soc/fsl/dpio/qbman-portal.c index 740ee0d19582..d1f49caa5b13 100644 --- a/drivers/soc/fsl/dpio/qbman-portal.c +++ b/drivers/soc/fsl/dpio/qbman-portal.c @@ -249,10 +249,11 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) u32 mask_size; u32 eqcr_pi; - spin_lock_init(&p->access_spinlock); - if (!p) return NULL; + + spin_lock_init(&p->access_spinlock); + p->desc = d; p->mc.valid_bit = QB_VALID_BIT; p->sdq = 0; From 07553b1e83b46414caa693ba10d1a16487409b61 Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 12 Feb 2020 13:44:12 -0800 Subject: [PATCH 0632/4444] scsi: qla2xxx: Add beacon LED config sysfs interface This patch provides an interface to do the following (using MBC 0x3B): - Displays (in hex) the LED config words for all three LEDs. - Programs the config words for one LED or for all three LEDs. The sysfs node defined is named beacon_config. First, to allow driver to gain LED control, do this: # echo 1 > /sys/class/scsi_host/host#/beacon Then, to display config words for all three LEDs do this: # cat /sys/class/scsi_host/host#/beacon_config To set config words for all three LEDs do this: # echo 3 xxxx yyyy zzzz > /sys/class/scsi_host/host#/beacon_config Or, to set config word for a specific single LED n do this: # echo n xxxx > /sys/class/scsi_host/host#/beacon_config where n is the LED number (0, 1, 2) Finally, to restore LED control back to firmware, do this: # echo 0 > /sys/class/scsi_host/host#/beacon Link: https://lore.kernel.org/r/20200212214436.25532-2-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_attr.c | 76 +++++++++++++++++++++++++++++++++ drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_mbx.c | 57 +++++++++++++++++++++++++ 4 files changed, 135 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index d7e7043f9eab..d6a59c92c5a8 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1323,6 +1323,79 @@ qla2x00_beacon_store(struct device *dev, struct device_attribute *attr, return count; } +static ssize_t +qla2x00_beacon_config_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + struct qla_hw_data *ha = vha->hw; + uint16_t led[3] = { 0 }; + + if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + return -EPERM; + + if (ql26xx_led_config(vha, 0, led)) + return scnprintf(buf, PAGE_SIZE, "\n"); + + return scnprintf(buf, PAGE_SIZE, "%#04hx %#04hx %#04hx\n", + led[0], led[1], led[2]); +} + +static ssize_t +qla2x00_beacon_config_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + struct qla_hw_data *ha = vha->hw; + uint16_t options = BIT_0; + uint16_t led[3] = { 0 }; + uint16_t word[4]; + int n; + + if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + return -EPERM; + + n = sscanf(buf, "%hx %hx %hx %hx", word+0, word+1, word+2, word+3); + if (n == 4) { + if (word[0] == 3) { + options |= BIT_3|BIT_2|BIT_1; + led[0] = word[1]; + led[1] = word[2]; + led[2] = word[3]; + goto write; + } + return -EINVAL; + } + + if (n == 2) { + /* check led index */ + if (word[0] == 0) { + options |= BIT_2; + led[0] = word[1]; + goto write; + } + if (word[0] == 1) { + options |= BIT_3; + led[1] = word[1]; + goto write; + } + if (word[0] == 2) { + options |= BIT_1; + led[2] = word[1]; + goto write; + } + return -EINVAL; + } + + return -EINVAL; + +write: + if (ql26xx_led_config(vha, options, led)) + return -EFAULT; + + return count; +} + static ssize_t qla2x00_optrom_bios_version_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -2264,6 +2337,8 @@ static DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show, qla2x00_zio_timer_store); static DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show, qla2x00_beacon_store); +static DEVICE_ATTR(beacon_config, 0644, qla2x00_beacon_config_show, + qla2x00_beacon_config_store); static DEVICE_ATTR(optrom_bios_version, S_IRUGO, qla2x00_optrom_bios_version_show, NULL); static DEVICE_ATTR(optrom_efi_version, S_IRUGO, @@ -2327,6 +2402,7 @@ struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_zio, &dev_attr_zio_timer, &dev_attr_beacon, + &dev_attr_beacon_config, &dev_attr_optrom_bios_version, &dev_attr_optrom_efi_version, &dev_attr_optrom_fcode_version, diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index ed32e9715794..b59643883ad1 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1134,6 +1134,7 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs) #define MBC_GET_FIRMWARE_OPTION 0x28 /* Get Firmware Options. */ #define MBC_GET_MEM_OFFLOAD_CNTRL_STAT 0x34 /* Memory Offload ctrl/Stat*/ #define MBC_SET_FIRMWARE_OPTION 0x38 /* Set Firmware Options. */ +#define MBC_SET_GET_FC_LED_CONFIG 0x3b /* Set/Get FC LED config */ #define MBC_LOOP_PORT_BYPASS 0x40 /* Loop Port Bypass. */ #define MBC_LOOP_PORT_ENABLE 0x41 /* Loop Port Enable. */ #define MBC_GET_RESOURCE_COUNTS 0x42 /* Get Resource Counts. */ diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 2a64729a2bc5..156ad11a15c4 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -844,6 +844,7 @@ extern void qla82xx_clear_pending_mbx(scsi_qla_host_t *); extern int qla82xx_read_temperature(scsi_qla_host_t *); extern int qla8044_read_temperature(scsi_qla_host_t *); extern int qla2x00_read_sfp_dev(struct scsi_qla_host *, char *, int); +extern int ql26xx_led_config(scsi_qla_host_t *, uint16_t, uint16_t *); /* BSG related functions */ extern int qla24xx_bsg_request(struct bsg_job *); diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 9e09964f5c0e..e1916bec5e36 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -6688,3 +6688,60 @@ int qla2xxx_read_remote_register(scsi_qla_host_t *vha, uint32_t addr, return rval; } + +int +ql26xx_led_config(scsi_qla_host_t *vha, uint16_t options, uint16_t *led) +{ + struct qla_hw_data *ha = vha->hw; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + int rval; + + if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + return QLA_FUNCTION_FAILED; + + ql_dbg(ql_dbg_mbx, vha, 0x7070, "Entered %s (options=%x).\n", + __func__, options); + + mcp->mb[0] = MBC_SET_GET_FC_LED_CONFIG; + mcp->mb[1] = options; + mcp->out_mb = MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + if (options & BIT_0) { + if (options & BIT_1) { + mcp->mb[2] = led[2]; + mcp->out_mb |= MBX_2; + } + if (options & BIT_2) { + mcp->mb[3] = led[0]; + mcp->out_mb |= MBX_3; + } + if (options & BIT_3) { + mcp->mb[4] = led[1]; + mcp->out_mb |= MBX_4; + } + } else { + mcp->in_mb |= MBX_4|MBX_3|MBX_2; + } + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + if (rval) { + ql_dbg(ql_dbg_mbx, vha, 0x7071, "Failed %s %x (mb=%x,%x)\n", + __func__, rval, mcp->mb[0], mcp->mb[1]); + return rval; + } + + if (options & BIT_0) { + ha->beacon_blink_led = 0; + ql_dbg(ql_dbg_mbx, vha, 0x7072, "Done %s\n", __func__); + } else { + led[2] = mcp->mb[2]; + led[0] = mcp->mb[3]; + led[1] = mcp->mb[4]; + ql_dbg(ql_dbg_mbx, vha, 0x7073, "Done %s (led=%x,%x,%x)\n", + __func__, led[0], led[1], led[2]); + } + + return rval; +} From 054f4382417098b4d0028f8145fa214d448792d7 Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 12 Feb 2020 13:44:13 -0800 Subject: [PATCH 0633/4444] scsi: qla2xxx: Move free of fcport out of interrupt context This patch moves freeing of fcport out of interrupt context. Link: https://lore.kernel.org/r/20200212214436.25532-3-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_bsg.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index d7169e43f5e1..5870d26ab707 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -11,6 +11,14 @@ #include #include +static void qla2xxx_free_fcport_work(struct work_struct *work) +{ + struct fc_port *fcport = container_of(work, typeof(*fcport), + free_work); + + qla2x00_free_fcport(fcport); +} + /* BSG support for ELS/CT pass through */ void qla2x00_bsg_job_done(srb_t *sp, int res) { @@ -53,8 +61,10 @@ void qla2x00_bsg_sp_free(srb_t *sp) if (sp->type == SRB_CT_CMD || sp->type == SRB_FXIOCB_BCMD || - sp->type == SRB_ELS_CMD_HST) - qla2x00_free_fcport(sp->fcport); + sp->type == SRB_ELS_CMD_HST) { + INIT_WORK(&sp->fcport->free_work, qla2xxx_free_fcport_work); + queue_work(ha->wq, &sp->fcport->free_work); + } qla2x00_rel_sp(sp); } From e6ad2b79b82f41a51f90c95686c39cd8be4a35f3 Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 12 Feb 2020 13:44:14 -0800 Subject: [PATCH 0634/4444] scsi: qla2xxx: Add sysfs node for D-Port Diagnostics AEN data This patch adds sysfs node to show D-Port diag data. Link: https://lore.kernel.org/r/20200212214436.25532-4-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_attr.c | 21 +++++++++++++++++++++ drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_isr.c | 1 + 3 files changed, 23 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index d6a59c92c5a8..401b5ee1f1e6 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -2323,6 +2323,26 @@ qla2x00_port_no_show(struct device *dev, struct device_attribute *attr, return scnprintf(buf, PAGE_SIZE, "%u\n", vha->hw->port_no); } +static ssize_t +qla2x00_dport_diagnostics_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + + if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) && + !IS_QLA28XX(vha->hw)) + return scnprintf(buf, PAGE_SIZE, "\n"); + + if (!*vha->dport_data) + return scnprintf(buf, PAGE_SIZE, "\n"); + + return scnprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n", + vha->dport_data[0], vha->dport_data[1], + vha->dport_data[2], vha->dport_data[3]); +} +static DEVICE_ATTR(dport_diagnostics, 0444, + qla2x00_dport_diagnostics_show, NULL); + static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_driver_version_show, NULL); static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); @@ -2431,6 +2451,7 @@ struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_port_speed, &dev_attr_port_no, &dev_attr_fw_attr, + &dev_attr_dport_diagnostics, NULL, /* reserve for qlini_mode */ NULL, /* reserve for ql2xiniexchg */ NULL, /* reserve for ql2xexchoffld */ diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index b59643883ad1..22f859bef778 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -4541,6 +4541,7 @@ typedef struct scsi_qla_host { uint8_t n2n_node_name[WWN_SIZE]; uint8_t n2n_port_name[WWN_SIZE]; uint16_t n2n_id; + __le16 dport_data[4]; struct list_head gpnid_list; struct fab_scan scan; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index e40705d38cea..73b6cfd14581 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1254,6 +1254,7 @@ global_port_update: ql_dbg(ql_dbg_async, vha, 0x5052, "D-Port Diagnostics: %04x %04x %04x %04x\n", mb[0], mb[1], mb[2], mb[3]); + memcpy(vha->dport_data, mb, sizeof(vha->dport_data)); if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { static char *results[] = { "start", "done(pass)", "done(error)", "undefined" }; From a5e7a22d73a63dbb8313b2d831bc60419435a841 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 20 Feb 2020 15:28:05 +0100 Subject: [PATCH 0635/4444] ARM: dts: exynos: Fix MMC regulator on Arndale5250 board According to the schematic, both eMMC and SDMMC use dedicated fixed regulators connected directly to the DC5V and MAIN_DC rails. Remove the GPX1-1 line assigned to the MMC regulator, because such control connection doesn't exist. Also change its name to VDD_MMC to avoid conflict with LDO18 output of S5M8767 PMIC. Signed-off-by: Marek Szyprowski Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos5250-arndale.dts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index f8ebc620f42d..bff24c61212b 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -98,11 +98,9 @@ mmc_reg: regulator@1 { compatible = "regulator-fixed"; reg = <1>; - regulator-name = "VDD_33ON_2.8V"; + regulator-name = "VDD_MMC"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; - gpio = <&gpx1 1 GPIO_ACTIVE_HIGH>; - enable-active-high; }; reg_hdmi_en: regulator@2 { From 8f274b90b87840665a751aefd798e771e8e4ef35 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 20 Feb 2020 15:28:06 +0100 Subject: [PATCH 0636/4444] ARM: dts: exynos: Make fixed regulators always-on on Arndale5250 The fixed regulators defined for Arndale5250 boards have no control lines, so mark them as 'always-on' to better describe the hardware and also kill the strange messages like 'MAIN_DC: disabling' after boot. Signed-off-by: Marek Szyprowski Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos5250-arndale.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index bff24c61212b..6904091d4837 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -93,6 +93,7 @@ compatible = "regulator-fixed"; reg = <0>; regulator-name = "MAIN_DC"; + regulator-always-on; }; mmc_reg: regulator@1 { @@ -101,12 +102,14 @@ regulator-name = "VDD_MMC"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; + regulator-always-on; }; reg_hdmi_en: regulator@2 { compatible = "regulator-fixed"; reg = <2>; regulator-name = "hdmi-en"; + regulator-always-on; }; vcc_1v2_reg: regulator@3 { @@ -115,6 +118,7 @@ regulator-name = "VCC_1V2"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; + regulator-always-on; }; vcc_1v8_reg: regulator@4 { @@ -123,6 +127,7 @@ regulator-name = "VCC_1V8"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; + regulator-always-on; }; vcc_3v3_reg: regulator@5 { @@ -131,6 +136,7 @@ regulator-name = "VCC_3V3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; + regulator-always-on; }; }; From 78856f25510369bfdc385b867303cab6a071d13d Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 19 Feb 2020 22:23:11 -0800 Subject: [PATCH 0637/4444] ppdev: Distribute switch variables for initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Variables declared in a switch statement before any case statements cannot be automatically initialized with compiler instrumentation (as they are not part of any execution flow). With GCC's proposed automatic stack variable initialization feature, this triggers a warning (and they don't get initialized). Clang's automatic stack variable initialization (via CONFIG_INIT_STACK_ALL=y) doesn't throw a warning, but it also doesn't initialize such variables[1]. Note that these warnings (or silent skipping) happen before the dead-store elimination optimization phase, so even when the automatic initializations are later elided in favor of direct initializations, the warnings remain. To avoid these problems, move such variables into the "case" where they're used or lift them up into the main function body. drivers/char/ppdev.c: In function ‘pp_do_ioctl’: drivers/char/ppdev.c:516:25: warning: statement will never be executed [-Wswitch-unreachable] 516 | struct ieee1284_info *info; | ^~~~ [1] https://bugs.llvm.org/show_bug.cgi?id=44916 Signed-off-by: Kees Cook Link: https://lore.kernel.org/r/20200220062311.69121-1-keescook@chromium.org Signed-off-by: Greg Kroah-Hartman --- drivers/char/ppdev.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 2c2381a806ae..38b46c7d1737 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -355,14 +355,19 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct pp_struct *pp = file->private_data; struct parport *port; void __user *argp = (void __user *)arg; + struct ieee1284_info *info; + unsigned char reg; + unsigned char mask; + int mode; + s32 time32[2]; + s64 time64[2]; + struct timespec64 ts; + int ret; /* First handle the cases that don't take arguments. */ switch (cmd) { case PPCLAIM: { - struct ieee1284_info *info; - int ret; - if (pp->flags & PP_CLAIMED) { dev_dbg(&pp->pdev->dev, "you've already got it!\n"); return -EINVAL; @@ -513,15 +518,6 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) port = pp->pdev->port; switch (cmd) { - struct ieee1284_info *info; - unsigned char reg; - unsigned char mask; - int mode; - s32 time32[2]; - s64 time64[2]; - struct timespec64 ts; - int ret; - case PPRSTATUS: reg = parport_read_status(port); if (copy_to_user(argp, ®, sizeof(reg))) From 78c244226613c938729dc5528738df6157a77dd1 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 19 Feb 2020 22:23:08 -0800 Subject: [PATCH 0638/4444] pcmcia: Distribute switch variables for initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Variables declared in a switch statement before any case statements cannot be automatically initialized with compiler instrumentation (as they are not part of any execution flow). With GCC's proposed automatic stack variable initialization feature, this triggers a warning (and they don't get initialized). Clang's automatic stack variable initialization (via CONFIG_INIT_STACK_ALL=y) doesn't throw a warning, but it also doesn't initialize such variables[1]. Note that these warnings (or silent skipping) happen before the dead-store elimination optimization phase, so even when the automatic initializations are later elided in favor of direct initializations, the warnings remain. To avoid these problems, move such variables into the "case" where they're used or lift them up into the main function body. drivers/char/pcmcia/cm4000_cs.c: In function ‘monitor_card’: drivers/char/pcmcia/cm4000_cs.c:734:17: warning: statement will never be executed [-Wswitch-unreachable] 734 | unsigned char flags0; | ^~~~~~ [1] https://bugs.llvm.org/show_bug.cgi?id=44916 Signed-off-by: Kees Cook Link: https://lore.kernel.org/r/20200220062308.69032-1-keescook@chromium.org Signed-off-by: Greg Kroah-Hartman --- drivers/char/pcmcia/cm4000_cs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 15bf585af5d3..4edb4174a1e2 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -731,8 +731,9 @@ static void monitor_card(struct timer_list *t) } switch (dev->mstate) { + case M_CARDOFF: { unsigned char flags0; - case M_CARDOFF: + DEBUGP(4, dev, "M_CARDOFF\n"); flags0 = inb(REG_FLAGS0(iobase)); if (flags0 & 0x02) { @@ -755,6 +756,7 @@ static void monitor_card(struct timer_list *t) dev->mdelay = T_50MSEC; } break; + } case M_FETCH_ATR: DEBUGP(4, dev, "M_FETCH_ATR\n"); xoutb(0x80, REG_FLAGS0(iobase)); From a27ad0f7da7ba3d4cf50a08ee5e2cb4b578a4a4c Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 23 Feb 2020 22:44:19 +0200 Subject: [PATCH 0639/4444] mei: remove unused includes from pci-{me,txe}.c During the development some of the module functions were factored out of pci-mei.c and pci-txe.c files, but the includes have remain there. We can remove them now. Signed-off-by: Tomas Winkler Link: https://lore.kernel.org/r/20200223204419.2634-1-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/pci-me.c | 11 +---------- drivers/misc/mei/pci-txe.c | 5 +---- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 2711451b3d87..f51e5326b8bd 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -1,25 +1,16 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2003-2019, Intel Corporation. All rights reserved. + * Copyright (c) 2003-2020, Intel Corporation. All rights reserved. * Intel Management Engine Interface (Intel MEI) Linux driver */ #include -#include #include #include -#include #include #include -#include #include -#include -#include -#include #include -#include -#include -#include #include #include diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c index f1c16a587495..beacf2a2f2b5 100644 --- a/drivers/misc/mei/pci-txe.c +++ b/drivers/misc/mei/pci-txe.c @@ -1,20 +1,17 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2013-2017, Intel Corporation. All rights reserved. + * Copyright (c) 2013-2020, Intel Corporation. All rights reserved. * Intel Management Engine Interface (Intel MEI) Linux driver */ #include #include #include -#include #include #include #include #include #include -#include -#include #include #include #include From b1ad0e7d45e205b9fd0577081de62e03b578ac9f Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Thu, 13 Feb 2020 12:06:43 +0800 Subject: [PATCH 0640/4444] arm64: dts: lx2160a: Add PCIe controller DT nodes The LX2160A integrated 6 PCIe Gen4 controllers. Signed-off-by: Hou Zhiqiang Reviewed-by: Minghuan Lian Signed-off-by: Shawn Guo --- .../arm64/boot/dts/freescale/fsl-lx2160a.dtsi | 162 ++++++++++++++++++ 1 file changed, 162 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi index e5ee5591e52b..98a8f6def55e 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi @@ -834,6 +834,168 @@ status = "disabled"; }; + pcie@3400000 { + compatible = "fsl,lx2160a-pcie"; + reg = <0x00 0x03400000 0x0 0x00100000 /* controller registers */ + 0x80 0x00000000 0x0 0x00001000>; /* configuration space */ + reg-names = "csr_axi_slave", "config_axi_slave"; + interrupts = , /* AER interrupt */ + , /* PME interrupt */ + ; /* controller interrupt */ + interrupt-names = "aer", "pme", "intr"; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + dma-coherent; + apio-wins = <8>; + ppio-wins = <8>; + bus-range = <0x0 0xff>; + ranges = <0x82000000 0x0 0x40000000 0x80 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ + msi-parent = <&its>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 2 &gic 0 0 GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 3 &gic 0 0 GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 4 &gic 0 0 GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + pcie@3500000 { + compatible = "fsl,lx2160a-pcie"; + reg = <0x00 0x03500000 0x0 0x00100000 /* controller registers */ + 0x88 0x00000000 0x0 0x00001000>; /* configuration space */ + reg-names = "csr_axi_slave", "config_axi_slave"; + interrupts = , /* AER interrupt */ + , /* PME interrupt */ + ; /* controller interrupt */ + interrupt-names = "aer", "pme", "intr"; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + dma-coherent; + apio-wins = <8>; + ppio-wins = <8>; + bus-range = <0x0 0xff>; + ranges = <0x82000000 0x0 0x40000000 0x88 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ + msi-parent = <&its>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 2 &gic 0 0 GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 3 &gic 0 0 GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 4 &gic 0 0 GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + pcie@3600000 { + compatible = "fsl,lx2160a-pcie"; + reg = <0x00 0x03600000 0x0 0x00100000 /* controller registers */ + 0x90 0x00000000 0x0 0x00001000>; /* configuration space */ + reg-names = "csr_axi_slave", "config_axi_slave"; + interrupts = , /* AER interrupt */ + , /* PME interrupt */ + ; /* controller interrupt */ + interrupt-names = "aer", "pme", "intr"; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + dma-coherent; + apio-wins = <256>; + ppio-wins = <24>; + bus-range = <0x0 0xff>; + ranges = <0x82000000 0x0 0x40000000 0x90 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ + msi-parent = <&its>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 2 &gic 0 0 GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 3 &gic 0 0 GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 4 &gic 0 0 GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + pcie@3700000 { + compatible = "fsl,lx2160a-pcie"; + reg = <0x00 0x03700000 0x0 0x00100000 /* controller registers */ + 0x98 0x00000000 0x0 0x00001000>; /* configuration space */ + reg-names = "csr_axi_slave", "config_axi_slave"; + interrupts = , /* AER interrupt */ + , /* PME interrupt */ + ; /* controller interrupt */ + interrupt-names = "aer", "pme", "intr"; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + dma-coherent; + apio-wins = <8>; + ppio-wins = <8>; + bus-range = <0x0 0xff>; + ranges = <0x82000000 0x0 0x40000000 0x98 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ + msi-parent = <&its>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 2 &gic 0 0 GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 3 &gic 0 0 GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 4 &gic 0 0 GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + pcie@3800000 { + compatible = "fsl,lx2160a-pcie"; + reg = <0x00 0x03800000 0x0 0x00100000 /* controller registers */ + 0xa0 0x00000000 0x0 0x00001000>; /* configuration space */ + reg-names = "csr_axi_slave", "config_axi_slave"; + interrupts = , /* AER interrupt */ + , /* PME interrupt */ + ; /* controller interrupt */ + interrupt-names = "aer", "pme", "intr"; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + dma-coherent; + apio-wins = <256>; + ppio-wins = <24>; + bus-range = <0x0 0xff>; + ranges = <0x82000000 0x0 0x40000000 0xa0 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ + msi-parent = <&its>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 2 &gic 0 0 GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 3 &gic 0 0 GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 4 &gic 0 0 GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + pcie@3900000 { + compatible = "fsl,lx2160a-pcie"; + reg = <0x00 0x03900000 0x0 0x00100000 /* controller registers */ + 0xa8 0x00000000 0x0 0x00001000>; /* configuration space */ + reg-names = "csr_axi_slave", "config_axi_slave"; + interrupts = , /* AER interrupt */ + , /* PME interrupt */ + ; /* controller interrupt */ + interrupt-names = "aer", "pme", "intr"; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + dma-coherent; + apio-wins = <8>; + ppio-wins = <8>; + bus-range = <0x0 0xff>; + ranges = <0x82000000 0x0 0x40000000 0xa8 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ + msi-parent = <&its>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 2 &gic 0 0 GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 3 &gic 0 0 GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 4 &gic 0 0 GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + smmu: iommu@5000000 { compatible = "arm,mmu-500"; reg = <0 0x5000000 0 0x800000>; From 6d4ff02cf9690b9493153db8b9d50cef143f3bc2 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Thu, 13 Feb 2020 12:06:44 +0800 Subject: [PATCH 0641/4444] arm64: defconfig: Enable CONFIG_PCIE_LAYERSCAPE_GEN4 Enable the PCIe Gen4 controller driver for Layerscape SoCs. Signed-off-by: Hou Zhiqiang Reviewed-by: Minghuan Lian Signed-off-by: Shawn Guo --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 1c744379c9c7..256345fef287 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -195,6 +195,7 @@ CONFIG_PCI_HOST_THUNDER_ECAM=y CONFIG_PCIE_ROCKCHIP_HOST=m CONFIG_PCIE_BRCMSTB=m CONFIG_PCI_LAYERSCAPE=y +CONFIG_PCIE_LAYERSCAPE_GEN4=y CONFIG_PCI_HISI=y CONFIG_PCIE_QCOM=y CONFIG_PCIE_ARMADA_8K=y From 3da63fceab9634407637bc59f570061743f83056 Mon Sep 17 00:00:00 2001 From: Alifer Moraes Date: Fri, 14 Feb 2020 16:27:49 -0300 Subject: [PATCH 0642/4444] arm64: dts: imx8mm-evk: add phy-reset-gpios for fec1 imx8mm-evk has a GPIO connected to AR8031 Ethernet PHY's reset pin. Describe it in the device tree, following phy's datasheet reset duration of 10ms. Tested booting via NFS. Signed-off-by: Alifer Moraes Reviewed-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mm-evk.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk.dts index 9e54747cf4e6..951e14a3de0e 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-evk.dts @@ -107,6 +107,8 @@ pinctrl-0 = <&pinctrl_fec1>; phy-mode = "rgmii-id"; phy-handle = <ðphy0>; + phy-reset-gpios = <&gpio4 22 GPIO_ACTIVE_LOW>; + phy-reset-duration = <10>; fsl,magic-packet; status = "okay"; From 2462aaf13c790312c97dd8af9953cd10968ca4c9 Mon Sep 17 00:00:00 2001 From: Alifer Moraes Date: Fri, 14 Feb 2020 16:27:50 -0300 Subject: [PATCH 0643/4444] arm64: dts: imx8mq-evk: add phy-reset-gpios for fec1 imx8mq-evk has a GPIO connected to AR8031 Ethernet PHY's reset pin. Describe it in the device tree, following phy's datasheet reset duration of 10ms. Tested booting via NFS. Signed-off-by: Alifer Moraes Reviewed-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mq-evk.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts index 94066d49d6ed..c9241abf0df3 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts @@ -137,6 +137,8 @@ pinctrl-0 = <&pinctrl_fec1>; phy-mode = "rgmii-id"; phy-handle = <ðphy0>; + phy-reset-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; + phy-reset-duration = <10>; fsl,magic-packet; status = "okay"; From 50d336b12f345808b2e1f47a08443d3fff93c002 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 18 Feb 2020 13:14:59 +0800 Subject: [PATCH 0644/4444] arm64: dts: imx8mp-evk: Add GPIO LED support i.MX8MP EVK board has a GPIO LED to indicate status, add support for it. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts index 6df3beb92dc8..a97a03c81517 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts @@ -15,6 +15,18 @@ stdout-path = &uart2; }; + gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_led>; + + status { + label = "yellow:status"; + gpios = <&gpio3 16 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + }; + memory@40000000 { device_type = "memory"; reg = <0x0 0x40000000 0 0xc0000000>, @@ -120,6 +132,12 @@ >; }; + pinctrl_gpio_led: gpioledgrp { + fsl,pins = < + MX8MP_IOMUXC_NAND_READY_B__GPIO3_IO16 0x19 + >; + }; + pinctrl_reg_usdhc2_vmmc: regusdhc2vmmc { fsl,pins = < MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19 0x41 From c267bd443f38972ab4ad29976f15f5eee9ed6f45 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 19 Feb 2020 14:04:09 +0800 Subject: [PATCH 0645/4444] clk: imx8mp: Rename the IMX8MP_CLK_HDMI_27M clock On i.MX8MP, internal HDMI 27M clock is actually 24MHz, so rename the IMX8MP_CLK_HDMI_27M to IMX8MP_CLK_HDMI_24M. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mp.c | 4 ++-- include/dt-bindings/clock/imx8mp-clock.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index 3adc8aa46200..a6313cf4a30c 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -342,7 +342,7 @@ static const char * const imx8mp_hdmi_fdcc_tst_sels[] = {"osc_24m", "sys_pll1_26 "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll1_out", }; -static const char * const imx8mp_hdmi_27m_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", +static const char * const imx8mp_hdmi_24m_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out", "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", }; @@ -632,7 +632,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) hws[IMX8MP_CLK_IPP_DO_CLKO1] = imx8m_clk_hw_composite("ipp_do_clko1", imx8mp_ipp_do_clko1_sels, ccm_base + 0xba00); hws[IMX8MP_CLK_IPP_DO_CLKO2] = imx8m_clk_hw_composite("ipp_do_clko2", imx8mp_ipp_do_clko2_sels, ccm_base + 0xba80); hws[IMX8MP_CLK_HDMI_FDCC_TST] = imx8m_clk_hw_composite("hdmi_fdcc_tst", imx8mp_hdmi_fdcc_tst_sels, ccm_base + 0xbb00); - hws[IMX8MP_CLK_HDMI_27M] = imx8m_clk_hw_composite("hdmi_27m", imx8mp_hdmi_27m_sels, ccm_base + 0xbb80); + hws[IMX8MP_CLK_HDMI_24M] = imx8m_clk_hw_composite("hdmi_24m", imx8mp_hdmi_24m_sels, ccm_base + 0xbb80); hws[IMX8MP_CLK_HDMI_REF_266M] = imx8m_clk_hw_composite("hdmi_ref_266m", imx8mp_hdmi_ref_266m_sels, ccm_base + 0xbc00); hws[IMX8MP_CLK_USDHC3] = imx8m_clk_hw_composite("usdhc3", imx8mp_usdhc3_sels, ccm_base + 0xbc80); hws[IMX8MP_CLK_MEDIA_CAM1_PIX] = imx8m_clk_hw_composite("media_cam1_pix", imx8mp_media_cam1_pix_sels, ccm_base + 0xbd00); diff --git a/include/dt-bindings/clock/imx8mp-clock.h b/include/dt-bindings/clock/imx8mp-clock.h index 2fab63186bca..00d4d2288990 100644 --- a/include/dt-bindings/clock/imx8mp-clock.h +++ b/include/dt-bindings/clock/imx8mp-clock.h @@ -173,7 +173,7 @@ #define IMX8MP_CLK_IPP_DO_CLKO1 164 #define IMX8MP_CLK_IPP_DO_CLKO2 165 #define IMX8MP_CLK_HDMI_FDCC_TST 166 -#define IMX8MP_CLK_HDMI_27M 167 +#define IMX8MP_CLK_HDMI_24M 167 #define IMX8MP_CLK_HDMI_REF_266M 168 #define IMX8MP_CLK_USDHC3 169 #define IMX8MP_CLK_MEDIA_CAM1_PIX 170 From 8083d7261a4c0094499251c18f0fcc06a72ec266 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Wed, 19 Feb 2020 13:00:50 +0000 Subject: [PATCH 0646/4444] ARM: dts: imx7-colibri: Convert to SPDX license tags for Colibri iMX7 Replace boiler plate licenses texts with the SPDX license identifiers in Colibri iMX7 DTS files. Signed-off-by: Oleksandr Suvorov Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi | 40 ++------------------- arch/arm/boot/dts/imx7-colibri.dtsi | 40 ++------------------- arch/arm/boot/dts/imx7d-colibri-eval-v3.dts | 40 ++------------------- arch/arm/boot/dts/imx7s-colibri-eval-v3.dts | 40 ++------------------- 4 files changed, 8 insertions(+), 152 deletions(-) diff --git a/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi b/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi index 9e9e85c10acb..20a82b1c2690 100644 --- a/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi +++ b/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi @@ -1,43 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) /* - * Copyright 2016 Toradex AG + * Copyright 2016-2020 Toradex AG * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. */ / { diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsi index ad7536da4313..e078487a1347 100644 --- a/arch/arm/boot/dts/imx7-colibri.dtsi +++ b/arch/arm/boot/dts/imx7-colibri.dtsi @@ -1,43 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) /* - * Copyright 2016 Toradex AG + * Copyright 2016-20 Toradex AG * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. */ / { diff --git a/arch/arm/boot/dts/imx7d-colibri-eval-v3.dts b/arch/arm/boot/dts/imx7d-colibri-eval-v3.dts index 136e11ab4893..699b9dda2fb0 100644 --- a/arch/arm/boot/dts/imx7d-colibri-eval-v3.dts +++ b/arch/arm/boot/dts/imx7d-colibri-eval-v3.dts @@ -1,43 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) /* - * Copyright 2016 Toradex AG + * Copyright 2016-2020 Toradex AG * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; diff --git a/arch/arm/boot/dts/imx7s-colibri-eval-v3.dts b/arch/arm/boot/dts/imx7s-colibri-eval-v3.dts index bd2a49c1ade6..ab139266ce23 100644 --- a/arch/arm/boot/dts/imx7s-colibri-eval-v3.dts +++ b/arch/arm/boot/dts/imx7s-colibri-eval-v3.dts @@ -1,43 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) /* - * Copyright 2016 Toradex AG + * Copyright 2016-2020 Toradex AG * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; From 1608bf1f9120176942b3a927e2260684767c6ecb Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Wed, 19 Feb 2020 13:00:54 +0000 Subject: [PATCH 0647/4444] ARM: dts: imx7-colibri: add support for Toradex Aster carrier board Add support for the Toradex Aster carrier board. Follow the usual hierarchic include model, maintaining shared configuration imx7-colibri-aster.dtsi. Signed-off-by: Oleksandr Suvorov Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 3 + arch/arm/boot/dts/imx7-colibri-aster.dtsi | 169 ++++++++++++++++++ arch/arm/boot/dts/imx7-colibri.dtsi | 2 - arch/arm/boot/dts/imx7d-colibri-aster.dts | 20 +++ .../arm/boot/dts/imx7d-colibri-emmc-aster.dts | 20 +++ arch/arm/boot/dts/imx7s-colibri-aster.dts | 15 ++ 6 files changed, 227 insertions(+), 2 deletions(-) create mode 100644 arch/arm/boot/dts/imx7-colibri-aster.dtsi create mode 100644 arch/arm/boot/dts/imx7d-colibri-aster.dts create mode 100644 arch/arm/boot/dts/imx7d-colibri-emmc-aster.dts create mode 100644 arch/arm/boot/dts/imx7s-colibri-aster.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index d6546d2676b9..e874fbf5a1f3 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -610,6 +610,8 @@ dtb-$(CONFIG_SOC_IMX6UL) += \ imx6ulz-14x14-evk.dtb dtb-$(CONFIG_SOC_IMX7D) += \ imx7d-cl-som-imx7.dtb \ + imx7d-colibri-aster.dtb \ + imx7d-colibri-emmc-aster.dtb \ imx7d-colibri-emmc-eval-v3.dtb \ imx7d-colibri-eval-v3.dtb \ imx7d-mba7.dtb \ @@ -623,6 +625,7 @@ dtb-$(CONFIG_SOC_IMX7D) += \ imx7d-sdb-sht11.dtb \ imx7d-zii-rmu2.dtb \ imx7d-zii-rpu2.dtb \ + imx7s-colibri-aster.dtb \ imx7s-colibri-eval-v3.dtb \ imx7s-mba7.dtb \ imx7s-warp.dtb diff --git a/arch/arm/boot/dts/imx7-colibri-aster.dtsi b/arch/arm/boot/dts/imx7-colibri-aster.dtsi new file mode 100644 index 000000000000..9fa701bec2ec --- /dev/null +++ b/arch/arm/boot/dts/imx7-colibri-aster.dtsi @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright 2017-2020 Toradex AG + * + */ + + +#include +#include + +/ { + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpiokeys>; + + power { + label = "Wake-Up"; + gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; + linux,code = ; + debounce-interval = <10>; + wakeup-source; + }; + }; + + panel: panel { + compatible = "edt,et057090dhu"; + backlight = <&bl>; + power-supply = <®_3v3>; + + port { + panel_in: endpoint { + remote-endpoint = <&lcdif_out>; + }; + }; + }; + + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + reg_5v0: regulator-5v0 { + compatible = "regulator-fixed"; + regulator-name = "5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + reg_usbh_vbus: regulator-usbh-vbus { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbh_reg>; + regulator-name = "VCC_USB[1-4]"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio4 7 GPIO_ACTIVE_LOW>; + vin-supply = <®_5v0>; + }; +}; + +&adc1 { + status = "okay"; +}; + +/* + * ADC2 is not available on the Aster board and + * conflicts with AD7879 resistive touchscreen. + */ +&adc2 { + status = "disabled"; +}; + +&bl { + brightness-levels = <0 4 8 16 32 64 128 255>; + default-brightness-level = <6>; + power-supply = <®_3v3>; + status = "okay"; +}; + +&fec1 { + status = "okay"; +}; + +&i2c4 { + status = "okay"; + + /* Microchip/Atmel maxtouch controller */ + touchscreen@4a { + compatible = "atmel,maxtouch"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpiotouch>; + reg = <0x4a>; + interrupt-parent = <&gpio2>; + interrupts = <15 IRQ_TYPE_EDGE_FALLING>; /* SODIMM 107 */ + reset-gpios = <&gpio2 28 GPIO_ACTIVE_HIGH>; /* SODIMM 106 */ + }; + + /* M41T0M6 real time clock on carrier board */ + rtc: m41t0m6@68 { + compatible = "st,m41t0"; + reg = <0x68>; + }; +}; + +&iomuxc { + pinctrl_gpiotouch: touchgpios { + fsl,pins = < + MX7D_PAD_EPDC_DATA15__GPIO2_IO15 0x74 + MX7D_PAD_EPDC_BDR0__GPIO2_IO28 0x14 + >; + }; +}; + +&lcdif { + status = "okay"; + + port { + lcdif_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; +}; + +&pwm1 { + status = "okay"; +}; + +&pwm2 { + status = "okay"; +}; + +&pwm3 { + status = "okay"; +}; + +&pwm4 { + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&uart3 { + status = "okay"; +}; + +&usbotg1 { + status = "okay"; +}; + +&usdhc1 { + keep-power-in-suspend; + no-1-8-v; + wakeup-source; + vmmc-supply = <®_3v3>; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsi index e078487a1347..973fe5715e96 100644 --- a/arch/arm/boot/dts/imx7-colibri.dtsi +++ b/arch/arm/boot/dts/imx7-colibri.dtsi @@ -499,7 +499,6 @@ MX7D_PAD_EPDC_DATA13__GPIO2_IO13 0x14 /* SODIMM 95 */ MX7D_PAD_ENET1_RGMII_TXC__GPIO7_IO11 0x14 /* SODIMM 99 */ MX7D_PAD_EPDC_DATA10__GPIO2_IO10 0x74 /* SODIMM 105 */ - MX7D_PAD_EPDC_DATA15__GPIO2_IO15 0x74 /* SODIMM 107 */ MX7D_PAD_EPDC_DATA00__GPIO2_IO0 0x14 /* SODIMM 111 */ MX7D_PAD_EPDC_DATA01__GPIO2_IO1 0x14 /* SODIMM 113 */ MX7D_PAD_EPDC_DATA02__GPIO2_IO2 0x14 /* SODIMM 115 */ @@ -516,7 +515,6 @@ MX7D_PAD_SD2_DATA2__GPIO5_IO16 0x14 /* SODIMM 100 */ MX7D_PAD_SD2_DATA3__GPIO5_IO17 0x14 /* SODIMM 102 */ MX7D_PAD_EPDC_GDSP__GPIO2_IO27 0x14 /* SODIMM 104 */ - MX7D_PAD_EPDC_BDR0__GPIO2_IO28 0x74 /* SODIMM 106 */ MX7D_PAD_EPDC_BDR1__GPIO2_IO29 0x14 /* SODIMM 110 */ MX7D_PAD_EPDC_PWR_COM__GPIO2_IO30 0x14 /* SODIMM 112 */ MX7D_PAD_EPDC_SDCLK__GPIO2_IO16 0x14 /* SODIMM 114 */ diff --git a/arch/arm/boot/dts/imx7d-colibri-aster.dts b/arch/arm/boot/dts/imx7d-colibri-aster.dts new file mode 100644 index 000000000000..f3f0537d5a37 --- /dev/null +++ b/arch/arm/boot/dts/imx7d-colibri-aster.dts @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright 2017-2020 Toradex AG + * + */ + +/dts-v1/; +#include "imx7d-colibri.dtsi" +#include "imx7-colibri-aster.dtsi" + +/ { + model = "Toradex Colibri iMX7D on Aster Carrier Board"; + compatible = "toradex,colibri-imx7d-aster", "toradex,colibri-imx7d", + "fsl,imx7d"; +}; + +&usbotg2 { + vbus-supply = <®_usbh_vbus>; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/imx7d-colibri-emmc-aster.dts b/arch/arm/boot/dts/imx7d-colibri-emmc-aster.dts new file mode 100644 index 000000000000..20480276cb0e --- /dev/null +++ b/arch/arm/boot/dts/imx7d-colibri-emmc-aster.dts @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright 2017-2020 Toradex AG + * + */ + +/dts-v1/; +#include "imx7d-colibri-emmc.dtsi" +#include "imx7-colibri-aster.dtsi" + +/ { + model = "Toradex Colibri iMX7D 1GB (eMMC) on Aster Carrier Board"; + compatible = "toradex,colibri-imx7d-emmc-aster", + "toradex,colibri-imx7d-emmc", "fsl,imx7d"; +}; + +&usbotg2 { + vbus-supply = <®_usbh_vbus>; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/imx7s-colibri-aster.dts b/arch/arm/boot/dts/imx7s-colibri-aster.dts new file mode 100644 index 000000000000..fca4e0a95c1b --- /dev/null +++ b/arch/arm/boot/dts/imx7s-colibri-aster.dts @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright 2017-2020 Toradex AG + * + */ + +/dts-v1/; +#include "imx7s-colibri.dtsi" +#include "imx7-colibri-aster.dtsi" + +/ { + model = "Toradex Colibri iMX7S on Aster Carrier Board"; + compatible = "toradex,colibri-imx7s-aster", "toradex,colibri-imx7s", + "fsl,imx7s"; +}; From 795d392e4abe685a38d367f7fe64ef3a46fb15ac Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Wed, 19 Feb 2020 13:00:52 +0000 Subject: [PATCH 0648/4444] dt-bindings: arm: fsl: add nxp based toradex colibri-imx7 bindings Document the NXP SoC based Toradex Colibri iMX7S/D module and the Aster carrier board devicetree bindings. Signed-off-by: Oleksandr Suvorov Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index e654a6376bc4..239ac2c31f49 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -274,6 +274,7 @@ properties: items: - enum: - toradex,colibri-imx7s # Colibri iMX7 Solo Module + - toradex,colibri-imx7s-aster # Colibri iMX7 Solo Module on Aster Carrier Board - toradex,colibri-imx7s-eval-v3 # Colibri iMX7 Solo Module on Colibri Evaluation Board V3 - tq,imx7s-mba7 # i.MX7S TQ MBa7 with TQMa7S SoM - const: fsl,imx7s @@ -285,7 +286,9 @@ properties: - fsl,imx7d-sdb-reva # i.MX7 SabreSD Rev-A Board - novtech,imx7d-meerkat96 # i.MX7 Meerkat96 Board - toradex,colibri-imx7d # Colibri iMX7 Dual Module + - toradex,colibri-imx7d-aster # Colibri iMX7 Dual Module on Aster Carrier Board - toradex,colibri-imx7d-emmc # Colibri iMX7 Dual 1GB (eMMC) Module + - toradex,colibri-imx7d-emmc-aster # Colibri iMX7 Dual 1GB (eMMC) Module on Aster Carrier Board - toradex,colibri-imx7d-emmc-eval-v3 # Colibri iMX7 Dual 1GB (eMMC) Module on Colibri Evaluation Board V3 - toradex,colibri-imx7d-eval-v3 # Colibri iMX7 Dual Module on Colibri Evaluation Board V3 - tq,imx7d-mba7 # i.MX7D TQ MBa7 with TQMa7D SoM From fae58b1aab717d704b7199802470c1e681d4b3a6 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Thu, 20 Feb 2020 12:50:32 +0800 Subject: [PATCH 0649/4444] arm64: dts: imx8mp: Add system counter timer node System counter timer is necessary as broadcast timer for cpu-idle, add support for it. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mp.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi index 61cf373ad268..71b0c8f23693 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi @@ -358,6 +358,14 @@ #pwm-cells = <2>; status = "disabled"; }; + + system_counter: timer@306a0000 { + compatible = "nxp,sysctr-timer"; + reg = <0x306a0000 0x20000>; + interrupts = ; + clocks = <&osc_24m>; + clock-names = "per"; + }; }; aips3: bus@30800000 { From 4f929d0877543df8a834afa5b8732d469c05cd84 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Thu, 20 Feb 2020 17:56:49 +0200 Subject: [PATCH 0650/4444] firmware: imx: Remove IMX_SC_RPC_SVC_ABORT This is not used by linux and not supported as part of imx SCU api, it was added by mistake. The constant value "9" has since been reassigned in firmware to a different service. Signed-off-by: Leonard Crestez Signed-off-by: Shawn Guo --- include/linux/firmware/imx/ipc.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/firmware/imx/ipc.h b/include/linux/firmware/imx/ipc.h index 6312c8cb084a..891057434858 100644 --- a/include/linux/firmware/imx/ipc.h +++ b/include/linux/firmware/imx/ipc.h @@ -25,7 +25,6 @@ enum imx_sc_rpc_svc { IMX_SC_RPC_SVC_PAD = 6, IMX_SC_RPC_SVC_MISC = 7, IMX_SC_RPC_SVC_IRQ = 8, - IMX_SC_RPC_SVC_ABORT = 9 }; struct imx_sc_rpc_msg { From d6fb02f054127c23b048f4753176c57f3e440e79 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Feb 2020 18:17:06 +0800 Subject: [PATCH 0651/4444] clk: imx: imx8mq: fix a53 cpu clock The A53 CCM clk root only accepts input up to 1GHz, CCM A53 root signoff timing is 1Ghz, however the A53 core which sources from CCM root could run above 1GHz which violates the CCM. There is a CORE_SEL slice before A53 core, we need to configure the CORE_SEL slice source from ARM PLL, not A53 CCM clk root. The A53 CCM clk root should only be used when need to change ARM PLL frequency. Add arm_a53_core clk that could source from arm_a53_div and arm_pll_out. Configure a53 ccm root sources from 800MHz sys pll Configure a53 core sources from arm_pll_out Mark arm_a53_core as critical clock Fixes: db27e40b27f1 ("clk: imx8mq: Add the missing ARM clock") Reviewed-by: Jacky Bai Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mq.c | 16 ++++++++++++---- include/dt-bindings/clock/imx8mq-clock.h | 4 +++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c index 1f5ea1eaad65..b81f02ab7eb1 100644 --- a/drivers/clk/imx/clk-imx8mq.c +++ b/drivers/clk/imx/clk-imx8mq.c @@ -41,6 +41,8 @@ static const char * const video2_pll_out_sels[] = {"video2_pll1_ref_sel", }; static const char * const imx8mq_a53_sels[] = {"osc_25m", "arm_pll_out", "sys2_pll_500m", "sys2_pll_1000m", "sys1_pll_800m", "sys1_pll_400m", "audio_pll1_out", "sys3_pll_out", }; +static const char * const imx8mq_a53_core_sels[] = {"arm_a53_div", "arm_pll_out", }; + static const char * const imx8mq_arm_m4_sels[] = {"osc_25m", "sys2_pll_200m", "sys2_pll_250m", "sys1_pll_266m", "sys1_pll_800m", "audio_pll1_out", "video_pll1_out", "sys3_pll_out", }; @@ -425,6 +427,9 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) hws[IMX8MQ_CLK_GPU_SHADER_CG] = hws[IMX8MQ_CLK_GPU_SHADER]; hws[IMX8MQ_CLK_GPU_SHADER_DIV] = hws[IMX8MQ_CLK_GPU_SHADER]; + /* CORE SEL */ + hws[IMX8MQ_CLK_A53_CORE] = imx_clk_hw_mux2_flags("arm_a53_core", base + 0x9880, 24, 1, imx8mq_a53_core_sels, ARRAY_SIZE(imx8mq_a53_core_sels), CLK_IS_CRITICAL); + /* BUS */ hws[IMX8MQ_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mq_main_axi_sels, base + 0x8800); hws[IMX8MQ_CLK_ENET_AXI] = imx8m_clk_hw_composite("enet_axi", imx8mq_enet_axi_sels, base + 0x8880); @@ -588,11 +593,14 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) hws[IMX8MQ_GPT_3M_CLK] = imx_clk_hw_fixed_factor("gpt_3m", "osc_25m", 1, 8); hws[IMX8MQ_CLK_DRAM_ALT_ROOT] = imx_clk_hw_fixed_factor("dram_alt_root", "dram_alt", 1, 4); - hws[IMX8MQ_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_div", - hws[IMX8MQ_CLK_A53_DIV]->clk, - hws[IMX8MQ_CLK_A53_SRC]->clk, + clk_hw_set_parent(hws[IMX8MQ_CLK_A53_SRC], hws[IMX8MQ_SYS1_PLL_800M]); + clk_hw_set_parent(hws[IMX8MQ_CLK_A53_CORE], hws[IMX8MQ_ARM_PLL_OUT]); + + hws[IMX8MQ_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_core", + hws[IMX8MQ_CLK_A53_CORE]->clk, + hws[IMX8MQ_CLK_A53_CORE]->clk, hws[IMX8MQ_ARM_PLL_OUT]->clk, - hws[IMX8MQ_SYS1_PLL_800M]->clk); + hws[IMX8MQ_CLK_A53_DIV]->clk); imx_check_clk_hws(hws, IMX8MQ_CLK_END); diff --git a/include/dt-bindings/clock/imx8mq-clock.h b/include/dt-bindings/clock/imx8mq-clock.h index 2b88723310bd..9b8045d75b8b 100644 --- a/include/dt-bindings/clock/imx8mq-clock.h +++ b/include/dt-bindings/clock/imx8mq-clock.h @@ -429,6 +429,8 @@ #define IMX8MQ_CLK_M4_CORE 287 #define IMX8MQ_CLK_VPU_CORE 288 -#define IMX8MQ_CLK_END 289 +#define IMX8MQ_CLK_A53_CORE 289 + +#define IMX8MQ_CLK_END 290 #endif /* __DT_BINDINGS_CLOCK_IMX8MQ_H */ From d3b70cd87e773bb298eb78fbafed68afaf06b1a2 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Feb 2020 18:17:07 +0800 Subject: [PATCH 0652/4444] clk: imx: imx8mm: fix a53 cpu clock The A53 CCM clk root only accepts input up to 1GHz, CCM A53 root signoff timing is 1Ghz, however the A53 core which sources from CCM root could run above 1GHz which voilates the CCM. There is a CORE_SEL slice before A53 core, we need configure the CORE_SEL slice source from ARM PLL, not A53 CCM clk root. The A53 CCM clk root should only be used when need to change ARM PLL frequency. Add arm_a53_core clk that could source from arm_a53_div and arm_pll_out. Configure a53 ccm root sources from 800MHz sys pll Configure a53 core sources from arm_pll_out Mark arm_a53_core as critical clock Fixes: ba5625c3e272 ("clk: imx: Add clock driver support for imx8mm") Reviewed-by: Jacky Bai Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mm.c | 16 ++++++++++++---- include/dt-bindings/clock/imx8mm-clock.h | 4 +++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c index 481d20ae4e0b..9feda4f5b3d6 100644 --- a/drivers/clk/imx/clk-imx8mm.c +++ b/drivers/clk/imx/clk-imx8mm.c @@ -39,6 +39,8 @@ static const char *sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", }; static const char *imx8mm_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pll2_500m", "sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m", "audio_pll1_out", "sys_pll3_out", }; +static const char * const imx8mm_a53_core_sels[] = {"arm_a53_div", "arm_pll_out", }; + static const char *imx8mm_m4_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_250m", "sys_pll1_266m", "sys_pll1_800m", "audio_pll1_out", "video_pll1_out", "sys_pll3_out", }; @@ -437,6 +439,9 @@ static int imx8mm_clocks_probe(struct platform_device *pdev) hws[IMX8MM_CLK_GPU2D_CG] = hws[IMX8MM_CLK_GPU2D_CORE]; hws[IMX8MM_CLK_GPU2D_DIV] = hws[IMX8MM_CLK_GPU2D_CORE]; + /* CORE SEL */ + hws[IMX8MM_CLK_A53_CORE] = imx_clk_hw_mux2_flags("arm_a53_core", base + 0x9880, 24, 1, imx8mm_a53_core_sels, ARRAY_SIZE(imx8mm_a53_core_sels), CLK_IS_CRITICAL); + /* BUS */ hws[IMX8MM_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mm_main_axi_sels, base + 0x8800); hws[IMX8MM_CLK_ENET_AXI] = imx8m_clk_hw_composite("enet_axi", imx8mm_enet_axi_sels, base + 0x8880); @@ -603,11 +608,14 @@ static int imx8mm_clocks_probe(struct platform_device *pdev) hws[IMX8MM_CLK_DRAM_ALT_ROOT] = imx_clk_hw_fixed_factor("dram_alt_root", "dram_alt", 1, 4); hws[IMX8MM_CLK_DRAM_CORE] = imx_clk_hw_mux2_flags("dram_core_clk", base + 0x9800, 24, 1, imx8mm_dram_core_sels, ARRAY_SIZE(imx8mm_dram_core_sels), CLK_IS_CRITICAL); - hws[IMX8MM_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_div", - hws[IMX8MM_CLK_A53_DIV]->clk, - hws[IMX8MM_CLK_A53_SRC]->clk, + clk_hw_set_parent(hws[IMX8MM_CLK_A53_SRC], hws[IMX8MM_SYS_PLL1_800M]); + clk_hw_set_parent(hws[IMX8MM_CLK_A53_CORE], hws[IMX8MM_ARM_PLL_OUT]); + + hws[IMX8MM_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_core", + hws[IMX8MM_CLK_A53_CORE]->clk, + hws[IMX8MM_CLK_A53_CORE]->clk, hws[IMX8MM_ARM_PLL_OUT]->clk, - hws[IMX8MM_SYS_PLL1_800M]->clk); + hws[IMX8MM_CLK_A53_DIV]->clk); imx_check_clk_hws(hws, IMX8MM_CLK_END); diff --git a/include/dt-bindings/clock/imx8mm-clock.h b/include/dt-bindings/clock/imx8mm-clock.h index dbfee6579d6c..e63a5530aed7 100644 --- a/include/dt-bindings/clock/imx8mm-clock.h +++ b/include/dt-bindings/clock/imx8mm-clock.h @@ -272,6 +272,8 @@ #define IMX8MM_CLK_CLKO2 250 -#define IMX8MM_CLK_END 251 +#define IMX8MM_CLK_A53_CORE 251 + +#define IMX8MM_CLK_END 252 #endif From c69def88987995f5d3ea28f12febd1b2c567f511 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Feb 2020 18:17:08 +0800 Subject: [PATCH 0653/4444] clk: imx: imx8mn: fix a53 cpu clock The A53 CCM clk root only accepts input up to 1GHz, CCM A53 root signoff timing is 1Ghz, however the A53 core which sources from CCM root could run above 1GHz which voilates the CCM. There is a CORE_SEL slice before A53 core, we need configure the CORE_SEL slice source from ARM PLL, not A53 CCM clk root. The A53 CCM clk root should only be used when need to change ARM PLL frequency. Add arm_a53_core clk that could source from arm_a53_div and arm_pll_out. Configure a53 ccm root sources from 800MHz sys pll Configure a53 core sources from arm_pll_out Mark arm_a53_core as critical clk. Fixes: 96d6392b54db ("clk: imx: Add support for i.MX8MN clock driver") Reviewed-by: Jacky Bai Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mn.c | 16 ++++++++++++---- include/dt-bindings/clock/imx8mn-clock.h | 4 +++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c index fb47f86e35e8..83618affca8b 100644 --- a/drivers/clk/imx/clk-imx8mn.c +++ b/drivers/clk/imx/clk-imx8mn.c @@ -38,6 +38,8 @@ static const char * const imx8mn_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pl "sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m", "audio_pll1_out", "sys_pll3_out", }; +static const char * const imx8mn_a53_core_sels[] = {"arm_a53_div", "arm_pll_out", }; + static const char * const imx8mn_gpu_core_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m", "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out", "video_pll1_out", "audio_pll2_out", }; @@ -425,6 +427,9 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) hws[IMX8MN_CLK_GPU_SHADER_CG] = hws[IMX8MN_CLK_GPU_SHADER]; hws[IMX8MN_CLK_GPU_SHADER_DIV] = hws[IMX8MN_CLK_GPU_SHADER]; + /* CORE SEL */ + hws[IMX8MN_CLK_A53_CORE] = imx_clk_hw_mux2_flags("arm_a53_core", base + 0x9880, 24, 1, imx8mn_a53_core_sels, ARRAY_SIZE(imx8mn_a53_core_sels), CLK_IS_CRITICAL); + /* BUS */ hws[IMX8MN_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mn_main_axi_sels, base + 0x8800); hws[IMX8MN_CLK_ENET_AXI] = imx8m_clk_hw_composite("enet_axi", imx8mn_enet_axi_sels, base + 0x8880); @@ -554,11 +559,14 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) hws[IMX8MN_CLK_DRAM_ALT_ROOT] = imx_clk_hw_fixed_factor("dram_alt_root", "dram_alt", 1, 4); - hws[IMX8MN_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_div", - hws[IMX8MN_CLK_A53_DIV]->clk, - hws[IMX8MN_CLK_A53_SRC]->clk, + clk_hw_set_parent(hws[IMX8MN_CLK_A53_SRC], hws[IMX8MN_SYS_PLL1_800M]); + clk_hw_set_parent(hws[IMX8MN_CLK_A53_CORE], hws[IMX8MN_ARM_PLL_OUT]); + + hws[IMX8MN_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_core", + hws[IMX8MN_CLK_A53_CORE]->clk, + hws[IMX8MN_CLK_A53_CORE]->clk, hws[IMX8MN_ARM_PLL_OUT]->clk, - hws[IMX8MN_SYS_PLL1_800M]->clk); + hws[IMX8MN_CLK_A53_DIV]->clk); imx_check_clk_hws(hws, IMX8MN_CLK_END); diff --git a/include/dt-bindings/clock/imx8mn-clock.h b/include/dt-bindings/clock/imx8mn-clock.h index c42a22d3cf7c..6c4364c01c50 100644 --- a/include/dt-bindings/clock/imx8mn-clock.h +++ b/include/dt-bindings/clock/imx8mn-clock.h @@ -232,6 +232,8 @@ #define IMX8MN_CLK_GPU_CORE 212 #define IMX8MN_CLK_GPU_SHADER 213 -#define IMX8MN_CLK_END 214 +#define IMX8MN_CLK_A53_CORE 214 + +#define IMX8MN_CLK_END 215 #endif From 7ab227210110a4137b005b7be3df1ec2d668ac96 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Feb 2020 18:17:09 +0800 Subject: [PATCH 0654/4444] clk: imx: imx8mp: fix a53 cpu clock The A53 CCM clk root only accepts input up to 1GHz, CCM A53 root signoff timing is 1Ghz, however the A53 core which sources from CCM root could run above 1GHz which voilates the CCM. There is a CORE_SEL slice before A53 core, we need configure the CORE_SEL slice source from ARM PLL, not A53 CCM clk root. The A53 CCM clk root should only be used when need to change ARM PLL frequency. Add arm_a53_core clk that could source from arm_a53_div and arm_pll_out. Configure a53 ccm root sources from 800MHz sys pll Configure a53 core sources from arm_pll_out Mark arm_a53_core as critical clk Reviewed-by: Jacky Bai Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mp.c | 16 ++++++++++++---- include/dt-bindings/clock/imx8mp-clock.h | 3 ++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index a6313cf4a30c..c6161a4af201 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -34,6 +34,8 @@ static const char * const imx8mp_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pl "sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m", "audio_pll1_out", "sys_pll3_out", }; +static const char * const imx8mp_a53_core_sels[] = {"arm_a53_div", "arm_pll_out", }; + static const char * const imx8mp_m7_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_250m", "vpu_pll_out", "sys_pll1_800m", "audio_pll1_out", "video_pll1_out", "sys_pll3_out", }; @@ -554,6 +556,9 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) hws[IMX8MP_CLK_HSIO_AXI_DIV] = imx_clk_hw_divider2("hsio_axi_div", "hsio_axi_cg", ccm_base + 0x8380, 0, 3); hws[IMX8MP_CLK_MEDIA_ISP_DIV] = imx_clk_hw_divider2("media_isp_div", "media_isp_cg", ccm_base + 0x8400, 0, 3); + /* CORE SEL */ + hws[IMX8MP_CLK_A53_CORE] = imx_clk_hw_mux2_flags("arm_a53_core", ccm_base + 0x9880, 24, 1, imx8mp_a53_core_sels, ARRAY_SIZE(imx8mp_a53_core_sels), CLK_IS_CRITICAL); + hws[IMX8MP_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mp_main_axi_sels, ccm_base + 0x8800); hws[IMX8MP_CLK_ENET_AXI] = imx8m_clk_hw_composite("enet_axi", imx8mp_enet_axi_sels, ccm_base + 0x8880); hws[IMX8MP_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_critical("nand_usdhc_bus", imx8mp_nand_usdhc_sels, ccm_base + 0x8900); @@ -724,11 +729,14 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) hws[IMX8MP_CLK_VPU_ROOT] = imx_clk_hw_gate4("vpu_root_clk", "vpu_bus", ccm_base + 0x4630, 0); hws[IMX8MP_CLK_AUDIO_ROOT] = imx_clk_hw_gate4("audio_root_clk", "ipg_root", ccm_base + 0x4650, 0); - hws[IMX8MP_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_div", - hws[IMX8MP_CLK_A53_DIV]->clk, - hws[IMX8MP_CLK_A53_SRC]->clk, + clk_hw_set_parent(hws[IMX8MP_CLK_A53_SRC], hws[IMX8MP_SYS_PLL1_800M]); + clk_hw_set_parent(hws[IMX8MP_CLK_A53_CORE], hws[IMX8MP_ARM_PLL_OUT]); + + hws[IMX8MP_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_core", + hws[IMX8MP_CLK_A53_CORE]->clk, + hws[IMX8MP_CLK_A53_CORE]->clk, hws[IMX8MP_ARM_PLL_OUT]->clk, - hws[IMX8MP_SYS_PLL1_800M]->clk); + hws[IMX8MP_CLK_A53_DIV]->clk); imx_check_clk_hws(hws, IMX8MP_CLK_END); diff --git a/include/dt-bindings/clock/imx8mp-clock.h b/include/dt-bindings/clock/imx8mp-clock.h index 00d4d2288990..47ab082238b4 100644 --- a/include/dt-bindings/clock/imx8mp-clock.h +++ b/include/dt-bindings/clock/imx8mp-clock.h @@ -294,7 +294,8 @@ #define IMX8MP_CLK_DRAM_ALT_ROOT 285 #define IMX8MP_CLK_DRAM_CORE 286 #define IMX8MP_CLK_ARM 287 +#define IMX8MP_CLK_A53_CORE 288 -#define IMX8MP_CLK_END 288 +#define IMX8MP_CLK_END 289 #endif From 530cf8d49f2a650625eee6ce28793bd7974e14bd Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 21 Feb 2020 14:31:56 +0800 Subject: [PATCH 0655/4444] clk: imx: pll14xx: Return error if pll type is invalid When pll type is invalid, ONLY output error message is NOT enough, should return error immediately. Signed-off-by: Anson Huang Reviewed-by: Stephen Boyd Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-pll14xx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c index 37e311e1d058..a83bbbee77d9 100644 --- a/drivers/clk/imx/clk-pll14xx.c +++ b/drivers/clk/imx/clk-pll14xx.c @@ -410,6 +410,8 @@ struct clk_hw *imx_clk_hw_pll14xx(const char *name, const char *parent_name, default: pr_err("%s: Unknown pll type for pll clk %s\n", __func__, name); + kfree(pll); + return ERR_PTR(-EINVAL); }; pll->base = base; From bffe02ccca5b0c276956b07e166d302d09b5e890 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 21 Feb 2020 10:13:20 +0800 Subject: [PATCH 0656/4444] ARM: dts: imx: make wdog node name generic Node name should be generic, use "watchdog" instead of "wdog" for wdog nodes. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl.dtsi | 4 ++-- arch/arm/boot/dts/imx6sl.dtsi | 4 ++-- arch/arm/boot/dts/imx6sx.dtsi | 6 +++--- arch/arm/boot/dts/imx6ul.dtsi | 6 +++--- arch/arm/boot/dts/imx7s.dtsi | 8 ++++---- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index 97c0a8551c87..886ab8104a8c 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -669,14 +669,14 @@ status = "disabled"; }; - wdog1: wdog@20bc000 { + wdog1: watchdog@20bc000 { compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt"; reg = <0x020bc000 0x4000>; interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clks IMX6QDL_CLK_IPG>; }; - wdog2: wdog@20c0000 { + wdog2: watchdog@20c0000 { compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt"; reg = <0x020c0000 0x4000>; interrupts = <0 81 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi index ea889f75e09b..db626b2dcb2b 100644 --- a/arch/arm/boot/dts/imx6sl.dtsi +++ b/arch/arm/boot/dts/imx6sl.dtsi @@ -499,14 +499,14 @@ status = "disabled"; }; - wdog1: wdog@20bc000 { + wdog1: watchdog@20bc000 { compatible = "fsl,imx6sl-wdt", "fsl,imx21-wdt"; reg = <0x020bc000 0x4000>; interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clks IMX6SL_CLK_IPG>; }; - wdog2: wdog@20c0000 { + wdog2: watchdog@20c0000 { compatible = "fsl,imx6sl-wdt", "fsl,imx21-wdt"; reg = <0x020c0000 0x4000>; interrupts = <0 81 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index 1198117a4728..6db9ca092cc7 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -567,14 +567,14 @@ status = "disabled"; }; - wdog1: wdog@20bc000 { + wdog1: watchdog@20bc000 { compatible = "fsl,imx6sx-wdt", "fsl,imx21-wdt"; reg = <0x020bc000 0x4000>; interrupts = ; clocks = <&clks IMX6SX_CLK_IPG>; }; - wdog2: wdog@20c0000 { + wdog2: watchdog@20c0000 { compatible = "fsl,imx6sx-wdt", "fsl,imx21-wdt"; reg = <0x020c0000 0x4000>; interrupts = ; @@ -1289,7 +1289,7 @@ status = "disabled"; }; - wdog3: wdog@2288000 { + wdog3: watchdog@2288000 { compatible = "fsl,imx6sx-wdt", "fsl,imx21-wdt"; reg = <0x02288000 0x4000>; interrupts = ; diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi index 30cce35c6b3c..e1807e9d385a 100644 --- a/arch/arm/boot/dts/imx6ul.dtsi +++ b/arch/arm/boot/dts/imx6ul.dtsi @@ -531,14 +531,14 @@ status = "disabled"; }; - wdog1: wdog@20bc000 { + wdog1: watchdog@20bc000 { compatible = "fsl,imx6ul-wdt", "fsl,imx21-wdt"; reg = <0x020bc000 0x4000>; interrupts = ; clocks = <&clks IMX6UL_CLK_WDOG1>; }; - wdog2: wdog@20c0000 { + wdog2: watchdog@20c0000 { compatible = "fsl,imx6ul-wdt", "fsl,imx21-wdt"; reg = <0x020c0000 0x4000>; interrupts = ; @@ -1007,7 +1007,7 @@ status = "disabled"; }; - wdog3: wdog@21e4000 { + wdog3: watchdog@21e4000 { compatible = "fsl,imx6ul-wdt", "fsl,imx21-wdt"; reg = <0x021e4000 0x4000>; interrupts = ; diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index 1ac5045812bf..196bbd6f6fcc 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -406,14 +406,14 @@ gpio-ranges = <&iomuxc 0 139 16>; }; - wdog1: wdog@30280000 { + wdog1: watchdog@30280000 { compatible = "fsl,imx7d-wdt", "fsl,imx21-wdt"; reg = <0x30280000 0x10000>; interrupts = ; clocks = <&clks IMX7D_WDOG1_ROOT_CLK>; }; - wdog2: wdog@30290000 { + wdog2: watchdog@30290000 { compatible = "fsl,imx7d-wdt", "fsl,imx21-wdt"; reg = <0x30290000 0x10000>; interrupts = ; @@ -421,7 +421,7 @@ status = "disabled"; }; - wdog3: wdog@302a0000 { + wdog3: watchdog@302a0000 { compatible = "fsl,imx7d-wdt", "fsl,imx21-wdt"; reg = <0x302a0000 0x10000>; interrupts = ; @@ -429,7 +429,7 @@ status = "disabled"; }; - wdog4: wdog@302b0000 { + wdog4: watchdog@302b0000 { compatible = "fsl,imx7d-wdt", "fsl,imx21-wdt"; reg = <0x302b0000 0x10000>; interrupts = ; From 95d014c812f10df5c8f542d04146e59d169c6dde Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 21 Feb 2020 10:45:53 +0800 Subject: [PATCH 0657/4444] ARM: dts: imx: Align ocotp node name Node name should be generic, use "ocotp-ctrl" instead of "ocotp" for all i.MX6 SoCs. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl.dtsi | 2 +- arch/arm/boot/dts/imx6sl.dtsi | 2 +- arch/arm/boot/dts/imx6sx.dtsi | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index 886ab8104a8c..70fb8b56b1d7 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -1161,7 +1161,7 @@ status = "disabled"; }; - ocotp: ocotp@21bc000 { + ocotp: ocotp-ctrl@21bc000 { compatible = "fsl,imx6q-ocotp", "syscon"; reg = <0x021bc000 0x4000>; clocks = <&clks IMX6QDL_CLK_IIM>; diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi index db626b2dcb2b..c8ec46fe8302 100644 --- a/arch/arm/boot/dts/imx6sl.dtsi +++ b/arch/arm/boot/dts/imx6sl.dtsi @@ -949,7 +949,7 @@ status = "disabled"; }; - ocotp: ocotp@21bc000 { + ocotp: ocotp-ctrl@21bc000 { compatible = "fsl,imx6sl-ocotp", "syscon"; reg = <0x021bc000 0x4000>; clocks = <&clks IMX6SL_CLK_OCOTP>; diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index 6db9ca092cc7..e47d346a3543 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -1051,7 +1051,7 @@ status = "disabled"; }; - ocotp: ocotp@21bc000 { + ocotp: ocotp-ctrl@21bc000 { #address-cells = <1>; #size-cells = <1>; compatible = "fsl,imx6sx-ocotp", "syscon"; From eeca5721baeb11935dac85e71f7fd5a62919ed85 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 21 Feb 2020 14:59:36 +0800 Subject: [PATCH 0658/4444] clk: imx: clk-sscg-pll: Drop unnecessary initialization No need to initialize 'ret' in many functions, as it will get the return value from function call, so remove the initializtion of 'ret'. Signed-off-by: Anson Huang Reviewed-by: Stephen Boyd Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-sscg-pll.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/clk/imx/clk-sscg-pll.c b/drivers/clk/imx/clk-sscg-pll.c index acd1b9002be6..d4a2be16d132 100644 --- a/drivers/clk/imx/clk-sscg-pll.c +++ b/drivers/clk/imx/clk-sscg-pll.c @@ -195,10 +195,10 @@ static int clk_sscg_pll2_find_setup(struct clk_sscg_pll_setup *setup, uint64_t ref) { - int ret = -EINVAL; + int ret; if (ref < PLL_STAGE1_MIN_FREQ || ref > PLL_STAGE1_MAX_FREQ) - return ret; + return -EINVAL; temp_setup->vco1 = ref; @@ -254,10 +254,10 @@ static int clk_sscg_pll1_find_setup(struct clk_sscg_pll_setup *setup, uint64_t ref) { - int ret = -EINVAL; + int ret; if (ref < PLL_REF_MIN_FREQ || ref > PLL_REF_MAX_FREQ) - return ret; + return -EINVAL; temp_setup->ref = ref; @@ -428,7 +428,7 @@ static int __clk_sscg_pll_determine_rate(struct clk_hw *hw, struct clk_sscg_pll_setup *setup = &pll->setup; struct clk_hw *parent_hw = NULL; int bypass_parent_index; - int ret = -EINVAL; + int ret; req->max_rate = max; req->min_rate = min; @@ -467,10 +467,10 @@ static int clk_sscg_pll_determine_rate(struct clk_hw *hw, uint64_t rate = req->rate; uint64_t min = req->min_rate; uint64_t max = req->max_rate; - int ret = -EINVAL; + int ret; if (rate < PLL_OUT_MIN_FREQ || rate > PLL_OUT_MAX_FREQ) - return ret; + return -EINVAL; ret = __clk_sscg_pll_determine_rate(hw, req, req->rate, req->rate, rate, PLL_BYPASS2); From 80b06c5cae5487f590988fd296be36ecd97ede2a Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Mon, 24 Feb 2020 10:07:40 +0800 Subject: [PATCH 0659/4444] arm64: dts: imx8mn: Adjust 1.2GHz OPP voltage to OD mode According to latest datasheet Rev.0, 10/2019, there is restriction as below: "If VDD_SOC/GPU/DDR = 0.95V, then VDD_ARM must be >= 0.95V." As by default SoC is running at OD mode(VDD_SOC = 0.95V), so VDD_ARM 1.2GHz OPP's voltage should be increased to 0.95V. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mn.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi index c98a37666347..f2775724377f 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi @@ -116,7 +116,7 @@ opp-1200000000 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <850000>; + opp-microvolt = <950000>; opp-supported-hw = <0xb00>, <0x7>; clock-latency-ns = <150000>; opp-suspend; From 7efbada45edc660d59cee2842726b5bb1a8b0322 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Sun, 23 Feb 2020 04:16:13 +0100 Subject: [PATCH 0660/4444] dt-bindings: arm: sunxi: Add PocketBook Touch Lux 3 Add a new board name. Signed-off-by: Ondrej Jirman Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/arm/sunxi.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml index 1e63c9867749..5b22b77e4bb7 100644 --- a/Documentation/devicetree/bindings/arm/sunxi.yaml +++ b/Documentation/devicetree/bindings/arm/sunxi.yaml @@ -658,6 +658,11 @@ properties: - const: pineriver,mini-xplus - const: allwinner,sun4i-a10 + - description: PocketBook Touch Lux 3 + items: + - const: pocketbook,touch-lux-3 + - const: allwinner,sun5i-a13 + - description: Point of View Protab2-IPS9 items: - const: pov,protab2-ips9 From cd3e42c9f7458a65fd3b26716230c0ee45a6344f Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Sun, 23 Feb 2020 04:16:14 +0100 Subject: [PATCH 0661/4444] ARM: dts: sun5i: Add PocketBook Touch Lux 3 support What works: - Serial console - mmc0, mmc2 (both microSD card slots on the board) - All buttons (gpio and lradc based) - Power LED - PMIC - RTC - USB OTG/gadgets mode - Realtek USB WiFi - Display backlight - eInk display SPI NOR flash memory Signed-off-by: Ondrej Jirman Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 1 + .../dts/sun5i-a13-pocketbook-touch-lux-3.dts | 257 ++++++++++++++++++ 2 files changed, 258 insertions(+) create mode 100644 arch/arm/boot/dts/sun5i-a13-pocketbook-touch-lux-3.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index e9ddca2946ce..78f144e332f6 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1056,6 +1056,7 @@ dtb-$(CONFIG_MACH_SUN5I) += \ sun5i-a13-licheepi-one.dtb \ sun5i-a13-olinuxino.dtb \ sun5i-a13-olinuxino-micro.dtb \ + sun5i-a13-pocketbook-touch-lux-3.dtb \ sun5i-a13-q8-tablet.dtb \ sun5i-a13-utoo-p66.dtb \ sun5i-gr8-chip-pro.dtb \ diff --git a/arch/arm/boot/dts/sun5i-a13-pocketbook-touch-lux-3.dts b/arch/arm/boot/dts/sun5i-a13-pocketbook-touch-lux-3.dts new file mode 100644 index 000000000000..e9ef97c9c893 --- /dev/null +++ b/arch/arm/boot/dts/sun5i-a13-pocketbook-touch-lux-3.dts @@ -0,0 +1,257 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +/* + * Copyright 2019 Ondrej Jirman + */ + +/dts-v1/; +#include "sun5i-a13.dtsi" +#include "sunxi-common-regulators.dtsi" +#include +#include +#include +#include + +/ { + model = "PocketBook Touch Lux 3"; + compatible = "pocketbook,touch-lux-3", "allwinner,sun5i-a13"; + + aliases { + serial0 = &uart1; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + }; + + backlight { + compatible = "pwm-backlight"; + pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>; + enable-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* PB4 */ + brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>; + default-brightness-level = <8>; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + + power { + gpios = <&pio 4 8 GPIO_ACTIVE_LOW>; /* PE8 */ + default-state = "on"; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + autorepeat; + label = "GPIO Keys"; + + key-right { + label = "Right"; + linux,code = ; + gpios = <&pio 6 9 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PG9 */ + }; + + key-left { + label = "Left"; + linux,code = ; + gpios = <&pio 6 10 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PG10 */ + }; + }; + + reg_1v8: regulator-1v8 { + compatible = "regulator-fixed"; + regulator-name = "vdd-1v8-nor-ctp"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&pio 2 15 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_1v8_nor: regulator-nor { + compatible = "regulator-fixed"; + regulator-name = "vdd-nor"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&pio 2 14 GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <®_1v8>; + regulator-always-on; + }; + + reg_1v8_ctp: regulator-ctp { + compatible = "regulator-fixed"; + regulator-name = "vdd-ctp"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&pio 2 13 GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <®_1v8>; + }; + + reg_3v3_mmc0: regulator-mmc0 { + compatible = "regulator-fixed"; + regulator-name = "vdd-mmc0"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pio 4 4 GPIO_ACTIVE_LOW>; /* PE4 */ + vin-supply = <®_vcc3v3>; + }; +}; + +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + +&ehci0 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + axp209: pmic@34 { + reg = <0x34>; + interrupts = <0>; + }; +}; + +#include "axp209.dtsi" + +&i2c1 { + status = "okay"; + + pcf8563: rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; +}; + +&i2c2 { + status = "okay"; + + /* Touchpanel is connected here. */ +}; + +&lradc { + vref-supply = <®_ldo2>; + status = "okay"; + + button-200 { + label = "Home"; + linux,code = ; + channel = <0>; + voltage = <200000>; + }; + + button-400 { + label = "Menu"; + linux,code = ; + channel = <0>; + voltage = <400000>; + }; +}; + +&mmc0 { + vmmc-supply = <®_3v3_mmc0>; + bus-width = <4>; + cd-gpios = <&pio 6 0 GPIO_ACTIVE_LOW>; /* PG0 */ + status = "okay"; +}; + +&mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_4bit_pc_pins>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + non-removable; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&otg_sram { + status = "okay"; +}; + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm0_pin>; + status = "okay"; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-name = "vdd-int-pll"; +}; + +®_ldo1 { + regulator-name = "vdd-rtc"; +}; + +®_ldo2 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; +}; + +®_ldo3 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-wifi"; + /* We need this otherwise the LDO3 would overload */ + regulator-soft-start; + regulator-ramp-delay = <1600>; +}; + +&spi2 { + pinctrl-names = "default"; + pinctrl-0 = <&spi2_pe_pins>, <&spi2_cs0_pe_pin>; + status = "okay"; + + epd_flash: flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "macronix,mx25u4033", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <4000000>; + }; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pg_pins>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "peripheral"; + status = "okay"; +}; + +&battery_power_supply { + status = "okay"; +}; + +&usb_power_supply { + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_ldo3>; + status = "okay"; +}; From 3abe422fdc65ba08054659b0d27c71e24346021d Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Sun, 23 Feb 2020 11:40:19 +0100 Subject: [PATCH 0662/4444] arm64: dts: sun50i-h5-orange-pi-pc2: Add CPUX voltage regulator Orange Pi PC2 features sy8106a regulator just like Orange Pi PC. Signed-off-by: Ondrej Jirman Reviewed-by: Samuel Holland Signed-off-by: Maxime Ripard --- .../dts/allwinner/sun50i-h5-orangepi-pc2.dts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts index c4f89c312f42..7d7aad18f078 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts @@ -94,6 +94,10 @@ status = "okay"; }; +&cpu0 { + cpu-supply = <®_vdd_cpux>; +}; + &de { status = "okay"; }; @@ -169,6 +173,22 @@ status = "okay"; }; +&r_i2c { + status = "okay"; + + reg_vdd_cpux: regulator@65 { + compatible = "silergy,sy8106a"; + reg = <0x65>; + regulator-name = "vdd-cpux"; + silergy,fixed-microvolt = <1100000>; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-ramp-delay = <200>; + regulator-boot-on; + regulator-always-on; + }; +}; + &spi0 { status = "okay"; From 9680d194d53f035c45c0e0153b1996c5fb6f55d5 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Sat, 22 Feb 2020 23:31:54 +0100 Subject: [PATCH 0663/4444] ARM: dts: sun8i-a83t-tbs-a711: Drop superfluous dr_mode Property dr_mode = "otg" is the default in sun8i-a83t.dtsi Signed-off-by: Ondrej Jirman Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts index 2fd31a0a0b34..4ab4568de8c6 100644 --- a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts +++ b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts @@ -493,7 +493,6 @@ }; &usb_otg { - dr_mode = "otg"; status = "okay"; }; From 5779dd0a7dbd71e82478fb0bf125cc6cd3c43266 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Mon, 24 Feb 2020 15:23:34 +0530 Subject: [PATCH 0664/4444] PCI: endpoint: Use notification chain mechanism to notify EPC events to EPF Use atomic_notifier_call_chain() to notify EPC events like linkup to EPF driver instead of using linkup ops in EPF driver. This is in preparation for adding proper locking mechanism to EPF ops. This will also enable to add more events (in addition to linkup) in the future. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Lorenzo Pieralisi Tested-by: Vidya Sagar --- drivers/pci/endpoint/functions/pci-epf-test.c | 13 ++++++++--- drivers/pci/endpoint/pci-epc-core.c | 9 ++------ drivers/pci/endpoint/pci-epf-core.c | 22 +------------------ include/linux/pci-epc.h | 8 +++++++ include/linux/pci-epf.h | 6 ++--- 5 files changed, 23 insertions(+), 35 deletions(-) diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index 5d74f81ddfe4..bddff15052cc 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -360,12 +360,16 @@ reset_handler: msecs_to_jiffies(1)); } -static void pci_epf_test_linkup(struct pci_epf *epf) +static int pci_epf_test_notifier(struct notifier_block *nb, unsigned long val, + void *data) { + struct pci_epf *epf = container_of(nb, struct pci_epf, nb); struct pci_epf_test *epf_test = epf_get_drvdata(epf); queue_delayed_work(kpcitest_workqueue, &epf_test->cmd_handler, msecs_to_jiffies(1)); + + return NOTIFY_OK; } static void pci_epf_test_unbind(struct pci_epf *epf) @@ -546,8 +550,12 @@ static int pci_epf_test_bind(struct pci_epf *epf) } } - if (!linkup_notifier) + if (linkup_notifier) { + epf->nb.notifier_call = pci_epf_test_notifier; + pci_epc_register_notifier(epc, &epf->nb); + } else { queue_work(kpcitest_workqueue, &epf_test->cmd_handler.work); + } return 0; } @@ -580,7 +588,6 @@ static int pci_epf_test_probe(struct pci_epf *epf) static struct pci_epf_ops ops = { .unbind = pci_epf_test_unbind, .bind = pci_epf_test_bind, - .linkup = pci_epf_test_linkup, }; static struct pci_epf_driver test_driver = { diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index 2091508c1620..2f6436599fcb 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -539,16 +539,10 @@ EXPORT_SYMBOL_GPL(pci_epc_remove_epf); */ void pci_epc_linkup(struct pci_epc *epc) { - unsigned long flags; - struct pci_epf *epf; - if (!epc || IS_ERR(epc)) return; - spin_lock_irqsave(&epc->lock, flags); - list_for_each_entry(epf, &epc->pci_epf, list) - pci_epf_linkup(epf); - spin_unlock_irqrestore(&epc->lock, flags); + atomic_notifier_call_chain(&epc->notifier, 0, NULL); } EXPORT_SYMBOL_GPL(pci_epc_linkup); @@ -612,6 +606,7 @@ __pci_epc_create(struct device *dev, const struct pci_epc_ops *ops, spin_lock_init(&epc->lock); INIT_LIST_HEAD(&epc->pci_epf); + ATOMIC_INIT_NOTIFIER_HEAD(&epc->notifier); device_initialize(&epc->dev); epc->dev.class = pci_epc_class; diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c index fb1306de8f40..93f28c65ace0 100644 --- a/drivers/pci/endpoint/pci-epf-core.c +++ b/drivers/pci/endpoint/pci-epf-core.c @@ -20,26 +20,6 @@ static DEFINE_MUTEX(pci_epf_mutex); static struct bus_type pci_epf_bus_type; static const struct device_type pci_epf_type; -/** - * pci_epf_linkup() - Notify the function driver that EPC device has - * established a connection with the Root Complex. - * @epf: the EPF device bound to the EPC device which has established - * the connection with the host - * - * Invoke to notify the function driver that EPC device has established - * a connection with the Root Complex. - */ -void pci_epf_linkup(struct pci_epf *epf) -{ - if (!epf->driver) { - dev_WARN(&epf->dev, "epf device not bound to driver\n"); - return; - } - - epf->driver->ops->linkup(epf); -} -EXPORT_SYMBOL_GPL(pci_epf_linkup); - /** * pci_epf_unbind() - Notify the function driver that the binding between the * EPF device and EPC device has been lost @@ -214,7 +194,7 @@ int __pci_epf_register_driver(struct pci_epf_driver *driver, if (!driver->ops) return -EINVAL; - if (!driver->ops->bind || !driver->ops->unbind || !driver->ops->linkup) + if (!driver->ops->bind || !driver->ops->unbind) return -EINVAL; driver->driver.bus = &pci_epf_bus_type; diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h index 56f1846b9d39..36644ccd32ac 100644 --- a/include/linux/pci-epc.h +++ b/include/linux/pci-epc.h @@ -89,6 +89,7 @@ struct pci_epc_mem { * @max_functions: max number of functions that can be configured in this EPC * @group: configfs group representing the PCI EPC device * @lock: spinlock to protect pci_epc ops + * @notifier: used to notify EPF of any EPC events (like linkup) */ struct pci_epc { struct device dev; @@ -99,6 +100,7 @@ struct pci_epc { struct config_group *group; /* spinlock to protect against concurrent access of EP controller */ spinlock_t lock; + struct atomic_notifier_head notifier; }; /** @@ -141,6 +143,12 @@ static inline void *epc_get_drvdata(struct pci_epc *epc) return dev_get_drvdata(&epc->dev); } +static inline int +pci_epc_register_notifier(struct pci_epc *epc, struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&epc->notifier, nb); +} + struct pci_epc * __devm_pci_epc_create(struct device *dev, const struct pci_epc_ops *ops, struct module *owner); diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h index 2d6f07556682..4993f7f6439b 100644 --- a/include/linux/pci-epf.h +++ b/include/linux/pci-epf.h @@ -55,13 +55,10 @@ struct pci_epf_header { * @bind: ops to perform when a EPC device has been bound to EPF device * @unbind: ops to perform when a binding has been lost between a EPC device * and EPF device - * @linkup: ops to perform when the EPC device has established a connection with - * a host system */ struct pci_epf_ops { int (*bind)(struct pci_epf *epf); void (*unbind)(struct pci_epf *epf); - void (*linkup)(struct pci_epf *epf); }; /** @@ -112,6 +109,7 @@ struct pci_epf_bar { * @epc: the EPC device to which this EPF device is bound * @driver: the EPF driver to which this EPF device is bound * @list: to add pci_epf as a list of PCI endpoint functions to pci_epc + * @nb: notifier block to notify EPF of any EPC events (like linkup) */ struct pci_epf { struct device dev; @@ -125,6 +123,7 @@ struct pci_epf { struct pci_epc *epc; struct pci_epf_driver *driver; struct list_head list; + struct notifier_block nb; }; #define to_pci_epf(epf_dev) container_of((epf_dev), struct pci_epf, dev) @@ -154,5 +153,4 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar, void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar); int pci_epf_bind(struct pci_epf *epf); void pci_epf_unbind(struct pci_epf *epf); -void pci_epf_linkup(struct pci_epf *epf); #endif /* __LINUX_PCI_EPF_H */ From 3d3248dbd018502f654064c78efcd2e165ab3486 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Mon, 24 Feb 2020 15:23:35 +0530 Subject: [PATCH 0665/4444] PCI: endpoint: Replace spinlock with mutex The pci_epc_ops is not intended to be invoked from interrupt context. Hence replace spin_lock_irqsave and spin_unlock_irqrestore with mutex_lock and mutex_unlock respectively. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Lorenzo Pieralisi --- drivers/pci/endpoint/pci-epc-core.c | 82 +++++++++++------------------ include/linux/pci-epc.h | 6 +-- 2 files changed, 34 insertions(+), 54 deletions(-) diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index 2f6436599fcb..e51a12ed85bb 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -120,7 +120,6 @@ const struct pci_epc_features *pci_epc_get_features(struct pci_epc *epc, u8 func_no) { const struct pci_epc_features *epc_features; - unsigned long flags; if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) return NULL; @@ -128,9 +127,9 @@ const struct pci_epc_features *pci_epc_get_features(struct pci_epc *epc, if (!epc->ops->get_features) return NULL; - spin_lock_irqsave(&epc->lock, flags); + mutex_lock(&epc->lock); epc_features = epc->ops->get_features(epc, func_no); - spin_unlock_irqrestore(&epc->lock, flags); + mutex_unlock(&epc->lock); return epc_features; } @@ -144,14 +143,12 @@ EXPORT_SYMBOL_GPL(pci_epc_get_features); */ void pci_epc_stop(struct pci_epc *epc) { - unsigned long flags; - if (IS_ERR(epc) || !epc->ops->stop) return; - spin_lock_irqsave(&epc->lock, flags); + mutex_lock(&epc->lock); epc->ops->stop(epc); - spin_unlock_irqrestore(&epc->lock, flags); + mutex_unlock(&epc->lock); } EXPORT_SYMBOL_GPL(pci_epc_stop); @@ -164,7 +161,6 @@ EXPORT_SYMBOL_GPL(pci_epc_stop); int pci_epc_start(struct pci_epc *epc) { int ret; - unsigned long flags; if (IS_ERR(epc)) return -EINVAL; @@ -172,9 +168,9 @@ int pci_epc_start(struct pci_epc *epc) if (!epc->ops->start) return 0; - spin_lock_irqsave(&epc->lock, flags); + mutex_lock(&epc->lock); ret = epc->ops->start(epc); - spin_unlock_irqrestore(&epc->lock, flags); + mutex_unlock(&epc->lock); return ret; } @@ -193,7 +189,6 @@ int pci_epc_raise_irq(struct pci_epc *epc, u8 func_no, enum pci_epc_irq_type type, u16 interrupt_num) { int ret; - unsigned long flags; if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) return -EINVAL; @@ -201,9 +196,9 @@ int pci_epc_raise_irq(struct pci_epc *epc, u8 func_no, if (!epc->ops->raise_irq) return 0; - spin_lock_irqsave(&epc->lock, flags); + mutex_lock(&epc->lock); ret = epc->ops->raise_irq(epc, func_no, type, interrupt_num); - spin_unlock_irqrestore(&epc->lock, flags); + mutex_unlock(&epc->lock); return ret; } @@ -219,7 +214,6 @@ EXPORT_SYMBOL_GPL(pci_epc_raise_irq); int pci_epc_get_msi(struct pci_epc *epc, u8 func_no) { int interrupt; - unsigned long flags; if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) return 0; @@ -227,9 +221,9 @@ int pci_epc_get_msi(struct pci_epc *epc, u8 func_no) if (!epc->ops->get_msi) return 0; - spin_lock_irqsave(&epc->lock, flags); + mutex_lock(&epc->lock); interrupt = epc->ops->get_msi(epc, func_no); - spin_unlock_irqrestore(&epc->lock, flags); + mutex_unlock(&epc->lock); if (interrupt < 0) return 0; @@ -252,7 +246,6 @@ int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts) { int ret; u8 encode_int; - unsigned long flags; if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions || interrupts > 32) @@ -263,9 +256,9 @@ int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts) encode_int = order_base_2(interrupts); - spin_lock_irqsave(&epc->lock, flags); + mutex_lock(&epc->lock); ret = epc->ops->set_msi(epc, func_no, encode_int); - spin_unlock_irqrestore(&epc->lock, flags); + mutex_unlock(&epc->lock); return ret; } @@ -281,7 +274,6 @@ EXPORT_SYMBOL_GPL(pci_epc_set_msi); int pci_epc_get_msix(struct pci_epc *epc, u8 func_no) { int interrupt; - unsigned long flags; if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) return 0; @@ -289,9 +281,9 @@ int pci_epc_get_msix(struct pci_epc *epc, u8 func_no) if (!epc->ops->get_msix) return 0; - spin_lock_irqsave(&epc->lock, flags); + mutex_lock(&epc->lock); interrupt = epc->ops->get_msix(epc, func_no); - spin_unlock_irqrestore(&epc->lock, flags); + mutex_unlock(&epc->lock); if (interrupt < 0) return 0; @@ -311,7 +303,6 @@ EXPORT_SYMBOL_GPL(pci_epc_get_msix); int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts) { int ret; - unsigned long flags; if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions || interrupts < 1 || interrupts > 2048) @@ -320,9 +311,9 @@ int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts) if (!epc->ops->set_msix) return 0; - spin_lock_irqsave(&epc->lock, flags); + mutex_lock(&epc->lock); ret = epc->ops->set_msix(epc, func_no, interrupts - 1); - spin_unlock_irqrestore(&epc->lock, flags); + mutex_unlock(&epc->lock); return ret; } @@ -339,17 +330,15 @@ EXPORT_SYMBOL_GPL(pci_epc_set_msix); void pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no, phys_addr_t phys_addr) { - unsigned long flags; - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) return; if (!epc->ops->unmap_addr) return; - spin_lock_irqsave(&epc->lock, flags); + mutex_lock(&epc->lock); epc->ops->unmap_addr(epc, func_no, phys_addr); - spin_unlock_irqrestore(&epc->lock, flags); + mutex_unlock(&epc->lock); } EXPORT_SYMBOL_GPL(pci_epc_unmap_addr); @@ -367,7 +356,6 @@ int pci_epc_map_addr(struct pci_epc *epc, u8 func_no, phys_addr_t phys_addr, u64 pci_addr, size_t size) { int ret; - unsigned long flags; if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) return -EINVAL; @@ -375,9 +363,9 @@ int pci_epc_map_addr(struct pci_epc *epc, u8 func_no, if (!epc->ops->map_addr) return 0; - spin_lock_irqsave(&epc->lock, flags); + mutex_lock(&epc->lock); ret = epc->ops->map_addr(epc, func_no, phys_addr, pci_addr, size); - spin_unlock_irqrestore(&epc->lock, flags); + mutex_unlock(&epc->lock); return ret; } @@ -394,8 +382,6 @@ EXPORT_SYMBOL_GPL(pci_epc_map_addr); void pci_epc_clear_bar(struct pci_epc *epc, u8 func_no, struct pci_epf_bar *epf_bar) { - unsigned long flags; - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions || (epf_bar->barno == BAR_5 && epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64)) @@ -404,9 +390,9 @@ void pci_epc_clear_bar(struct pci_epc *epc, u8 func_no, if (!epc->ops->clear_bar) return; - spin_lock_irqsave(&epc->lock, flags); + mutex_lock(&epc->lock); epc->ops->clear_bar(epc, func_no, epf_bar); - spin_unlock_irqrestore(&epc->lock, flags); + mutex_unlock(&epc->lock); } EXPORT_SYMBOL_GPL(pci_epc_clear_bar); @@ -422,7 +408,6 @@ int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, struct pci_epf_bar *epf_bar) { int ret; - unsigned long irq_flags; int flags = epf_bar->flags; if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions || @@ -437,9 +422,9 @@ int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, if (!epc->ops->set_bar) return 0; - spin_lock_irqsave(&epc->lock, irq_flags); + mutex_lock(&epc->lock); ret = epc->ops->set_bar(epc, func_no, epf_bar); - spin_unlock_irqrestore(&epc->lock, irq_flags); + mutex_unlock(&epc->lock); return ret; } @@ -460,7 +445,6 @@ int pci_epc_write_header(struct pci_epc *epc, u8 func_no, struct pci_epf_header *header) { int ret; - unsigned long flags; if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) return -EINVAL; @@ -468,9 +452,9 @@ int pci_epc_write_header(struct pci_epc *epc, u8 func_no, if (!epc->ops->write_header) return 0; - spin_lock_irqsave(&epc->lock, flags); + mutex_lock(&epc->lock); ret = epc->ops->write_header(epc, func_no, header); - spin_unlock_irqrestore(&epc->lock, flags); + mutex_unlock(&epc->lock); return ret; } @@ -487,8 +471,6 @@ EXPORT_SYMBOL_GPL(pci_epc_write_header); */ int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf) { - unsigned long flags; - if (epf->epc) return -EBUSY; @@ -500,9 +482,9 @@ int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf) epf->epc = epc; - spin_lock_irqsave(&epc->lock, flags); + mutex_lock(&epc->lock); list_add_tail(&epf->list, &epc->pci_epf); - spin_unlock_irqrestore(&epc->lock, flags); + mutex_unlock(&epc->lock); return 0; } @@ -517,15 +499,13 @@ EXPORT_SYMBOL_GPL(pci_epc_add_epf); */ void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf) { - unsigned long flags; - if (!epc || IS_ERR(epc) || !epf) return; - spin_lock_irqsave(&epc->lock, flags); + mutex_lock(&epc->lock); list_del(&epf->list); epf->epc = NULL; - spin_unlock_irqrestore(&epc->lock, flags); + mutex_unlock(&epc->lock); } EXPORT_SYMBOL_GPL(pci_epc_remove_epf); @@ -604,7 +584,7 @@ __pci_epc_create(struct device *dev, const struct pci_epc_ops *ops, goto err_ret; } - spin_lock_init(&epc->lock); + mutex_init(&epc->lock); INIT_LIST_HEAD(&epc->pci_epf); ATOMIC_INIT_NOTIFIER_HEAD(&epc->notifier); diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h index 36644ccd32ac..9dd60f2e9705 100644 --- a/include/linux/pci-epc.h +++ b/include/linux/pci-epc.h @@ -88,7 +88,7 @@ struct pci_epc_mem { * @mem: address space of the endpoint controller * @max_functions: max number of functions that can be configured in this EPC * @group: configfs group representing the PCI EPC device - * @lock: spinlock to protect pci_epc ops + * @lock: mutex to protect pci_epc ops * @notifier: used to notify EPF of any EPC events (like linkup) */ struct pci_epc { @@ -98,8 +98,8 @@ struct pci_epc { struct pci_epc_mem *mem; u8 max_functions; struct config_group *group; - /* spinlock to protect against concurrent access of EP controller */ - spinlock_t lock; + /* mutex to protect against concurrent access of EP controller */ + struct mutex lock; struct atomic_notifier_head notifier; }; From 04e046ca57ebed3943422dee10eec9e73aec081e Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Mon, 24 Feb 2020 15:23:36 +0530 Subject: [PATCH 0666/4444] PCI: endpoint: Fix for concurrent memory allocation in OB address region pci-epc-mem uses a bitmap to manage the Endpoint outbound (OB) address region. This address region will be shared by multiple endpoint functions (in the case of multi function endpoint) and it has to be protected from concurrent access to avoid updating an inconsistent state. Use a mutex to protect bitmap updates to prevent the memory allocation API from returning incorrect addresses. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Lorenzo Pieralisi Cc: stable@vger.kernel.org # v4.14+ --- drivers/pci/endpoint/pci-epc-mem.c | 10 ++++++++-- include/linux/pci-epc.h | 3 +++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/pci/endpoint/pci-epc-mem.c b/drivers/pci/endpoint/pci-epc-mem.c index d2b174ce15de..abfac1109a13 100644 --- a/drivers/pci/endpoint/pci-epc-mem.c +++ b/drivers/pci/endpoint/pci-epc-mem.c @@ -79,6 +79,7 @@ int __pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size, mem->page_size = page_size; mem->pages = pages; mem->size = size; + mutex_init(&mem->lock); epc->mem = mem; @@ -122,7 +123,7 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc, phys_addr_t *phys_addr, size_t size) { int pageno; - void __iomem *virt_addr; + void __iomem *virt_addr = NULL; struct pci_epc_mem *mem = epc->mem; unsigned int page_shift = ilog2(mem->page_size); int order; @@ -130,15 +131,18 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc, size = ALIGN(size, mem->page_size); order = pci_epc_mem_get_order(mem, size); + mutex_lock(&mem->lock); pageno = bitmap_find_free_region(mem->bitmap, mem->pages, order); if (pageno < 0) - return NULL; + goto ret; *phys_addr = mem->phys_base + ((phys_addr_t)pageno << page_shift); virt_addr = ioremap(*phys_addr, size); if (!virt_addr) bitmap_release_region(mem->bitmap, pageno, order); +ret: + mutex_unlock(&mem->lock); return virt_addr; } EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr); @@ -164,7 +168,9 @@ void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr, pageno = (phys_addr - mem->phys_base) >> page_shift; size = ALIGN(size, mem->page_size); order = pci_epc_mem_get_order(mem, size); + mutex_lock(&mem->lock); bitmap_release_region(mem->bitmap, pageno, order); + mutex_unlock(&mem->lock); } EXPORT_SYMBOL_GPL(pci_epc_mem_free_addr); diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h index 9dd60f2e9705..4e3e527c49d1 100644 --- a/include/linux/pci-epc.h +++ b/include/linux/pci-epc.h @@ -71,6 +71,7 @@ struct pci_epc_ops { * @bitmap: bitmap to manage the PCI address space * @pages: number of bits representing the address region * @page_size: size of each page + * @lock: mutex to protect bitmap */ struct pci_epc_mem { phys_addr_t phys_base; @@ -78,6 +79,8 @@ struct pci_epc_mem { unsigned long *bitmap; size_t page_size; int pages; + /* mutex to protect against concurrent access for memory allocation*/ + struct mutex lock; }; /** From 07301c982643a432212840a4b648b5d3f5a061fa Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Mon, 24 Feb 2020 15:23:37 +0530 Subject: [PATCH 0667/4444] PCI: endpoint: Protect concurrent access to pci_epf_ops with mutex Protect concurrent access to pci_epf_ops with a mutex. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Lorenzo Pieralisi --- drivers/pci/endpoint/pci-epf-core.c | 11 ++++++++++- include/linux/pci-epf.h | 3 +++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c index 93f28c65ace0..6e0648991b5c 100644 --- a/drivers/pci/endpoint/pci-epf-core.c +++ b/drivers/pci/endpoint/pci-epf-core.c @@ -35,7 +35,9 @@ void pci_epf_unbind(struct pci_epf *epf) return; } + mutex_lock(&epf->lock); epf->driver->ops->unbind(epf); + mutex_unlock(&epf->lock); module_put(epf->driver->owner); } EXPORT_SYMBOL_GPL(pci_epf_unbind); @@ -49,6 +51,8 @@ EXPORT_SYMBOL_GPL(pci_epf_unbind); */ int pci_epf_bind(struct pci_epf *epf) { + int ret; + if (!epf->driver) { dev_WARN(&epf->dev, "epf device not bound to driver\n"); return -EINVAL; @@ -57,7 +61,11 @@ int pci_epf_bind(struct pci_epf *epf) if (!try_module_get(epf->driver->owner)) return -EAGAIN; - return epf->driver->ops->bind(epf); + mutex_lock(&epf->lock); + ret = epf->driver->ops->bind(epf); + mutex_unlock(&epf->lock); + + return ret; } EXPORT_SYMBOL_GPL(pci_epf_bind); @@ -252,6 +260,7 @@ struct pci_epf *pci_epf_create(const char *name) device_initialize(dev); dev->bus = &pci_epf_bus_type; dev->type = &pci_epf_type; + mutex_init(&epf->lock); ret = dev_set_name(dev, "%s", name); if (ret) { diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h index 4993f7f6439b..bcdf4f07bde7 100644 --- a/include/linux/pci-epf.h +++ b/include/linux/pci-epf.h @@ -110,6 +110,7 @@ struct pci_epf_bar { * @driver: the EPF driver to which this EPF device is bound * @list: to add pci_epf as a list of PCI endpoint functions to pci_epc * @nb: notifier block to notify EPF of any EPC events (like linkup) + * @lock: mutex to protect pci_epf_ops */ struct pci_epf { struct device dev; @@ -124,6 +125,8 @@ struct pci_epf { struct pci_epf_driver *driver; struct list_head list; struct notifier_block nb; + /* mutex to protect against concurrent access of pci_epf_ops */ + struct mutex lock; }; #define to_pci_epf(epf_dev) container_of((epf_dev), struct pci_epf, dev) From 2499ee84e02774a8573b7b4c76c8f2ea38669313 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Mon, 24 Feb 2020 15:23:38 +0530 Subject: [PATCH 0668/4444] PCI: endpoint: Assign function number for each PF in EPC core The PCIe endpoint core relies on the drivers that invoke the pci_epc_add_epf() API to allocate and assign a function number to each physical function (PF). Since endpoint function device can be created by multiple mechanisms (configfs, devicetree, etc..), allowing each of these mechanisms to assign a function number would result in mutliple endpoint function devices having the same function number. In order to avoid this, let EPC core assign a function number to the endpoint device. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Lorenzo Pieralisi --- drivers/pci/endpoint/pci-ep-cfs.c | 27 +++++---------------------- drivers/pci/endpoint/pci-epc-core.c | 26 ++++++++++++++++++++++---- include/linux/pci-epc.h | 2 ++ 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c index d1288a0bd530..e7e8367eead1 100644 --- a/drivers/pci/endpoint/pci-ep-cfs.c +++ b/drivers/pci/endpoint/pci-ep-cfs.c @@ -29,7 +29,6 @@ struct pci_epc_group { struct config_group group; struct pci_epc *epc; bool start; - unsigned long function_num_map; }; static inline struct pci_epf_group *to_pci_epf_group(struct config_item *item) @@ -89,37 +88,22 @@ static int pci_epc_epf_link(struct config_item *epc_item, struct config_item *epf_item) { int ret; - u32 func_no = 0; struct pci_epf_group *epf_group = to_pci_epf_group(epf_item); struct pci_epc_group *epc_group = to_pci_epc_group(epc_item); struct pci_epc *epc = epc_group->epc; struct pci_epf *epf = epf_group->epf; - func_no = find_first_zero_bit(&epc_group->function_num_map, - BITS_PER_LONG); - if (func_no >= BITS_PER_LONG) - return -EINVAL; - - set_bit(func_no, &epc_group->function_num_map); - epf->func_no = func_no; - ret = pci_epc_add_epf(epc, epf); if (ret) - goto err_add_epf; + return ret; ret = pci_epf_bind(epf); - if (ret) - goto err_epf_bind; + if (ret) { + pci_epc_remove_epf(epc, epf); + return ret; + } return 0; - -err_epf_bind: - pci_epc_remove_epf(epc, epf); - -err_add_epf: - clear_bit(func_no, &epc_group->function_num_map); - - return ret; } static void pci_epc_epf_unlink(struct config_item *epc_item, @@ -134,7 +118,6 @@ static void pci_epc_epf_unlink(struct config_item *epc_item, epc = epc_group->epc; epf = epf_group->epf; - clear_bit(epf->func_no, &epc_group->function_num_map); pci_epf_unbind(epf); pci_epc_remove_epf(epc, epf); } diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index e51a12ed85bb..dc1c673534e0 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -471,22 +471,39 @@ EXPORT_SYMBOL_GPL(pci_epc_write_header); */ int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf) { + u32 func_no; + int ret = 0; + if (epf->epc) return -EBUSY; if (IS_ERR(epc)) return -EINVAL; - if (epf->func_no > epc->max_functions - 1) - return -EINVAL; + mutex_lock(&epc->lock); + func_no = find_first_zero_bit(&epc->function_num_map, + BITS_PER_LONG); + if (func_no >= BITS_PER_LONG) { + ret = -EINVAL; + goto ret; + } + if (func_no > epc->max_functions - 1) { + dev_err(&epc->dev, "Exceeding max supported Function Number\n"); + ret = -EINVAL; + goto ret; + } + + set_bit(func_no, &epc->function_num_map); + epf->func_no = func_no; epf->epc = epc; - mutex_lock(&epc->lock); list_add_tail(&epf->list, &epc->pci_epf); + +ret: mutex_unlock(&epc->lock); - return 0; + return ret; } EXPORT_SYMBOL_GPL(pci_epc_add_epf); @@ -503,6 +520,7 @@ void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf) return; mutex_lock(&epc->lock); + clear_bit(epf->func_no, &epc->function_num_map); list_del(&epf->list); epf->epc = NULL; mutex_unlock(&epc->lock); diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h index 4e3e527c49d1..ccaf6e3fa931 100644 --- a/include/linux/pci-epc.h +++ b/include/linux/pci-epc.h @@ -92,6 +92,7 @@ struct pci_epc_mem { * @max_functions: max number of functions that can be configured in this EPC * @group: configfs group representing the PCI EPC device * @lock: mutex to protect pci_epc ops + * @function_num_map: bitmap to manage physical function number * @notifier: used to notify EPF of any EPC events (like linkup) */ struct pci_epc { @@ -103,6 +104,7 @@ struct pci_epc { struct config_group *group; /* mutex to protect against concurrent access of EP controller */ struct mutex lock; + unsigned long function_num_map; struct atomic_notifier_head notifier; }; From e658a4fea8efe70ce3b9b6628268485e134508d1 Mon Sep 17 00:00:00 2001 From: Dexuan Cui Date: Fri, 21 Feb 2020 21:59:56 -0800 Subject: [PATCH 0669/4444] PCI: hv: Remove unnecessary type casting from kzalloc In C, there is no need to cast a void * to any other pointer type, remove an unnecessary cast. Signed-off-by: Dexuan Cui Signed-off-by: Lorenzo Pieralisi Reviewed-by: Michael Kelley --- drivers/pci/controller/pci-hyperv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index 9977abff92fc..0fe0283368d2 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -2922,7 +2922,7 @@ static int hv_pci_probe(struct hv_device *hdev, * positive by using kmemleak_alloc() and kmemleak_free() to ask * kmemleak to track and scan the hbus buffer. */ - hbus = (struct hv_pcibus_device *)kzalloc(HV_HYP_PAGE_SIZE, GFP_KERNEL); + hbus = kzalloc(HV_HYP_PAGE_SIZE, GFP_KERNEL); if (!hbus) return -ENOMEM; hbus->state = hv_pcibus_init; From 42c3d41832ef4fcf60aaa6f748de01ad99572adf Mon Sep 17 00:00:00 2001 From: Dexuan Cui Date: Fri, 21 Feb 2020 21:59:57 -0800 Subject: [PATCH 0670/4444] PCI: hv: Add missing kfree(hbus) in hv_pci_probe()'s error handling path Now that we use kzalloc() to allocate the hbus buffer, we must call kfree() in the error path as well to prevent memory leakage. Fixes: 877b911a5ba0 ("PCI: hv: Avoid a kmemleak false positive caused by the hbus buffer") Signed-off-by: Dexuan Cui Signed-off-by: Lorenzo Pieralisi Reviewed-by: Michael Kelley --- drivers/pci/controller/pci-hyperv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index 0fe0283368d2..15011a349520 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -3058,7 +3058,7 @@ destroy_wq: free_dom: hv_put_dom_num(hbus->sysdata.domain); free_bus: - free_page((unsigned long)hbus); + kfree(hbus); return ret; } From 5a309875787db47d69610e45f00a727ef9e62aa0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 24 Feb 2020 12:25:37 +0100 Subject: [PATCH 0671/4444] ASoC: Fix SND_SOC_ALL_CODECS imply ac97 fallout On i386 randconfig: sound/soc/codecs/wm9705.o: In function `wm9705_soc_resume': wm9705.c:(.text+0x128): undefined reference to `snd_ac97_reset' sound/soc/codecs/wm9712.o: In function `wm9712_soc_resume': wm9712.c:(.text+0x2d1): undefined reference to `snd_ac97_reset' sound/soc/codecs/wm9713.o: In function `wm9713_soc_resume': wm9713.c:(.text+0x820): undefined reference to `snd_ac97_reset' Fix this by adding the missing dependencies on SND_SOC_AC97_BUS. Reported-by: Randy Dunlap Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200224112537.14483-1-geert@linux-m68k.org Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9e9d54e4576c..a7e89567edbe 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -1610,16 +1610,19 @@ config SND_SOC_WM9090 config SND_SOC_WM9705 tristate + depends on SND_SOC_AC97_BUS select REGMAP_AC97 select AC97_BUS_COMPAT if AC97_BUS_NEW config SND_SOC_WM9712 tristate + depends on SND_SOC_AC97_BUS select REGMAP_AC97 select AC97_BUS_COMPAT if AC97_BUS_NEW config SND_SOC_WM9713 tristate + depends on SND_SOC_AC97_BUS select REGMAP_AC97 select AC97_BUS_COMPAT if AC97_BUS_NEW From 6e0a7c403da29a01090d8d1ffbc5276fdfdbac3d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 18 Feb 2020 14:22:17 +0100 Subject: [PATCH 0672/4444] ARM: dts: r8a7745: Convert to new DU DT bindings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DU DT bindings have been updated to drop the reg-names property. Update the r8a7745 device tree accordingly. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham Link: https://lore.kernel.org/r/20200218132217.21454-1-geert+renesas@glider.be --- arch/arm/boot/dts/r8a7745.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/r8a7745.dtsi b/arch/arm/boot/dts/r8a7745.dtsi index 3f88a7e34af2..3b413658eb8d 100644 --- a/arch/arm/boot/dts/r8a7745.dtsi +++ b/arch/arm/boot/dts/r8a7745.dtsi @@ -1506,7 +1506,6 @@ du: display@feb00000 { compatible = "renesas,du-r8a7745"; reg = <0 0xfeb00000 0 0x40000>; - reg-names = "du"; interrupts = , ; clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>; From d15881f29ee8d6fada59597741d1a944de117df7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 18 Feb 2020 14:30:16 +0100 Subject: [PATCH 0673/4444] ARM: dts: rcar-gen2: Add reset control properties for display Add reset control properties to the device nodes for the Display Units on all supported R-Car Gen2 SoCs. Note that on these SoCs, there is only a single reset for all DU channels. Join the clocks lines while at it, to increase uniformity. Signed-off-by: Geert Uytterhoeven Reviewed-by: Ulrich Hecht Reviewed-by: Laurent Pinchart Link: https://lore.kernel.org/r/20200218133019.22299-2-geert+renesas@glider.be --- arch/arm/boot/dts/r8a7790.dtsi | 2 ++ arch/arm/boot/dts/r8a7791.dtsi | 5 +++-- arch/arm/boot/dts/r8a7792.dtsi | 5 +++-- arch/arm/boot/dts/r8a7793.dtsi | 5 +++-- arch/arm/boot/dts/r8a7794.dtsi | 2 ++ 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index 334ba19769b9..e5ef9fd4284a 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -1719,6 +1719,8 @@ clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>, <&cpg CPG_MOD 722>; clock-names = "du.0", "du.1", "du.2"; + resets = <&cpg 724>; + reset-names = "du.0"; status = "disabled"; ports { diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 59a55e87fcc6..6e5bd86731cd 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1681,9 +1681,10 @@ reg = <0 0xfeb00000 0 0x40000>; interrupts = , ; - clocks = <&cpg CPG_MOD 724>, - <&cpg CPG_MOD 723>; + clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>; clock-names = "du.0", "du.1"; + resets = <&cpg 724>; + reset-names = "du.0"; status = "disabled"; ports { diff --git a/arch/arm/boot/dts/r8a7792.dtsi b/arch/arm/boot/dts/r8a7792.dtsi index 39af16caa2ae..4627eefa502b 100644 --- a/arch/arm/boot/dts/r8a7792.dtsi +++ b/arch/arm/boot/dts/r8a7792.dtsi @@ -852,9 +852,10 @@ reg = <0 0xfeb00000 0 0x40000>; interrupts = , ; - clocks = <&cpg CPG_MOD 724>, - <&cpg CPG_MOD 723>; + clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>; clock-names = "du.0", "du.1"; + resets = <&cpg 724>; + reset-names = "du.0"; status = "disabled"; ports { diff --git a/arch/arm/boot/dts/r8a7793.dtsi b/arch/arm/boot/dts/r8a7793.dtsi index eef035c4d983..dadbda16161b 100644 --- a/arch/arm/boot/dts/r8a7793.dtsi +++ b/arch/arm/boot/dts/r8a7793.dtsi @@ -1341,9 +1341,10 @@ reg = <0 0xfeb00000 0 0x40000>; interrupts = , ; - clocks = <&cpg CPG_MOD 724>, - <&cpg CPG_MOD 723>; + clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>; clock-names = "du.0", "du.1"; + resets = <&cpg 724>; + reset-names = "du.0"; status = "disabled"; ports { diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 05ef79c6ed7f..2c9e7a1ebfec 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -1356,6 +1356,8 @@ ; clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>; clock-names = "du.0", "du.1"; + resets = <&cpg 724>; + reset-names = "du.0"; status = "disabled"; ports { From 9e1232631d4e8e30096fa758a0e1fb9e08f219f9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 18 Feb 2020 14:30:17 +0100 Subject: [PATCH 0674/4444] ARM: dts: rzg1: Add reset control properties for display Add reset control properties to the devices node for the Display Units on all supported RZ/G1 SoCs. Note that on these SoCs, there is only a single reset for all DU channels. Join the clocks lines while at it, to increase uniformity. Signed-off-by: Geert Uytterhoeven Reviewed-by: Ulrich Hecht Reviewed-by: Laurent Pinchart Link: https://lore.kernel.org/r/20200218133019.22299-3-geert+renesas@glider.be --- arch/arm/boot/dts/r8a7743.dtsi | 5 +++-- arch/arm/boot/dts/r8a7744.dtsi | 5 +++-- arch/arm/boot/dts/r8a7745.dtsi | 2 ++ arch/arm/boot/dts/r8a77470.dtsi | 5 +++-- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/r8a7743.dtsi b/arch/arm/boot/dts/r8a7743.dtsi index 1cd19a569bd0..e8b340bb99bc 100644 --- a/arch/arm/boot/dts/r8a7743.dtsi +++ b/arch/arm/boot/dts/r8a7743.dtsi @@ -1669,9 +1669,10 @@ reg = <0 0xfeb00000 0 0x40000>; interrupts = , ; - clocks = <&cpg CPG_MOD 724>, - <&cpg CPG_MOD 723>; + clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>; clock-names = "du.0", "du.1"; + resets = <&cpg 724>; + reset-names = "du.0"; status = "disabled"; ports { diff --git a/arch/arm/boot/dts/r8a7744.dtsi b/arch/arm/boot/dts/r8a7744.dtsi index 1c82dd0abd76..def840b8b2d3 100644 --- a/arch/arm/boot/dts/r8a7744.dtsi +++ b/arch/arm/boot/dts/r8a7744.dtsi @@ -1655,9 +1655,10 @@ reg = <0 0xfeb00000 0 0x40000>; interrupts = , ; - clocks = <&cpg CPG_MOD 724>, - <&cpg CPG_MOD 723>; + clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>; clock-names = "du.0", "du.1"; + resets = <&cpg 724>; + reset-names = "du.0"; status = "disabled"; ports { diff --git a/arch/arm/boot/dts/r8a7745.dtsi b/arch/arm/boot/dts/r8a7745.dtsi index 3b413658eb8d..7ab58d8bb740 100644 --- a/arch/arm/boot/dts/r8a7745.dtsi +++ b/arch/arm/boot/dts/r8a7745.dtsi @@ -1510,6 +1510,8 @@ ; clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>; clock-names = "du.0", "du.1"; + resets = <&cpg 724>; + reset-names = "du.0"; status = "disabled"; ports { diff --git a/arch/arm/boot/dts/r8a77470.dtsi b/arch/arm/boot/dts/r8a77470.dtsi index 6efcef1670e1..f55153192276 100644 --- a/arch/arm/boot/dts/r8a77470.dtsi +++ b/arch/arm/boot/dts/r8a77470.dtsi @@ -942,9 +942,10 @@ reg = <0 0xfeb00000 0 0x40000>; interrupts = , ; - clocks = <&cpg CPG_MOD 724>, - <&cpg CPG_MOD 723>; + clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>; clock-names = "du.0", "du.1"; + resets = <&cpg 724>; + reset-names = "du.0"; status = "disabled"; ports { From 1640c8df0bbac9e5156132e24c0f0a932c2b2865 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Sun, 23 Feb 2020 01:01:54 +0800 Subject: [PATCH 0675/4444] ASoC: meson: aiu: fix semicolon.cocci warnings sound/soc/meson/aiu-encoder-i2s.c:129:2-3: Unneeded semicolon Remove unneeded semicolon. Generated by: scripts/coccinelle/misc/semicolon.cocci Fixes: 3e25c44598aa ("ASoC: meson: aiu: add support for the Meson8 and Meson8b SoC families") Signed-off-by: kbuild test robot CC: Martin Blumenstingl Link: https://lore.kernel.org/r/20200222170154.GA119396@e50d7db646c3 Signed-off-by: Mark Brown --- sound/soc/meson/aiu-encoder-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encoder-i2s.c index cc73b5d5c2b7..832e22d275fe 100644 --- a/sound/soc/meson/aiu-encoder-i2s.c +++ b/sound/soc/meson/aiu-encoder-i2s.c @@ -126,7 +126,7 @@ static int aiu_encoder_i2s_set_legacy_div(struct snd_soc_component *component, default: dev_err(component->dev, "Unsupported i2s divider: %u\n", bs); return -EINVAL; - }; + } snd_soc_component_update_bits(component, AIU_CLK_CTRL, AIU_CLK_CTRL_I2S_DIV, From 94e99b194e5fc024c12f1194f3a08471cea51177 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 28 Oct 2019 17:51:36 -0500 Subject: [PATCH 0676/4444] PCI: tegra: Use pci_parse_request_of_pci_ranges() Convert Tegra PCI host driver to use the common pci_parse_request_of_pci_ranges(). This allows removing the DT ranges parsing, PCI resource handling, and private storage of resources from the driver. Tested-by: Vidya Sagar Signed-off-by: Rob Herring Signed-off-by: Lorenzo Pieralisi Acked-by: Thierry Reding Cc: Thierry Reding Cc: Lorenzo Pieralisi Cc: Andrew Murray Cc: Bjorn Helgaas Cc: Jonathan Hunter Cc: linux-tegra@vger.kernel.org --- drivers/pci/controller/pci-tegra.c | 183 +++++++---------------------- 1 file changed, 44 insertions(+), 139 deletions(-) diff --git a/drivers/pci/controller/pci-tegra.c b/drivers/pci/controller/pci-tegra.c index 0e03cef72840..3e64ba6a36a8 100644 --- a/drivers/pci/controller/pci-tegra.c +++ b/drivers/pci/controller/pci-tegra.c @@ -355,16 +355,6 @@ struct tegra_pcie { int irq; struct resource cs; - struct resource io; - struct resource pio; - struct resource mem; - struct resource prefetch; - struct resource busn; - - struct { - resource_size_t mem; - resource_size_t io; - } offset; struct clk *pex_clk; struct clk *afi_clk; @@ -797,38 +787,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0bf1, tegra_pcie_relax_enable); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0e1c, tegra_pcie_relax_enable); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0e1d, tegra_pcie_relax_enable); -static int tegra_pcie_request_resources(struct tegra_pcie *pcie) -{ - struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); - struct list_head *windows = &host->windows; - struct device *dev = pcie->dev; - int err; - - pci_add_resource_offset(windows, &pcie->pio, pcie->offset.io); - pci_add_resource_offset(windows, &pcie->mem, pcie->offset.mem); - pci_add_resource_offset(windows, &pcie->prefetch, pcie->offset.mem); - pci_add_resource(windows, &pcie->busn); - - err = devm_request_pci_bus_resources(dev, windows); - if (err < 0) { - pci_free_resource_list(windows); - return err; - } - - pci_remap_iospace(&pcie->pio, pcie->io.start); - - return 0; -} - -static void tegra_pcie_free_resources(struct tegra_pcie *pcie) -{ - struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); - struct list_head *windows = &host->windows; - - pci_unmap_iospace(&pcie->pio); - pci_free_resource_list(windows); -} - static int tegra_pcie_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin) { struct tegra_pcie *pcie = pdev->bus->sysdata; @@ -909,36 +867,49 @@ static irqreturn_t tegra_pcie_isr(int irq, void *arg) */ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie) { - u32 fpci_bar, size, axi_address; + u32 size; + struct resource_entry *entry; + struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); /* Bar 0: type 1 extended configuration space */ size = resource_size(&pcie->cs); afi_writel(pcie, pcie->cs.start, AFI_AXI_BAR0_START); afi_writel(pcie, size >> 12, AFI_AXI_BAR0_SZ); - /* Bar 1: downstream IO bar */ - fpci_bar = 0xfdfc0000; - size = resource_size(&pcie->io); - axi_address = pcie->io.start; - afi_writel(pcie, axi_address, AFI_AXI_BAR1_START); - afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ); - afi_writel(pcie, fpci_bar, AFI_FPCI_BAR1); + resource_list_for_each_entry(entry, &bridge->windows) { + u32 fpci_bar, axi_address; + struct resource *res = entry->res; - /* Bar 2: prefetchable memory BAR */ - fpci_bar = (((pcie->prefetch.start >> 12) & 0x0fffffff) << 4) | 0x1; - size = resource_size(&pcie->prefetch); - axi_address = pcie->prefetch.start; - afi_writel(pcie, axi_address, AFI_AXI_BAR2_START); - afi_writel(pcie, size >> 12, AFI_AXI_BAR2_SZ); - afi_writel(pcie, fpci_bar, AFI_FPCI_BAR2); + size = resource_size(res); - /* Bar 3: non prefetchable memory BAR */ - fpci_bar = (((pcie->mem.start >> 12) & 0x0fffffff) << 4) | 0x1; - size = resource_size(&pcie->mem); - axi_address = pcie->mem.start; - afi_writel(pcie, axi_address, AFI_AXI_BAR3_START); - afi_writel(pcie, size >> 12, AFI_AXI_BAR3_SZ); - afi_writel(pcie, fpci_bar, AFI_FPCI_BAR3); + switch (resource_type(res)) { + case IORESOURCE_IO: + /* Bar 1: downstream IO bar */ + fpci_bar = 0xfdfc0000; + axi_address = pci_pio_to_address(res->start); + afi_writel(pcie, axi_address, AFI_AXI_BAR1_START); + afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ); + afi_writel(pcie, fpci_bar, AFI_FPCI_BAR1); + break; + case IORESOURCE_MEM: + fpci_bar = (((res->start >> 12) & 0x0fffffff) << 4) | 0x1; + axi_address = res->start; + + if (res->flags & IORESOURCE_PREFETCH) { + /* Bar 2: prefetchable memory BAR */ + afi_writel(pcie, axi_address, AFI_AXI_BAR2_START); + afi_writel(pcie, size >> 12, AFI_AXI_BAR2_SZ); + afi_writel(pcie, fpci_bar, AFI_FPCI_BAR2); + + } else { + /* Bar 3: non prefetchable memory BAR */ + afi_writel(pcie, axi_address, AFI_AXI_BAR3_START); + afi_writel(pcie, size >> 12, AFI_AXI_BAR3_SZ); + afi_writel(pcie, fpci_bar, AFI_FPCI_BAR3); + } + break; + } + } /* NULL out the remaining BARs as they are not used */ afi_writel(pcie, 0, AFI_AXI_BAR4_START); @@ -2157,76 +2128,10 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) struct device *dev = pcie->dev; struct device_node *np = dev->of_node, *port; const struct tegra_pcie_soc *soc = pcie->soc; - struct of_pci_range_parser parser; - struct of_pci_range range; u32 lanes = 0, mask = 0; unsigned int lane = 0; - struct resource res; int err; - if (of_pci_range_parser_init(&parser, np)) { - dev_err(dev, "missing \"ranges\" property\n"); - return -EINVAL; - } - - for_each_of_pci_range(&parser, &range) { - err = of_pci_range_to_resource(&range, np, &res); - if (err < 0) - return err; - - switch (res.flags & IORESOURCE_TYPE_BITS) { - case IORESOURCE_IO: - /* Track the bus -> CPU I/O mapping offset. */ - pcie->offset.io = res.start - range.pci_addr; - - memcpy(&pcie->pio, &res, sizeof(res)); - pcie->pio.name = np->full_name; - - /* - * The Tegra PCIe host bridge uses this to program the - * mapping of the I/O space to the physical address, - * so we override the .start and .end fields here that - * of_pci_range_to_resource() converted to I/O space. - * We also set the IORESOURCE_MEM type to clarify that - * the resource is in the physical memory space. - */ - pcie->io.start = range.cpu_addr; - pcie->io.end = range.cpu_addr + range.size - 1; - pcie->io.flags = IORESOURCE_MEM; - pcie->io.name = "I/O"; - - memcpy(&res, &pcie->io, sizeof(res)); - break; - - case IORESOURCE_MEM: - /* - * Track the bus -> CPU memory mapping offset. This - * assumes that the prefetchable and non-prefetchable - * regions will be the last of type IORESOURCE_MEM in - * the ranges property. - * */ - pcie->offset.mem = res.start - range.pci_addr; - - if (res.flags & IORESOURCE_PREFETCH) { - memcpy(&pcie->prefetch, &res, sizeof(res)); - pcie->prefetch.name = "prefetchable"; - } else { - memcpy(&pcie->mem, &res, sizeof(res)); - pcie->mem.name = "non-prefetchable"; - } - break; - } - } - - err = of_pci_parse_bus_range(np, &pcie->busn); - if (err < 0) { - dev_err(dev, "failed to parse ranges property: %d\n", err); - pcie->busn.name = np->name; - pcie->busn.start = 0; - pcie->busn.end = 0xff; - pcie->busn.flags = IORESOURCE_BUS; - } - /* parse root ports */ for_each_child_of_node(np, port) { struct tegra_pcie_port *rp; @@ -2766,6 +2671,7 @@ static int tegra_pcie_probe(struct platform_device *pdev) struct pci_host_bridge *host; struct tegra_pcie *pcie; struct pci_bus *child; + struct resource *bus; int err; host = devm_pci_alloc_host_bridge(dev, sizeof(*pcie)); @@ -2780,6 +2686,12 @@ static int tegra_pcie_probe(struct platform_device *pdev) INIT_LIST_HEAD(&pcie->ports); pcie->dev = dev; + err = pci_parse_request_of_pci_ranges(dev, &host->windows, NULL, &bus); + if (err) { + dev_err(dev, "Getting bridge resources failed\n"); + return err; + } + err = tegra_pcie_parse_dt(pcie); if (err < 0) return err; @@ -2803,11 +2715,7 @@ static int tegra_pcie_probe(struct platform_device *pdev) goto teardown_msi; } - err = tegra_pcie_request_resources(pcie); - if (err) - goto pm_runtime_put; - - host->busnr = pcie->busn.start; + host->busnr = bus->start; host->dev.parent = &pdev->dev; host->ops = &tegra_pcie_ops; host->map_irq = tegra_pcie_map_irq; @@ -2816,7 +2724,7 @@ static int tegra_pcie_probe(struct platform_device *pdev) err = pci_scan_root_bus_bridge(host); if (err < 0) { dev_err(dev, "failed to register host: %d\n", err); - goto free_resources; + goto pm_runtime_put; } pci_bus_size_bridges(host->bus); @@ -2835,8 +2743,6 @@ static int tegra_pcie_probe(struct platform_device *pdev) return 0; -free_resources: - tegra_pcie_free_resources(pcie); pm_runtime_put: pm_runtime_put_sync(pcie->dev); pm_runtime_disable(pcie->dev); @@ -2858,7 +2764,6 @@ static int tegra_pcie_remove(struct platform_device *pdev) pci_stop_root_bus(host->bus); pci_remove_root_bus(host->bus); - tegra_pcie_free_resources(pcie); pm_runtime_put_sync(pcie->dev); pm_runtime_disable(pcie->dev); From 7cb819c856d9668f6146ba3caa46d54efb17d9e9 Mon Sep 17 00:00:00 2001 From: Pierre-Yves MORDRET Date: Mon, 27 Jan 2020 09:53:29 +0100 Subject: [PATCH 0677/4444] dmaengine: stm32-mdma: add suspend/resume power management support Add suspend/resume power management relying on PM Runtime engine. Signed-off-by: Pierre-Yves MORDRET Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200127085334.13163-2-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-mdma.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c index 5838311cf990..2898411941d5 100644 --- a/drivers/dma/stm32-mdma.c +++ b/drivers/dma/stm32-mdma.c @@ -1697,7 +1697,40 @@ static int stm32_mdma_runtime_resume(struct device *dev) } #endif +#ifdef CONFIG_PM_SLEEP +static int stm32_mdma_pm_suspend(struct device *dev) +{ + struct stm32_mdma_device *dmadev = dev_get_drvdata(dev); + u32 ccr, id; + int ret; + + ret = pm_runtime_get_sync(dev); + if (ret < 0) + return ret; + + for (id = 0; id < dmadev->nr_channels; id++) { + ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(id)); + if (ccr & STM32_MDMA_CCR_EN) { + dev_warn(dev, "Suspend is prevented by Chan %i\n", id); + return -EBUSY; + } + } + + pm_runtime_put_sync(dev); + + pm_runtime_force_suspend(dev); + + return 0; +} + +static int stm32_mdma_pm_resume(struct device *dev) +{ + return pm_runtime_force_resume(dev); +} +#endif + static const struct dev_pm_ops stm32_mdma_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(stm32_mdma_pm_suspend, stm32_mdma_pm_resume) SET_RUNTIME_PM_OPS(stm32_mdma_runtime_suspend, stm32_mdma_runtime_resume, NULL) }; From 54d50c8184f69947949ab004f80552ceee3f6ea1 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Mon, 27 Jan 2020 09:53:30 +0100 Subject: [PATCH 0678/4444] dmaengine: stm32-mdma: use reset controller only at probe time Remove reset controller reference from device instance since it is used only at probe time. Signed-off-by: Etienne Carriere Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200127085334.13163-3-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-mdma.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c index 2898411941d5..a0fb80dfb2e9 100644 --- a/drivers/dma/stm32-mdma.c +++ b/drivers/dma/stm32-mdma.c @@ -273,7 +273,6 @@ struct stm32_mdma_device { void __iomem *base; struct clk *clk; int irq; - struct reset_control *rst; u32 nr_channels; u32 nr_requests; u32 nr_ahb_addr_masks; @@ -1532,6 +1531,7 @@ static int stm32_mdma_probe(struct platform_device *pdev) struct dma_device *dd; struct device_node *of_node; struct resource *res; + struct reset_control *rst; u32 nr_channels, nr_requests; int i, count, ret; @@ -1590,11 +1590,11 @@ static int stm32_mdma_probe(struct platform_device *pdev) return ret; } - dmadev->rst = devm_reset_control_get(&pdev->dev, NULL); - if (!IS_ERR(dmadev->rst)) { - reset_control_assert(dmadev->rst); + rst = devm_reset_control_get(&pdev->dev, NULL); + if (!IS_ERR(rst)) { + reset_control_assert(rst); udelay(2); - reset_control_deassert(dmadev->rst); + reset_control_deassert(rst); } dd = &dmadev->ddev; From cb0bc2d09166e4d46cec82af6981cbf5aa01b158 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Mon, 27 Jan 2020 09:53:31 +0100 Subject: [PATCH 0679/4444] dmaengine: stm32-mdma: disable clock in case of error during probe This patch disables the clock in case of error during probe. The unneeded err_unregister label is renamed err_clk instead. Signed-off-by: Etienne Carriere Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200127085334.13163-4-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-mdma.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c index a0fb80dfb2e9..f23c82e3990c 100644 --- a/drivers/dma/stm32-mdma.c +++ b/drivers/dma/stm32-mdma.c @@ -1637,25 +1637,27 @@ static int stm32_mdma_probe(struct platform_device *pdev) } dmadev->irq = platform_get_irq(pdev, 0); - if (dmadev->irq < 0) - return dmadev->irq; + if (dmadev->irq < 0) { + ret = dmadev->irq; + goto err_clk; + } ret = devm_request_irq(&pdev->dev, dmadev->irq, stm32_mdma_irq_handler, 0, dev_name(&pdev->dev), dmadev); if (ret) { dev_err(&pdev->dev, "failed to request IRQ\n"); - return ret; + goto err_clk; } ret = dmaenginem_async_device_register(dd); if (ret) - return ret; + goto err_clk; ret = of_dma_controller_register(of_node, stm32_mdma_of_xlate, dmadev); if (ret < 0) { dev_err(&pdev->dev, "STM32 MDMA DMA OF registration failed %d\n", ret); - goto err_unregister; + goto err_clk; } platform_set_drvdata(pdev, dmadev); @@ -1668,7 +1670,9 @@ static int stm32_mdma_probe(struct platform_device *pdev) return 0; -err_unregister: +err_clk: + clk_disable_unprepare(dmadev->clk); + return ret; } From 56cf8ddaa3115db5543d2a49b669bf4010eaff19 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Mon, 27 Jan 2020 09:53:32 +0100 Subject: [PATCH 0680/4444] dmaengine: stm32-mdma: driver defers probe for clock and reset This patch changes error log when failing to get the clock so that it is not printed on failure with probe deferring. It also defers probe when reset controller is expected but has not been probed yet when MDMA device is probed. Signed-off-by: Etienne Carriere Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200127085334.13163-5-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-mdma.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c index f23c82e3990c..2dbd1f38a6f5 100644 --- a/drivers/dma/stm32-mdma.c +++ b/drivers/dma/stm32-mdma.c @@ -1579,8 +1579,8 @@ static int stm32_mdma_probe(struct platform_device *pdev) dmadev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(dmadev->clk)) { ret = PTR_ERR(dmadev->clk); - if (ret == -EPROBE_DEFER) - dev_info(&pdev->dev, "Missing controller clock\n"); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Missing clock controller\n"); return ret; } @@ -1591,7 +1591,11 @@ static int stm32_mdma_probe(struct platform_device *pdev) } rst = devm_reset_control_get(&pdev->dev, NULL); - if (!IS_ERR(rst)) { + if (IS_ERR(rst)) { + ret = PTR_ERR(rst); + if (ret == -EPROBE_DEFER) + goto err_clk; + } else { reset_control_assert(rst); udelay(2); reset_control_deassert(rst); From 542fbc463aabdd93c2d3db7f604903f357a0ebf8 Mon Sep 17 00:00:00 2001 From: Pierre-Yves MORDRET Date: Mon, 27 Jan 2020 09:53:33 +0100 Subject: [PATCH 0681/4444] dmaengine: stm32-mdma: enable descriptor_reuse Enable descriptor reuse to allow client to resubmit already processed descriptors in order to save descriptor creation time. Signed-off-by: Pierre-Yves MORDRET Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200127085334.13163-6-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-mdma.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c index 2dbd1f38a6f5..f2043f47ae9e 100644 --- a/drivers/dma/stm32-mdma.c +++ b/drivers/dma/stm32-mdma.c @@ -1618,6 +1618,8 @@ static int stm32_mdma_probe(struct platform_device *pdev) dd->device_resume = stm32_mdma_resume; dd->device_terminate_all = stm32_mdma_terminate_all; dd->device_synchronize = stm32_mdma_synchronize; + dd->descriptor_reuse = true; + dd->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | From dfc708812a2acfc0ca56f56233b3c3e7b0d4ffe7 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Mon, 27 Jan 2020 09:53:34 +0100 Subject: [PATCH 0682/4444] dmaengine: stm32-mdma: use vchan_terminate_vdesc() in .terminate_all To avoid race with vchan_complete, use the race free way to terminate running transfer. Move vdesc->node list_del in stm32_mdma_start_transfer instead of in stm32_mdma_xfer_end to avoid another race in vchan_dma_desc_free_list. Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200127085334.13163-7-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-mdma.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c index f2043f47ae9e..5469563703d1 100644 --- a/drivers/dma/stm32-mdma.c +++ b/drivers/dma/stm32-mdma.c @@ -1126,6 +1126,8 @@ static void stm32_mdma_start_transfer(struct stm32_mdma_chan *chan) return; } + list_del(&vdesc->node); + chan->desc = to_stm32_mdma_desc(vdesc); hwdesc = chan->desc->node[0].hwdesc; chan->curr_hwdesc = 0; @@ -1241,8 +1243,10 @@ static int stm32_mdma_terminate_all(struct dma_chan *c) LIST_HEAD(head); spin_lock_irqsave(&chan->vchan.lock, flags); - if (chan->busy) { - stm32_mdma_stop(chan); + if (chan->desc) { + vchan_terminate_vdesc(&chan->desc->vdesc); + if (chan->busy) + stm32_mdma_stop(chan); chan->desc = NULL; } vchan_get_all_descriptors(&chan->vchan, &head); @@ -1330,7 +1334,6 @@ static enum dma_status stm32_mdma_tx_status(struct dma_chan *c, static void stm32_mdma_xfer_end(struct stm32_mdma_chan *chan) { - list_del(&chan->desc->vdesc.node); vchan_cookie_complete(&chan->desc->vdesc); chan->desc = NULL; chan->busy = false; From f65c2e14b096736585aa04cb7a43d5d54d287ddd Mon Sep 17 00:00:00 2001 From: Pierre-Yves MORDRET Date: Tue, 28 Jan 2020 10:41:55 +0100 Subject: [PATCH 0683/4444] dmaengine: stm32-dmamux: add suspend/resume power management support Add suspend/resume power management relying on PM Runtime engine. Signed-off-by: Pierre-Yves MORDRET Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200128094158.20361-2-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-dmamux.c | 50 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/drivers/dma/stm32-dmamux.c b/drivers/dma/stm32-dmamux.c index 3c89bd39e096..08d2395c8943 100644 --- a/drivers/dma/stm32-dmamux.c +++ b/drivers/dma/stm32-dmamux.c @@ -41,6 +41,9 @@ struct stm32_dmamux_data { u32 dmamux_requests; /* Number of DMA requests routed toward DMAs */ spinlock_t lock; /* Protects register access */ unsigned long *dma_inuse; /* Used DMA channel */ + u32 ccr[STM32_DMAMUX_MAX_DMA_REQUESTS]; /* Used to backup CCR register + * in suspend + */ u32 dma_reqs[]; /* Number of DMA Request per DMA masters. * [0] holds number of DMA Masters. * To be kept at very end end of this structure @@ -318,7 +321,54 @@ static int stm32_dmamux_runtime_resume(struct device *dev) } #endif +#ifdef CONFIG_PM_SLEEP +static int stm32_dmamux_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct stm32_dmamux_data *stm32_dmamux = platform_get_drvdata(pdev); + int i, ret; + + ret = pm_runtime_get_sync(dev); + if (ret < 0) + return ret; + + for (i = 0; i < stm32_dmamux->dma_requests; i++) + stm32_dmamux->ccr[i] = stm32_dmamux_read(stm32_dmamux->iomem, + STM32_DMAMUX_CCR(i)); + + pm_runtime_put_sync(dev); + + pm_runtime_force_suspend(dev); + + return 0; +} + +static int stm32_dmamux_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct stm32_dmamux_data *stm32_dmamux = platform_get_drvdata(pdev); + int i, ret; + + ret = pm_runtime_force_resume(dev); + if (ret < 0) + return ret; + + ret = pm_runtime_get_sync(dev); + if (ret < 0) + return ret; + + for (i = 0; i < stm32_dmamux->dma_requests; i++) + stm32_dmamux_write(stm32_dmamux->iomem, STM32_DMAMUX_CCR(i), + stm32_dmamux->ccr[i]); + + pm_runtime_put_sync(dev); + + return 0; +} +#endif + static const struct dev_pm_ops stm32_dmamux_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(stm32_dmamux_suspend, stm32_dmamux_resume) SET_RUNTIME_PM_OPS(stm32_dmamux_runtime_suspend, stm32_dmamux_runtime_resume, NULL) }; From 57e9f3666a1ba54500b1f61b279f994ac2f23de9 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Tue, 28 Jan 2020 10:41:56 +0100 Subject: [PATCH 0684/4444] dmaengine: stm32-dmamux: fix clock handling in probe sequence This change ensures the DMAMUX device is reset only once it is clocked and that clock is released in a safe state when probe operation fails. Signed-off-by: Etienne Carriere Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200128094158.20361-3-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-dmamux.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/dma/stm32-dmamux.c b/drivers/dma/stm32-dmamux.c index 08d2395c8943..a862d3339fb7 100644 --- a/drivers/dma/stm32-dmamux.c +++ b/drivers/dma/stm32-dmamux.c @@ -259,6 +259,12 @@ static int stm32_dmamux_probe(struct platform_device *pdev) return ret; } + ret = clk_prepare_enable(stm32_dmamux->clk); + if (ret < 0) { + dev_err(&pdev->dev, "clk_prep_enable error: %d\n", ret); + return ret; + } + stm32_dmamux->rst = devm_reset_control_get(&pdev->dev, NULL); if (!IS_ERR(stm32_dmamux->rst)) { reset_control_assert(stm32_dmamux->rst); @@ -274,14 +280,6 @@ static int stm32_dmamux_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); - if (!IS_ERR(stm32_dmamux->clk)) { - ret = clk_prepare_enable(stm32_dmamux->clk); - if (ret < 0) { - dev_err(&pdev->dev, "clk_prep_enable error: %d\n", ret); - return ret; - } - } - pm_runtime_get_noresume(&pdev->dev); /* Reset the dmamux */ @@ -290,8 +288,12 @@ static int stm32_dmamux_probe(struct platform_device *pdev) pm_runtime_put(&pdev->dev); - return of_dma_router_register(node, stm32_dmamux_route_allocate, + ret = of_dma_router_register(node, stm32_dmamux_route_allocate, &stm32_dmamux->dmarouter); + if (ret) + clk_disable_unprepare(stm32_dmamux->clk); + + return ret; } #ifdef CONFIG_PM From d04d2f620dcfd6baddd276f6dad5268c17c70aa1 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Tue, 28 Jan 2020 10:41:57 +0100 Subject: [PATCH 0685/4444] dmaengine: stm32-dmamux: use reset controller only at probe time Remove reset controller reference from device instance since it is used only at probe time. Signed-off-by: Etienne Carriere Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200128094158.20361-4-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-dmamux.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/dma/stm32-dmamux.c b/drivers/dma/stm32-dmamux.c index a862d3339fb7..1dfecbac64cf 100644 --- a/drivers/dma/stm32-dmamux.c +++ b/drivers/dma/stm32-dmamux.c @@ -35,7 +35,6 @@ struct stm32_dmamux { struct stm32_dmamux_data { struct dma_router dmarouter; struct clk *clk; - struct reset_control *rst; void __iomem *iomem; u32 dma_requests; /* Number of DMA requests connected to DMAMUX */ u32 dmamux_requests; /* Number of DMA requests routed toward DMAs */ @@ -182,6 +181,7 @@ static int stm32_dmamux_probe(struct platform_device *pdev) struct stm32_dmamux_data *stm32_dmamux; struct resource *res; void __iomem *iomem; + struct reset_control *rst; int i, count, ret; u32 dma_req; @@ -265,11 +265,11 @@ static int stm32_dmamux_probe(struct platform_device *pdev) return ret; } - stm32_dmamux->rst = devm_reset_control_get(&pdev->dev, NULL); - if (!IS_ERR(stm32_dmamux->rst)) { - reset_control_assert(stm32_dmamux->rst); + rst = devm_reset_control_get(&pdev->dev, NULL); + if (!IS_ERR(rst)) { + reset_control_assert(rst); udelay(2); - reset_control_deassert(stm32_dmamux->rst); + reset_control_deassert(rst); } stm32_dmamux->iomem = iomem; From 6cc7089764ab88784cd82895d819e882f01942ce Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Tue, 28 Jan 2020 10:41:58 +0100 Subject: [PATCH 0686/4444] dmaengine: stm32-dmamux: driver defers probe for clock and reset Changes STM32 DMAMUX driver to defer its probe operation when reset controller is expected but has not been probed yet. Changes error traces when failing to get a system resource so that it is not printed on failure with deferred probing. Signed-off-by: Etienne Carriere Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200128094158.20361-5-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-dmamux.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/dma/stm32-dmamux.c b/drivers/dma/stm32-dmamux.c index 1dfecbac64cf..12f7637e13a1 100644 --- a/drivers/dma/stm32-dmamux.c +++ b/drivers/dma/stm32-dmamux.c @@ -254,8 +254,8 @@ static int stm32_dmamux_probe(struct platform_device *pdev) stm32_dmamux->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(stm32_dmamux->clk)) { ret = PTR_ERR(stm32_dmamux->clk); - if (ret == -EPROBE_DEFER) - dev_info(&pdev->dev, "Missing controller clock\n"); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Missing clock controller\n"); return ret; } @@ -266,7 +266,11 @@ static int stm32_dmamux_probe(struct platform_device *pdev) } rst = devm_reset_control_get(&pdev->dev, NULL); - if (!IS_ERR(rst)) { + if (IS_ERR(rst)) { + ret = PTR_ERR(rst); + if (ret == -EPROBE_DEFER) + goto err_clk; + } else { reset_control_assert(rst); udelay(2); reset_control_deassert(rst); @@ -291,7 +295,12 @@ static int stm32_dmamux_probe(struct platform_device *pdev) ret = of_dma_router_register(node, stm32_dmamux_route_allocate, &stm32_dmamux->dmarouter); if (ret) - clk_disable_unprepare(stm32_dmamux->clk); + goto err_clk; + + return 0; + +err_clk: + clk_disable_unprepare(stm32_dmamux->clk); return ret; } From 2575cb81a9662ab69ad4a66e29cbc9708d6cc90c Mon Sep 17 00:00:00 2001 From: Radhey Shyam Pandey Date: Wed, 29 Jan 2020 13:15:09 +0530 Subject: [PATCH 0687/4444] dmaengine: xilinx_dma: Reset DMA channel in dma_terminate_all Reset DMA channel after stop to ensure that pending transfers and FIFOs in the datapath are flushed or completed. It also cleanup the terminate path and removes stop for the cyclic mode as after the reset stop is not required. This fixes intermittent data verification failure when xilinx dma test the client is stressed and loaded/unloaded multiple times. Signed-off-by: Radhey Shyam Pandey Link: https://lore.kernel.org/r/1580283909-32678-1-git-send-email-radhey.shyam.pandey@xilinx.com Signed-off-by: Vinod Koul --- drivers/dma/xilinx/xilinx_dma.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index a9c5d5cc9f2b..6f1539cad1ee 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -2404,16 +2404,17 @@ static int xilinx_dma_terminate_all(struct dma_chan *dchan) u32 reg; int err; - if (chan->cyclic) - xilinx_dma_chan_reset(chan); - - err = chan->stop_transfer(chan); - if (err) { - dev_err(chan->dev, "Cannot stop channel %p: %x\n", - chan, dma_ctrl_read(chan, XILINX_DMA_REG_DMASR)); - chan->err = true; + if (!chan->cyclic) { + err = chan->stop_transfer(chan); + if (err) { + dev_err(chan->dev, "Cannot stop channel %p: %x\n", + chan, dma_ctrl_read(chan, + XILINX_DMA_REG_DMASR)); + chan->err = true; + } } + xilinx_dma_chan_reset(chan); /* Remove and free all of the descriptors in the lists */ xilinx_dma_free_descriptors(chan); chan->idle = true; From 5b11e5d784c2dab41cd3171f4d297bdcac1b85ed Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Thu, 20 Feb 2020 21:58:12 -0300 Subject: [PATCH 0688/4444] power/supply: ingenic-battery: Don't print error on -EPROBE_DEFER Don't print an error message if devm_power_supply_register() returns -EPROBE_DEFER, since the driver will simply re-probe later. Signed-off-by: Paul Cercueil Signed-off-by: Sebastian Reichel --- drivers/power/supply/ingenic-battery.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/ingenic-battery.c b/drivers/power/supply/ingenic-battery.c index 2748715c4c75..dd3d93dfe3eb 100644 --- a/drivers/power/supply/ingenic-battery.c +++ b/drivers/power/supply/ingenic-battery.c @@ -148,7 +148,8 @@ static int ingenic_battery_probe(struct platform_device *pdev) bat->battery = devm_power_supply_register(dev, desc, &psy_cfg); if (IS_ERR(bat->battery)) { - dev_err(dev, "Unable to register battery\n"); + if (PTR_ERR(bat->battery) != -EPROBE_DEFER) + dev_err(dev, "Unable to register battery\n"); return PTR_ERR(bat->battery); } From 1c5dfc5e3f2df5892a849621d729daa87cfef436 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Fri, 14 Feb 2020 13:38:58 +0800 Subject: [PATCH 0689/4444] power: supply: sc27xx: Add POWER_SUPPLY_PROP_CHARGE_NOW attribute Add the POWER_SUPPLY_PROP_CHARGE_NOW attribute to allow user to get current battery capacity (uAh) to do measurement. Signed-off-by: Baolin Wang Signed-off-by: Sebastian Reichel --- drivers/power/supply/sc27xx_fuel_gauge.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c index 469c83fdaa8e..a7c8a8453db1 100644 --- a/drivers/power/supply/sc27xx_fuel_gauge.c +++ b/drivers/power/supply/sc27xx_fuel_gauge.c @@ -614,6 +614,17 @@ static int sc27xx_fgu_get_property(struct power_supply *psy, val->intval = data->total_cap * 1000; break; + case POWER_SUPPLY_PROP_CHARGE_NOW: + ret = sc27xx_fgu_get_clbcnt(data, &value); + if (ret) + goto error; + + value = DIV_ROUND_CLOSEST(value * 10, + 36 * SC27XX_FGU_SAMPLE_HZ); + val->intval = sc27xx_fgu_adc_to_current(data, value); + + break; + default: ret = -EINVAL; break; @@ -682,6 +693,7 @@ static enum power_supply_property sc27xx_fgu_props[] = { POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, POWER_SUPPLY_PROP_CALIBRATE, + POWER_SUPPLY_PROP_CHARGE_NOW }; static const struct power_supply_desc sc27xx_fgu_desc = { From 974c086045446a7cdad5de26ff691d9ac82a24a6 Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 12 Feb 2020 13:44:16 -0800 Subject: [PATCH 0690/4444] scsi: qla2xxx: Add endianizer macro calls to fc host stats This patch fixes endian warning for fc_host_stats. Link: https://lore.kernel.org/r/20200212214436.25532-6-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_attr.c | 36 ++++++++++------- drivers/scsi/qla2xxx/qla_def.h | 69 ++++++++++++++++----------------- 2 files changed, 54 insertions(+), 51 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 401b5ee1f1e6..97cabd7e0014 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -2745,22 +2745,28 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) if (rval != QLA_SUCCESS) goto done_free; - p->link_failure_count = stats->link_fail_cnt; - p->loss_of_sync_count = stats->loss_sync_cnt; - p->loss_of_signal_count = stats->loss_sig_cnt; - p->prim_seq_protocol_err_count = stats->prim_seq_err_cnt; - p->invalid_tx_word_count = stats->inval_xmit_word_cnt; - p->invalid_crc_count = stats->inval_crc_cnt; + p->link_failure_count = le32_to_cpu(stats->link_fail_cnt); + p->loss_of_sync_count = le32_to_cpu(stats->loss_sync_cnt); + p->loss_of_signal_count = le32_to_cpu(stats->loss_sig_cnt); + p->prim_seq_protocol_err_count = le32_to_cpu(stats->prim_seq_err_cnt); + p->invalid_tx_word_count = le32_to_cpu(stats->inval_xmit_word_cnt); + p->invalid_crc_count = le32_to_cpu(stats->inval_crc_cnt); if (IS_FWI2_CAPABLE(ha)) { - p->lip_count = stats->lip_cnt; - p->tx_frames = stats->tx_frames; - p->rx_frames = stats->rx_frames; - p->dumped_frames = stats->discarded_frames; - p->nos_count = stats->nos_rcvd; + p->lip_count = le32_to_cpu(stats->lip_cnt); + p->tx_frames = le32_to_cpu(stats->tx_frames); + p->rx_frames = le32_to_cpu(stats->rx_frames); + p->dumped_frames = le32_to_cpu(stats->discarded_frames); + p->nos_count = le32_to_cpu(stats->nos_rcvd); p->error_frames = - stats->dropped_frames + stats->discarded_frames; - p->rx_words = vha->qla_stats.input_bytes; - p->tx_words = vha->qla_stats.output_bytes; + le32_to_cpu(stats->dropped_frames) + + le32_to_cpu(stats->discarded_frames); + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + p->rx_words = le64_to_cpu(stats->fpm_recv_word_cnt); + p->tx_words = le64_to_cpu(stats->fpm_xmit_word_cnt); + } else { + p->rx_words = vha->qla_stats.input_bytes; + p->tx_words = vha->qla_stats.output_bytes; + } } p->fcp_control_requests = vha->qla_stats.control_requests; p->fcp_input_requests = vha->qla_stats.input_requests; @@ -2768,7 +2774,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) p->fcp_input_megabytes = vha->qla_stats.input_bytes >> 20; p->fcp_output_megabytes = vha->qla_stats.output_bytes >> 20; p->seconds_since_last_reset = - get_jiffies_64() - vha->qla_stats.jiffies_at_last_reset; + get_jiffies_64() - vha->qla_stats.jiffies_at_last_reset; do_div(p->seconds_since_last_reset, HZ); done_free: diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 22f859bef778..3021736d0abd 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1475,47 +1475,44 @@ typedef struct { #define GLSO_USE_DID BIT_3 struct link_statistics { - uint32_t link_fail_cnt; - uint32_t loss_sync_cnt; - uint32_t loss_sig_cnt; - uint32_t prim_seq_err_cnt; - uint32_t inval_xmit_word_cnt; - uint32_t inval_crc_cnt; - uint32_t lip_cnt; - uint32_t link_up_cnt; - uint32_t link_down_loop_init_tmo; - uint32_t link_down_los; - uint32_t link_down_loss_rcv_clk; + __le32 link_fail_cnt; + __le32 loss_sync_cnt; + __le32 loss_sig_cnt; + __le32 prim_seq_err_cnt; + __le32 inval_xmit_word_cnt; + __le32 inval_crc_cnt; + __le32 lip_cnt; + __le32 link_up_cnt; + __le32 link_down_loop_init_tmo; + __le32 link_down_los; + __le32 link_down_loss_rcv_clk; uint32_t reserved0[5]; - uint32_t port_cfg_chg; + __le32 port_cfg_chg; uint32_t reserved1[11]; - uint32_t rsp_q_full; - uint32_t atio_q_full; - uint32_t drop_ae; - uint32_t els_proto_err; - uint32_t reserved2; - uint32_t tx_frames; - uint32_t rx_frames; - uint32_t discarded_frames; - uint32_t dropped_frames; + __le32 rsp_q_full; + __le32 atio_q_full; + __le32 drop_ae; + __le32 els_proto_err; + __le32 reserved2; + __le32 tx_frames; + __le32 rx_frames; + __le32 discarded_frames; + __le32 dropped_frames; uint32_t reserved3; - uint32_t nos_rcvd; + __le32 nos_rcvd; uint32_t reserved4[4]; - uint32_t tx_prjt; - uint32_t rcv_exfail; - uint32_t rcv_abts; - uint32_t seq_frm_miss; - uint32_t corr_err; - uint32_t mb_rqst; - uint32_t nport_full; - uint32_t eofa; + __le32 tx_prjt; + __le32 rcv_exfail; + __le32 rcv_abts; + __le32 seq_frm_miss; + __le32 corr_err; + __le32 mb_rqst; + __le32 nport_full; + __le32 eofa; uint32_t reserved5; - uint32_t fpm_recv_word_cnt_lo; - uint32_t fpm_recv_word_cnt_hi; - uint32_t fpm_disc_word_cnt_lo; - uint32_t fpm_disc_word_cnt_hi; - uint32_t fpm_xmit_word_cnt_lo; - uint32_t fpm_xmit_word_cnt_hi; + __le64 fpm_recv_word_cnt; + __le64 fpm_disc_word_cnt; + __le64 fpm_xmit_word_cnt; uint32_t reserved6[70]; }; From 818c7f87a177781bc155a2bfa39066c89c5a6cdc Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 12 Feb 2020 13:44:17 -0800 Subject: [PATCH 0691/4444] scsi: qla2xxx: Add changes in preparation for vendor extended FDMI/RDP This patch prepares code for implementing Vendor specific extended FDMI/RDP commands. It also addes support for MBC_GET_PORT_DATABASE and MBC_GET_RNID_PARAMS commands. Link: https://lore.kernel.org/r/20200212214436.25532-7-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 3 + drivers/scsi/qla2xxx/qla_fw.h | 4 ++ drivers/scsi/qla2xxx/qla_gbl.h | 12 +++- drivers/scsi/qla2xxx/qla_gs.c | 15 ++-- drivers/scsi/qla2xxx/qla_init.c | 28 +++++--- drivers/scsi/qla2xxx/qla_mbx.c | 121 +++++++++++++++++++++++++++----- drivers/scsi/qla2xxx/qla_mid.c | 3 + drivers/scsi/qla2xxx/qla_os.c | 4 +- 8 files changed, 155 insertions(+), 35 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 3021736d0abd..d3a8fcb22c78 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1261,7 +1261,9 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs) #define MBX_1 BIT_1 #define MBX_0 BIT_0 +#define RNID_TYPE_ELS_CMD 0x5 #define RNID_TYPE_PORT_LOGIN 0x7 +#define RNID_BUFFER_CREDITS 0x8 #define RNID_TYPE_SET_VERSION 0x9 #define RNID_TYPE_ASIC_TEMP 0xC @@ -4459,6 +4461,7 @@ typedef struct scsi_qla_host { uint8_t node_name[WWN_SIZE]; uint8_t port_name[WWN_SIZE]; uint8_t fabric_node_name[WWN_SIZE]; + uint8_t fabric_port_name[WWN_SIZE]; struct nvme_fc_local_port *nvme_local_port; struct completion nvme_del_done; diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index d641918cdd46..02c1dbb4abc8 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -31,6 +31,9 @@ #define PDO_FORCE_ADISC BIT_1 #define PDO_FORCE_PLOGI BIT_0 +struct buffer_credit_24xx { + u32 parameter[28]; +}; #define PORT_DATABASE_24XX_SIZE 64 struct port_database_24xx { @@ -1883,6 +1886,7 @@ struct nvram_81xx { * BIT 6-15 = Unused */ uint16_t enhanced_features; + uint16_t reserved_24[4]; /* Offset 416. */ diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 156ad11a15c4..5b995519a2c1 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -32,6 +32,8 @@ extern int qla81xx_nvram_config(struct scsi_qla_host *); extern void qla2x00_update_fw_options(struct scsi_qla_host *); extern void qla24xx_update_fw_options(scsi_qla_host_t *); extern void qla81xx_update_fw_options(scsi_qla_host_t *); +extern void qla83xx_update_fw_options(scsi_qla_host_t *); + extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *); extern int qla24xx_load_risc(scsi_qla_host_t *, uint32_t *); extern int qla81xx_load_risc(scsi_qla_host_t *, uint32_t *); @@ -142,6 +144,7 @@ extern int qlport_down_retry; extern int ql2xplogiabsentdevice; extern int ql2xloginretrycount; extern int ql2xfdmienable; +extern int ql2xsmartsan; extern int ql2xallocfwdump; extern int ql2xextended_error_logging; extern int ql2xiidmaenable; @@ -353,6 +356,9 @@ qla2x00_init_firmware(scsi_qla_host_t *, uint16_t); extern int qla2x00_get_port_database(scsi_qla_host_t *, fc_port_t *, uint8_t); +extern int +qla24xx_get_port_database(scsi_qla_host_t *, u16, struct port_database_24xx *); + extern int qla2x00_get_firmware_state(scsi_qla_host_t *, uint16_t *); @@ -451,6 +457,10 @@ qla82xx_set_driver_version(scsi_qla_host_t *, char *); extern int qla25xx_set_driver_version(scsi_qla_host_t *, char *); +extern int +qla24xx_get_buffer_credits(scsi_qla_host_t *, struct buffer_credit_24xx *, + dma_addr_t); + extern int qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint8_t *, uint16_t, uint16_t, uint16_t, uint16_t); @@ -656,7 +666,7 @@ extern void *qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t); extern int qla2x00_fdmi_register(scsi_qla_host_t *); extern int qla2x00_gfpn_id(scsi_qla_host_t *, sw_info_t *); extern int qla2x00_gpsc(scsi_qla_host_t *, sw_info_t *); -extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *, size_t); +extern size_t qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *, size_t); extern int qla2x00_chk_ms_status(scsi_qla_host_t *, ms_iocb_entry_t *, struct ct_sns_rsp *, const char *); extern void qla2x00_async_iocb_timeout(void *data); diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index aaa4a5bbf2ff..c01eb87c709f 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -844,19 +844,18 @@ done: return rval; } -void +size_t qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn, size_t size) { struct qla_hw_data *ha = vha->hw; if (IS_QLAFX00(ha)) - snprintf(snn, size, "%s FW:v%s DVR:v%s", ha->model_number, - ha->mr.fw_version, qla2x00_version_str); - else - snprintf(snn, size, - "%s FW:v%d.%02d.%02d DVR:v%s", ha->model_number, - ha->fw_major_version, ha->fw_minor_version, - ha->fw_subminor_version, qla2x00_version_str); + return scnprintf(snn, size, "%s FW:v%s DVR:v%s", + ha->model_number, ha->mr.fw_version, qla2x00_version_str); + + return scnprintf(snn, size, "%s FW:v%d.%02d.%02d DVR:v%s", + ha->model_number, ha->fw_major_version, ha->fw_minor_version, + ha->fw_subminor_version, qla2x00_version_str); } /** diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 9e6b56527b25..9887602529a3 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -5541,24 +5541,22 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) } vha->device_flags |= SWITCH_FOUND; + rval = qla2x00_get_port_name(vha, loop_id, vha->fabric_port_name, 0); + if (rval != QLA_SUCCESS) + ql_dbg(ql_dbg_disc, vha, 0x20ff, + "Failed to get Fabric Port Name\n"); if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) { rval = qla2x00_send_change_request(vha, 0x3, 0); if (rval != QLA_SUCCESS) ql_log(ql_log_warn, vha, 0x121, - "Failed to enable receiving of RSCN requests: 0x%x.\n", - rval); + "Failed to enable receiving of RSCN requests: 0x%x.\n", + rval); } - do { qla2x00_mgmt_svr_login(vha); - /* FDMI support. */ - if (ql2xfdmienable && - test_and_clear_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags)) - qla2x00_fdmi_register(vha); - /* Ensure we are logged into the SNS. */ loop_id = NPH_SNS_LID(ha); rval = ha->isp_ops->fabric_login(vha, loop_id, 0xff, 0xff, @@ -5570,6 +5568,12 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); return rval; } + + /* FDMI support. */ + if (ql2xfdmienable && + test_and_clear_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags)) + qla2x00_fdmi_register(vha); + if (test_and_clear_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags)) { if (qla2x00_rft_id(vha)) { /* EMPTY */ @@ -8663,6 +8667,14 @@ qla82xx_restart_isp(scsi_qla_host_t *vha) return status; } +void +qla83xx_update_fw_options(scsi_qla_host_t *vha) +{ + struct qla_hw_data *ha = vha->hw; + + qla2x00_set_fw_options(vha, ha->fw_options); +} + void qla81xx_update_fw_options(scsi_qla_host_t *vha) { diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index e1916bec5e36..f1c2a9ea5446 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -643,7 +643,6 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr, return rval; } -#define EXTENDED_BB_CREDITS BIT_0 #define NVME_ENABLE_FLAG BIT_3 static inline uint16_t qla25xx_set_sfp_lr_dist(struct qla_hw_data *ha) { @@ -1410,12 +1409,12 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, mcp->mb[0] = MBC_IOCB_COMMAND_A64; mcp->mb[1] = 0; - mcp->mb[2] = MSW(phys_addr); - mcp->mb[3] = LSW(phys_addr); + mcp->mb[2] = MSW(LSD(phys_addr)); + mcp->mb[3] = LSW(LSD(phys_addr)); mcp->mb[6] = MSW(MSD(phys_addr)); mcp->mb[7] = LSW(MSD(phys_addr)); mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; - mcp->in_mb = MBX_2|MBX_0; + mcp->in_mb = MBX_1|MBX_0; mcp->tov = tov; mcp->flags = 0; rval = qla2x00_mailbox_command(vha, mcp); @@ -1424,13 +1423,14 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, /*EMPTY*/ ql_dbg(ql_dbg_mbx, vha, 0x1039, "Failed=%x.\n", rval); } else { - sts_entry_t *sts_entry = (sts_entry_t *) buffer; + sts_entry_t *sts_entry = buffer; /* Mask reserved bits. */ sts_entry->entry_status &= IS_FWI2_CAPABLE(vha->hw) ? RF_MASK_24XX : RF_MASK; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103a, - "Done %s.\n", __func__); + "Done %s (status=%x).\n", __func__, + sts_entry->entry_status); } return rval; @@ -2045,6 +2045,57 @@ gpd_error_out: return rval; } +int +qla24xx_get_port_database(scsi_qla_host_t *vha, u16 nport_handle, + struct port_database_24xx *pdb) +{ + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + dma_addr_t pdb_dma; + int rval; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1115, + "Entered %s.\n", __func__); + + memset(pdb, 0, sizeof(*pdb)); + + pdb_dma = dma_map_single(&vha->hw->pdev->dev, pdb, + sizeof(*pdb), DMA_FROM_DEVICE); + if (!pdb_dma) { + ql_log(ql_log_warn, vha, 0x1116, "Failed to map dma buffer.\n"); + return QLA_MEMORY_ALLOC_FAILED; + } + + mcp->mb[0] = MBC_GET_PORT_DATABASE; + mcp->mb[1] = nport_handle; + mcp->mb[2] = MSW(LSD(pdb_dma)); + mcp->mb[3] = LSW(LSD(pdb_dma)); + mcp->mb[6] = MSW(MSD(pdb_dma)); + mcp->mb[7] = LSW(MSD(pdb_dma)); + mcp->mb[9] = 0; + mcp->mb[10] = 0; + mcp->out_mb = MBX_10|MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->buf_size = sizeof(*pdb); + mcp->flags = MBX_DMA_IN; + mcp->tov = vha->hw->login_timeout * 2; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x111a, + "Failed=%x mb[0]=%x mb[1]=%x.\n", + rval, mcp->mb[0], mcp->mb[1]); + } else { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x111b, + "Done %s.\n", __func__); + } + + dma_unmap_single(&vha->hw->pdev->dev, pdb_dma, + sizeof(*pdb), DMA_FROM_DEVICE); + + return rval; +} + /* * qla2x00_get_firmware_state * Get adapter firmware state. @@ -3060,18 +3111,19 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats, int rval; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - uint32_t *iter, dwords; + uint32_t *iter = (void *)stats; + ushort dwords = sizeof(*stats)/sizeof(*iter); ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1088, "Entered %s.\n", __func__); memset(&mc, 0, sizeof(mc)); mc.mb[0] = MBC_GET_LINK_PRIV_STATS; - mc.mb[2] = MSW(stats_dma); - mc.mb[3] = LSW(stats_dma); + mc.mb[2] = MSW(LSD(stats_dma)); + mc.mb[3] = LSW(LSD(stats_dma)); mc.mb[6] = MSW(MSD(stats_dma)); mc.mb[7] = LSW(MSD(stats_dma)); - mc.mb[8] = sizeof(struct link_statistics) / 4; + mc.mb[8] = dwords; mc.mb[9] = cpu_to_le16(vha->vp_idx); mc.mb[10] = cpu_to_le16(options); @@ -3086,8 +3138,6 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats, ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108a, "Done %s.\n", __func__); /* Re-endianize - firmware data is le32. */ - dwords = sizeof(struct link_statistics) / 4; - iter = &stats->link_fail_cnt; for ( ; dwords--; iter++) le32_to_cpus(iter); } @@ -4827,6 +4877,45 @@ qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma, return rval; } +int +qla24xx_get_buffer_credits(scsi_qla_host_t *vha, struct buffer_credit_24xx *bbc, + dma_addr_t bbc_dma) +{ + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + int rval; + + if (!IS_FWI2_CAPABLE(vha->hw)) + return QLA_FUNCTION_FAILED; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118e, + "Entered %s.\n", __func__); + + mcp->mb[0] = MBC_GET_RNID_PARAMS; + mcp->mb[1] = RNID_BUFFER_CREDITS << 8; + mcp->mb[2] = MSW(LSD(bbc_dma)); + mcp->mb[3] = LSW(LSD(bbc_dma)); + mcp->mb[6] = MSW(MSD(bbc_dma)); + mcp->mb[7] = LSW(MSD(bbc_dma)); + mcp->mb[8] = sizeof(*bbc) / sizeof(*bbc->parameter); + mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->buf_size = sizeof(*bbc); + mcp->flags = MBX_DMA_IN; + mcp->tov = MBX_TOV_SECONDS; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x118f, + "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]); + } else { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1190, + "Done %s.\n", __func__); + } + + return rval; +} + static int qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp) { @@ -4880,8 +4969,8 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, mcp->mb[0] = MBC_READ_SFP; mcp->mb[1] = dev; - mcp->mb[2] = MSW(sfp_dma); - mcp->mb[3] = LSW(sfp_dma); + mcp->mb[2] = MSW(LSD(sfp_dma)); + mcp->mb[3] = LSW(LSD(sfp_dma)); mcp->mb[6] = MSW(MSD(sfp_dma)); mcp->mb[7] = LSW(MSD(sfp_dma)); mcp->mb[8] = len; @@ -4934,8 +5023,8 @@ qla2x00_write_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, mcp->mb[0] = MBC_WRITE_SFP; mcp->mb[1] = dev; - mcp->mb[2] = MSW(sfp_dma); - mcp->mb[3] = LSW(sfp_dma); + mcp->mb[2] = MSW(LSD(sfp_dma)); + mcp->mb[3] = LSW(LSD(sfp_dma)); mcp->mb[6] = MSW(MSD(sfp_dma)); mcp->mb[7] = LSW(MSD(sfp_dma)); mcp->mb[8] = len; diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 8ae639d089d1..d211f803c699 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -509,6 +509,9 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) vha->mgmt_svr_loop_id = qla2x00_reserve_mgmt_server_loop_id(vha); vha->dpc_flags = 0L; + ha->dpc_active = 0; + set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags); + set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags); /* * To fix the issue of processing a parent's RSCN for the vport before diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 79387ac8936f..d97e696b64d0 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2287,7 +2287,7 @@ static struct isp_operations qla81xx_isp_ops = { .config_rings = qla24xx_config_rings, .reset_adapter = qla24xx_reset_adapter, .nvram_config = qla81xx_nvram_config, - .update_fw_options = qla81xx_update_fw_options, + .update_fw_options = qla83xx_update_fw_options, .load_risc = qla81xx_load_risc, .pci_info_str = qla24xx_pci_info_str, .fw_version_str = qla24xx_fw_version_str, @@ -2404,7 +2404,7 @@ static struct isp_operations qla83xx_isp_ops = { .config_rings = qla24xx_config_rings, .reset_adapter = qla24xx_reset_adapter, .nvram_config = qla81xx_nvram_config, - .update_fw_options = qla81xx_update_fw_options, + .update_fw_options = qla83xx_update_fw_options, .load_risc = qla81xx_load_risc, .pci_info_str = qla24xx_pci_info_str, .fw_version_str = qla24xx_fw_version_str, From d83a80ee57f0cb38baccc75e96bc56ac47d300b3 Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 12 Feb 2020 13:44:18 -0800 Subject: [PATCH 0692/4444] scsi: qla2xxx: Add vendor extended RDP additions and amendments This patch adds RDP command support in the driver. With the help of new ql2xsmartsan parameter, driver will use PUREX IOCB mode to send RDP command to switch and will be able to receive various diagnostic data. Link: https://lore.kernel.org/r/20200212214436.25532-8-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 135 ++++++++ drivers/scsi/qla2xxx/qla_fw.h | 44 +++ drivers/scsi/qla2xxx/qla_gbl.h | 3 + drivers/scsi/qla2xxx/qla_init.c | 15 +- drivers/scsi/qla2xxx/qla_isr.c | 10 + drivers/scsi/qla2xxx/qla_mbx.c | 58 ++++ drivers/scsi/qla2xxx/qla_os.c | 546 +++++++++++++++++++++++++++++++- 7 files changed, 807 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index d3a8fcb22c78..cb4409b8cdb1 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1267,6 +1267,9 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs) #define RNID_TYPE_SET_VERSION 0x9 #define RNID_TYPE_ASIC_TEMP 0xC +#define ELS_CMD_MAP_SIZE 32 +#define ELS_COMMAND_RDP 0x18 + /* * Firmware state codes from get firmware state mailbox command */ @@ -3562,6 +3565,133 @@ struct qlfc_fw { uint32_t len; }; +struct rdp_req_payload { + uint32_t els_request; + uint32_t desc_list_len; + + /* NPIV descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint8_t reserved; + uint8_t nport_id[3]; + } npiv_desc; +}; + +struct rdp_rsp_payload { + struct { + uint32_t cmd; + uint32_t len; + } hdr; + + /* LS Request Info descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint32_t req_payload_word_0; + } ls_req_info_desc; + + /* LS Request Info descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint32_t req_payload_word_0; + } ls_req_info_desc2; + + /* SFP diagnostic param descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint16_t temperature; + uint16_t vcc; + uint16_t tx_bias; + uint16_t tx_power; + uint16_t rx_power; + uint16_t sfp_flags; + } sfp_diag_desc; + + /* Port Speed Descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint16_t speed_capab; + uint16_t operating_speed; + } port_speed_desc; + + /* Link Error Status Descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint32_t link_fail_cnt; + uint32_t loss_sync_cnt; + uint32_t loss_sig_cnt; + uint32_t prim_seq_err_cnt; + uint32_t inval_xmit_word_cnt; + uint32_t inval_crc_cnt; + uint8_t pn_port_phy_type; + uint8_t reserved[3]; + } ls_err_desc; + + /* Port name description with diag param */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint8_t WWNN[WWN_SIZE]; + uint8_t WWPN[WWN_SIZE]; + } port_name_diag_desc; + + /* Port Name desc for Direct attached Fx_Port or Nx_Port */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint8_t WWNN[WWN_SIZE]; + uint8_t WWPN[WWN_SIZE]; + } port_name_direct_desc; + + /* Buffer Credit descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint32_t fcport_b2b; + uint32_t attached_fcport_b2b; + uint32_t fcport_rtt; + } buffer_credit_desc; + + /* Optical Element Data Descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint16_t high_alarm; + uint16_t low_alarm; + uint16_t high_warn; + uint16_t low_warn; + uint32_t element_flags; + } optical_elmt_desc[5]; + + /* Optical Product Data Descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint8_t vendor_name[16]; + uint8_t part_number[16]; + uint8_t serial_number[16]; + uint8_t revision[4]; + uint8_t date[8]; + } optical_prod_desc; +}; + +#define RDP_DESC_LEN(obj) \ + (sizeof(obj) - sizeof((obj).desc_tag) - sizeof((obj).desc_len)) + +#define RDP_PORT_SPEED_1GB BIT_15 +#define RDP_PORT_SPEED_2GB BIT_14 +#define RDP_PORT_SPEED_4GB BIT_13 +#define RDP_PORT_SPEED_10GB BIT_12 +#define RDP_PORT_SPEED_8GB BIT_11 +#define RDP_PORT_SPEED_16GB BIT_10 +#define RDP_PORT_SPEED_32GB BIT_9 +#define RDP_PORT_SPEED_UNKNOWN BIT_0 + struct scsi_qlt_host { void *target_lport_ptr; struct mutex tgt_mutex; @@ -3965,6 +4095,8 @@ struct qla_hw_data { #define SFP_DEV_SIZE 512 #define SFP_BLOCK_SIZE 64 +#define SFP_RTDI_LEN SFP_BLOCK_SIZE + void *sfp_data; dma_addr_t sfp_data_dma; @@ -4424,6 +4556,8 @@ typedef struct scsi_qla_host { #define ISP_ABORT_TO_ROM 33 #define VPORT_DELETE 34 +#define PROCESS_PUREX_IOCB 63 + unsigned long pci_flags; #define PFLG_DISCONNECTED 0 /* PCI device removed */ #define PFLG_DRIVER_REMOVING 1 /* PCI driver .remove */ @@ -4532,6 +4666,7 @@ typedef struct scsi_qla_host { uint16_t ql2xexchoffld; uint16_t ql2xiniexchg; + void *purex_data; struct name_list_extended gnl; /* Count of active session/fcport */ int fcport_count; diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 02c1dbb4abc8..649bdfd61bc5 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -723,6 +723,50 @@ struct ct_entry_24xx { struct dsd64 dsd[2]; }; +/* + * ISP queue - PUREX IOCB entry structure definition + */ +#define PUREX_IOCB_TYPE 0x51 /* CT Pass Through IOCB entry */ +typedef struct purex_entry_24xx { + uint8_t entry_type; /* Entry type. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + + uint16_t reserved1; + uint8_t vp_idx; + uint8_t reserved2; + + uint16_t status_flags; + uint16_t nport_handle; + + uint16_t frame_size; + uint16_t trunc_frame_size; + + uint32_t rx_xchg_addr; + + uint8_t d_id[3]; + uint8_t r_ctl; + + uint8_t s_id[3]; + uint8_t cs_ctl; + + uint8_t f_ctl[3]; + uint8_t type; + + uint16_t seq_cnt; + uint8_t df_ctl; + uint8_t seq_id; + + uint16_t rx_id; + uint16_t ox_id; + uint32_t param; + + uint8_t els_frame_payload[20]; +} purex_entry_24xx_t; + +#define PUREX_ENTRY_SIZE (sizeof(purex_entry_24xx_t)) + /* * ISP queue - ELS Pass-Through entry structure definition. */ diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 5b995519a2c1..0c5b56cea253 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -457,6 +457,9 @@ qla82xx_set_driver_version(scsi_qla_host_t *, char *); extern int qla25xx_set_driver_version(scsi_qla_host_t *, char *); +extern int +qla25xx_set_els_cmds_supported(scsi_qla_host_t *); + extern int qla24xx_get_buffer_credits(scsi_qla_host_t *, struct buffer_credit_24xx *, dma_addr_t); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 9887602529a3..2b36a1bdcc5f 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3708,6 +3708,10 @@ enable_82xx_npiv: "ISP Firmware failed checksum.\n"); goto failed; } + + /* Enable PUREX PASSTHRU */ + if (ql2xsmartsan) + qla25xx_set_els_cmds_supported(vha); } else goto failed; @@ -3929,7 +3933,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) /* Update Serial Link options. */ if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0) - return; + goto enable_purex; rval = qla2x00_set_serdes_params(vha, le16_to_cpu(ha->fw_seriallink_options24[1]), @@ -3939,6 +3943,12 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) ql_log(ql_log_warn, vha, 0x0104, "Unable to update Serial Link options (%x).\n", rval); } + +enable_purex: + if (ql2xsmartsan) + ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; + + qla2x00_set_fw_options(vha, ha->fw_options); } void @@ -8672,6 +8682,9 @@ qla83xx_update_fw_options(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; + if (ql2xsmartsan) + ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; + qla2x00_set_fw_options(vha, ha->fw_options); } diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 73b6cfd14581..96f73a5b3c83 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -31,6 +31,13 @@ const char *const port_state_str[] = { "ONLINE" }; +static void qla24xx_purex_iocb(scsi_qla_host_t *vha, struct req_que *req, + struct sts_entry_24xx *pkt) +{ + memcpy(vha->purex_data, pkt, PUREX_ENTRY_SIZE); + set_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags); +} + /** * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. * @irq: interrupt number @@ -3128,6 +3135,9 @@ process_err: qla_ctrlvp_completed(vha, rsp->req, (struct vp_ctrl_entry_24xx *)pkt); break; + case PUREX_IOCB_TYPE: + qla24xx_purex_iocb(vha, rsp->req, pkt); + break; default: /* Type Not Supported. */ ql_dbg(ql_dbg_async, vha, 0x5042, diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index f1c2a9ea5446..2d029616e836 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -4877,6 +4877,64 @@ qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma, return rval; } +int +qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + uint8_t *els_cmd_map; + dma_addr_t els_cmd_map_dma; + uint cmd_opcode = ELS_COMMAND_RDP; + uint index = cmd_opcode / 8; + uint bit = cmd_opcode % 8; + struct qla_hw_data *ha = vha->hw; + + if (!IS_QLA25XX(ha) && !IS_QLA2031(ha) && !IS_QLA27XX(ha)) + return QLA_SUCCESS; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1197, + "Entered %s.\n", __func__); + + els_cmd_map = dma_alloc_coherent(&ha->pdev->dev, ELS_CMD_MAP_SIZE, + &els_cmd_map_dma, GFP_KERNEL); + if (!els_cmd_map) { + ql_log(ql_log_warn, vha, 0x7101, + "Failed to allocate RDP els command param.\n"); + return QLA_MEMORY_ALLOC_FAILED; + } + + memset(els_cmd_map, 0, ELS_CMD_MAP_SIZE); + + els_cmd_map[index] |= 1 << bit; + + mcp->mb[0] = MBC_SET_RNID_PARAMS; + mcp->mb[1] = RNID_TYPE_ELS_CMD << 8; + mcp->mb[2] = MSW(LSD(els_cmd_map_dma)); + mcp->mb[3] = LSW(LSD(els_cmd_map_dma)); + mcp->mb[6] = MSW(MSD(els_cmd_map_dma)); + mcp->mb[7] = LSW(MSD(els_cmd_map_dma)); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = MBX_DMA_OUT; + mcp->buf_size = ELS_CMD_MAP_SIZE; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x118d, + "Failed=%x (%x,%x).\n", rval, mcp->mb[0], mcp->mb[1]); + } else { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118c, + "Done %s.\n", __func__); + } + + dma_free_coherent(&ha->pdev->dev, DMA_POOL_SIZE, + els_cmd_map, els_cmd_map_dma); + + return rval; +} + int qla24xx_get_buffer_credits(scsi_qla_host_t *vha, struct buffer_credit_24xx *bbc, dma_addr_t bbc_dma) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index d97e696b64d0..5245a18be275 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -306,6 +306,15 @@ MODULE_PARM_DESC(ql2xdifbundlinginternalbuffers, "0 (Default). Based on check.\n" "1 Force using internal buffers\n"); +int ql2xsmartsan; +module_param(ql2xsmartsan, int, 0444); +module_param_named(smartsan, ql2xsmartsan, int, 0444); +MODULE_PARM_DESC(ql2xsmartsan, + "Send SmartSAN Management Attributes for FDMI Registration." + " Default is 0 - No SmartSAN registration," + " 1 - Register SmartSAN Management Attributes."); + + static void qla2x00_clear_drv_active(struct qla_hw_data *); static void qla2x00_free_device(scsi_qla_host_t *); static int qla2xxx_map_queues(struct Scsi_Host *shost); @@ -3269,6 +3278,11 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) goto probe_failed; } + base_vha->purex_data = kzalloc(PUREX_ENTRY_SIZE, GFP_KERNEL); + if (!base_vha->purex_data) + ql_log(ql_log_warn, base_vha, 0x7118, + "Failed to allocate memory for PUREX data\n"); + if (IS_QLAFX00(ha)) host->can_queue = QLAFX00_MAX_CANQUEUE; else @@ -3451,6 +3465,7 @@ skip_dpc: return 0; probe_failed: + kfree(base_vha->purex_data); if (base_vha->gnl.l) { dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma); @@ -3767,6 +3782,8 @@ qla2x00_remove_one(struct pci_dev *pdev) qla84xx_put_chip(base_vha); + kfree(base_vha->purex_data); + /* Disable timer */ if (base_vha->timer_active) qla2x00_stop_timer(base_vha); @@ -5733,6 +5750,518 @@ retry_lock: return; } +static uint +qla25xx_rdp_port_speed_capability(struct qla_hw_data *ha) +{ + if (IS_CNA_CAPABLE(ha)) + return RDP_PORT_SPEED_10GB; + + if (IS_QLA27XX(ha)) { + if (FW_ABILITY_MAX_SPEED(ha) == FW_ABILITY_MAX_SPEED_32G) + return RDP_PORT_SPEED_32GB|RDP_PORT_SPEED_16GB| + RDP_PORT_SPEED_8GB; + + return RDP_PORT_SPEED_16GB|RDP_PORT_SPEED_8GB| + RDP_PORT_SPEED_4GB; + } + + if (IS_QLA2031(ha)) + return RDP_PORT_SPEED_16GB|RDP_PORT_SPEED_8GB| + RDP_PORT_SPEED_4GB; + + if (IS_QLA25XX(ha)) + return RDP_PORT_SPEED_8GB|RDP_PORT_SPEED_4GB| + RDP_PORT_SPEED_2GB|RDP_PORT_SPEED_1GB; + + if (IS_QLA24XX_TYPE(ha)) + return RDP_PORT_SPEED_4GB|RDP_PORT_SPEED_2GB| + RDP_PORT_SPEED_1GB; + + if (IS_QLA23XX(ha)) + return RDP_PORT_SPEED_2GB|RDP_PORT_SPEED_1GB; + + return RDP_PORT_SPEED_1GB; +} + +static uint +qla25xx_rdp_port_speed_currently(struct qla_hw_data *ha) +{ + switch (ha->link_data_rate) { + case PORT_SPEED_1GB: + return RDP_PORT_SPEED_1GB; + + case PORT_SPEED_2GB: + return RDP_PORT_SPEED_2GB; + + case PORT_SPEED_4GB: + return RDP_PORT_SPEED_4GB; + + case PORT_SPEED_8GB: + return RDP_PORT_SPEED_8GB; + + case PORT_SPEED_10GB: + return RDP_PORT_SPEED_10GB; + + case PORT_SPEED_16GB: + return RDP_PORT_SPEED_16GB; + + case PORT_SPEED_32GB: + return RDP_PORT_SPEED_32GB; + + default: + return RDP_PORT_SPEED_UNKNOWN; + } +} + +/* + * Function Name: qla24xx_process_purex_iocb + * + * Description: + * Prepare a RDP response and send to Fabric switch + * + * PARAMETERS: + * vha: SCSI qla host + * purex: RDP request received by HBA + */ +static int qla24xx_process_purex_iocb(struct scsi_qla_host *vha, void *pkt) +{ + struct qla_hw_data *ha = vha->hw; + struct purex_entry_24xx *purex = pkt; + struct port_database_24xx *pdb = NULL; + dma_addr_t rsp_els_dma; + dma_addr_t rsp_payload_dma; + dma_addr_t stat_dma; + dma_addr_t bbc_dma; + dma_addr_t sfp_dma; + struct els_entry_24xx *rsp_els = NULL; + struct rdp_rsp_payload *rsp_payload = NULL; + struct link_statistics *stat = NULL; + struct buffer_credit_24xx *bbc = NULL; + uint8_t *sfp = NULL; + uint16_t sfp_flags = 0; + int rval = -ENOMEM; + + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0180, + "%s: Enter\n", __func__); + + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0181, + "-------- ELS REQ -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0182, + (void *)purex, sizeof(*purex)); + + rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els), + &rsp_els_dma, GFP_KERNEL); + if (!rsp_els) + goto dealloc; + + rsp_payload = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_payload), + &rsp_payload_dma, GFP_KERNEL); + if (!rsp_payload) + goto dealloc; + + sfp = dma_alloc_coherent(&ha->pdev->dev, SFP_RTDI_LEN, + &sfp_dma, GFP_KERNEL); + + stat = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stat), + &stat_dma, GFP_KERNEL); + + bbc = dma_alloc_coherent(&ha->pdev->dev, sizeof(*bbc), + &bbc_dma, GFP_KERNEL); + + /* Prepare Response IOCB */ + memset(rsp_els, 0, sizeof(*rsp_els)); + rsp_els->entry_type = ELS_IOCB_TYPE; + rsp_els->entry_count = 1; + rsp_els->sys_define = 0; + rsp_els->entry_status = 0; + rsp_els->handle = 0; + rsp_els->nport_handle = purex->nport_handle; + rsp_els->tx_dsd_count = 1; + rsp_els->vp_index = purex->vp_idx; + rsp_els->sof_type = EST_SOFI3; + rsp_els->rx_xchg_address = purex->rx_xchg_addr; + rsp_els->rx_dsd_count = 0; + rsp_els->opcode = purex->els_frame_payload[0]; + + rsp_els->port_id[0] = purex->s_id[0]; + rsp_els->port_id[1] = purex->s_id[1]; + rsp_els->port_id[2] = purex->s_id[2]; + + rsp_els->control_flags = EPD_ELS_ACC; + rsp_els->rx_byte_count = 0; + rsp_els->tx_byte_count = cpu_to_le32(sizeof(*rsp_payload)); + + put_unaligned_le64(rsp_payload_dma, &rsp_els->tx_address); + rsp_els->tx_len = rsp_els->tx_byte_count; + + rsp_els->rx_address = 0; + rsp_els->rx_len = 0; + + if (sizeof(*rsp_payload) <= 0x100) + goto accept; + + pdb = kzalloc(sizeof(*pdb), GFP_KERNEL); + if (!pdb) + goto reduce; + + rval = qla24xx_get_port_database(vha, purex->nport_handle, pdb); + if (rval) + goto reduce; + + if (pdb->port_id[0] != purex->s_id[2] || + pdb->port_id[1] != purex->s_id[1] || + pdb->port_id[2] != purex->s_id[0]) + goto reduce; + + if (pdb->current_login_state == PDS_PLOGI_COMPLETE || + pdb->current_login_state == PDS_PRLI_COMPLETE) + goto accept; + +reduce: + ql_dbg(ql_dbg_init, vha, 0x016e, "Requesting port is not logged in.\n"); + rsp_els->tx_byte_count = rsp_els->tx_len = + offsetof(struct rdp_rsp_payload, buffer_credit_desc); + ql_dbg(ql_dbg_init, vha, 0x016f, "Reduced response payload size %u.\n", + rsp_els->tx_byte_count); + +accept: + /* Prepare Response Payload */ + rsp_payload->hdr.cmd = cpu_to_be32(0x2 << 24); /* LS_ACC */ + rsp_payload->hdr.len = cpu_to_be32( + rsp_els->tx_byte_count - sizeof(rsp_payload->hdr)); + + /* Link service Request Info Descriptor */ + rsp_payload->ls_req_info_desc.desc_tag = cpu_to_be32(0x1); + rsp_payload->ls_req_info_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_req_info_desc)); + rsp_payload->ls_req_info_desc.req_payload_word_0 = + cpu_to_be32p((uint32_t *)purex->els_frame_payload); + + /* Link service Request Info Descriptor 2 */ + rsp_payload->ls_req_info_desc2.desc_tag = cpu_to_be32(0x1); + rsp_payload->ls_req_info_desc2.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_req_info_desc2)); + rsp_payload->ls_req_info_desc2.req_payload_word_0 = + cpu_to_be32p((uint32_t *)purex->els_frame_payload); + + if (sfp) { + /* SFP Flags */ + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 0x7, 2, 0); + if (!rval) { + /* SFP Flags bits 3-0: Port Tx Laser Type */ + if (sfp[0] & BIT_2 || sfp[1] & (BIT_6|BIT_5)) + sfp_flags |= BIT_0; /* short wave */ + else if (sfp[0] & BIT_1) + sfp_flags |= BIT_1; /* long wave 1310nm */ + else if (sfp[1] & BIT_4) + sfp_flags |= BIT_1|BIT_0; /* long wave 1550nm */ + } + + /* SFP Type */ + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 0x0, 1, 0); + if (!rval) { + sfp_flags |= BIT_4; /* optical */ + if (sfp[0] == 0x3) + sfp_flags |= BIT_6; /* sfp+ */ + } + + /* SFP Diagnostics */ + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0x60, 10, 0); + if (!rval && sfp_flags) { + uint16_t *trx = (void *)sfp; /* already be16 */ + + rsp_payload->sfp_diag_desc.desc_tag = + cpu_to_be32(0x10000); + rsp_payload->sfp_diag_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->sfp_diag_desc)); + rsp_payload->sfp_diag_desc.temperature = trx[0]; + rsp_payload->sfp_diag_desc.vcc = trx[1]; + rsp_payload->sfp_diag_desc.tx_bias = trx[2]; + rsp_payload->sfp_diag_desc.tx_power = trx[3]; + rsp_payload->sfp_diag_desc.rx_power = trx[4]; + rsp_payload->sfp_diag_desc.sfp_flags = + cpu_to_be16(sfp_flags); + } + } + + /* Port Speed Descriptor */ + rsp_payload->port_speed_desc.desc_tag = cpu_to_be32(0x10001); + rsp_payload->port_speed_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_speed_desc)); + rsp_payload->port_speed_desc.speed_capab = cpu_to_be16( + qla25xx_rdp_port_speed_capability(ha)); + rsp_payload->port_speed_desc.operating_speed = cpu_to_be16( + qla25xx_rdp_port_speed_currently(ha)); + + if (stat) { + rval = qla24xx_get_isp_stats(vha, stat, stat_dma, 0); + if (!rval) { + /* Link Error Status Descriptor */ + rsp_payload->ls_err_desc.desc_tag = + cpu_to_be32(0x10002); + rsp_payload->ls_err_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_err_desc)); + rsp_payload->ls_err_desc.link_fail_cnt = + cpu_to_be32(stat->link_fail_cnt); + rsp_payload->ls_err_desc.loss_sync_cnt = + cpu_to_be32(stat->loss_sync_cnt); + rsp_payload->ls_err_desc.loss_sig_cnt = + cpu_to_be32(stat->loss_sig_cnt); + rsp_payload->ls_err_desc.prim_seq_err_cnt = + cpu_to_be32(stat->prim_seq_err_cnt); + rsp_payload->ls_err_desc.inval_xmit_word_cnt = + cpu_to_be32(stat->inval_xmit_word_cnt); + rsp_payload->ls_err_desc.inval_crc_cnt = + cpu_to_be32(stat->inval_crc_cnt); + rsp_payload->ls_err_desc.pn_port_phy_type |= BIT_6; + } + } + + /* Portname Descriptor */ + rsp_payload->port_name_diag_desc.desc_tag = cpu_to_be32(0x10003); + rsp_payload->port_name_diag_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_name_diag_desc)); + memcpy(rsp_payload->port_name_diag_desc.WWNN, + vha->node_name, + sizeof(rsp_payload->port_name_diag_desc.WWNN)); + memcpy(rsp_payload->port_name_diag_desc.WWPN, + vha->port_name, + sizeof(rsp_payload->port_name_diag_desc.WWPN)); + + /* F-Port Portname Descriptor */ + rsp_payload->port_name_direct_desc.desc_tag = cpu_to_be32(0x10003); + rsp_payload->port_name_direct_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_name_direct_desc)); + memcpy(rsp_payload->port_name_direct_desc.WWNN, + vha->fabric_node_name, + sizeof(rsp_payload->port_name_direct_desc.WWNN)); + memcpy(rsp_payload->port_name_direct_desc.WWPN, + vha->fabric_port_name, + sizeof(rsp_payload->port_name_direct_desc.WWPN)); + + if (rsp_els->tx_byte_count < sizeof(*rsp_payload)) + goto send; + + if (bbc) { + memset(bbc, 0, sizeof(*bbc)); + rval = qla24xx_get_buffer_credits(vha, bbc, bbc_dma); + if (!rval) { + /* Bufer Credit Descriptor */ + rsp_payload->buffer_credit_desc.desc_tag = + cpu_to_be32(0x10006); + rsp_payload->buffer_credit_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN( + rsp_payload->buffer_credit_desc)); + rsp_payload->buffer_credit_desc.fcport_b2b = + cpu_to_be32(LSW(bbc->parameter[0])); + rsp_payload->buffer_credit_desc.attached_fcport_b2b = + cpu_to_be32(0); + rsp_payload->buffer_credit_desc.fcport_rtt = + cpu_to_be32(0); + } + } + + if (sfp) { + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0, 64, 0); + if (!rval) { + uint16_t *trx = (void *)sfp; /* already be16 */ + + /* Optical Element Descriptor, Temperature */ + rsp_payload->optical_elmt_desc[0].desc_tag = + cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[0].desc_len = + cpu_to_be32(RDP_DESC_LEN( + *rsp_payload->optical_elmt_desc)); + rsp_payload->optical_elmt_desc[0].high_alarm = trx[0]; + rsp_payload->optical_elmt_desc[0].low_alarm = trx[1]; + rsp_payload->optical_elmt_desc[0].high_warn = trx[2]; + rsp_payload->optical_elmt_desc[0].low_warn = trx[3]; + rsp_payload->optical_elmt_desc[0].element_flags = + cpu_to_be32(1 << 28); + + /* Optical Element Descriptor, Voltage */ + rsp_payload->optical_elmt_desc[1].desc_tag = + cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[1].desc_len = + cpu_to_be32(RDP_DESC_LEN( + *rsp_payload->optical_elmt_desc)); + rsp_payload->optical_elmt_desc[1].high_alarm = trx[4]; + rsp_payload->optical_elmt_desc[1].low_alarm = trx[5]; + rsp_payload->optical_elmt_desc[1].high_warn = trx[6]; + rsp_payload->optical_elmt_desc[1].low_warn = trx[7]; + rsp_payload->optical_elmt_desc[1].element_flags = + cpu_to_be32(2 << 28); + + /* Optical Element Descriptor, Tx Bias Current */ + rsp_payload->optical_elmt_desc[2].desc_tag = + cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[2].desc_len = + cpu_to_be32(RDP_DESC_LEN( + *rsp_payload->optical_elmt_desc)); + rsp_payload->optical_elmt_desc[2].high_alarm = trx[8]; + rsp_payload->optical_elmt_desc[2].low_alarm = trx[9]; + rsp_payload->optical_elmt_desc[2].high_warn = trx[10]; + rsp_payload->optical_elmt_desc[2].low_warn = trx[11]; + rsp_payload->optical_elmt_desc[2].element_flags = + cpu_to_be32(3 << 28); + + /* Optical Element Descriptor, Tx Power */ + rsp_payload->optical_elmt_desc[3].desc_tag = + cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[3].desc_len = + cpu_to_be32(RDP_DESC_LEN( + *rsp_payload->optical_elmt_desc)); + rsp_payload->optical_elmt_desc[3].high_alarm = trx[12]; + rsp_payload->optical_elmt_desc[3].low_alarm = trx[13]; + rsp_payload->optical_elmt_desc[3].high_warn = trx[14]; + rsp_payload->optical_elmt_desc[3].low_warn = trx[15]; + rsp_payload->optical_elmt_desc[3].element_flags = + cpu_to_be32(4 << 28); + + /* Optical Element Descriptor, Rx Power */ + rsp_payload->optical_elmt_desc[4].desc_tag = + cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[4].desc_len = + cpu_to_be32(RDP_DESC_LEN( + *rsp_payload->optical_elmt_desc)); + rsp_payload->optical_elmt_desc[4].high_alarm = trx[16]; + rsp_payload->optical_elmt_desc[4].low_alarm = trx[17]; + rsp_payload->optical_elmt_desc[4].high_warn = trx[18]; + rsp_payload->optical_elmt_desc[4].low_warn = trx[19]; + rsp_payload->optical_elmt_desc[4].element_flags = + cpu_to_be32(5 << 28); + } + + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 112, 64, 0); + if (!rval) { + /* Temperature high/low alarm/warning */ + rsp_payload->optical_elmt_desc[0].element_flags |= + cpu_to_be32( + (sfp[0] >> 7 & 1) << 3 | + (sfp[0] >> 6 & 1) << 2 | + (sfp[4] >> 7 & 1) << 1 | + (sfp[4] >> 6 & 1) << 0); + + /* Voltage high/low alarm/warning */ + rsp_payload->optical_elmt_desc[1].element_flags |= + cpu_to_be32( + (sfp[0] >> 5 & 1) << 3 | + (sfp[0] >> 4 & 1) << 2 | + (sfp[4] >> 5 & 1) << 1 | + (sfp[4] >> 4 & 1) << 0); + + /* Tx Bias Current high/low alarm/warning */ + rsp_payload->optical_elmt_desc[2].element_flags |= + cpu_to_be32( + (sfp[0] >> 3 & 1) << 3 | + (sfp[0] >> 2 & 1) << 2 | + (sfp[4] >> 3 & 1) << 1 | + (sfp[4] >> 2 & 1) << 0); + + /* Tx Power high/low alarm/warning */ + rsp_payload->optical_elmt_desc[3].element_flags |= + cpu_to_be32( + (sfp[0] >> 1 & 1) << 3 | + (sfp[0] >> 0 & 1) << 2 | + (sfp[4] >> 1 & 1) << 1 | + (sfp[4] >> 0 & 1) << 0); + + /* Rx Power high/low alarm/warning */ + rsp_payload->optical_elmt_desc[4].element_flags |= + cpu_to_be32( + (sfp[1] >> 7 & 1) << 3 | + (sfp[1] >> 6 & 1) << 2 | + (sfp[5] >> 7 & 1) << 1 | + (sfp[5] >> 6 & 1) << 0); + } + } + + if (sfp) { + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 20, 64, 0); + if (!rval) { + /* Optical Product Data Descriptor */ + rsp_payload->optical_prod_desc.desc_tag = + cpu_to_be32(0x10008); + rsp_payload->optical_prod_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN( + rsp_payload->optical_prod_desc)); + memcpy(rsp_payload->optical_prod_desc.vendor_name, + sfp + 0, + sizeof(rsp_payload->optical_prod_desc.vendor_name)); + memcpy(rsp_payload->optical_prod_desc.part_number, + sfp + 20, + sizeof(rsp_payload->optical_prod_desc.part_number)); + memcpy(rsp_payload->optical_prod_desc.revision, + sfp + 36, + sizeof(rsp_payload->optical_prod_desc.revision)); + memcpy(rsp_payload->optical_prod_desc.serial_number, + sfp + 48, + sizeof(rsp_payload->optical_prod_desc.serial_number)); + } + + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 84, 8, 0); + if (!rval) { + memcpy(rsp_payload->optical_prod_desc.date, + sfp + 0, + sizeof(rsp_payload->optical_prod_desc.date)); + } + } + +send: + ql_dbg(ql_dbg_init, vha, 0x0183, + "Sending ELS Response to RDP Request...\n"); + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0184, + "-------- ELS RSP -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0185, + (void *)rsp_els, sizeof(*rsp_els)); + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0186, + "-------- ELS RSP PAYLOAD -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0187, + (void *)rsp_payload, rsp_els->tx_byte_count); + + rval = qla2x00_issue_iocb(vha, rsp_els, rsp_els_dma, 0); + + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0x0188, + "%s: failed to issue IOCB (%x).\n", __func__, rval); + } else if (rsp_els->entry_status != 0) { + ql_log(ql_log_warn, vha, 0x0189, + "%s: failed to complete IOCB -- error status (%x).\n", + __func__, rsp_els->entry_status); + rval = QLA_FUNCTION_FAILED; + } else { + ql_dbg(ql_dbg_init, vha, 0x018a, "%s: done.\n", __func__); + } + +dealloc: + kfree(pdb); + + if (bbc) + dma_free_coherent(&ha->pdev->dev, sizeof(*bbc), + bbc, bbc_dma); + if (stat) + dma_free_coherent(&ha->pdev->dev, sizeof(*stat), + stat, stat_dma); + if (sfp) + dma_free_coherent(&ha->pdev->dev, SFP_RTDI_LEN, + sfp, sfp_dma); + if (rsp_payload) + dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_payload), + rsp_payload, rsp_payload_dma); + if (rsp_els) + dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els), + rsp_els, rsp_els_dma); + + return rval; +} + void qla83xx_idc_unlock(scsi_qla_host_t *base_vha, uint16_t requester_id) { @@ -6080,6 +6609,8 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work) base_vha->flags.online = 0; + kfree(base_vha->purex_data); + qla2x00_destroy_deferred_work(ha); /* @@ -6303,6 +6834,13 @@ qla2x00_do_dpc(void *data) } } + if (test_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags) && + (atomic_read(&base_vha->loop_state) == LOOP_READY)) { + qla24xx_process_purex_iocb(base_vha, + base_vha->purex_data); + clear_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags); + } + if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags)) { qla2x00_update_fcports(base_vha); @@ -6694,7 +7232,8 @@ qla2x00_timer(struct timer_list *t) test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags) || test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags) || test_bit(VP_DPC_NEEDED, &vha->dpc_flags) || - test_bit(RELOGIN_NEEDED, &vha->dpc_flags))) { + test_bit(RELOGIN_NEEDED, &vha->dpc_flags) || + test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags))) { ql_dbg(ql_dbg_timer, vha, 0x600b, "isp_abort_needed=%d loop_resync_needed=%d " "fcport_update_needed=%d start_dpc=%d " @@ -6707,12 +7246,13 @@ qla2x00_timer(struct timer_list *t) ql_dbg(ql_dbg_timer, vha, 0x600c, "beacon_blink_needed=%d isp_unrecoverable=%d " "fcoe_ctx_reset_needed=%d vp_dpc_needed=%d " - "relogin_needed=%d.\n", + "relogin_needed=%d, Process_purex_iocb=%d.\n", test_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags), test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags), test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags), test_bit(VP_DPC_NEEDED, &vha->dpc_flags), - test_bit(RELOGIN_NEEDED, &vha->dpc_flags)); + test_bit(RELOGIN_NEEDED, &vha->dpc_flags), + test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags)); qla2xxx_wake_dpc(vha); } From bd7de0b1c3947e176effb5f5b4a47eab79db771e Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 12 Feb 2020 13:44:19 -0800 Subject: [PATCH 0693/4444] scsi: qla2xxx: Add ql2xrdpenable module parameter for RDP This patch provides separate module parameter ql2xrdpenable to turn on/off RDP capability in the driver. However, if ql2xsmartsan parameter is enabled, it will also turn on ql2xfdmienable parameter since it is required for RDP to work. Link: https://lore.kernel.org/r/20200212214436.25532-9-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_init.c | 12 +++++++++--- drivers/scsi/qla2xxx/qla_os.c | 10 +++++++++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 0c5b56cea253..0c35ab91e381 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -144,6 +144,7 @@ extern int qlport_down_retry; extern int ql2xplogiabsentdevice; extern int ql2xloginretrycount; extern int ql2xfdmienable; +extern int ql2xrdpenable; extern int ql2xsmartsan; extern int ql2xallocfwdump; extern int ql2xextended_error_logging; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 2b36a1bdcc5f..8fee3f5154c7 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2270,6 +2270,12 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) ql_dbg(ql_dbg_init, vha, 0x0078, "Verifying loaded RISC code...\n"); + /* If smartsan enabled then require fdmi and rdp enabled */ + if (ql2xsmartsan) { + ql2xfdmienable = 1; + ql2xrdpenable = 1; + } + if (qla2x00_isp_firmware(vha) != QLA_SUCCESS) { rval = ha->isp_ops->chip_diag(vha); if (rval) @@ -3710,7 +3716,7 @@ enable_82xx_npiv: } /* Enable PUREX PASSTHRU */ - if (ql2xsmartsan) + if (ql2xrdpenable) qla25xx_set_els_cmds_supported(vha); } else goto failed; @@ -3945,7 +3951,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) } enable_purex: - if (ql2xsmartsan) + if (ql2xrdpenable) ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; qla2x00_set_fw_options(vha, ha->fw_options); @@ -8682,7 +8688,7 @@ qla83xx_update_fw_options(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; - if (ql2xsmartsan) + if (ql2xrdpenable) ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; qla2x00_set_fw_options(vha, ha->fw_options); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 5245a18be275..3e6f7fac1c8e 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -113,7 +113,8 @@ module_param(ql2xfdmienable, int, S_IRUGO|S_IWUSR); module_param_named(fdmi, ql2xfdmienable, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(ql2xfdmienable, "Enables FDMI registrations. " - "0 - no FDMI. Default is 1 - perform FDMI."); + "0 - no FDMI registrations. " + "1 - provide FDMI registrations (default)."); #define MAX_Q_DEPTH 64 static int ql2xmaxqdepth = MAX_Q_DEPTH; @@ -314,6 +315,13 @@ MODULE_PARM_DESC(ql2xsmartsan, " Default is 0 - No SmartSAN registration," " 1 - Register SmartSAN Management Attributes."); +int ql2xrdpenable; +module_param(ql2xrdpenable, int, 0444); +module_param_named(rdpenable, ql2xrdpenable, int, 0444); +MODULE_PARM_DESC(ql2xrdpenable, + "Enables RDP responses. " + "0 - no RDP responses (default). " + "1 - provide RDP responses."); static void qla2x00_clear_drv_active(struct qla_hw_data *); static void qla2x00_free_device(scsi_qla_host_t *); From 52bfb089d9d384a1ac0f6d94da7636eb9373a8f9 Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 12 Feb 2020 13:44:20 -0800 Subject: [PATCH 0694/4444] scsi: qla2xxx: Add vendor extended FDMI commands This patch adds support for extended FDMI commands and cleans up code to reduce duplication. Link: https://lore.kernel.org/r/20200212214436.25532-10-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 158 ++- drivers/scsi/qla2xxx/qla_gs.c | 1743 +++++++++++++++----------------- 2 files changed, 870 insertions(+), 1031 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index cb4409b8cdb1..4275d76ff16b 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2627,10 +2627,11 @@ static const char * const port_dstate_str[] = { #define GFF_ID_RSP_SIZE (16 + 128) /* - * HBA attribute types. + * FDMI HBA attribute types. */ -#define FDMI_HBA_ATTR_COUNT 9 -#define FDMIV2_HBA_ATTR_COUNT 17 +#define FDMI1_HBA_ATTR_COUNT 9 +#define FDMI2_HBA_ATTR_COUNT 17 + #define FDMI_HBA_NODE_NAME 0x1 #define FDMI_HBA_MANUFACTURER 0x2 #define FDMI_HBA_SERIAL_NUMBER 0x3 @@ -2642,12 +2643,13 @@ static const char * const port_dstate_str[] = { #define FDMI_HBA_FIRMWARE_VERSION 0x9 #define FDMI_HBA_OS_NAME_AND_VERSION 0xa #define FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH 0xb + #define FDMI_HBA_NODE_SYMBOLIC_NAME 0xc -#define FDMI_HBA_VENDOR_ID 0xd +#define FDMI_HBA_VENDOR_SPECIFIC_INFO 0xd #define FDMI_HBA_NUM_PORTS 0xe #define FDMI_HBA_FABRIC_NAME 0xf #define FDMI_HBA_BOOT_BIOS_NAME 0x10 -#define FDMI_HBA_TYPE_VENDOR_IDENTIFIER 0xe0 +#define FDMI_HBA_VENDOR_IDENTIFIER 0xe0 struct ct_fdmi_hba_attr { uint16_t type; @@ -2664,31 +2666,9 @@ struct ct_fdmi_hba_attr { uint8_t fw_version[32]; uint8_t os_version[128]; uint32_t max_ct_len; - } a; -}; -struct ct_fdmi_hba_attributes { - uint32_t count; - struct ct_fdmi_hba_attr entry[FDMI_HBA_ATTR_COUNT]; -}; - -struct ct_fdmiv2_hba_attr { - uint16_t type; - uint16_t len; - union { - uint8_t node_name[WWN_SIZE]; - uint8_t manufacturer[64]; - uint8_t serial_num[32]; - uint8_t model[16+1]; - uint8_t model_desc[80]; - uint8_t hw_version[16]; - uint8_t driver_version[32]; - uint8_t orom_version[16]; - uint8_t fw_version[32]; - uint8_t os_version[128]; - uint32_t max_ct_len; uint8_t sym_name[256]; - uint32_t vendor_id; + uint32_t vendor_specific_info; uint32_t num_ports; uint8_t fabric_name[WWN_SIZE]; uint8_t bios_name[32]; @@ -2696,22 +2676,30 @@ struct ct_fdmiv2_hba_attr { } a; }; -struct ct_fdmiv2_hba_attributes { +struct ct_fdmi1_hba_attributes { uint32_t count; - struct ct_fdmiv2_hba_attr entry[FDMIV2_HBA_ATTR_COUNT]; + struct ct_fdmi_hba_attr entry[FDMI1_HBA_ATTR_COUNT]; +}; + +struct ct_fdmi2_hba_attributes { + uint32_t count; + struct ct_fdmi_hba_attr entry[FDMI2_HBA_ATTR_COUNT]; }; /* - * Port attribute types. + * FDMI Port attribute types. */ -#define FDMI_PORT_ATTR_COUNT 6 -#define FDMIV2_PORT_ATTR_COUNT 16 +#define FDMI1_PORT_ATTR_COUNT 6 +#define FDMI2_PORT_ATTR_COUNT 16 +#define FDMI2_SMARTSAN_PORT_ATTR_COUNT 23 + #define FDMI_PORT_FC4_TYPES 0x1 #define FDMI_PORT_SUPPORT_SPEED 0x2 #define FDMI_PORT_CURRENT_SPEED 0x3 #define FDMI_PORT_MAX_FRAME_SIZE 0x4 #define FDMI_PORT_OS_DEVICE_NAME 0x5 #define FDMI_PORT_HOST_NAME 0x6 + #define FDMI_PORT_NODE_NAME 0x7 #define FDMI_PORT_NAME 0x8 #define FDMI_PORT_SYM_NAME 0x9 @@ -2721,7 +2709,15 @@ struct ct_fdmiv2_hba_attributes { #define FDMI_PORT_FC4_TYPE 0xd #define FDMI_PORT_STATE 0x101 #define FDMI_PORT_COUNT 0x102 -#define FDMI_PORT_ID 0x103 +#define FDMI_PORT_IDENTIFIER 0x103 + +#define FDMI_SMARTSAN_SERVICE 0xF100 +#define FDMI_SMARTSAN_GUID 0xF101 +#define FDMI_SMARTSAN_VERSION 0xF102 +#define FDMI_SMARTSAN_PROD_NAME 0xF103 +#define FDMI_SMARTSAN_PORT_INFO 0xF104 +#define FDMI_SMARTSAN_QOS_SUPPORT 0xF105 +#define FDMI_SMARTSAN_SECURITY_SUPPORT 0xF106 #define FDMI_PORT_SPEED_1GB 0x1 #define FDMI_PORT_SPEED_2GB 0x2 @@ -2737,37 +2733,6 @@ struct ct_fdmiv2_hba_attributes { #define FC_CLASS_3 0x08 #define FC_CLASS_2_3 0x0C -struct ct_fdmiv2_port_attr { - uint16_t type; - uint16_t len; - union { - uint8_t fc4_types[32]; - uint32_t sup_speed; - uint32_t cur_speed; - uint32_t max_frame_size; - uint8_t os_dev_name[32]; - uint8_t host_name[256]; - uint8_t node_name[WWN_SIZE]; - uint8_t port_name[WWN_SIZE]; - uint8_t port_sym_name[128]; - uint32_t port_type; - uint32_t port_supported_cos; - uint8_t fabric_name[WWN_SIZE]; - uint8_t port_fc4_type[32]; - uint32_t port_state; - uint32_t num_ports; - uint32_t port_id; - } a; -}; - -/* - * Port Attribute Block. - */ -struct ct_fdmiv2_port_attributes { - uint32_t count; - struct ct_fdmiv2_port_attr entry[FDMIV2_PORT_ATTR_COUNT]; -}; - struct ct_fdmi_port_attr { uint16_t type; uint16_t len; @@ -2778,14 +2743,49 @@ struct ct_fdmi_port_attr { uint32_t max_frame_size; uint8_t os_dev_name[32]; uint8_t host_name[256]; + + uint8_t node_name[WWN_SIZE]; + uint8_t port_name[WWN_SIZE]; + uint8_t port_sym_name[128]; + uint32_t port_type; + uint32_t port_supported_cos; + uint8_t fabric_name[WWN_SIZE]; + uint8_t port_fc4_type[32]; + uint32_t port_state; + uint32_t num_ports; + uint32_t port_id; + + uint8_t smartsan_service[24]; + uint8_t smartsan_guid[16]; + uint8_t smartsan_version[24]; + uint8_t smartsan_prod_name[16]; + uint32_t smartsan_port_info; + uint32_t smartsan_qos_support; + uint32_t smartsan_security_support; } a; }; -struct ct_fdmi_port_attributes { +struct ct_fdmi1_port_attributes { uint32_t count; - struct ct_fdmi_port_attr entry[FDMI_PORT_ATTR_COUNT]; + struct ct_fdmi_port_attr entry[FDMI1_PORT_ATTR_COUNT]; }; +struct ct_fdmi2_port_attributes { + uint32_t count; + struct ct_fdmi_port_attr entry[FDMI2_PORT_ATTR_COUNT]; +}; + +#define FDMI_ATTR_TYPELEN(obj) \ + (sizeof((obj)->type) + sizeof((obj)->len)) + +#define FDMI_ATTR_ALIGNMENT(len) \ + (4 - ((len) & 3)) + +/* FDMI register call options */ +#define CALLOPT_FDMI1 0 +#define CALLOPT_FDMI2 1 +#define CALLOPT_FDMI2_SMARTSAN 2 + /* FDMI definitions. */ #define GRHL_CMD 0x100 #define GHAT_CMD 0x101 @@ -2796,10 +2796,13 @@ struct ct_fdmi_port_attributes { #define RHBA_RSP_SIZE 16 #define RHAT_CMD 0x201 + #define RPRT_CMD 0x210 +#define RPRT_RSP_SIZE 24 #define RPA_CMD 0x211 #define RPA_RSP_SIZE 16 +#define SMARTSAN_RPA_RSP_SIZE 24 #define DHBA_CMD 0x300 #define DHBA_REQ_SIZE (16 + 8) @@ -2882,30 +2885,24 @@ struct ct_sns_req { uint8_t hba_identifier[8]; uint32_t entry_count; uint8_t port_name[8]; - struct ct_fdmi_hba_attributes attrs; + struct ct_fdmi2_hba_attributes attrs; } rhba; struct { uint8_t hba_identifier[8]; - uint32_t entry_count; - uint8_t port_name[8]; - struct ct_fdmiv2_hba_attributes attrs; - } rhba2; - - struct { - uint8_t hba_identifier[8]; - struct ct_fdmi_hba_attributes attrs; + struct ct_fdmi1_hba_attributes attrs; } rhat; struct { uint8_t port_name[8]; - struct ct_fdmi_port_attributes attrs; + struct ct_fdmi2_port_attributes attrs; } rpa; struct { + uint8_t hba_identifier[8]; uint8_t port_name[8]; - struct ct_fdmiv2_port_attributes attrs; - } rpa2; + struct ct_fdmi2_port_attributes attrs; + } rprt; struct { uint8_t port_name[8]; @@ -3019,7 +3016,7 @@ struct ct_sns_rsp { struct { uint32_t entry_count; uint8_t port_name[8]; - struct ct_fdmi_hba_attributes attrs; + struct ct_fdmi1_hba_attributes attrs; } ghat; struct { @@ -3690,6 +3687,7 @@ struct rdp_rsp_payload { #define RDP_PORT_SPEED_8GB BIT_11 #define RDP_PORT_SPEED_16GB BIT_10 #define RDP_PORT_SPEED_32GB BIT_9 +#define RDP_PORT_SPEED_64GB BIT_8 #define RDP_PORT_SPEED_UNKNOWN BIT_0 struct scsi_qlt_host { diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index c01eb87c709f..e67105aca497 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -19,6 +19,8 @@ static int qla_async_rffid(scsi_qla_host_t *, port_id_t *, u8, u8); static int qla_async_rnnid(scsi_qla_host_t *, port_id_t *, u8*); static int qla_async_rsnn_nn(scsi_qla_host_t *); + + /** * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query. * @vha: HA context @@ -1500,747 +1502,732 @@ qla2x00_prep_ct_fdmi_req(struct ct_sns_pkt *p, uint16_t cmd, return &p->p.req; } -/** - * qla2x00_fdmi_rhba() - perform RHBA FDMI registration - * @vha: HA context - * - * Returns 0 on success. - */ -static int -qla2x00_fdmi_rhba(scsi_qla_host_t *vha) +static uint +qla25xx_fdmi_port_speed_capability(struct qla_hw_data *ha) { - int rval, alen; - uint32_t size, sn; - - ms_iocb_entry_t *ms_pkt; - struct ct_sns_req *ct_req; - struct ct_sns_rsp *ct_rsp; - void *entries; - struct ct_fdmi_hba_attr *eiter; - struct qla_hw_data *ha = vha->hw; - - /* Issue RHBA */ - /* Prepare common MS IOCB */ - /* Request size adjusted after CT preparation */ - ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE); - - /* Prepare CT request */ - ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, RHBA_RSP_SIZE); - ct_rsp = &ha->ct_sns->p.rsp; - - /* Prepare FDMI command arguments -- attribute block, attributes. */ - memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, WWN_SIZE); - ct_req->req.rhba.entry_count = cpu_to_be32(1); - memcpy(ct_req->req.rhba.port_name, vha->port_name, WWN_SIZE); - size = 2 * WWN_SIZE + 4 + 4; - - /* Attributes */ - ct_req->req.rhba.attrs.count = - cpu_to_be32(FDMI_HBA_ATTR_COUNT); - entries = &ct_req->req; - - /* Nodename. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE); - size += 4 + WWN_SIZE; - - ql_dbg(ql_dbg_disc, vha, 0x2025, - "NodeName = %8phN.\n", eiter->a.node_name); - - /* Manufacturer. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER); - alen = strlen(QLA2XXX_MANUFACTURER); - snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer), - "%s", "QLogic Corporation"); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x2026, - "Manufacturer = %s.\n", eiter->a.manufacturer); - - /* Serial number. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER); - if (IS_FWI2_CAPABLE(ha)) - qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num, - sizeof(eiter->a.serial_num)); - else { - sn = ((ha->serial0 & 0x1f) << 16) | - (ha->serial2 << 8) | ha->serial1; - snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num), - "%c%05d", 'A' + sn / 100000, sn % 100000); - } - alen = strlen(eiter->a.serial_num); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x2027, - "Serial no. = %s.\n", eiter->a.serial_num); - - /* Model name. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_MODEL); - snprintf(eiter->a.model, sizeof(eiter->a.model), - "%s", ha->model_number); - alen = strlen(eiter->a.model); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x2028, - "Model Name = %s.\n", eiter->a.model); - - /* Model description. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION); - snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc), - "%s", ha->model_desc); - alen = strlen(eiter->a.model_desc); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x2029, - "Model Desc = %s.\n", eiter->a.model_desc); - - /* Hardware version. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION); - if (!IS_FWI2_CAPABLE(ha)) { - snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version), - "HW:%s", ha->adapter_id); - } else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version, - sizeof(eiter->a.hw_version))) { - ; - } else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version, - sizeof(eiter->a.hw_version))) { - ; - } else { - snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version), - "HW:%s", ha->adapter_id); - } - alen = strlen(eiter->a.hw_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x202a, - "Hardware ver = %s.\n", eiter->a.hw_version); - - /* Driver version. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION); - snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version), - "%s", qla2x00_version_str); - alen = strlen(eiter->a.driver_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x202b, - "Driver ver = %s.\n", eiter->a.driver_version); - - /* Option ROM version. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION); - snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version), - "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]); - alen = strlen(eiter->a.orom_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha , 0x202c, - "Optrom vers = %s.\n", eiter->a.orom_version); - - /* Firmware version */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION); - ha->isp_ops->fw_version_str(vha, eiter->a.fw_version, - sizeof(eiter->a.fw_version)); - alen = strlen(eiter->a.fw_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x202d, - "Firmware vers = %s.\n", eiter->a.fw_version); - - /* Update MS request size. */ - qla2x00_update_ms_fdmi_iocb(vha, size + 16); - - ql_dbg(ql_dbg_disc, vha, 0x202e, - "RHBA identifier = %8phN size=%d.\n", - ct_req->req.rhba.hba_identifier, size); - ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2076, - entries, size); - - /* Execute MS IOCB */ - rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, - sizeof(ms_iocb_entry_t)); - if (rval != QLA_SUCCESS) { - /*EMPTY*/ - ql_dbg(ql_dbg_disc, vha, 0x2030, - "RHBA issue IOCB failed (%d).\n", rval); - } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") != - QLA_SUCCESS) { - rval = QLA_FUNCTION_FAILED; - if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && - ct_rsp->header.explanation_code == - CT_EXPL_ALREADY_REGISTERED) { - ql_dbg(ql_dbg_disc, vha, 0x2034, - "HBA already registered.\n"); - rval = QLA_ALREADY_REGISTERED; - } else { - ql_dbg(ql_dbg_disc, vha, 0x20ad, - "RHBA FDMI registration failed, CT Reason code: 0x%x, CT Explanation 0x%x\n", - ct_rsp->header.reason_code, - ct_rsp->header.explanation_code); - } - } else { - ql_dbg(ql_dbg_disc, vha, 0x2035, - "RHBA exiting normally.\n"); - } - - return rval; -} - -/** - * qla2x00_fdmi_rpa() - perform RPA registration - * @vha: HA context - * - * Returns 0 on success. - */ -static int -qla2x00_fdmi_rpa(scsi_qla_host_t *vha) -{ - int rval, alen; - uint32_t size; - struct qla_hw_data *ha = vha->hw; - ms_iocb_entry_t *ms_pkt; - struct ct_sns_req *ct_req; - struct ct_sns_rsp *ct_rsp; - void *entries; - struct ct_fdmi_port_attr *eiter; - struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb; - struct new_utsname *p_sysid = NULL; - - /* Issue RPA */ - /* Prepare common MS IOCB */ - /* Request size adjusted after CT preparation */ - ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE); - - /* Prepare CT request */ - ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, - RPA_RSP_SIZE); - ct_rsp = &ha->ct_sns->p.rsp; - - /* Prepare FDMI command arguments -- attribute block, attributes. */ - memcpy(ct_req->req.rpa.port_name, vha->port_name, WWN_SIZE); - size = WWN_SIZE + 4; - - /* Attributes */ - ct_req->req.rpa.attrs.count = cpu_to_be32(FDMI_PORT_ATTR_COUNT); - entries = &ct_req->req; - - /* FC4 types. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES); - eiter->len = cpu_to_be16(4 + 32); - eiter->a.fc4_types[2] = 0x01; - size += 4 + 32; - - ql_dbg(ql_dbg_disc, vha, 0x2039, - "FC4_TYPES=%02x %02x.\n", - eiter->a.fc4_types[2], - eiter->a.fc4_types[1]); - - /* Supported speed. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); - eiter->len = cpu_to_be16(4 + 4); if (IS_CNA_CAPABLE(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_10GB); - else if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_32GB| - FDMI_PORT_SPEED_16GB| - FDMI_PORT_SPEED_8GB); - else if (IS_QLA2031(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_16GB| - FDMI_PORT_SPEED_8GB| - FDMI_PORT_SPEED_4GB); - else if (IS_QLA25XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_8GB| - FDMI_PORT_SPEED_4GB| - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else if (IS_QLA24XX_TYPE(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_4GB| - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else if (IS_QLA23XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_1GB); - size += 4 + 4; + return FDMI_PORT_SPEED_10GB; + if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) { + uint speeds = 0; - ql_dbg(ql_dbg_disc, vha, 0x203a, - "Supported_Speed=%x.\n", eiter->a.sup_speed); - - /* Current speed. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED); - eiter->len = cpu_to_be16(4 + 4); + if (ha->max_supported_speed == 2) { + if (ha->min_supported_speed <= 6) + speeds |= FDMI_PORT_SPEED_64GB; + } + if (ha->max_supported_speed == 2 || + ha->max_supported_speed == 1) { + if (ha->min_supported_speed <= 5) + speeds |= FDMI_PORT_SPEED_32GB; + } + if (ha->max_supported_speed == 2 || + ha->max_supported_speed == 1 || + ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 4) + speeds |= FDMI_PORT_SPEED_16GB; + } + if (ha->max_supported_speed == 1 || + ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 3) + speeds |= FDMI_PORT_SPEED_8GB; + } + if (ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 2) + speeds |= FDMI_PORT_SPEED_4GB; + } + return speeds; + } + if (IS_QLA2031(ha)) + return FDMI_PORT_SPEED_16GB|FDMI_PORT_SPEED_8GB| + FDMI_PORT_SPEED_4GB; + if (IS_QLA25XX(ha)) + return FDMI_PORT_SPEED_8GB|FDMI_PORT_SPEED_4GB| + FDMI_PORT_SPEED_2GB|FDMI_PORT_SPEED_1GB; + if (IS_QLA24XX_TYPE(ha)) + return FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_2GB| + FDMI_PORT_SPEED_1GB; + if (IS_QLA23XX(ha)) + return FDMI_PORT_SPEED_2GB|FDMI_PORT_SPEED_1GB; + return FDMI_PORT_SPEED_1GB; +} +static uint +qla25xx_fdmi_port_speed_currently(struct qla_hw_data *ha) +{ switch (ha->link_data_rate) { case PORT_SPEED_1GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_1GB); - break; + return FDMI_PORT_SPEED_1GB; case PORT_SPEED_2GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_2GB); - break; + return FDMI_PORT_SPEED_2GB; case PORT_SPEED_4GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_4GB); - break; + return FDMI_PORT_SPEED_4GB; case PORT_SPEED_8GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_8GB); - break; + return FDMI_PORT_SPEED_8GB; case PORT_SPEED_10GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_10GB); - break; + return FDMI_PORT_SPEED_10GB; case PORT_SPEED_16GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_16GB); - break; + return FDMI_PORT_SPEED_16GB; case PORT_SPEED_32GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_32GB); - break; + return FDMI_PORT_SPEED_32GB; + case PORT_SPEED_64GB: + return FDMI_PORT_SPEED_64GB; default: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN); - break; + return FDMI_PORT_SPEED_UNKNOWN; } - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x203b, - "Current_Speed=%x.\n", eiter->a.cur_speed); - - /* Max frame size. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); - eiter->len = cpu_to_be16(4 + 4); - eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ? - le16_to_cpu(icb24->frame_payload_size) : - le16_to_cpu(ha->init_cb->frame_payload_size); - eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x203c, - "Max_Frame_Size=%x.\n", eiter->a.max_frame_size); - - /* OS device name. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME); - snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name), - "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no); - alen = strlen(eiter->a.os_dev_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x204b, - "OS_Device_Name=%s.\n", eiter->a.os_dev_name); - - /* Hostname. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME); - p_sysid = utsname(); - if (p_sysid) { - snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), - "%s", p_sysid->nodename); - } else { - snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), - "%s", fc_host_system_hostname(vha->host)); - } - alen = strlen(eiter->a.host_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x203d, "HostName=%s.\n", eiter->a.host_name); - - /* Update MS request size. */ - qla2x00_update_ms_fdmi_iocb(vha, size + 16); - - ql_dbg(ql_dbg_disc, vha, 0x203e, - "RPA portname %016llx, size = %d.\n", - wwn_to_u64(ct_req->req.rpa.port_name), size); - ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2079, - entries, size); - - /* Execute MS IOCB */ - rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, - sizeof(ms_iocb_entry_t)); - if (rval != QLA_SUCCESS) { - /*EMPTY*/ - ql_dbg(ql_dbg_disc, vha, 0x2040, - "RPA issue IOCB failed (%d).\n", rval); - } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") != - QLA_SUCCESS) { - rval = QLA_FUNCTION_FAILED; - if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && - ct_rsp->header.explanation_code == - CT_EXPL_ALREADY_REGISTERED) { - ql_dbg(ql_dbg_disc, vha, 0x20cd, - "RPA already registered.\n"); - rval = QLA_ALREADY_REGISTERED; - } - - } else { - ql_dbg(ql_dbg_disc, vha, 0x2041, - "RPA exiting normally.\n"); - } - - return rval; } /** - * qla2x00_fdmiv2_rhba() - perform RHBA FDMI v2 registration + * qla2x00_hba_attributes() perform HBA attributes registration * @vha: HA context + * @entries: number of entries to use + * @callopt: Option to issue extended or standard FDMI + * command parameter * * Returns 0 on success. */ -static int -qla2x00_fdmiv2_rhba(scsi_qla_host_t *vha) +static unsigned long +qla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries, + unsigned int callopt) { - int rval, alen; - uint32_t size, sn; - ms_iocb_entry_t *ms_pkt; - struct ct_sns_req *ct_req; - struct ct_sns_rsp *ct_rsp; - void *entries; - struct ct_fdmiv2_hba_attr *eiter; struct qla_hw_data *ha = vha->hw; - struct new_utsname *p_sysid = NULL; - - /* Issue RHBA */ - /* Prepare common MS IOCB */ - /* Request size adjusted after CT preparation */ - ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE); - - /* Prepare CT request */ - ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, - RHBA_RSP_SIZE); - ct_rsp = &ha->ct_sns->p.rsp; - - /* Prepare FDMI command arguments -- attribute block, attributes. */ - memcpy(ct_req->req.rhba2.hba_identifier, vha->port_name, WWN_SIZE); - ct_req->req.rhba2.entry_count = cpu_to_be32(1); - memcpy(ct_req->req.rhba2.port_name, vha->port_name, WWN_SIZE); - size = 2 * WWN_SIZE + 4 + 4; - - /* Attributes */ - ct_req->req.rhba2.attrs.count = cpu_to_be32(FDMIV2_HBA_ATTR_COUNT); - entries = &ct_req->req; + struct init_cb_24xx *icb24 = (void *)ha->init_cb; + struct new_utsname *p_sysid = utsname(); + struct ct_fdmi_hba_attr *eiter; + uint16_t alen; + unsigned long size = 0; /* Nodename. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE); - size += 4 + WWN_SIZE; - - ql_dbg(ql_dbg_disc, vha, 0x207d, - "NodeName = %016llx.\n", wwn_to_u64(eiter->a.node_name)); - + memcpy(eiter->a.node_name, vha->node_name, sizeof(eiter->a.node_name)); + alen = sizeof(eiter->a.node_name); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a0, + "NODENAME = %016llx.\n", wwn_to_u64(eiter->a.node_name)); /* Manufacturer. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER); - snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer), - "%s", "QLogic Corporation"); - eiter->a.manufacturer[strlen("QLogic Corporation")] = '\0'; - alen = strlen(eiter->a.manufacturer); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20a5, - "Manufacturer = %s.\n", eiter->a.manufacturer); - + alen = scnprintf( + eiter->a.manufacturer, sizeof(eiter->a.manufacturer), + "%s", "QLogic Corporation"); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a1, + "MANUFACTURER = %s.\n", eiter->a.manufacturer); /* Serial number. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER); - if (IS_FWI2_CAPABLE(ha)) - qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num, - sizeof(eiter->a.serial_num)); - else { - sn = ((ha->serial0 & 0x1f) << 16) | - (ha->serial2 << 8) | ha->serial1; - snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num), - "%c%05d", 'A' + sn / 100000, sn % 100000); + alen = 0; + if (IS_FWI2_CAPABLE(ha)) { + alen = qla2xxx_get_vpd_field(vha, "SN", + eiter->a.serial_num, sizeof(eiter->a.serial_num)); } - alen = strlen(eiter->a.serial_num); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20a6, - "Serial no. = %s.\n", eiter->a.serial_num); - + if (!alen) { + uint32_t sn = ((ha->serial0 & 0x1f) << 16) | + (ha->serial2 << 8) | ha->serial1; + alen = scnprintf( + eiter->a.serial_num, sizeof(eiter->a.serial_num), + "%c%05d", 'A' + sn / 100000, sn % 100000); + } + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a2, + "SERIAL NUMBER = %s.\n", eiter->a.serial_num); /* Model name. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_MODEL); - snprintf(eiter->a.model, sizeof(eiter->a.model), - "%s", ha->model_number); - alen = strlen(eiter->a.model); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20a7, - "Model Name = %s.\n", eiter->a.model); - + alen = scnprintf( + eiter->a.model, sizeof(eiter->a.model), + "%s", ha->model_number); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a3, + "MODEL NAME = %s.\n", eiter->a.model); /* Model description. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION); - snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc), - "%s", ha->model_desc); - alen = strlen(eiter->a.model_desc); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20a8, - "Model Desc = %s.\n", eiter->a.model_desc); - + alen = scnprintf( + eiter->a.model_desc, sizeof(eiter->a.model_desc), + "%s", ha->model_desc); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a4, + "MODEL DESCRIPTION = %s.\n", eiter->a.model_desc); /* Hardware version. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION); - if (!IS_FWI2_CAPABLE(ha)) { - snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version), - "HW:%s", ha->adapter_id); - } else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version, - sizeof(eiter->a.hw_version))) { - ; - } else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version, - sizeof(eiter->a.hw_version))) { - ; - } else { - snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version), - "HW:%s", ha->adapter_id); + alen = 0; + if (IS_FWI2_CAPABLE(ha)) { + if (!alen) { + alen = qla2xxx_get_vpd_field(vha, "MN", + eiter->a.hw_version, sizeof(eiter->a.hw_version)); + } + if (!alen) { + alen = qla2xxx_get_vpd_field(vha, "EC", + eiter->a.hw_version, sizeof(eiter->a.hw_version)); + } } - alen = strlen(eiter->a.hw_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20a9, - "Hardware ver = %s.\n", eiter->a.hw_version); - + if (!alen) { + alen = scnprintf( + eiter->a.hw_version, sizeof(eiter->a.hw_version), + "HW:%s", ha->adapter_id); + } + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a5, + "HARDWARE VERSION = %s.\n", eiter->a.hw_version); /* Driver version. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION); - snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version), - "%s", qla2x00_version_str); - alen = strlen(eiter->a.driver_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20aa, - "Driver ver = %s.\n", eiter->a.driver_version); - + alen = scnprintf( + eiter->a.driver_version, sizeof(eiter->a.driver_version), + "%s", qla2x00_version_str); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a6, + "DRIVER VERSION = %s.\n", eiter->a.driver_version); /* Option ROM version. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION); - snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version), - "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]); - alen = strlen(eiter->a.orom_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha , 0x20ab, - "Optrom version = %d.%02d.\n", eiter->a.orom_version[1], - eiter->a.orom_version[0]); + alen = scnprintf( + eiter->a.orom_version, sizeof(eiter->a.orom_version), + "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a7, + "OPTROM VERSION = %d.%02d.\n", + eiter->a.orom_version[1], eiter->a.orom_version[0]); /* Firmware version */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION); ha->isp_ops->fw_version_str(vha, eiter->a.fw_version, sizeof(eiter->a.fw_version)); - alen = strlen(eiter->a.fw_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20ac, - "Firmware vers = %s.\n", eiter->a.fw_version); - + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a8, + "FIRMWARE VERSION = %s.\n", eiter->a.fw_version); + if (callopt == CALLOPT_FDMI1) + goto done; /* OS Name and Version */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_OS_NAME_AND_VERSION); - p_sysid = utsname(); + alen = 0; if (p_sysid) { - snprintf(eiter->a.os_version, sizeof(eiter->a.os_version), - "%s %s %s", - p_sysid->sysname, p_sysid->release, p_sysid->version); - } else { - snprintf(eiter->a.os_version, sizeof(eiter->a.os_version), - "%s %s", "Linux", fc_host_system_hostname(vha->host)); + alen = scnprintf( + eiter->a.os_version, sizeof(eiter->a.os_version), + "%s %s %s", + p_sysid->sysname, p_sysid->release, p_sysid->machine); } - alen = strlen(eiter->a.os_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20ae, - "OS Name and Version = %s.\n", eiter->a.os_version); - + if (!alen) { + alen = scnprintf( + eiter->a.os_version, sizeof(eiter->a.os_version), + "%s %s", + "Linux", fc_host_system_hostname(vha->host)); + } + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a9, + "OS VERSION = %s.\n", eiter->a.os_version); /* MAX CT Payload Length */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH); - eiter->a.max_ct_len = cpu_to_be32(ha->frame_payload_size); - eiter->a.max_ct_len = cpu_to_be32(eiter->a.max_ct_len); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20af, - "CT Payload Length = 0x%x.\n", eiter->a.max_ct_len); - + eiter->a.max_ct_len = cpu_to_be32(le16_to_cpu(IS_FWI2_CAPABLE(ha) ? + icb24->frame_payload_size : ha->init_cb->frame_payload_size)); + alen = sizeof(eiter->a.max_ct_len); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20aa, + "CT PAYLOAD LENGTH = 0x%x.\n", be32_to_cpu(eiter->a.max_ct_len)); /* Node Sybolic Name */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_NODE_SYMBOLIC_NAME); - qla2x00_get_sym_node_name(vha, eiter->a.sym_name, + alen = qla2x00_get_sym_node_name(vha, eiter->a.sym_name, sizeof(eiter->a.sym_name)); - alen = strlen(eiter->a.sym_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20b0, - "Symbolic Name = %s.\n", eiter->a.sym_name); - - /* Vendor Id */ + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ab, + "SYMBOLIC NAME = %s.\n", eiter->a.sym_name); + /* Vendor Specific information */ eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_ID); - eiter->a.vendor_id = cpu_to_be32(0x1077); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20b1, - "Vendor Id = %x.\n", eiter->a.vendor_id); - + eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_SPECIFIC_INFO); + eiter->a.vendor_specific_info = cpu_to_be32(PCI_VENDOR_ID_QLOGIC); + alen = sizeof(eiter->a.vendor_specific_info); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ac, + "VENDOR SPECIFIC INFO = 0x%x.\n", + be32_to_cpu(eiter->a.vendor_specific_info)); /* Num Ports */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_NUM_PORTS); eiter->a.num_ports = cpu_to_be32(1); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20b2, - "Port Num = %x.\n", eiter->a.num_ports); - + alen = sizeof(eiter->a.num_ports); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ad, + "PORT COUNT = %x.\n", be32_to_cpu(eiter->a.num_ports)); /* Fabric Name */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_FABRIC_NAME); - memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - size += 4 + WWN_SIZE; - - ql_dbg(ql_dbg_disc, vha, 0x20b3, - "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name)); - + memcpy(eiter->a.fabric_name, vha->fabric_node_name, + sizeof(eiter->a.fabric_name)); + alen = sizeof(eiter->a.fabric_name); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ae, + "FABRIC NAME = %016llx.\n", wwn_to_u64(eiter->a.fabric_name)); /* BIOS Version */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_BOOT_BIOS_NAME); - snprintf(eiter->a.bios_name, sizeof(eiter->a.bios_name), - "BIOS %d.%02d", ha->bios_revision[1], ha->bios_revision[0]); - alen = strlen(eiter->a.bios_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20b4, - "BIOS Name = %s\n", eiter->a.bios_name); - + alen = scnprintf( + eiter->a.bios_name, sizeof(eiter->a.bios_name), + "BIOS %d.%02d", ha->bios_revision[1], ha->bios_revision[0]); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20af, + "BIOS NAME = %s\n", eiter->a.bios_name); /* Vendor Identifier */ eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_TYPE_VENDOR_IDENTIFIER); - snprintf(eiter->a.vendor_identifier, sizeof(eiter->a.vendor_identifier), - "%s", "QLGC"); - alen = strlen(eiter->a.vendor_identifier); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; + eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_IDENTIFIER); + alen = scnprintf( + eiter->a.vendor_identifier, sizeof(eiter->a.vendor_identifier), + "%s", "QLGC"); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20b0, + "VENDOR IDENTIFIER = %s.\n", eiter->a.vendor_identifier); +done: + return size; +} - ql_dbg(ql_dbg_disc, vha, 0x201b, - "Vendor Identifier = %s.\n", eiter->a.vendor_identifier); +/** + * qla2x00_port_attributes() perform Port attributes registration + * @vha: HA context + * @entries: number of entries to use + * @callopt: Option to issue extended or standard FDMI + * command parameter + * + * Returns 0 on success. + */ +static unsigned long +qla2x00_port_attributes(scsi_qla_host_t *vha, void *entries, + unsigned int callopt) +{ + struct qla_hw_data *ha = vha->hw; + struct init_cb_24xx *icb24 = (void *)ha->init_cb; + struct new_utsname *p_sysid = utsname(); + char *hostname = p_sysid ? + p_sysid->nodename : fc_host_system_hostname(vha->host); + struct ct_fdmi_port_attr *eiter; + uint16_t alen; + unsigned long size = 0; + + /* FC4 types. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES); + eiter->a.fc4_types[0] = 0x00; + eiter->a.fc4_types[1] = 0x00; + eiter->a.fc4_types[2] = 0x01; + eiter->a.fc4_types[3] = 0x00; + alen = sizeof(eiter->a.fc4_types); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c0, + "FC4 TYPES = %016llx.\n", *(uint64_t *)eiter->a.fc4_types); + if (vha->flags.nvme_enabled) { + eiter->a.fc4_types[6] = 1; /* NVMe type 28h */ + ql_dbg(ql_dbg_disc, vha, 0x211f, + "NVME FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n", + eiter->a.fc4_types[6]); + } + /* Supported speed. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); + eiter->a.sup_speed = cpu_to_be32( + qla25xx_fdmi_port_speed_capability(ha)); + alen = sizeof(eiter->a.sup_speed); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c1, + "SUPPORTED SPEED = %x.\n", be32_to_cpu(eiter->a.sup_speed)); + /* Current speed. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED); + eiter->a.cur_speed = cpu_to_be32( + qla25xx_fdmi_port_speed_currently(ha)); + alen = sizeof(eiter->a.cur_speed); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c2, + "CURRENT SPEED = %x.\n", be32_to_cpu(eiter->a.cur_speed)); + /* Max frame size. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); + eiter->a.max_frame_size = cpu_to_be32(le16_to_cpu(IS_FWI2_CAPABLE(ha) ? + icb24->frame_payload_size : ha->init_cb->frame_payload_size)); + alen = sizeof(eiter->a.max_frame_size); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c3, + "MAX FRAME SIZE = %x.\n", be32_to_cpu(eiter->a.max_frame_size)); + /* OS device name. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME); + alen = scnprintf( + eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name), + "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c4, + "OS DEVICE NAME = %s.\n", eiter->a.os_dev_name); + /* Hostname. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME); + if (!*hostname || !strncmp(hostname, "(none)", 6)) + hostname = "Linux-default"; + alen = scnprintf( + eiter->a.host_name, sizeof(eiter->a.host_name), + "%s", hostname); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c5, + "HOSTNAME = %s.\n", eiter->a.host_name); + + if (callopt == CALLOPT_FDMI1) + goto done; + + /* Node Name */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_NODE_NAME); + memcpy(eiter->a.node_name, vha->node_name, sizeof(eiter->a.node_name)); + alen = sizeof(eiter->a.node_name); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c6, + "NODENAME = %016llx.\n", wwn_to_u64(eiter->a.node_name)); + + /* Port Name */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_NAME); + memcpy(eiter->a.port_name, vha->port_name, sizeof(eiter->a.port_name)); + alen = sizeof(eiter->a.port_name); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c7, + "PORTNAME = %016llx.\n", wwn_to_u64(eiter->a.port_name)); + + /* Port Symbolic Name */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_SYM_NAME); + alen = qla2x00_get_sym_node_name(vha, eiter->a.port_sym_name, + sizeof(eiter->a.port_sym_name)); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c8, + "PORT SYMBOLIC NAME = %s\n", eiter->a.port_sym_name); + + /* Port Type */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_TYPE); + eiter->a.port_type = cpu_to_be32(NS_NX_PORT_TYPE); + alen = sizeof(eiter->a.port_type); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c9, + "PORT TYPE = %x.\n", be32_to_cpu(eiter->a.port_type)); + + /* Supported Class of Service */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_SUPP_COS); + eiter->a.port_supported_cos = cpu_to_be32(FC_CLASS_3); + alen = sizeof(eiter->a.port_supported_cos); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ca, + "SUPPORTED COS = %08x\n", be32_to_cpu(eiter->a.port_supported_cos)); + + /* Port Fabric Name */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_FABRIC_NAME); + memcpy(eiter->a.fabric_name, vha->fabric_node_name, + sizeof(eiter->a.fabric_name)); + alen = sizeof(eiter->a.fabric_name); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20cb, + "FABRIC NAME = %016llx.\n", wwn_to_u64(eiter->a.fabric_name)); + + /* FC4_type */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPE); + eiter->a.port_fc4_type[0] = 0x00; + eiter->a.port_fc4_type[1] = 0x00; + eiter->a.port_fc4_type[2] = 0x01; + eiter->a.port_fc4_type[3] = 0x00; + alen = sizeof(eiter->a.port_fc4_type); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20cc, + "PORT ACTIVE FC4 TYPE = %016llx.\n", + *(uint64_t *)eiter->a.port_fc4_type); + + /* Port State */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_STATE); + eiter->a.port_state = cpu_to_be32(2); + alen = sizeof(eiter->a.port_state); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20cd, + "PORT_STATE = %x.\n", be32_to_cpu(eiter->a.port_state)); + + /* Number of Ports */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_COUNT); + eiter->a.num_ports = cpu_to_be32(1); + alen = sizeof(eiter->a.num_ports); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ce, + "PORT COUNT = %x.\n", be32_to_cpu(eiter->a.num_ports)); + + /* Port Identifier */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_IDENTIFIER); + eiter->a.port_id = cpu_to_be32(vha->d_id.b24); + alen = sizeof(eiter->a.port_id); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20cf, + "PORT ID = %x.\n", be32_to_cpu(eiter->a.port_id)); + + if (callopt == CALLOPT_FDMI2 || !ql2xsmartsan) + goto done; + + /* Smart SAN Service Category (Populate Smart SAN Initiator)*/ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_SERVICE); + alen = scnprintf( + eiter->a.smartsan_service, sizeof(eiter->a.smartsan_service), + "%s", "Smart SAN Initiator"); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d0, + "SMARTSAN SERVICE CATEGORY = %s.\n", eiter->a.smartsan_service); + + /* Smart SAN GUID (NWWN+PWWN) */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_GUID); + memcpy(eiter->a.smartsan_guid, vha->node_name, WWN_SIZE); + memcpy(eiter->a.smartsan_guid + WWN_SIZE, vha->port_name, WWN_SIZE); + alen = sizeof(eiter->a.smartsan_guid); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d1, + "Smart SAN GUID = %016llx-%016llx\n", + wwn_to_u64(eiter->a.smartsan_guid), + wwn_to_u64(eiter->a.smartsan_guid + WWN_SIZE)); + + /* Smart SAN Version (populate "Smart SAN Version 1.0") */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_VERSION); + alen = scnprintf( + eiter->a.smartsan_version, sizeof(eiter->a.smartsan_version), + "%s", "Smart SAN Version 2.0"); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d2, + "SMARTSAN VERSION = %s\n", eiter->a.smartsan_version); + + /* Smart SAN Product Name (Specify Adapter Model No) */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_PROD_NAME); + alen = scnprintf(eiter->a.smartsan_prod_name, + sizeof(eiter->a.smartsan_prod_name), + "ISP%04x", ha->pdev->device); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d3, + "SMARTSAN PRODUCT NAME = %s\n", eiter->a.smartsan_prod_name); + + /* Smart SAN Port Info (specify: 1=Physical, 2=NPIV, 3=SRIOV) */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_PORT_INFO); + eiter->a.smartsan_port_info = cpu_to_be32(vha->vp_idx ? 2 : 1); + alen = sizeof(eiter->a.smartsan_port_info); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d4, + "SMARTSAN PORT INFO = %x\n", eiter->a.smartsan_port_info); + + /* Smart SAN Security Support */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_SECURITY_SUPPORT); + eiter->a.smartsan_security_support = cpu_to_be32(1); + alen = sizeof(eiter->a.smartsan_security_support); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d6, + "SMARTSAN SECURITY SUPPORT = %d\n", + be32_to_cpu(eiter->a.smartsan_security_support)); + +done: + return size; +} + +/** + * qla2x00_fdmi_rhba() - perform RHBA FDMI registration + * @vha: HA context + * @callopt: Option to issue FDMI registration + * + * Returns 0 on success. + */ +static int +qla2x00_fdmi_rhba(scsi_qla_host_t *vha, unsigned int callopt) +{ + struct qla_hw_data *ha = vha->hw; + unsigned long size = 0; + unsigned int rval, count; + ms_iocb_entry_t *ms_pkt; + struct ct_sns_req *ct_req; + struct ct_sns_rsp *ct_rsp; + void *entries; + + count = callopt != CALLOPT_FDMI1 ? + FDMI2_HBA_ATTR_COUNT : FDMI1_HBA_ATTR_COUNT; + + size = RHBA_RSP_SIZE; + + ql_dbg(ql_dbg_disc, vha, 0x20e0, + "RHBA (callopt=%x count=%u size=%lu).\n", callopt, count, size); + + /* Request size adjusted after CT preparation */ + ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size); + + /* Prepare CT request */ + ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, size); + ct_rsp = &ha->ct_sns->p.rsp; + + /* Prepare FDMI command entries */ + memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, + sizeof(ct_req->req.rhba.hba_identifier)); + size += sizeof(ct_req->req.rhba.hba_identifier); + + ct_req->req.rhba.entry_count = cpu_to_be32(1); + size += sizeof(ct_req->req.rhba.entry_count); + + memcpy(ct_req->req.rhba.port_name, vha->port_name, + sizeof(ct_req->req.rhba.port_name)); + size += sizeof(ct_req->req.rhba.port_name); + + /* Attribute count */ + ct_req->req.rhba.attrs.count = cpu_to_be32(count); + size += sizeof(ct_req->req.rhba.attrs.count); + + /* Attribute block */ + entries = &ct_req->req.rhba.attrs.entry; + + size += qla2x00_hba_attributes(vha, entries, callopt); /* Update MS request size. */ qla2x00_update_ms_fdmi_iocb(vha, size + 16); - ql_dbg(ql_dbg_disc, vha, 0x20b5, - "RHBA identifier = %016llx.\n", - wwn_to_u64(ct_req->req.rhba2.hba_identifier)); - ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20b6, + ql_dbg(ql_dbg_disc, vha, 0x20e1, + "RHBA %016llx %016llx.\n", + wwn_to_u64(ct_req->req.rhba.hba_identifier), + wwn_to_u64(ct_req->req.rhba.port_name)); + + ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20e2, entries, size); /* Execute MS IOCB */ rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, - sizeof(ms_iocb_entry_t)); - if (rval != QLA_SUCCESS) { - /*EMPTY*/ - ql_dbg(ql_dbg_disc, vha, 0x20b7, - "RHBA issue IOCB failed (%d).\n", rval); - } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") != - QLA_SUCCESS) { - rval = QLA_FUNCTION_FAILED; + sizeof(*ha->ms_iocb)); + if (rval) { + ql_dbg(ql_dbg_disc, vha, 0x20e3, + "RHBA iocb failed (%d).\n", rval); + return rval; + } + rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA"); + if (rval) { if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && ct_rsp->header.explanation_code == CT_EXPL_ALREADY_REGISTERED) { - ql_dbg(ql_dbg_disc, vha, 0x20b8, - "HBA already registered.\n"); - rval = QLA_ALREADY_REGISTERED; - } else { - ql_dbg(ql_dbg_disc, vha, 0x2016, - "RHBA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n", - ct_rsp->header.reason_code, - ct_rsp->header.explanation_code); + ql_dbg(ql_dbg_disc, vha, 0x20e4, + "RHBA already registered.\n"); + return QLA_ALREADY_REGISTERED; } - } else { - ql_dbg(ql_dbg_disc, vha, 0x20b9, - "RHBA FDMI V2 exiting normally.\n"); + + ql_dbg(ql_dbg_disc, vha, 0x20e5, + "RHBA failed, CT Reason %#x, CT Explanation %#x\n", + ct_rsp->header.reason_code, + ct_rsp->header.explanation_code); + return rval; } + ql_dbg(ql_dbg_disc, vha, 0x20e6, "RHBA exiting normally.\n"); return rval; } -/** - * qla2x00_fdmi_dhba() - - * @vha: HA context - * - * Returns 0 on success. - */ + static int qla2x00_fdmi_dhba(scsi_qla_host_t *vha) { @@ -2249,22 +2236,17 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *vha) ms_iocb_entry_t *ms_pkt; struct ct_sns_req *ct_req; struct ct_sns_rsp *ct_rsp; - /* Issue RPA */ /* Prepare common MS IOCB */ ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, DHBA_REQ_SIZE, DHBA_RSP_SIZE); - /* Prepare CT request */ ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, DHBA_CMD, DHBA_RSP_SIZE); ct_rsp = &ha->ct_sns->p.rsp; - /* Prepare FDMI command arguments -- portname. */ memcpy(ct_req->req.dhba.port_name, vha->port_name, WWN_SIZE); - ql_dbg(ql_dbg_disc, vha, 0x2036, "DHBA portname = %8phN.\n", ct_req->req.dhba.port_name); - /* Execute MS IOCB */ rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, sizeof(ms_iocb_entry_t)); @@ -2279,337 +2261,178 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *vha) ql_dbg(ql_dbg_disc, vha, 0x2038, "DHBA exiting normally.\n"); } - return rval; } /** - * qla2x00_fdmiv2_rpa() - + * qla2x00_fdmi_rprt() perform RPRT registration * @vha: HA context + * @callopt: Option to issue extended or standard FDMI + * command parameter * * Returns 0 on success. */ static int -qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha) +qla2x00_fdmi_rprt(scsi_qla_host_t *vha, int callopt) { - int rval, alen; - uint32_t size; + struct scsi_qla_host *base_vha = pci_get_drvdata(vha->hw->pdev); struct qla_hw_data *ha = vha->hw; + ulong size = 0; + uint rval, count; ms_iocb_entry_t *ms_pkt; struct ct_sns_req *ct_req; struct ct_sns_rsp *ct_rsp; void *entries; - struct ct_fdmiv2_port_attr *eiter; - struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb; - struct new_utsname *p_sysid = NULL; + count = callopt == CALLOPT_FDMI2_SMARTSAN && ql2xsmartsan ? + FDMI2_SMARTSAN_PORT_ATTR_COUNT : + callopt != CALLOPT_FDMI1 ? + FDMI2_PORT_ATTR_COUNT : FDMI1_PORT_ATTR_COUNT; - /* Issue RPA */ - /* Prepare common MS IOCB */ - /* Request size adjusted after CT preparation */ - ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE); + size = RPRT_RSP_SIZE; + ql_dbg(ql_dbg_disc, vha, 0x20e8, + "RPRT (callopt=%x count=%u size=%lu).\n", callopt, count, size); + /* Request size adjusted after CT preparation */ + ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size); + /* Prepare CT request */ + ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPRT_CMD, size); + ct_rsp = &ha->ct_sns->p.rsp; + /* Prepare FDMI command entries */ + memcpy(ct_req->req.rprt.hba_identifier, base_vha->port_name, + sizeof(ct_req->req.rprt.hba_identifier)); + size += sizeof(ct_req->req.rprt.hba_identifier); + memcpy(ct_req->req.rprt.port_name, vha->port_name, + sizeof(ct_req->req.rprt.port_name)); + size += sizeof(ct_req->req.rprt.port_name); + /* Attribute count */ + ct_req->req.rprt.attrs.count = cpu_to_be32(count); + size += sizeof(ct_req->req.rprt.attrs.count); + /* Attribute block */ + entries = ct_req->req.rprt.attrs.entry; + size += qla2x00_port_attributes(vha, entries, callopt); + /* Update MS request size. */ + qla2x00_update_ms_fdmi_iocb(vha, size + 16); + ql_dbg(ql_dbg_disc, vha, 0x20e9, + "RPRT %016llx %016llx.\n", + wwn_to_u64(ct_req->req.rprt.port_name), + wwn_to_u64(ct_req->req.rprt.port_name)); + ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20ea, + entries, size); + /* Execute MS IOCB */ + rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, + sizeof(*ha->ms_iocb)); + if (rval) { + ql_dbg(ql_dbg_disc, vha, 0x20eb, + "RPRT iocb failed (%d).\n", rval); + return rval; + } + rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPRT"); + if (rval) { + if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && + ct_rsp->header.explanation_code == + CT_EXPL_ALREADY_REGISTERED) { + ql_dbg(ql_dbg_disc, vha, 0x20ec, + "RPRT already registered.\n"); + return QLA_ALREADY_REGISTERED; + } + + ql_dbg(ql_dbg_disc, vha, 0x20ed, + "RPRT failed, CT Reason code: %#x, CT Explanation %#x\n", + ct_rsp->header.reason_code, + ct_rsp->header.explanation_code); + return rval; + } + ql_dbg(ql_dbg_disc, vha, 0x20ee, "RPRT exiting normally.\n"); + return rval; +} + +/** + * qla2x00_fdmi_rpa() - perform RPA registration + * @vha: HA context + * @callopt: Option to issue FDMI registration + * + * Returns 0 on success. + */ +static int +qla2x00_fdmi_rpa(scsi_qla_host_t *vha, uint callopt) +{ + struct qla_hw_data *ha = vha->hw; + ulong size = 0; + uint rval, count; + ms_iocb_entry_t *ms_pkt; + struct ct_sns_req *ct_req; + struct ct_sns_rsp *ct_rsp; + void *entries; + + count = + callopt == CALLOPT_FDMI2_SMARTSAN && ql2xsmartsan ? + FDMI2_SMARTSAN_PORT_ATTR_COUNT : + callopt != CALLOPT_FDMI1 ? + FDMI2_PORT_ATTR_COUNT : FDMI1_PORT_ATTR_COUNT; + + size = + callopt != CALLOPT_FDMI1 ? + SMARTSAN_RPA_RSP_SIZE : RPA_RSP_SIZE; + + ql_dbg(ql_dbg_disc, vha, 0x20f0, + "RPA (callopt=%x count=%u size=%lu).\n", callopt, count, size); + + /* Request size adjusted after CT preparation */ + ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size); /* Prepare CT request */ - ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, RPA_RSP_SIZE); + ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, size); ct_rsp = &ha->ct_sns->p.rsp; - /* Prepare FDMI command arguments -- attribute block, attributes. */ - memcpy(ct_req->req.rpa2.port_name, vha->port_name, WWN_SIZE); - size = WWN_SIZE + 4; + /* Prepare FDMI command entries. */ + memcpy(ct_req->req.rpa.port_name, vha->port_name, + sizeof(ct_req->req.rpa.port_name)); + size += sizeof(ct_req->req.rpa.port_name); - /* Attributes */ - ct_req->req.rpa2.attrs.count = cpu_to_be32(FDMIV2_PORT_ATTR_COUNT); - entries = &ct_req->req; + /* Attribute count */ + ct_req->req.rpa.attrs.count = cpu_to_be32(count); + size += sizeof(ct_req->req.rpa.attrs.count); - /* FC4 types. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES); - eiter->len = cpu_to_be16(4 + 32); - eiter->a.fc4_types[2] = 0x01; - size += 4 + 32; + /* Attribute block */ + entries = ct_req->req.rpa.attrs.entry; - ql_dbg(ql_dbg_disc, vha, 0x20ba, - "FC4_TYPES=%02x %02x.\n", - eiter->a.fc4_types[2], - eiter->a.fc4_types[1]); - - if (vha->flags.nvme_enabled) { - eiter->a.fc4_types[6] = 1; /* NVMe type 28h */ - ql_dbg(ql_dbg_disc, vha, 0x211f, - "NVME FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n", - eiter->a.fc4_types[6]); - } - - /* Supported speed. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); - eiter->len = cpu_to_be16(4 + 4); - if (IS_CNA_CAPABLE(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_10GB); - else if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_32GB| - FDMI_PORT_SPEED_16GB| - FDMI_PORT_SPEED_8GB); - else if (IS_QLA2031(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_16GB| - FDMI_PORT_SPEED_8GB| - FDMI_PORT_SPEED_4GB); - else if (IS_QLA25XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_8GB| - FDMI_PORT_SPEED_4GB| - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else if (IS_QLA24XX_TYPE(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_4GB| - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else if (IS_QLA23XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_1GB); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20bb, - "Supported Port Speed = %x.\n", eiter->a.sup_speed); - - /* Current speed. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED); - eiter->len = cpu_to_be16(4 + 4); - switch (ha->link_data_rate) { - case PORT_SPEED_1GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_1GB); - break; - case PORT_SPEED_2GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_2GB); - break; - case PORT_SPEED_4GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_4GB); - break; - case PORT_SPEED_8GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_8GB); - break; - case PORT_SPEED_10GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_10GB); - break; - case PORT_SPEED_16GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_16GB); - break; - case PORT_SPEED_32GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_32GB); - break; - default: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN); - break; - } - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x2017, - "Current_Speed = %x.\n", eiter->a.cur_speed); - - /* Max frame size. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); - eiter->len = cpu_to_be16(4 + 4); - eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ? - le16_to_cpu(icb24->frame_payload_size) : - le16_to_cpu(ha->init_cb->frame_payload_size); - eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20bc, - "Max_Frame_Size = %x.\n", eiter->a.max_frame_size); - - /* OS device name. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME); - alen = strlen(QLA2XXX_DRIVER_NAME); - snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name), - "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20be, - "OS_Device_Name = %s.\n", eiter->a.os_dev_name); - - /* Hostname. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME); - p_sysid = utsname(); - if (p_sysid) { - snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), - "%s", p_sysid->nodename); - } else { - snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), - "%s", fc_host_system_hostname(vha->host)); - } - alen = strlen(eiter->a.host_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x201a, - "HostName=%s.\n", eiter->a.host_name); - - /* Node Name */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_NODE_NAME); - memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - size += 4 + WWN_SIZE; - - ql_dbg(ql_dbg_disc, vha, 0x20c0, - "Node Name = %016llx.\n", wwn_to_u64(eiter->a.node_name)); - - /* Port Name */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_NAME); - memcpy(eiter->a.port_name, vha->port_name, WWN_SIZE); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - size += 4 + WWN_SIZE; - - ql_dbg(ql_dbg_disc, vha, 0x20c1, - "Port Name = %016llx.\n", wwn_to_u64(eiter->a.port_name)); - - /* Port Symbolic Name */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_SYM_NAME); - qla2x00_get_sym_node_name(vha, eiter->a.port_sym_name, - sizeof(eiter->a.port_sym_name)); - alen = strlen(eiter->a.port_sym_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20c2, - "port symbolic name = %s\n", eiter->a.port_sym_name); - - /* Port Type */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_TYPE); - eiter->a.port_type = cpu_to_be32(NS_NX_PORT_TYPE); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20c3, - "Port Type = %x.\n", eiter->a.port_type); - - /* Class of Service */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_SUPP_COS); - eiter->a.port_supported_cos = cpu_to_be32(FC_CLASS_3); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20c4, - "Supported COS = %08x\n", eiter->a.port_supported_cos); - - /* Port Fabric Name */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_FABRIC_NAME); - memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - size += 4 + WWN_SIZE; - - ql_dbg(ql_dbg_disc, vha, 0x20c5, - "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name)); - - /* FC4_type */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPE); - eiter->a.port_fc4_type[0] = 0; - eiter->a.port_fc4_type[1] = 0; - eiter->a.port_fc4_type[2] = 1; - eiter->a.port_fc4_type[3] = 0; - eiter->len = cpu_to_be16(4 + 32); - size += 4 + 32; - - ql_dbg(ql_dbg_disc, vha, 0x20c6, - "Port Active FC4 Type = %02x %02x.\n", - eiter->a.port_fc4_type[2], eiter->a.port_fc4_type[1]); - - if (vha->flags.nvme_enabled) { - eiter->a.port_fc4_type[4] = 0; - eiter->a.port_fc4_type[5] = 0; - eiter->a.port_fc4_type[6] = 1; /* NVMe type 28h */ - ql_dbg(ql_dbg_disc, vha, 0x2120, - "NVME Port Active FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n", - eiter->a.port_fc4_type[6]); - } - - /* Port State */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_STATE); - eiter->a.port_state = cpu_to_be32(1); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20c7, - "Port State = %x.\n", eiter->a.port_state); - - /* Number of Ports */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_COUNT); - eiter->a.num_ports = cpu_to_be32(1); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20c8, - "Number of ports = %x.\n", eiter->a.num_ports); - - /* Port Id */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_ID); - eiter->a.port_id = cpu_to_be32(vha->d_id.b24); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x201c, - "Port Id = %x.\n", eiter->a.port_id); + size += qla2x00_port_attributes(vha, entries, callopt); /* Update MS request size. */ qla2x00_update_ms_fdmi_iocb(vha, size + 16); - ql_dbg(ql_dbg_disc, vha, 0x2018, - "RPA portname= %8phN size=%d.\n", ct_req->req.rpa.port_name, size); - ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20ca, + ql_dbg(ql_dbg_disc, vha, 0x20f1, + "RPA %016llx.\n", wwn_to_u64(ct_req->req.rpa.port_name)); + + ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20f2, entries, size); /* Execute MS IOCB */ rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, - sizeof(ms_iocb_entry_t)); - if (rval != QLA_SUCCESS) { - /*EMPTY*/ - ql_dbg(ql_dbg_disc, vha, 0x20cb, - "RPA FDMI v2 issue IOCB failed (%d).\n", rval); - } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") != - QLA_SUCCESS) { - rval = QLA_FUNCTION_FAILED; + sizeof(*ha->ms_iocb)); + if (rval) { + ql_dbg(ql_dbg_disc, vha, 0x20f3, + "RPA iocb failed (%d).\n", rval); + return rval; + } + + rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA"); + if (rval) { if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && ct_rsp->header.explanation_code == CT_EXPL_ALREADY_REGISTERED) { - ql_dbg(ql_dbg_disc, vha, 0x20ce, - "RPA FDMI v2 already registered\n"); - rval = QLA_ALREADY_REGISTERED; - } else { - ql_dbg(ql_dbg_disc, vha, 0x2020, - "RPA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n", - ct_rsp->header.reason_code, - ct_rsp->header.explanation_code); + ql_dbg(ql_dbg_disc, vha, 0x20f4, + "RPA already registered.\n"); + return QLA_ALREADY_REGISTERED; } - } else { - ql_dbg(ql_dbg_disc, vha, 0x20cc, - "RPA FDMI V2 exiting normally.\n"); + + ql_dbg(ql_dbg_disc, vha, 0x20f5, + "RPA failed, CT Reason code: %#x, CT Explanation %#x\n", + ct_rsp->header.reason_code, + ct_rsp->header.explanation_code); + return rval; } + ql_dbg(ql_dbg_disc, vha, 0x20f6, "RPA exiting normally.\n"); return rval; } @@ -2622,18 +2445,31 @@ qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha) int qla2x00_fdmi_register(scsi_qla_host_t *vha) { - int rval = QLA_FUNCTION_FAILED; + int rval = QLA_SUCCESS; struct qla_hw_data *ha = vha->hw; if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLAFX00(ha)) - return QLA_FUNCTION_FAILED; + return rval; rval = qla2x00_mgmt_svr_login(vha); if (rval) return rval; - rval = qla2x00_fdmiv2_rhba(vha); + /* For npiv/vport send rprt only */ + if (vha->vp_idx) { + if (ql2xsmartsan) + rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI2_SMARTSAN); + if (rval || !ql2xsmartsan) + rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI2); + if (rval) + rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI1); + + return rval; + } + + /* Try fdmi2 first, if fails then try fdmi1 */ + rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI2); if (rval) { if (rval != QLA_ALREADY_REGISTERED) goto try_fdmi; @@ -2642,18 +2478,22 @@ qla2x00_fdmi_register(scsi_qla_host_t *vha) if (rval) goto try_fdmi; - rval = qla2x00_fdmiv2_rhba(vha); + rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI2); if (rval) goto try_fdmi; } - rval = qla2x00_fdmiv2_rpa(vha); + + if (ql2xsmartsan) + rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI2_SMARTSAN); + if (rval || !ql2xsmartsan) + rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI2); if (rval) goto try_fdmi; - goto out; + return rval; try_fdmi: - rval = qla2x00_fdmi_rhba(vha); + rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI1); if (rval) { if (rval != QLA_ALREADY_REGISTERED) return rval; @@ -2662,12 +2502,13 @@ try_fdmi: if (rval) return rval; - rval = qla2x00_fdmi_rhba(vha); + rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI1); if (rval) return rval; } - rval = qla2x00_fdmi_rpa(vha); -out: + + rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI1); + return rval; } From 75666f4a8c4103fb120717140c26cdbf6b1bf053 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Wed, 12 Feb 2020 13:44:21 -0800 Subject: [PATCH 0695/4444] scsi: qla2xxx: Display message for FCE enabled During Link up phase and Data rate MBX command response, print message indicating FCE is enabled. Link: https://lore.kernel.org/r/20200212214436.25532-11-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_isr.c | 6 ++++++ drivers/scsi/qla2xxx/qla_mbx.c | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 96f73a5b3c83..19daac087ddb 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -820,6 +820,12 @@ skip_rio: "LOOP UP detected (%s Gbps).\n", qla2x00_get_link_speed_str(ha, ha->link_data_rate)); + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + if (mb[2] & BIT_0) + ql_log(ql_log_info, vha, 0x11a0, + "FEC=enabled (link up).\n"); + } + vha->flags.management_server_logged_in = 0; qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate); diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 2d029616e836..c1698bf74c13 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -5554,6 +5554,15 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha) ql_dbg(ql_dbg_mbx, vha, 0x1107, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { + if (mcp->mb[1] != 0x7) + ha->link_data_rate = mcp->mb[1]; + + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + if (mcp->mb[4] & BIT_0) + ql_log(ql_log_info, vha, 0x11a2, + "FEC=enabled (data rate).\n"); + } + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1108, "Done %s.\n", __func__); if (mcp->mb[1] != 0x7) From 8b01e4db834db611555cc4ec5d8d9550024361af Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Wed, 12 Feb 2020 13:44:22 -0800 Subject: [PATCH 0696/4444] scsi: qla2xxx: Show correct port speed capabilities for RDP command This patch correctly displays port speed capability and current speed for RDP command. Link: https://lore.kernel.org/r/20200212214436.25532-12-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 41 ++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 3e6f7fac1c8e..f9422f4fe138 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -5764,13 +5764,39 @@ qla25xx_rdp_port_speed_capability(struct qla_hw_data *ha) if (IS_CNA_CAPABLE(ha)) return RDP_PORT_SPEED_10GB; - if (IS_QLA27XX(ha)) { - if (FW_ABILITY_MAX_SPEED(ha) == FW_ABILITY_MAX_SPEED_32G) - return RDP_PORT_SPEED_32GB|RDP_PORT_SPEED_16GB| - RDP_PORT_SPEED_8GB; + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + unsigned int speeds = 0; - return RDP_PORT_SPEED_16GB|RDP_PORT_SPEED_8GB| - RDP_PORT_SPEED_4GB; + if (ha->max_supported_speed == 2) { + if (ha->min_supported_speed <= 6) + speeds |= RDP_PORT_SPEED_64GB; + } + + if (ha->max_supported_speed == 2 || + ha->max_supported_speed == 1) { + if (ha->min_supported_speed <= 5) + speeds |= RDP_PORT_SPEED_32GB; + } + + if (ha->max_supported_speed == 2 || + ha->max_supported_speed == 1 || + ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 4) + speeds |= RDP_PORT_SPEED_16GB; + } + + if (ha->max_supported_speed == 1 || + ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 3) + speeds |= RDP_PORT_SPEED_8GB; + } + + if (ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 2) + speeds |= RDP_PORT_SPEED_4GB; + } + + return speeds; } if (IS_QLA2031(ha)) @@ -5816,6 +5842,9 @@ qla25xx_rdp_port_speed_currently(struct qla_hw_data *ha) case PORT_SPEED_32GB: return RDP_PORT_SPEED_32GB; + case PORT_SPEED_64GB: + return RDP_PORT_SPEED_64GB; + default: return RDP_PORT_SPEED_UNKNOWN; } From 09e382bc3dd946cfee74044d18d1886567874300 Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 12 Feb 2020 13:44:23 -0800 Subject: [PATCH 0697/4444] scsi: qla2xxx: Cleanup ELS/PUREX iocb fields This patch does the following to improve RDP processing: - Rename field port_id to d_id in ELS and PUREX iocb structs to match FW spec. - Remove redundant comments from ELS and PUREX iocb structs. - Refactor fields in ELS iocb struct for error subcode common access. - Properly use error subcode fields in rdp processing routine. - Add print logs for alloc failure in purex rdp processing routine. Link: https://lore.kernel.org/r/20200212214436.25532-13-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_fw.h | 39 +++++++++++++++++++++------------ drivers/scsi/qla2xxx/qla_iocb.c | 12 +++++----- drivers/scsi/qla2xxx/qla_os.c | 28 +++++++++++++---------- 3 files changed, 48 insertions(+), 31 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 649bdfd61bc5..f7a40dcda7ce 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -779,9 +779,8 @@ struct els_entry_24xx { uint32_t handle; /* System handle. */ - uint16_t reserved_1; - - uint16_t nport_handle; /* N_PORT handle. */ + uint16_t comp_status; /* response only */ + uint16_t nport_handle; uint16_t tx_dsd_count; @@ -796,7 +795,7 @@ struct els_entry_24xx { uint8_t opcode; uint8_t reserved_2; - uint8_t port_id[3]; + uint8_t d_id[3]; uint8_t s_id[3]; uint16_t control_flags; /* Control flags. */ @@ -808,13 +807,24 @@ struct els_entry_24xx { #define ECF_CLR_PASSTHRU_PEND BIT_12 #define ECF_INCL_FRAME_HDR BIT_11 - __le32 rx_byte_count; - __le32 tx_byte_count; + union { + struct { + __le32 rx_byte_count; + __le32 tx_byte_count; - __le64 tx_address __packed; /* Data segment 0 address. */ - __le32 tx_len; /* Data segment 0 length. */ - __le64 rx_address __packed; /* Data segment 1 address. */ - __le32 rx_len; /* Data segment 1 length. */ + __le64 tx_address __packed; /* DSD 0 address. */ + __le32 tx_len; /* DSD 0 length. */ + + __le64 rx_address __packed; /* DSD 1 address. */ + __le32 rx_len; /* DSD 1 length. */ + }; + struct { + uint32_t total_byte_count; + uint32_t error_subcode_1; + uint32_t error_subcode_2; + uint32_t error_subcode_3; + }; + }; }; struct els_sts_entry_24xx { @@ -840,15 +850,16 @@ struct els_sts_entry_24xx { uint8_t opcode; uint8_t reserved_3; - uint8_t port_id[3]; - uint8_t reserved_4; - - uint16_t reserved_5; + uint8_t d_id[3]; + uint8_t s_id[3]; uint16_t control_flags; /* Control flags. */ uint32_t total_byte_count; uint32_t error_subcode_1; uint32_t error_subcode_2; + uint32_t error_subcode_3; + + uint32_t reserved_4[4]; }; /* * ISP queue - Mailbox Command entry structure definition. diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 47bf60a9490a..5b73d09da739 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2684,9 +2684,9 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) els_iocb->rx_dsd_count = 0; els_iocb->opcode = elsio->u.els_logo.els_cmd; - els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; - els_iocb->port_id[1] = sp->fcport->d_id.b.area; - els_iocb->port_id[2] = sp->fcport->d_id.b.domain; + els_iocb->d_id[0] = sp->fcport->d_id.b.al_pa; + els_iocb->d_id[1] = sp->fcport->d_id.b.area; + els_iocb->d_id[2] = sp->fcport->d_id.b.domain; /* For SID the byte order is different than DID */ els_iocb->s_id[1] = vha->d_id.b.al_pa; els_iocb->s_id[2] = vha->d_id.b.area; @@ -3030,9 +3030,9 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) sp->type == SRB_ELS_CMD_RPT ? bsg_request->rqst_data.r_els.els_code : bsg_request->rqst_data.h_els.command_code; - els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; - els_iocb->port_id[1] = sp->fcport->d_id.b.area; - els_iocb->port_id[2] = sp->fcport->d_id.b.domain; + els_iocb->d_id[0] = sp->fcport->d_id.b.al_pa; + els_iocb->d_id[1] = sp->fcport->d_id.b.area; + els_iocb->d_id[2] = sp->fcport->d_id.b.domain; els_iocb->control_flags = 0; els_iocb->rx_byte_count = cpu_to_le32(bsg_job->reply_payload.payload_len); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index f9422f4fe138..c7dcf5656c22 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -5888,13 +5888,19 @@ static int qla24xx_process_purex_iocb(struct scsi_qla_host *vha, void *pkt) rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els), &rsp_els_dma, GFP_KERNEL); - if (!rsp_els) + if (!rsp_els) { + ql_log(ql_log_warn, vha, 0x0183, + "Failed allocate dma buffer ELS RSP.\n"); goto dealloc; + } rsp_payload = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_payload), &rsp_payload_dma, GFP_KERNEL); - if (!rsp_payload) + if (!rsp_payload) { + ql_log(ql_log_warn, vha, 0x0184, + "Failed allocate dma buffer ELS RSP payload.\n"); goto dealloc; + } sfp = dma_alloc_coherent(&ha->pdev->dev, SFP_RTDI_LEN, &sfp_dma, GFP_KERNEL); @@ -5920,9 +5926,9 @@ static int qla24xx_process_purex_iocb(struct scsi_qla_host *vha, void *pkt) rsp_els->rx_dsd_count = 0; rsp_els->opcode = purex->els_frame_payload[0]; - rsp_els->port_id[0] = purex->s_id[0]; - rsp_els->port_id[1] = purex->s_id[1]; - rsp_els->port_id[2] = purex->s_id[2]; + rsp_els->d_id[0] = purex->s_id[0]; + rsp_els->d_id[1] = purex->s_id[1]; + rsp_els->d_id[2] = purex->s_id[2]; rsp_els->control_flags = EPD_ELS_ACC; rsp_els->rx_byte_count = 0; @@ -6265,14 +6271,14 @@ send: rval = qla2x00_issue_iocb(vha, rsp_els, rsp_els_dma, 0); - if (rval != QLA_SUCCESS) { + if (rval) { ql_log(ql_log_warn, vha, 0x0188, - "%s: failed to issue IOCB (%x).\n", __func__, rval); - } else if (rsp_els->entry_status != 0) { + "%s: iocb failed to execute -> %x\n", __func__, rval); + } else if (rsp_els->comp_status) { ql_log(ql_log_warn, vha, 0x0189, - "%s: failed to complete IOCB -- error status (%x).\n", - __func__, rsp_els->entry_status); - rval = QLA_FUNCTION_FAILED; + "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n", + __func__, rsp_els->comp_status, + rsp_els->error_subcode_1, rsp_els->error_subcode_2); } else { ql_dbg(ql_dbg_init, vha, 0x018a, "%s: done.\n", __func__); } From 576bfde80b28232a1dfcf0466986ed2934146d0a Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 12 Feb 2020 13:44:24 -0800 Subject: [PATCH 0698/4444] scsi: qla2xxx: Add deferred queue for processing ABTS and RDP This patch adds deferred queue for processing aborts and RDP in the driver. Link: https://lore.kernel.org/r/20200212214436.25532-14-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 15 +++- drivers/scsi/qla2xxx/qla_fw.h | 91 ++++++++++++++++++- drivers/scsi/qla2xxx/qla_gbl.h | 2 + drivers/scsi/qla2xxx/qla_isr.c | 154 ++++++++++++++++++++++++++++++++- drivers/scsi/qla2xxx/qla_mid.c | 7 ++ drivers/scsi/qla2xxx/qla_os.c | 62 +++++++++---- 6 files changed, 304 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 4275d76ff16b..17367639953c 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -4474,6 +4474,15 @@ struct active_regions { #define QLA_SET_DATA_RATE_NOLR 1 #define QLA_SET_DATA_RATE_LR 2 /* Set speed and initiate LR */ +struct purex_item { + struct list_head list; + struct scsi_qla_host *vha; + void (*process_item)(struct scsi_qla_host *vha, void *pkt); + struct { + uint8_t iocb[64]; + } iocb; +}; + /* * Qlogic scsi host structure */ @@ -4664,7 +4673,11 @@ typedef struct scsi_qla_host { uint16_t ql2xexchoffld; uint16_t ql2xiniexchg; - void *purex_data; + struct purex_list { + struct list_head head; + spinlock_t lock; + } purex_list; + struct name_list_extended gnl; /* Count of active session/fcport */ int fcport_count; diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index f7a40dcda7ce..8af5bc4e2cc6 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -727,7 +727,7 @@ struct ct_entry_24xx { * ISP queue - PUREX IOCB entry structure definition */ #define PUREX_IOCB_TYPE 0x51 /* CT Pass Through IOCB entry */ -typedef struct purex_entry_24xx { +struct purex_entry_24xx { uint8_t entry_type; /* Entry type. */ uint8_t entry_count; /* Entry count. */ uint8_t sys_define; /* System defined. */ @@ -763,9 +763,7 @@ typedef struct purex_entry_24xx { uint32_t param; uint8_t els_frame_payload[20]; -} purex_entry_24xx_t; - -#define PUREX_ENTRY_SIZE (sizeof(purex_entry_24xx_t)) +}; /* * ISP queue - ELS Pass-Through entry structure definition. @@ -1000,6 +998,91 @@ struct abort_entry_24xx { uint8_t reserved_2[12]; }; +#define ABTS_RCV_TYPE 0x54 +#define ABTS_RSP_TYPE 0x55 +struct abts_entry_24xx { + uint8_t entry_type; + uint8_t entry_count; + uint8_t handle_count; + uint8_t entry_status; + + uint32_t handle; /* type 0x55 only */ + + uint16_t comp_status; /* type 0x55 only */ + uint16_t nport_handle; /* type 0x54 only */ + + uint16_t control_flags; /* type 0x55 only */ + uint8_t vp_idx; + uint8_t sof_type; /* sof_type is upper nibble */ + + uint32_t rx_xch_addr; + + uint8_t d_id[3]; + uint8_t r_ctl; + + uint8_t s_id[3]; + uint8_t cs_ctl; + + uint8_t f_ctl[3]; + uint8_t type; + + uint16_t seq_cnt; + uint8_t df_ctl; + uint8_t seq_id; + + uint16_t rx_id; + uint16_t ox_id; + + uint32_t param; + + union { + struct { + uint32_t subcode3; + uint32_t rsvd; + uint32_t subcode1; + uint32_t subcode2; + } error; + struct { + uint16_t rsrvd1; + uint8_t last_seq_id; + uint8_t seq_id_valid; + uint16_t aborted_rx_id; + uint16_t aborted_ox_id; + uint16_t high_seq_cnt; + uint16_t low_seq_cnt; + } ba_acc; + struct { + uint8_t vendor_unique; + uint8_t explanation; + uint8_t reason; + } ba_rjt; + } payload; + + uint32_t rx_xch_addr_to_abort; +} __packed; + +/* ABTS payload explanation values */ +#define BA_RJT_EXP_NO_ADDITIONAL 0 +#define BA_RJT_EXP_INV_OX_RX_ID 3 +#define BA_RJT_EXP_SEQ_ABORTED 5 + +/* ABTS payload reason values */ +#define BA_RJT_RSN_INV_CMD_CODE 1 +#define BA_RJT_RSN_LOGICAL_ERROR 3 +#define BA_RJT_RSN_LOGICAL_BUSY 5 +#define BA_RJT_RSN_PROTOCOL_ERROR 7 +#define BA_RJT_RSN_UNABLE_TO_PERFORM 9 +#define BA_RJT_RSN_VENDOR_SPECIFIC 0xff + +/* FC_F values */ +#define FC_TYPE_BLD 0x000 /* Basic link data */ +#define FC_F_CTL_RSP_CNTXT 0x800000 /* Responder of exchange */ +#define FC_F_CTL_LAST_SEQ 0x100000 /* Last sequence */ +#define FC_F_CTL_END_SEQ 0x80000 /* Last sequence */ +#define FC_F_CTL_SEQ_INIT 0x010000 /* Sequence initiative */ +#define FC_ROUTING_BLD 0x80 /* Basic link data frame */ +#define FC_R_CTL_BLD_BA_ACC 0x04 /* BA_ACC (basic accept) */ + /* * ISP I/O Register Set structure definitions. */ diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 0c35ab91e381..bb3dfef9afb8 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -230,6 +230,7 @@ void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *, int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *); int qla24xx_post_relogin_work(struct scsi_qla_host *vha); void qla2x00_wait_for_sess_deletion(scsi_qla_host_t *); +void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt); /* * Global Functions in qla_mid.c source file. @@ -928,6 +929,7 @@ void qlt_remove_target_resources(struct qla_hw_data *); void qlt_clr_qp_table(struct scsi_qla_host *vha); void qlt_set_mode(struct scsi_qla_host *); int qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode); +extern void qla24xx_process_purex_list(struct purex_list *); /* nvme.c */ void qla_nvme_unregister_remote_port(struct fc_port *fcport); diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 19daac087ddb..cb40261158c9 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -31,13 +31,144 @@ const char *const port_state_str[] = { "ONLINE" }; -static void qla24xx_purex_iocb(scsi_qla_host_t *vha, struct req_que *req, - struct sts_entry_24xx *pkt) +static void qla24xx_purex_iocb(scsi_qla_host_t *vha, void *pkt, + void (*process_item)(struct scsi_qla_host *vha, void *pkt)) { - memcpy(vha->purex_data, pkt, PUREX_ENTRY_SIZE); + struct purex_list *list = &vha->purex_list; + struct purex_item *item; + ulong flags; + + item = kzalloc(sizeof(*item), GFP_KERNEL); + if (!item) { + ql_log(ql_log_warn, vha, 0x5092, + ">> Failed allocate purex list item.\n"); + return; + } + + item->vha = vha; + item->process_item = process_item; + memcpy(&item->iocb, pkt, sizeof(item->iocb)); + + spin_lock_irqsave(&list->lock, flags); + list_add_tail(&item->list, &list->head); + spin_unlock_irqrestore(&list->lock, flags); + set_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags); } +static void +qla24xx_process_abts(struct scsi_qla_host *vha, void *pkt) +{ + struct abts_entry_24xx *abts = pkt; + struct qla_hw_data *ha = vha->hw; + struct els_entry_24xx *rsp_els; + struct abts_entry_24xx *abts_rsp; + dma_addr_t dma; + uint32_t fctl; + int rval; + + ql_dbg(ql_dbg_init, vha, 0x0286, "%s: entered.\n", __func__); + + ql_log(ql_log_warn, vha, 0x0287, + "Processing ABTS xchg=%#x oxid=%#x rxid=%#x seqid=%#x seqcnt=%#x\n", + abts->rx_xch_addr_to_abort, abts->ox_id, abts->rx_id, + abts->seq_id, abts->seq_cnt); + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0287, + "-------- ABTS RCV -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0287, + (uint8_t *)abts, sizeof(*abts)); + + rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els), &dma, + GFP_KERNEL); + if (!rsp_els) { + ql_log(ql_log_warn, vha, 0x0287, + "Failed allocate dma buffer ABTS/ELS RSP.\n"); + return; + } + + /* terminate exchange */ + memset(rsp_els, 0, sizeof(*rsp_els)); + rsp_els->entry_type = ELS_IOCB_TYPE; + rsp_els->entry_count = 1; + rsp_els->nport_handle = ~0; + rsp_els->rx_xchg_address = abts->rx_xch_addr_to_abort; + rsp_els->control_flags = EPD_RX_XCHG; + ql_dbg(ql_dbg_init, vha, 0x0283, + "Sending ELS Response to terminate exchange %#x...\n", + abts->rx_xch_addr_to_abort); + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0283, + "-------- ELS RSP -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0283, + (uint8_t *)rsp_els, sizeof(*rsp_els)); + rval = qla2x00_issue_iocb(vha, rsp_els, dma, 0); + if (rval) { + ql_log(ql_log_warn, vha, 0x0288, + "%s: iocb failed to execute -> %x\n", __func__, rval); + } else if (rsp_els->comp_status) { + ql_log(ql_log_warn, vha, 0x0289, + "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n", + __func__, rsp_els->comp_status, + rsp_els->error_subcode_1, rsp_els->error_subcode_2); + } else { + ql_dbg(ql_dbg_init, vha, 0x028a, + "%s: abort exchange done.\n", __func__); + } + + /* send ABTS response */ + abts_rsp = (void *)rsp_els; + memset(abts_rsp, 0, sizeof(*abts_rsp)); + abts_rsp->entry_type = ABTS_RSP_TYPE; + abts_rsp->entry_count = 1; + abts_rsp->nport_handle = abts->nport_handle; + abts_rsp->vp_idx = abts->vp_idx; + abts_rsp->sof_type = abts->sof_type & 0xf0; + abts_rsp->rx_xch_addr = abts->rx_xch_addr; + abts_rsp->d_id[0] = abts->s_id[0]; + abts_rsp->d_id[1] = abts->s_id[1]; + abts_rsp->d_id[2] = abts->s_id[2]; + abts_rsp->r_ctl = FC_ROUTING_BLD | FC_R_CTL_BLD_BA_ACC; + abts_rsp->s_id[0] = abts->d_id[0]; + abts_rsp->s_id[1] = abts->d_id[1]; + abts_rsp->s_id[2] = abts->d_id[2]; + abts_rsp->cs_ctl = abts->cs_ctl; + /* include flipping bit23 in fctl */ + fctl = ~(abts->f_ctl[2] | 0x7F) << 16 | + FC_F_CTL_LAST_SEQ | FC_F_CTL_END_SEQ | FC_F_CTL_SEQ_INIT; + abts_rsp->f_ctl[0] = fctl >> 0 & 0xff; + abts_rsp->f_ctl[1] = fctl >> 8 & 0xff; + abts_rsp->f_ctl[2] = fctl >> 16 & 0xff; + abts_rsp->type = FC_TYPE_BLD; + abts_rsp->rx_id = abts->rx_id; + abts_rsp->ox_id = abts->ox_id; + abts_rsp->payload.ba_acc.aborted_rx_id = abts->rx_id; + abts_rsp->payload.ba_acc.aborted_ox_id = abts->ox_id; + abts_rsp->payload.ba_acc.high_seq_cnt = ~0; + abts_rsp->rx_xch_addr_to_abort = abts->rx_xch_addr_to_abort; + ql_dbg(ql_dbg_init, vha, 0x028b, + "Sending BA ACC response to ABTS %#x...\n", + abts->rx_xch_addr_to_abort); + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x028b, + "-------- ELS RSP -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x028b, + (uint8_t *)abts_rsp, sizeof(*abts_rsp)); + rval = qla2x00_issue_iocb(vha, abts_rsp, dma, 0); + if (rval) { + ql_log(ql_log_warn, vha, 0x028c, + "%s: iocb failed to execute -> %x\n", __func__, rval); + } else if (abts_rsp->comp_status) { + ql_log(ql_log_warn, vha, 0x028d, + "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n", + __func__, abts_rsp->comp_status, + abts_rsp->payload.error.subcode1, + abts_rsp->payload.error.subcode2); + } else { + ql_dbg(ql_dbg_init, vha, 0x028ea, + "%s: done.\n", __func__); + } + + dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els), rsp_els, dma); +} + /** * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. * @irq: interrupt number @@ -3097,6 +3228,11 @@ process_err: qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE); break; case ABTS_RECV_24XX: + if (qla_ini_mode_enabled(vha)) { + qla24xx_purex_iocb(vha, pkt, + qla24xx_process_abts); + break; + } if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { /* ensure that the ATIO queue is empty */ @@ -3142,8 +3278,18 @@ process_err: (struct vp_ctrl_entry_24xx *)pkt); break; case PUREX_IOCB_TYPE: - qla24xx_purex_iocb(vha, rsp->req, pkt); + { + struct purex_entry_24xx *purex = (void *)pkt; + + if (purex->els_frame_payload[3] != ELS_COMMAND_RDP) { + ql_dbg(ql_dbg_init, vha, 0x5091, + "Discarding ELS Request opcode %#x...\n", + purex->els_frame_payload[3]); + break; + } + qla24xx_purex_iocb(vha, pkt, qla24xx_process_purex_rdp); break; + } default: /* Type Not Supported. */ ql_dbg(ql_dbg_async, vha, 0x5042, diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index d211f803c699..e86c94f78196 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -361,6 +361,13 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha) } } + if (test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags)) { + if (atomic_read(&vha->loop_state) == LOOP_READY) { + qla24xx_process_purex_list(&vha->purex_list); + clear_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags); + } + } + if (test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags)) { ql_dbg(ql_dbg_dpc, vha, 0x4016, "FCPort update scheduled.\n"); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index c7dcf5656c22..7ab32977ea96 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -3286,11 +3286,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) goto probe_failed; } - base_vha->purex_data = kzalloc(PUREX_ENTRY_SIZE, GFP_KERNEL); - if (!base_vha->purex_data) - ql_log(ql_log_warn, base_vha, 0x7118, - "Failed to allocate memory for PUREX data\n"); - if (IS_QLAFX00(ha)) host->can_queue = QLAFX00_MAX_CANQUEUE; else @@ -3473,7 +3468,6 @@ skip_dpc: return 0; probe_failed: - kfree(base_vha->purex_data); if (base_vha->gnl.l) { dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma); @@ -3790,8 +3784,6 @@ qla2x00_remove_one(struct pci_dev *pdev) qla84xx_put_chip(base_vha); - kfree(base_vha->purex_data); - /* Disable timer */ if (base_vha->timer_active) qla2x00_stop_timer(base_vha); @@ -3833,6 +3825,20 @@ qla2x00_remove_one(struct pci_dev *pdev) pci_disable_device(pdev); } +static inline void +qla24xx_free_purex_list(struct purex_list *list) +{ + struct list_head *item, *next; + ulong flags; + + spin_lock_irqsave(&list->lock, flags); + list_for_each_safe(item, next, &list->head) { + list_del(item); + kfree(list_entry(item, struct purex_item, list)); + } + spin_unlock_irqrestore(&list->lock, flags); +} + static void qla2x00_free_device(scsi_qla_host_t *vha) { @@ -3865,6 +3871,8 @@ qla2x00_free_device(scsi_qla_host_t *vha) } + qla24xx_free_purex_list(&vha->purex_list); + qla2x00_mem_free(ha); qla82xx_md_free(vha); @@ -4838,6 +4846,9 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, INIT_LIST_HEAD(&vha->gpnid_list); INIT_WORK(&vha->iocb_work, qla2x00_iocb_work_fn); + INIT_LIST_HEAD(&vha->purex_list.head); + spin_lock_init(&vha->purex_list.lock); + spin_lock_init(&vha->work_lock); spin_lock_init(&vha->cmd_list_lock); init_waitqueue_head(&vha->fcport_waitQ); @@ -5860,7 +5871,7 @@ qla25xx_rdp_port_speed_currently(struct qla_hw_data *ha) * vha: SCSI qla host * purex: RDP request received by HBA */ -static int qla24xx_process_purex_iocb(struct scsi_qla_host *vha, void *pkt) +void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) { struct qla_hw_data *ha = vha->hw; struct purex_entry_24xx *purex = pkt; @@ -5876,7 +5887,7 @@ static int qla24xx_process_purex_iocb(struct scsi_qla_host *vha, void *pkt) struct buffer_credit_24xx *bbc = NULL; uint8_t *sfp = NULL; uint16_t sfp_flags = 0; - int rval = -ENOMEM; + int rval; ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0180, "%s: Enter\n", __func__); @@ -6301,8 +6312,23 @@ dealloc: if (rsp_els) dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els), rsp_els, rsp_els_dma); +} - return rval; +void qla24xx_process_purex_list(struct purex_list *list) +{ + struct list_head head = LIST_HEAD_INIT(head); + struct purex_item *item, *next; + ulong flags; + + spin_lock_irqsave(&list->lock, flags); + list_splice_init(&list->head, &head); + spin_unlock_irqrestore(&list->lock, flags); + + list_for_each_entry_safe(item, next, &head, list) { + list_del(&item->list); + item->process_item(item->vha, &item->iocb); + kfree(item); + } } void @@ -6652,8 +6678,6 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work) base_vha->flags.online = 0; - kfree(base_vha->purex_data); - qla2x00_destroy_deferred_work(ha); /* @@ -6877,11 +6901,13 @@ qla2x00_do_dpc(void *data) } } - if (test_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags) && - (atomic_read(&base_vha->loop_state) == LOOP_READY)) { - qla24xx_process_purex_iocb(base_vha, - base_vha->purex_data); - clear_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags); + if (test_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags)) { + if (atomic_read(&base_vha->loop_state) == LOOP_READY) { + qla24xx_process_purex_list + (&base_vha->purex_list); + clear_bit(PROCESS_PUREX_IOCB, + &base_vha->dpc_flags); + } } if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, From 4879237cd28eebb9350a7e6d970677997abe2b9d Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 12 Feb 2020 13:44:25 -0800 Subject: [PATCH 0699/4444] scsi: qla2xxx: Handle cases for limiting RDP response payload length This patch reduces RDP response payload length, if requesting port is a domain controller (sid 0xfffc01) and fw is earlier than 8.09.00 and fw is not 8.05.65 then limit the RDP response payload length to maximum of 256 bytes by terminating the response just before the optical element descriptor. Link: https://lore.kernel.org/r/20200212214436.25532-15-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Joe Carnuccio Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 42 +++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 7ab32977ea96..0e6bad0e4c21 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -5769,6 +5769,32 @@ retry_lock: return; } +static bool +qla25xx_rdp_rsp_reduce_size(struct scsi_qla_host *vha, + struct purex_entry_24xx *purex) +{ + char fwstr[16]; + u32 sid = purex->s_id[2] << 16 | purex->s_id[1] << 8 | purex->s_id[0]; + + /* Domain Controller is always logged-out. */ + /* if RDP request is not from Domain Controller: */ + if (sid != 0xfffc01) + return false; + + ql_dbg(ql_dbg_init, vha, 0x0181, "%s: s_id=%#x\n", __func__, sid); + + vha->hw->isp_ops->fw_version_str(vha, fwstr, sizeof(fwstr)); + fwstr[strcspn(fwstr, " ")] = 0; + /* if FW version allows RDP response length upto 2048 bytes: */ + if (strcmp(fwstr, "8.09.00") > 0 || strcmp(fwstr, "8.05.65") == 0) + return false; + + ql_dbg(ql_dbg_init, vha, 0x0181, "%s: fw=%s\n", __func__, fwstr); + + /* RDP response length is to be reduced to maximum 256 bytes */ + return true; +} + static uint qla25xx_rdp_port_speed_capability(struct qla_hw_data *ha) { @@ -5887,6 +5913,7 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) struct buffer_credit_24xx *bbc = NULL; uint8_t *sfp = NULL; uint16_t sfp_flags = 0; + uint rsp_payload_length = sizeof(*rsp_payload); int rval; ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0180, @@ -5897,6 +5924,14 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0182, (void *)purex, sizeof(*purex)); + if (qla25xx_rdp_rsp_reduce_size(vha, purex)) { + rsp_payload_length = + offsetof(typeof(*rsp_payload), optical_elmt_desc); + ql_dbg(ql_dbg_init, vha, 0x0181, + "Reducing RSP payload length to %u bytes...\n", + rsp_payload_length); + } + rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els), &rsp_els_dma, GFP_KERNEL); if (!rsp_els) { @@ -5943,7 +5978,7 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) rsp_els->control_flags = EPD_ELS_ACC; rsp_els->rx_byte_count = 0; - rsp_els->tx_byte_count = cpu_to_le32(sizeof(*rsp_payload)); + rsp_els->tx_byte_count = cpu_to_le32(rsp_payload_length); put_unaligned_le64(rsp_payload_dma, &rsp_els->tx_address); rsp_els->tx_len = rsp_els->tx_byte_count; @@ -6118,6 +6153,9 @@ accept: } } + if (rsp_payload_length < sizeof(*rsp_payload)) + goto send; + if (sfp) { memset(sfp, 0, SFP_RTDI_LEN); rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0, 64, 0); @@ -6278,7 +6316,7 @@ send: ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0186, "-------- ELS RSP PAYLOAD -------\n"); ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0187, - (void *)rsp_payload, rsp_els->tx_byte_count); + (void *)rsp_payload, rsp_payload_length); rval = qla2x00_issue_iocb(vha, rsp_els, rsp_els_dma, 0); From 84f7d2e7b1f5203050b47cfa65e284182d32f203 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Wed, 12 Feb 2020 13:44:26 -0800 Subject: [PATCH 0700/4444] scsi: qla2xxx: Fix RDP response size This patch fixes RDP length in case when driver needs to reduce length of RDP response Link: https://lore.kernel.org/r/20200212214436.25532-16-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 53 +++++++++++++---------------------- 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 0e6bad0e4c21..f5a264f0afd6 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -5775,6 +5775,7 @@ qla25xx_rdp_rsp_reduce_size(struct scsi_qla_host *vha, { char fwstr[16]; u32 sid = purex->s_id[2] << 16 | purex->s_id[1] << 8 | purex->s_id[0]; + struct port_database_24xx *pdb; /* Domain Controller is always logged-out. */ /* if RDP request is not from Domain Controller: */ @@ -5783,6 +5784,24 @@ qla25xx_rdp_rsp_reduce_size(struct scsi_qla_host *vha, ql_dbg(ql_dbg_init, vha, 0x0181, "%s: s_id=%#x\n", __func__, sid); + pdb = kzalloc(sizeof(*pdb), GFP_KERNEL); + if (!pdb) { + ql_dbg(ql_dbg_init, vha, 0x0181, + "%s: Failed allocate pdb\n", __func__); + } else if (qla24xx_get_port_database(vha, purex->nport_handle, pdb)) { + ql_dbg(ql_dbg_init, vha, 0x0181, + "%s: Failed get pdb sid=%x\n", __func__, sid); + } else if (pdb->current_login_state != PDS_PLOGI_COMPLETE && + pdb->current_login_state != PDS_PRLI_COMPLETE) { + ql_dbg(ql_dbg_init, vha, 0x0181, + "%s: Port not logged in sid=%#x\n", __func__, sid); + } else { + /* RDP request is from logged in port */ + kfree(pdb); + return false; + } + kfree(pdb); + vha->hw->isp_ops->fw_version_str(vha, fwstr, sizeof(fwstr)); fwstr[strcspn(fwstr, " ")] = 0; /* if FW version allows RDP response length upto 2048 bytes: */ @@ -5901,7 +5920,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) { struct qla_hw_data *ha = vha->hw; struct purex_entry_24xx *purex = pkt; - struct port_database_24xx *pdb = NULL; dma_addr_t rsp_els_dma; dma_addr_t rsp_payload_dma; dma_addr_t stat_dma; @@ -5986,34 +6004,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) rsp_els->rx_address = 0; rsp_els->rx_len = 0; - if (sizeof(*rsp_payload) <= 0x100) - goto accept; - - pdb = kzalloc(sizeof(*pdb), GFP_KERNEL); - if (!pdb) - goto reduce; - - rval = qla24xx_get_port_database(vha, purex->nport_handle, pdb); - if (rval) - goto reduce; - - if (pdb->port_id[0] != purex->s_id[2] || - pdb->port_id[1] != purex->s_id[1] || - pdb->port_id[2] != purex->s_id[0]) - goto reduce; - - if (pdb->current_login_state == PDS_PLOGI_COMPLETE || - pdb->current_login_state == PDS_PRLI_COMPLETE) - goto accept; - -reduce: - ql_dbg(ql_dbg_init, vha, 0x016e, "Requesting port is not logged in.\n"); - rsp_els->tx_byte_count = rsp_els->tx_len = - offsetof(struct rdp_rsp_payload, buffer_credit_desc); - ql_dbg(ql_dbg_init, vha, 0x016f, "Reduced response payload size %u.\n", - rsp_els->tx_byte_count); - -accept: /* Prepare Response Payload */ rsp_payload->hdr.cmd = cpu_to_be32(0x2 << 24); /* LS_ACC */ rsp_payload->hdr.len = cpu_to_be32( @@ -6131,9 +6121,6 @@ accept: vha->fabric_port_name, sizeof(rsp_payload->port_name_direct_desc.WWPN)); - if (rsp_els->tx_byte_count < sizeof(*rsp_payload)) - goto send; - if (bbc) { memset(bbc, 0, sizeof(*bbc)); rval = qla24xx_get_buffer_credits(vha, bbc, bbc_dma); @@ -6333,8 +6320,6 @@ send: } dealloc: - kfree(pdb); - if (bbc) dma_free_coherent(&ha->pdev->dev, sizeof(*bbc), bbc, bbc_dma); From a31056ddc6651b457d72d8d71d32143764df86d2 Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 12 Feb 2020 13:44:27 -0800 Subject: [PATCH 0701/4444] scsi: qla2xxx: Use endian macros to assign static fields in fwdump header This takes care of big endian architectures. Link: https://lore.kernel.org/r/20200212214436.25532-17-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_tmpl.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c index 5b0c057def2b..6aeb1c3fb7a8 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.c +++ b/drivers/scsi/qla2xxx/qla_tmpl.c @@ -870,7 +870,7 @@ bailout: static void qla27xx_time_stamp(struct qla27xx_fwdt_template *tmp) { - tmp->capture_timestamp = jiffies; + tmp->capture_timestamp = cpu_to_le32(jiffies); } static void @@ -882,9 +882,10 @@ qla27xx_driver_info(struct qla27xx_fwdt_template *tmp) "%hhu.%hhu.%hhu.%hhu.%hhu.%hhu", v+0, v+1, v+2, v+3, v+4, v+5) != 6); - tmp->driver_info[0] = v[3] << 24 | v[2] << 16 | v[1] << 8 | v[0]; - tmp->driver_info[1] = v[5] << 8 | v[4]; - tmp->driver_info[2] = 0x12345678; + tmp->driver_info[0] = cpu_to_le32( + v[3] << 24 | v[2] << 16 | v[1] << 8 | v[0]); + tmp->driver_info[1] = cpu_to_le32(v[5] << 8 | v[4]); + tmp->driver_info[2] = __constant_cpu_to_le32(0x12345678); } static void @@ -894,10 +895,10 @@ qla27xx_firmware_info(struct scsi_qla_host *vha, tmp->firmware_version[0] = vha->hw->fw_major_version; tmp->firmware_version[1] = vha->hw->fw_minor_version; tmp->firmware_version[2] = vha->hw->fw_subminor_version; - tmp->firmware_version[3] = - vha->hw->fw_attributes_h << 16 | vha->hw->fw_attributes; - tmp->firmware_version[4] = - vha->hw->fw_attributes_ext[1] << 16 | vha->hw->fw_attributes_ext[0]; + tmp->firmware_version[3] = cpu_to_le32( + vha->hw->fw_attributes_h << 16 | vha->hw->fw_attributes); + tmp->firmware_version[4] = cpu_to_le32( + vha->hw->fw_attributes_ext[1] << 16 | vha->hw->fw_attributes_ext[0]); } static void From 64d21b314173c46d5c88a55cf559b0677e39d884 Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 12 Feb 2020 13:44:28 -0800 Subject: [PATCH 0702/4444] scsi: qla2xxx: Correction to selection of loopback/echo test This fixes loopback and echo test options. Link: https://lore.kernel.org/r/20200212214436.25532-18-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_bsg.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 5870d26ab707..34fa200900fc 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -728,7 +728,7 @@ qla2x00_process_loopback(struct bsg_job *bsg_job) uint16_t response[MAILBOX_REGISTER_COUNT]; uint16_t config[4], new_config[4]; uint8_t *fw_sts_ptr; - uint8_t *req_data = NULL; + void *req_data = NULL; dma_addr_t req_data_dma; uint32_t req_data_len; uint8_t *rsp_data = NULL; @@ -806,10 +806,11 @@ qla2x00_process_loopback(struct bsg_job *bsg_job) bsg_request->rqst_data.h_vendor.vendor_cmd[2]; if (atomic_read(&vha->loop_state) == LOOP_READY && - (ha->current_topology == ISP_CFG_F || - (get_unaligned_le32(req_data) == ELS_OPCODE_BYTE && - req_data_len == MAX_ELS_FRAME_PAYLOAD)) && - elreq.options == EXTERNAL_LOOPBACK) { + ((ha->current_topology == ISP_CFG_F && (elreq.options & 7) >= 2) || + ((IS_QLA81XX(ha) || IS_QLA8031(ha) || IS_QLA8044(ha)) && + get_unaligned_le32(req_data) == ELS_OPCODE_BYTE && + req_data_len == MAX_ELS_FRAME_PAYLOAD && + elreq.options == EXTERNAL_LOOPBACK))) { type = "FC_BSG_HST_VENDOR_ECHO_DIAG"; ql_dbg(ql_dbg_user, vha, 0x701e, "BSG request type: %s.\n", type); From 83cfd3dc002fc730387a1ec5fa0d4097cc31ee9f Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 12 Feb 2020 13:44:29 -0800 Subject: [PATCH 0703/4444] scsi: qla2xxx: Fix qla2x00_echo_test() based on ISP type Ths patch fixes MBX in-direction for setting right bits for qla2x00_echo_test() Link: https://lore.kernel.org/r/20200212214436.25532-19-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_mbx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index c1698bf74c13..cd4f441f7c25 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -5317,10 +5317,11 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, mcp->out_mb |= MBX_2; mcp->in_mb = MBX_0; - if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || - IS_CNA_CAPABLE(ha) || IS_QLA2031(ha)) + if (IS_CNA_CAPABLE(ha) || IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || + IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) mcp->in_mb |= MBX_1; - if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha)) + if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) mcp->in_mb |= MBX_3; mcp->tov = MBX_TOV_SECONDS; From cbe729a63d5a2c5909c6ae7e54665059496e43b9 Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 12 Feb 2020 13:44:30 -0800 Subject: [PATCH 0704/4444] scsi: qla2xxx: Print portname for logging in qla24xx_logio_entry() Add port name in the messages file to help debugging of Login/Logout IOCBs Link: https://lore.kernel.org/r/20200212214436.25532-20-hmadhani@marvell.com Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_isr.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index cb40261158c9..7c0c32d5d6ec 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1899,11 +1899,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, } if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) { - ql_dbg(ql_dbg_async, fcport->vha, 0x5036, - "Async-%s complete - %8phC hdl=%x portid=%02x%02x%02x " - "iop0=%x.\n", type, fcport->port_name, sp->handle, - fcport->d_id.b.domain, - fcport->d_id.b.area, fcport->d_id.b.al_pa, + ql_dbg(ql_dbg_async, sp->vha, 0x5036, + "Async-%s complete: handle=%x pid=%06x wwpn=%8phC iop0=%x\n", + type, sp->handle, fcport->d_id.b24, fcport->port_name, le32_to_cpu(logio->io_parameter[0])); vha->hw->exch_starvation = 0; @@ -1982,11 +1980,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, break; } - ql_dbg(ql_dbg_async, fcport->vha, 0x5037, - "Async-%s failed - %8phC hdl=%x portid=%02x%02x%02x comp=%x " - "iop0=%x iop1=%x.\n", type, fcport->port_name, - sp->handle, fcport->d_id.b.domain, - fcport->d_id.b.area, fcport->d_id.b.al_pa, + ql_dbg(ql_dbg_async, sp->vha, 0x5037, + "Async-%s failed: handle=%x pid=%06x wwpn=%8phC comp_status=%x iop0=%x iop1=%x\n", + type, sp->handle, fcport->d_id.b24, fcport->port_name, le16_to_cpu(logio->comp_status), le32_to_cpu(logio->io_parameter[0]), le32_to_cpu(logio->io_parameter[1])); From 8d4926d13076a89c1f750fe5af4c082d8ea15008 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Wed, 12 Feb 2020 13:44:31 -0800 Subject: [PATCH 0705/4444] scsi: qla2xxx: Use correct ISP28xx active FW region For ISP28xx, use 28xx call to retrieve active FW region. Link: https://lore.kernel.org/r/20200212214436.25532-21-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_bsg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 34fa200900fc..714bcf5e6e53 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -2415,7 +2415,7 @@ qla2x00_get_flash_image_status(struct bsg_job *bsg_job) regions.global_image = active_regions.global; if (IS_QLA28XX(ha)) { - qla27xx_get_active_image(vha, &active_regions); + qla28xx_get_aux_images(vha, &active_regions); regions.board_config = active_regions.aux.board_config; regions.vpd_nvram = active_regions.aux.vpd_nvram; regions.npiv_config_0_1 = active_regions.aux.npiv_config_0_1; From d26a8982c9bd92ce3596eb4f86e922cdaf6751e5 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Wed, 12 Feb 2020 13:44:32 -0800 Subject: [PATCH 0706/4444] scsi: qla2xxx: Save rscn_gen for new fcport Add missing rscn_gen when creating new fcport. Link: https://lore.kernel.org/r/20200212214436.25532-22-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_gs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index e67105aca497..5af49a7ddb22 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3487,6 +3487,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) if (memcmp(rp->port_name, fcport->port_name, WWN_SIZE)) continue; fcport->scan_state = QLA_FCPORT_FOUND; + fcport->last_rscn_gen = fcport->rscn_gen; found = true; /* * If device was not a fabric device before. From 419ae5fe73e50084fa794934fb62fab34f564b7c Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Wed, 12 Feb 2020 13:44:33 -0800 Subject: [PATCH 0707/4444] scsi: qla2xxx: Fix control flags for login/logout IOCB This patch fixes control flag options for login/logout IOCB. Link: https://lore.kernel.org/r/20200212214436.25532-23-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_iocb.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 5b73d09da739..4f022955eb94 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2362,6 +2362,8 @@ qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio) struct srb_iocb *lio = &sp->u.iocb_cmd; logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; + logio->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); + if (lio->u.logio.flags & SRB_LOGIN_PRLI_ONLY) { logio->control_flags = cpu_to_le16(LCF_COMMAND_PRLI); } else { @@ -2939,7 +2941,6 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, sp->fcport = fcport; elsio->timeout = qla2x00_els_dcmd2_iocb_timeout; - init_completion(&elsio->u.els_plogi.comp); if (wait) sp->flags = SRB_WAKEUP_ON_COMP; @@ -2949,7 +2950,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, elsio->u.els_plogi.tx_size = elsio->u.els_plogi.rx_size = DMA_POOL_SIZE; ptr = elsio->u.els_plogi.els_plogi_pyld = - dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE, + dma_alloc_coherent(&ha->pdev->dev, elsio->u.els_plogi.tx_size, &elsio->u.els_plogi.els_plogi_pyld_dma, GFP_KERNEL); if (!elsio->u.els_plogi.els_plogi_pyld) { @@ -2958,7 +2959,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, } resp_ptr = elsio->u.els_plogi.els_resp_pyld = - dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE, + dma_alloc_coherent(&ha->pdev->dev, elsio->u.els_plogi.rx_size, &elsio->u.els_plogi.els_resp_pyld_dma, GFP_KERNEL); if (!elsio->u.els_plogi.els_resp_pyld) { @@ -2982,6 +2983,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, (uint8_t *)elsio->u.els_plogi.els_plogi_pyld, sizeof(*elsio->u.els_plogi.els_plogi_pyld)); + init_completion(&elsio->u.els_plogi.comp); rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) { rval = QLA_FUNCTION_FAILED; From 345f574dac85276d1471492c6e90c57e3f90a4f3 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Wed, 12 Feb 2020 13:44:34 -0800 Subject: [PATCH 0708/4444] scsi: qla2xxx: Add fixes for mailbox command This patch fixes: - qla2x00_issue_iocb_timeout will now return if chip is down - only check for sp->qpair in abort handling Link: https://lore.kernel.org/r/20200212214436.25532-24-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_mbx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index cd4f441f7c25..3bb6ab6f254a 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1404,6 +1404,9 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; + if (qla2x00_chip_is_down(vha)) + return QLA_INVALID_COMMAND; + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1038, "Entered %s.\n", __func__); @@ -1475,7 +1478,7 @@ qla2x00_abort_command(srb_t *sp) ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103b, "Entered %s.\n", __func__); - if (vha->flags.qpairs_available && sp->qpair) + if (sp->qpair) req = sp->qpair->req; else req = vha->req; From 0fc5b7e62322e1aa8384013ee1caff3f87d30207 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Wed, 12 Feb 2020 13:44:35 -0800 Subject: [PATCH 0709/4444] scsi: qla2xxx: Use QLA_FW_STOPPED macro to propagate flag This patch uses QLA_FW_STOPPED macro so that flag is propogated to all the QPairs. Link: https://lore.kernel.org/r/20200212214436.25532-25-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 8fee3f5154c7..1ec93e28560e 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -6676,7 +6676,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) ha->flags.n2n_ae = 0; ha->flags.lip_ae = 0; ha->current_topology = 0; - ha->flags.fw_started = 0; + QLA_FW_STOPPED(ha); ha->flags.fw_init_done = 0; ha->chip_reset++; ha->base_qpair->chip_reset = ha->chip_reset; From 1939295a8dfa7be1cea478d6d7d283c091b780d4 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Wed, 12 Feb 2020 13:44:36 -0800 Subject: [PATCH 0710/4444] scsi: qla2xxx: Update driver version to 10.01.00.24-k Link: https://lore.kernel.org/r/20200212214436.25532-26-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index bb03c022e023..6b4ca3ed8f22 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.01.00.22-k" +#define QLA2XXX_VERSION "10.01.00.24-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 1 From 8f38fd5ba6164757065efebe551a0d63220ac58a Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 24 Feb 2020 09:51:00 -0800 Subject: [PATCH 0711/4444] ARM: dts: Configure omap5 AESS We are missing AESS for omap5. Looks like it's similar to what we have for omap4, and this gets ti-sysc interconnect target module driver to detect it properly. Note that we currently have no child device driver available for it. Cc: H. Nikolaus Schaller Cc: Matthijs van Duin Cc: Peter Ujfalusi Cc: Tero Kristo Tested-by: Nikolaus Schaller Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap5-l4-abe.dtsi | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/omap5-l4-abe.dtsi b/arch/arm/boot/dts/omap5-l4-abe.dtsi index 4ec7909df78b..bafd6adf9f45 100644 --- a/arch/arm/boot/dts/omap5-l4-abe.dtsi +++ b/arch/arm/boot/dts/omap5-l4-abe.dtsi @@ -426,8 +426,20 @@ }; target-module@f1000 { /* 0x401f1000, ap 32 20.0 */ - compatible = "ti,sysc"; - status = "disabled"; + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0xf1000 0x4>, + <0xf1010 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-midle = , + , + , + ; + ti,sysc-sidle = , + , + ; + /* Domains (V, P, C): iva, abe_pwrdm, abe_clkdm */ + clocks = <&abe_clkctrl OMAP5_AESS_CLKCTRL 0>; + clock-names = "fck"; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xf1000 0x1000>, From 66167283c21ef8ce35253397108263bdab258992 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Feb 2020 16:32:05 +0100 Subject: [PATCH 0712/4444] scsi: ch: fixup refcounting imbalance for SCSI devices The SCSI device is required to be present during ch_probe() and ch_open(). But the SCSI device itself is only checked during ch_open(), so it's anyones guess if it had been present during ch_probe(). And consequently we can't reliably detach it during ch_release(), as ch_remove() might have been called first. So initialize the changer device during ch_probe(), and take a reference to the SCSI device during both ch_probe() and ch_open(). [mkp: fixed checkpatch warning] Link: https://lore.kernel.org/r/20200213153207.123357-2-hare@suse.de Reviewed-by: Bart Van Assche Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/ch.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index ed5f4a6ae270..e3a006d194e0 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -569,6 +569,7 @@ static void ch_destroy(struct kref *ref) { scsi_changer *ch = container_of(ref, scsi_changer, ref); + ch->device = NULL; kfree(ch->dt); kfree(ch); } @@ -594,14 +595,17 @@ ch_open(struct inode *inode, struct file *file) spin_lock(&ch_index_lock); ch = idr_find(&ch_index_idr, minor); - if (NULL == ch || scsi_device_get(ch->device)) { + if (ch == NULL || !kref_get_unless_zero(&ch->ref)) { spin_unlock(&ch_index_lock); mutex_unlock(&ch_mutex); return -ENXIO; } - kref_get(&ch->ref); spin_unlock(&ch_index_lock); - + if (scsi_device_get(ch->device)) { + kref_put(&ch->ref, ch_destroy); + mutex_unlock(&ch_mutex); + return -ENXIO; + } file->private_data = ch; mutex_unlock(&ch_mutex); return 0; @@ -938,6 +942,12 @@ static int ch_probe(struct device *dev) ch->minor = ret; sprintf(ch->name,"ch%d",ch->minor); + ret = scsi_device_get(sd); + if (ret) { + sdev_printk(KERN_WARNING, sd, "ch%d: failed to get device\n", + ch->minor); + goto remove_idr; + } class_dev = device_create(ch_sysfs_class, dev, MKDEV(SCSI_CHANGER_MAJOR, ch->minor), ch, @@ -946,7 +956,7 @@ static int ch_probe(struct device *dev) sdev_printk(KERN_WARNING, sd, "ch%d: device_create failed\n", ch->minor); ret = PTR_ERR(class_dev); - goto remove_idr; + goto put_device; } mutex_init(&ch->lock); @@ -964,6 +974,8 @@ static int ch_probe(struct device *dev) return 0; destroy_dev: device_destroy(ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR, ch->minor)); +put_device: + scsi_device_put(sd); remove_idr: idr_remove(&ch_index_idr, ch->minor); free_ch: @@ -977,9 +989,11 @@ static int ch_remove(struct device *dev) spin_lock(&ch_index_lock); idr_remove(&ch_index_idr, ch->minor); + dev_set_drvdata(dev, NULL); spin_unlock(&ch_index_lock); device_destroy(ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR,ch->minor)); + scsi_device_put(ch->device); kref_put(&ch->ref, ch_destroy); return 0; } From 1c7ce4bcfb9a54073d4043c00a336a064ca6e231 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Feb 2020 16:32:06 +0100 Subject: [PATCH 0713/4444] scsi: ch: synchronize ch_probe() and ch_open() The 'ch' device node is created before the configuration is being read in, which leads to a race window when ch_open() is called before that. To avoid any races we should be taking the device mutex during ch_readconfig() and ch_init_elem(), and also during ch_open(). That ensures ch_probe is finished before ch_open() completes. Link: https://lore.kernel.org/r/20200213153207.123357-3-hare@suse.de Reviewed-by: Bart Van Assche Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/ch.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index e3a006d194e0..7fdb636339e4 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -606,7 +606,10 @@ ch_open(struct inode *inode, struct file *file) mutex_unlock(&ch_mutex); return -ENXIO; } + /* Synchronize with ch_probe() */ + mutex_lock(&ch->lock); file->private_data = ch; + mutex_unlock(&ch->lock); mutex_unlock(&ch_mutex); return 0; } @@ -949,6 +952,9 @@ static int ch_probe(struct device *dev) goto remove_idr; } + mutex_init(&ch->lock); + kref_init(&ch->ref); + ch->device = sd; class_dev = device_create(ch_sysfs_class, dev, MKDEV(SCSI_CHANGER_MAJOR, ch->minor), ch, "s%s", ch->name); @@ -959,15 +965,16 @@ static int ch_probe(struct device *dev) goto put_device; } - mutex_init(&ch->lock); - kref_init(&ch->ref); - ch->device = sd; + mutex_lock(&ch->lock); ret = ch_readconfig(ch); - if (ret) + if (ret) { + mutex_unlock(&ch->lock); goto destroy_dev; + } if (init) ch_init_elem(ch); + mutex_unlock(&ch->lock); dev_set_drvdata(dev, ch); sdev_printk(KERN_INFO, sd, "Attached scsi changer %s\n", ch->name); From 30f6d494cc78beebbeb845ead9dd668f2644be26 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Feb 2020 16:32:07 +0100 Subject: [PATCH 0714/4444] scsi: ch: remove ch_mutex() ch_mutex() was introduced with a mechanical conversion, but as we now have correct locking we can remove it altogether. Link: https://lore.kernel.org/r/20200213153207.123357-4-hare@suse.de Reviewed-by: Bart Van Assche Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/ch.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index 7fdb636339e4..cb74ab1ae5a4 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -44,7 +44,6 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(SCSI_CHANGER_MAJOR); MODULE_ALIAS_SCSI_DEVICE(TYPE_MEDIUM_CHANGER); -static DEFINE_MUTEX(ch_mutex); static int init = 1; module_param(init, int, 0444); MODULE_PARM_DESC(init, \ @@ -591,26 +590,22 @@ ch_open(struct inode *inode, struct file *file) scsi_changer *ch; int minor = iminor(inode); - mutex_lock(&ch_mutex); spin_lock(&ch_index_lock); ch = idr_find(&ch_index_idr, minor); if (ch == NULL || !kref_get_unless_zero(&ch->ref)) { spin_unlock(&ch_index_lock); - mutex_unlock(&ch_mutex); return -ENXIO; } spin_unlock(&ch_index_lock); if (scsi_device_get(ch->device)) { kref_put(&ch->ref, ch_destroy); - mutex_unlock(&ch_mutex); return -ENXIO; } /* Synchronize with ch_probe() */ mutex_lock(&ch->lock); file->private_data = ch; mutex_unlock(&ch->lock); - mutex_unlock(&ch_mutex); return 0; } From 679b2ec8e060ca7a90441aff5e7d384720a41b76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Elio=20Petten=C3=B2?= Date: Sun, 23 Feb 2020 19:11:44 +0000 Subject: [PATCH 0715/4444] scsi: sr: remove references to BLK_DEV_SR_VENDOR, leave it enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This kernel configuration is basically enabling/disabling sr driver quirks detection. While these quirks are for fairly rare devices (very old CD burners, and a glucometer), the additional detection of these models is a very minimal amount of code. The logic behind the quirks is always built into the sr driver. This also removes the config from all the defconfig files that are enabling this already. Link: https://lore.kernel.org/r/20200223191144.726-1-flameeyes@flameeyes.com Reviewed-by: Jens Axboe Signed-off-by: Diego Elio Pettenò Signed-off-by: Martin K. Petersen --- arch/alpha/configs/defconfig | 1 - arch/arm/configs/rpc_defconfig | 1 - arch/arm/configs/s3c2410_defconfig | 1 - arch/ia64/configs/zx1_defconfig | 1 - arch/m68k/configs/amiga_defconfig | 1 - arch/m68k/configs/apollo_defconfig | 1 - arch/m68k/configs/atari_defconfig | 1 - arch/m68k/configs/bvme6000_defconfig | 1 - arch/m68k/configs/hp300_defconfig | 1 - arch/m68k/configs/mac_defconfig | 1 - arch/m68k/configs/multi_defconfig | 1 - arch/m68k/configs/mvme147_defconfig | 1 - arch/m68k/configs/mvme16x_defconfig | 1 - arch/m68k/configs/q40_defconfig | 1 - arch/m68k/configs/sun3_defconfig | 1 - arch/m68k/configs/sun3x_defconfig | 1 - arch/mips/configs/bigsur_defconfig | 1 - arch/mips/configs/fuloong2e_defconfig | 1 - arch/mips/configs/ip27_defconfig | 1 - arch/mips/configs/ip32_defconfig | 1 - arch/mips/configs/jazz_defconfig | 1 - arch/mips/configs/malta_defconfig | 1 - arch/mips/configs/malta_kvm_defconfig | 1 - arch/mips/configs/malta_kvm_guest_defconfig | 1 - arch/mips/configs/maltaup_xpa_defconfig | 1 - arch/mips/configs/rm200_defconfig | 1 - arch/powerpc/configs/85xx-hw.config | 1 - arch/powerpc/configs/amigaone_defconfig | 1 - arch/powerpc/configs/chrp32_defconfig | 1 - arch/powerpc/configs/g5_defconfig | 1 - arch/powerpc/configs/maple_defconfig | 1 - arch/powerpc/configs/pasemi_defconfig | 1 - arch/powerpc/configs/pmac32_defconfig | 1 - arch/powerpc/configs/powernv_defconfig | 1 - arch/powerpc/configs/ppc64_defconfig | 1 - arch/powerpc/configs/ppc64e_defconfig | 1 - arch/powerpc/configs/ppc6xx_defconfig | 1 - arch/powerpc/configs/pseries_defconfig | 1 - arch/powerpc/configs/skiroot_defconfig | 1 - arch/sh/configs/sh03_defconfig | 1 - arch/sparc/configs/sparc64_defconfig | 1 - arch/x86/configs/i386_defconfig | 1 - arch/x86/configs/x86_64_defconfig | 1 - drivers/scsi/Kconfig | 9 --------- drivers/scsi/sr_vendor.c | 8 -------- 45 files changed, 60 deletions(-) diff --git a/arch/alpha/configs/defconfig b/arch/alpha/configs/defconfig index f4ec420d7f2d..3a132c91d45b 100644 --- a/arch/alpha/configs/defconfig +++ b/arch/alpha/configs/defconfig @@ -36,7 +36,6 @@ CONFIG_BLK_DEV_CY82C693=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_SCSI_AIC7XXX=m CONFIG_AIC7XXX_CMDS_PER_DEVICE=253 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set diff --git a/arch/arm/configs/rpc_defconfig b/arch/arm/configs/rpc_defconfig index 3b82b64950d9..c090643b1ecb 100644 --- a/arch/arm/configs/rpc_defconfig +++ b/arch/arm/configs/rpc_defconfig @@ -32,7 +32,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index 73ed73a8785a..153009130dab 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -202,7 +202,6 @@ CONFIG_EEPROM_AT24=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_CHR_DEV_SCH=m CONFIG_SCSI_CONSTANTS=y diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig index 8c92e095f8bb..d42f79a33e91 100644 --- a/arch/ia64/configs/zx1_defconfig +++ b/arch/ia64/configs/zx1_defconfig @@ -35,7 +35,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_CHR_DEV_OSST=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig index e1134c3e0b69..e53008a9f00b 100644 --- a/arch/m68k/configs/amiga_defconfig +++ b/arch/m68k/configs/amiga_defconfig @@ -334,7 +334,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig index 484cb1643df1..3b0bf9d36594 100644 --- a/arch/m68k/configs/apollo_defconfig +++ b/arch/m68k/configs/apollo_defconfig @@ -319,7 +319,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig index eb6a46b6d135..7b2bffe9538d 100644 --- a/arch/m68k/configs/atari_defconfig +++ b/arch/m68k/configs/atari_defconfig @@ -334,7 +334,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig index bee9263a409c..6a9cc4cd0418 100644 --- a/arch/m68k/configs/bvme6000_defconfig +++ b/arch/m68k/configs/bvme6000_defconfig @@ -316,7 +316,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig index c8847a8bcbd6..259787203552 100644 --- a/arch/m68k/configs/hp300_defconfig +++ b/arch/m68k/configs/hp300_defconfig @@ -318,7 +318,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig index 303ffafd9cad..980b4de08fb3 100644 --- a/arch/m68k/configs/mac_defconfig +++ b/arch/m68k/configs/mac_defconfig @@ -325,7 +325,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig index 89a704226cd9..50b34ef2f0e5 100644 --- a/arch/m68k/configs/multi_defconfig +++ b/arch/m68k/configs/multi_defconfig @@ -358,7 +358,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig index f62c1f4d03a0..ec3ad8a3b1c8 100644 --- a/arch/m68k/configs/mvme147_defconfig +++ b/arch/m68k/configs/mvme147_defconfig @@ -315,7 +315,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig index 58dcad26a751..5a276096f165 100644 --- a/arch/m68k/configs/mvme16x_defconfig +++ b/arch/m68k/configs/mvme16x_defconfig @@ -316,7 +316,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig index 5d3c28d1d545..3a501740d96f 100644 --- a/arch/m68k/configs/q40_defconfig +++ b/arch/m68k/configs/q40_defconfig @@ -324,7 +324,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig index 5ef9e17dcd51..87c8674920c7 100644 --- a/arch/m68k/configs/sun3_defconfig +++ b/arch/m68k/configs/sun3_defconfig @@ -313,7 +313,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig index 22e1accc60a3..2c791cff21c6 100644 --- a/arch/m68k/configs/sun3x_defconfig +++ b/arch/m68k/configs/sun3x_defconfig @@ -313,7 +313,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig index f14ad0538f4e..eea9b613bb74 100644 --- a/arch/mips/configs/bigsur_defconfig +++ b/arch/mips/configs/bigsur_defconfig @@ -112,7 +112,6 @@ CONFIG_BLK_DEV_TC86C001=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_CHR_DEV_SCH=m CONFIG_ATA=y diff --git a/arch/mips/configs/fuloong2e_defconfig b/arch/mips/configs/fuloong2e_defconfig index 1788ae23bff9..6466e83067b4 100644 --- a/arch/mips/configs/fuloong2e_defconfig +++ b/arch/mips/configs/fuloong2e_defconfig @@ -99,7 +99,6 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_ATA_OVER_ETH=m CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOWLEVEL is not set diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig index 82d942a6026e..638d7cf5ef01 100644 --- a/arch/mips/configs/ip27_defconfig +++ b/arch/mips/configs/ip27_defconfig @@ -99,7 +99,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_CHR_DEV_SCH=m CONFIG_SCSI_CONSTANTS=y diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig index 370884018aad..7b1fab518317 100644 --- a/arch/mips/configs/ip32_defconfig +++ b/arch/mips/configs/ip32_defconfig @@ -50,7 +50,6 @@ CONFIG_RAID_ATTRS=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig index 328d4dfeb4cb..982b990469af 100644 --- a/arch/mips/configs/jazz_defconfig +++ b/arch/mips/configs/jazz_defconfig @@ -191,7 +191,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SCAN_ASYNC=y CONFIG_SCSI_FC_ATTRS=y diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig index 59eedf55419d..211bd3d6e6cb 100644 --- a/arch/mips/configs/malta_defconfig +++ b/arch/mips/configs/malta_defconfig @@ -239,7 +239,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y diff --git a/arch/mips/configs/malta_kvm_defconfig b/arch/mips/configs/malta_kvm_defconfig index 8ef612552a19..62b1969b4f55 100644 --- a/arch/mips/configs/malta_kvm_defconfig +++ b/arch/mips/configs/malta_kvm_defconfig @@ -247,7 +247,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y diff --git a/arch/mips/configs/malta_kvm_guest_defconfig b/arch/mips/configs/malta_kvm_guest_defconfig index d2a008c9907c..9185e0a0aa45 100644 --- a/arch/mips/configs/malta_kvm_guest_defconfig +++ b/arch/mips/configs/malta_kvm_guest_defconfig @@ -245,7 +245,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y diff --git a/arch/mips/configs/maltaup_xpa_defconfig b/arch/mips/configs/maltaup_xpa_defconfig index 970df6d42728..636311d67a53 100644 --- a/arch/mips/configs/maltaup_xpa_defconfig +++ b/arch/mips/configs/maltaup_xpa_defconfig @@ -245,7 +245,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig index 2c7adea7638f..30d7c3db884e 100644 --- a/arch/mips/configs/rm200_defconfig +++ b/arch/mips/configs/rm200_defconfig @@ -203,7 +203,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SCAN_ASYNC=y CONFIG_SCSI_FC_ATTRS=y diff --git a/arch/powerpc/configs/85xx-hw.config b/arch/powerpc/configs/85xx-hw.config index 9575a38c9155..b507df6ac69f 100644 --- a/arch/powerpc/configs/85xx-hw.config +++ b/arch/powerpc/configs/85xx-hw.config @@ -2,7 +2,6 @@ CONFIG_AQUANTIA_PHY=y CONFIG_AT803X_PHY=y CONFIG_ATA=y CONFIG_BLK_DEV_SD=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_BLK_DEV_SR=y CONFIG_BROADCOM_PHY=y CONFIG_C293_PCIE=y diff --git a/arch/powerpc/configs/amigaone_defconfig b/arch/powerpc/configs/amigaone_defconfig index f6d140f2d922..200bb1ecb560 100644 --- a/arch/powerpc/configs/amigaone_defconfig +++ b/arch/powerpc/configs/amigaone_defconfig @@ -44,7 +44,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SYM53C8XX_2=y diff --git a/arch/powerpc/configs/chrp32_defconfig b/arch/powerpc/configs/chrp32_defconfig index 502a75d49789..a4a805b87469 100644 --- a/arch/powerpc/configs/chrp32_defconfig +++ b/arch/powerpc/configs/chrp32_defconfig @@ -42,7 +42,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SYM53C8XX_2=y diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig index fbfcc85e4dc0..a68c7f3af10e 100644 --- a/arch/powerpc/configs/g5_defconfig +++ b/arch/powerpc/configs/g5_defconfig @@ -62,7 +62,6 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SPI_ATTRS=y diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig index 2975e64629aa..161351a18517 100644 --- a/arch/powerpc/configs/maple_defconfig +++ b/arch/powerpc/configs/maple_defconfig @@ -41,7 +41,6 @@ CONFIG_BLK_DEV_RAM_SIZE=8192 # CONFIG_SCSI_PROC_FS is not set CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_IPR=y CONFIG_ATA=y diff --git a/arch/powerpc/configs/pasemi_defconfig b/arch/powerpc/configs/pasemi_defconfig index 4b6d31d4474e..08b7f4cef243 100644 --- a/arch/powerpc/configs/pasemi_defconfig +++ b/arch/powerpc/configs/pasemi_defconfig @@ -60,7 +60,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_CHR_DEV_OSST=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_CHR_DEV_SCH=y CONFIG_SCSI_CONSTANTS=y diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig index f492e7d35925..05e325ca3fbd 100644 --- a/arch/powerpc/configs/pmac32_defconfig +++ b/arch/powerpc/configs/pmac32_defconfig @@ -117,7 +117,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_FC_ATTRS=y diff --git a/arch/powerpc/configs/powernv_defconfig b/arch/powerpc/configs/powernv_defconfig index 71749377d164..df8bdbaa5d8f 100644 --- a/arch/powerpc/configs/powernv_defconfig +++ b/arch/powerpc/configs/powernv_defconfig @@ -108,7 +108,6 @@ CONFIG_BLK_DEV_NVME=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SCAN_ASYNC=y diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 7e68cb222c7b..bae8170d7401 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -110,7 +110,6 @@ CONFIG_VIRTIO_BLK=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_FC_ATTRS=y diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig index 0d746774c2bd..33a01a9e86be 100644 --- a/arch/powerpc/configs/ppc64e_defconfig +++ b/arch/powerpc/configs/ppc64e_defconfig @@ -60,7 +60,6 @@ CONFIG_BLK_DEV_RAM_SIZE=65536 CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_FC_ATTRS=y diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig index 3e2f44f38ac5..feb5d47d8d1e 100644 --- a/arch/powerpc/configs/ppc6xx_defconfig +++ b/arch/powerpc/configs/ppc6xx_defconfig @@ -368,7 +368,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_CHR_DEV_SCH=m CONFIG_SCSI_ENCLOSURE=m diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index 6b68109e248f..0bea4d3ffb85 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig @@ -97,7 +97,6 @@ CONFIG_VIRTIO_BLK=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_FC_ATTRS=y diff --git a/arch/powerpc/configs/skiroot_defconfig b/arch/powerpc/configs/skiroot_defconfig index 1b6bdad36b13..ad6739ac63dc 100644 --- a/arch/powerpc/configs/skiroot_defconfig +++ b/arch/powerpc/configs/skiroot_defconfig @@ -84,7 +84,6 @@ CONFIG_EEPROM_AT24=m # CONFIG_OCXL is not set CONFIG_BLK_DEV_SD=m CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SCAN_ASYNC=y diff --git a/arch/sh/configs/sh03_defconfig b/arch/sh/configs/sh03_defconfig index e5beb625ab88..87db9a84b5ec 100644 --- a/arch/sh/configs/sh03_defconfig +++ b/arch/sh/configs/sh03_defconfig @@ -46,7 +46,6 @@ CONFIG_BLK_DEV_IDETAPE=m CONFIG_SCSI=m CONFIG_BLK_DEV_SD=m CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_NETDEVICES=y CONFIG_NET_ETHERNET=y diff --git a/arch/sparc/configs/sparc64_defconfig b/arch/sparc/configs/sparc64_defconfig index 6c325d53a20a..bde4d21a8ac8 100644 --- a/arch/sparc/configs/sparc64_defconfig +++ b/arch/sparc/configs/sparc64_defconfig @@ -73,7 +73,6 @@ CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_MULTI_LUN=y CONFIG_SCSI_CONSTANTS=y diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig index 59ce9ed58430..18806b4fb26a 100644 --- a/arch/x86/configs/i386_defconfig +++ b/arch/x86/configs/i386_defconfig @@ -137,7 +137,6 @@ CONFIG_CONNECTOR=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SPI_ATTRS=y diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig index 0b9654c7a05c..7f5cb3bead37 100644 --- a/arch/x86/configs/x86_64_defconfig +++ b/arch/x86/configs/x86_64_defconfig @@ -135,7 +135,6 @@ CONFIG_CONNECTOR=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SPI_ATTRS=y diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index a7881f8eb05e..2b882b96e0d4 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -115,15 +115,6 @@ config BLK_DEV_SR . The module will be called sr_mod. -config BLK_DEV_SR_VENDOR - bool "Enable vendor-specific extensions (for SCSI CDROM)" - depends on BLK_DEV_SR - help - This enables the usage of vendor specific SCSI commands. This is - required to support multisession CDs with old NEC/TOSHIBA cdrom - drives (and HP Writers). If you have such a drive and get the first - session only, try saying Y here; everybody else says N. - config CHR_DEV_SG tristate "SCSI generic support" depends on SCSI diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c index 17a56c87d383..1f988a1b9166 100644 --- a/drivers/scsi/sr_vendor.c +++ b/drivers/scsi/sr_vendor.c @@ -67,9 +67,6 @@ void sr_vendor_init(Scsi_CD *cd) { -#ifndef CONFIG_BLK_DEV_SR_VENDOR - cd->vendor = VENDOR_SCSI3; -#else const char *vendor = cd->device->vendor; const char *model = cd->device->model; @@ -118,7 +115,6 @@ void sr_vendor_init(Scsi_CD *cd) CDC_PLAY_AUDIO ); } -#endif } @@ -132,10 +128,8 @@ int sr_set_blocklength(Scsi_CD *cd, int blocklength) struct ccs_modesel_head *modesel; int rc, density = 0; -#ifdef CONFIG_BLK_DEV_SR_VENDOR if (cd->vendor == VENDOR_TOSHIBA) density = (blocklength > 2048) ? 0x81 : 0x83; -#endif buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) @@ -223,7 +217,6 @@ int sr_cd_check(struct cdrom_device_info *cdi) } break; -#ifdef CONFIG_BLK_DEV_SR_VENDOR case VENDOR_NEC:{ unsigned long min, sec, frame; cgc.cmd[0] = 0xde; @@ -316,7 +309,6 @@ int sr_cd_check(struct cdrom_device_info *cdi) sector = buffer[11] + (buffer[10] << 8) + (buffer[9] << 16) + (buffer[8] << 24); break; -#endif /* CONFIG_BLK_DEV_SR_VENDOR */ default: /* should not happen */ From 51a858817dcdbbdee22cb54b0b2b26eb145ca5b6 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Tue, 18 Feb 2020 15:39:17 +0100 Subject: [PATCH 0716/4444] scsi: sr: get rid of sr global mutex When replacing the Big Kernel Lock in commit 2a48fc0ab242 ("block: autoconvert trivial BKL users to private mutex"), the lock was replaced with a sr-wide lock. This causes very poor performance when using multiple sr devices, as the sr driver was not able to execute more than one command to one drive at any given time, even when there were many CD drives available. Replace the global mutex with per-sr-device mutex. Someone tried this patch at the time, but it never made it upstream, due to possible concerns with race conditions, but it's not clear the patch actually caused those: https://www.spinics.net/lists/linux-scsi/msg63706.html https://www.spinics.net/lists/linux-scsi/msg63750.html Also see http://lists.xiph.org/pipermail/paranoia/2019-December/001647.html Link: https://lore.kernel.org/r/20200218143918.30267-1-merlijn@archive.org Acked-by: Arnd Bergmann Signed-off-by: Merlijn Wajer Signed-off-by: Martin K. Petersen --- drivers/scsi/sr.c | 20 +++++++++++--------- drivers/scsi/sr.h | 2 ++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 0fbb8fe6e521..fe0e1c721a99 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -79,7 +79,6 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM); CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \ CDC_MRW|CDC_MRW_W|CDC_RAM) -static DEFINE_MUTEX(sr_mutex); static int sr_probe(struct device *); static int sr_remove(struct device *); static blk_status_t sr_init_command(struct scsi_cmnd *SCpnt); @@ -536,9 +535,9 @@ static int sr_block_open(struct block_device *bdev, fmode_t mode) scsi_autopm_get_device(sdev); check_disk_change(bdev); - mutex_lock(&sr_mutex); + mutex_lock(&cd->lock); ret = cdrom_open(&cd->cdi, bdev, mode); - mutex_unlock(&sr_mutex); + mutex_unlock(&cd->lock); scsi_autopm_put_device(sdev); if (ret) @@ -551,10 +550,10 @@ out: static void sr_block_release(struct gendisk *disk, fmode_t mode) { struct scsi_cd *cd = scsi_cd(disk); - mutex_lock(&sr_mutex); + mutex_lock(&cd->lock); cdrom_release(&cd->cdi, mode); scsi_cd_put(cd); - mutex_unlock(&sr_mutex); + mutex_unlock(&cd->lock); } static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, @@ -565,7 +564,7 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, void __user *argp = (void __user *)arg; int ret; - mutex_lock(&sr_mutex); + mutex_lock(&cd->lock); ret = scsi_ioctl_block_when_processing_errors(sdev, cmd, (mode & FMODE_NDELAY) != 0); @@ -595,7 +594,7 @@ put: scsi_autopm_put_device(sdev); out: - mutex_unlock(&sr_mutex); + mutex_unlock(&cd->lock); return ret; } @@ -608,7 +607,7 @@ static int sr_block_compat_ioctl(struct block_device *bdev, fmode_t mode, unsign void __user *argp = compat_ptr(arg); int ret; - mutex_lock(&sr_mutex); + mutex_lock(&cd->lock); ret = scsi_ioctl_block_when_processing_errors(sdev, cmd, (mode & FMODE_NDELAY) != 0); @@ -638,7 +637,7 @@ put: scsi_autopm_put_device(sdev); out: - mutex_unlock(&sr_mutex); + mutex_unlock(&cd->lock); return ret; } @@ -745,6 +744,7 @@ static int sr_probe(struct device *dev) disk = alloc_disk(1); if (!disk) goto fail_free; + mutex_init(&cd->lock); spin_lock(&sr_index_lock); minor = find_first_zero_bit(sr_index_bits, SR_DISKS); @@ -1055,6 +1055,8 @@ static void sr_kref_release(struct kref *kref) put_disk(disk); + mutex_destroy(&cd->lock); + kfree(cd); } diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h index a2bb7b8bace5..339c624e04d8 100644 --- a/drivers/scsi/sr.h +++ b/drivers/scsi/sr.h @@ -20,6 +20,7 @@ #include #include +#include #define MAX_RETRIES 3 #define SR_TIMEOUT (30 * HZ) @@ -51,6 +52,7 @@ typedef struct scsi_cd { bool ignore_get_event:1; /* GET_EVENT is unreliable, use TUR */ struct cdrom_device_info cdi; + struct mutex lock; /* We hold gendisk and scsi_device references on probe and use * the refs on this kref to decide when to release them */ struct kref kref; From 162e250031cc6caca35738813720e4ed83f1b1bb Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 21 Feb 2020 15:48:41 +0000 Subject: [PATCH 0717/4444] scsi: lpfc: fix spelling mistake "Notication" -> "Notification" There is a spelling mistake in a lpfc_printf_vlog info message. Fix it. [mkp: fix spelling mistake in commit description] Link: https://lore.kernel.org/linux-scsi/20200221154841.77791-1-colin.king@canonical.com Reviewed-by: James Smart Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index a712f15bc88c..80d1e661b0d4 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -3128,7 +3128,7 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, for (i = 0; i < ELS_RDF_REG_TAG_CNT && i < be32_to_cpu(prdf->reg_d1.reg_desc.count); i++) lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, - "4677 Fabric RDF Notication Grant Data: " + "4677 Fabric RDF Notification Grant Data: " "0x%08x\n", be32_to_cpu( prdf->reg_d1.desc_tags[i])); From acf253c11329caa6be6d2abc14dfc8c0ec83718a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Feb 2020 15:56:30 +0900 Subject: [PATCH 0718/4444] ASoC: soc-pcm: add snd_soc_dai_get_pcm_stream() DAI driver has playback/capture stream. OTOH, we have SNDRV_PCM_STREAM_PLAYBACK/CAPTURE. Because of this kind of implementation, ALSA SoC needs to have many verbose code. To solve this issue, this patch adds snd_soc_dai_get_pcm_stream() macro to get playback/capture stream pointer from stream. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ftf7jcab.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 7 ++++++ sound/soc/soc-dai.c | 7 +----- sound/soc/soc-pcm.c | 49 ++++++++--------------------------------- 3 files changed, 17 insertions(+), 46 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 7481e468be39..c1089194ddf1 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -352,6 +352,13 @@ struct snd_soc_dai { unsigned int started:1; }; +static inline struct snd_soc_pcm_stream * +snd_soc_dai_get_pcm_stream(const struct snd_soc_dai *dai, int stream) +{ + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? + &dai->driver->playback : &dai->driver->capture; +} + static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai, const struct snd_pcm_substream *ss) { diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 73a829393652..19142f6e533c 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -390,12 +390,7 @@ int snd_soc_dai_compress_new(struct snd_soc_dai *dai, */ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir) { - struct snd_soc_pcm_stream *stream; - - if (dir == SNDRV_PCM_STREAM_PLAYBACK) - stream = &dai->driver->playback; - else - stream = &dai->driver->capture; + struct snd_soc_pcm_stream *stream = snd_soc_dai_get_pcm_stream(dai, dir); /* If the codec specifies any channels at all, it supports the stream */ return stream->channels_min; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index aff27c8599ef..7cb445bb1b54 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -396,20 +396,16 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) struct snd_pcm_hardware *hw = &runtime->hw; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai; - struct snd_soc_dai_driver *cpu_dai_drv = rtd->cpu_dai->driver; - struct snd_soc_dai_driver *codec_dai_drv; struct snd_soc_pcm_stream *codec_stream; struct snd_soc_pcm_stream *cpu_stream; unsigned int chan_min = 0, chan_max = UINT_MAX; unsigned int rate_min = 0, rate_max = UINT_MAX; unsigned int rates = UINT_MAX; u64 formats = ULLONG_MAX; + int stream = substream->stream; int i; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - cpu_stream = &cpu_dai_drv->playback; - else - cpu_stream = &cpu_dai_drv->capture; + cpu_stream = snd_soc_dai_get_pcm_stream(rtd->cpu_dai, stream); /* first calculate min/max only for CODECs in the DAI link */ for_each_rtd_codec_dai(rtd, i, codec_dai) { @@ -427,11 +423,8 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) substream->stream)) continue; - codec_dai_drv = codec_dai->driver; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - codec_stream = &codec_dai_drv->playback; - else - codec_stream = &codec_dai_drv->capture; + codec_stream = snd_soc_dai_get_pcm_stream(codec_dai, stream); + chan_min = max(chan_min, codec_stream->channels_min); chan_max = min(chan_max, codec_stream->channels_max); rate_min = max(rate_min, codec_stream->rate_min); @@ -1600,7 +1593,6 @@ static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, for_each_dpcm_be(fe, stream, dpcm) { struct snd_soc_pcm_runtime *be = dpcm->be; - struct snd_soc_dai_driver *codec_dai_drv; struct snd_soc_pcm_stream *codec_stream; int i; @@ -1612,11 +1604,7 @@ static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, if (!snd_soc_dai_stream_valid(dai, stream)) continue; - codec_dai_drv = dai->driver; - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - codec_stream = &codec_dai_drv->playback; - else - codec_stream = &codec_dai_drv->capture; + codec_stream = snd_soc_dai_get_pcm_stream(dai, stream); *formats &= codec_stream->formats; } @@ -1641,15 +1629,10 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream, for_each_dpcm_be(fe, stream, dpcm) { struct snd_soc_pcm_runtime *be = dpcm->be; - struct snd_soc_dai_driver *cpu_dai_drv = be->cpu_dai->driver; - struct snd_soc_dai_driver *codec_dai_drv; struct snd_soc_pcm_stream *codec_stream; struct snd_soc_pcm_stream *cpu_stream; - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - cpu_stream = &cpu_dai_drv->playback; - else - cpu_stream = &cpu_dai_drv->capture; + cpu_stream = snd_soc_dai_get_pcm_stream(be->cpu_dai, stream); *channels_min = max(*channels_min, cpu_stream->channels_min); *channels_max = min(*channels_max, cpu_stream->channels_max); @@ -1659,12 +1642,7 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream, * DAIs connected to a single CPU DAI, use CPU DAI's directly */ if (be->num_codecs == 1) { - codec_dai_drv = be->codec_dais[0]->driver; - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - codec_stream = &codec_dai_drv->playback; - else - codec_stream = &codec_dai_drv->capture; + codec_stream = snd_soc_dai_get_pcm_stream(be->codec_dais[0], stream); *channels_min = max(*channels_min, codec_stream->channels_min); @@ -1693,17 +1671,12 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, for_each_dpcm_be(fe, stream, dpcm) { struct snd_soc_pcm_runtime *be = dpcm->be; - struct snd_soc_dai_driver *cpu_dai_drv = be->cpu_dai->driver; - struct snd_soc_dai_driver *codec_dai_drv; struct snd_soc_pcm_stream *codec_stream; struct snd_soc_pcm_stream *cpu_stream; struct snd_soc_dai *dai; int i; - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - cpu_stream = &cpu_dai_drv->playback; - else - cpu_stream = &cpu_dai_drv->capture; + cpu_stream = snd_soc_dai_get_pcm_stream(be->cpu_dai, stream); *rate_min = max(*rate_min, cpu_stream->rate_min); *rate_max = min_not_zero(*rate_max, cpu_stream->rate_max); @@ -1717,11 +1690,7 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, if (!snd_soc_dai_stream_valid(dai, stream)) continue; - codec_dai_drv = dai->driver; - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - codec_stream = &codec_dai_drv->playback; - else - codec_stream = &codec_dai_drv->capture; + codec_stream = snd_soc_dai_get_pcm_stream(dai, stream); *rate_min = max(*rate_min, codec_stream->rate_min); *rate_max = min_not_zero(*rate_max, From 57be92066f68e63bd4a72a65d45c3407c0cb552a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Feb 2020 15:56:36 +0900 Subject: [PATCH 0719/4444] ASoC: soc-pcm: cleanup soc_pcm_apply_msb() soc_pcm_apply_msb() apply msb for CPU/Codec, but, it has duplicate code. The difference is only SNDRV_PCM_STREAM_PLAYBACK and SNDRV_PCM_STEAM_CAPTURE. It is very verbose and duplicate code. This patch simplify code by using snd_soc_dai_get_pcm_stream(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87eeurjca6.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 7cb445bb1b54..6f56526bbb26 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -363,29 +363,24 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_dai *codec_dai; + struct snd_soc_pcm_stream *pcm_codec, *pcm_cpu; + int stream = substream->stream; int i; unsigned int bits = 0, cpu_bits; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - for_each_rtd_codec_dai(rtd, i, codec_dai) { - if (codec_dai->driver->playback.sig_bits == 0) { - bits = 0; - break; - } - bits = max(codec_dai->driver->playback.sig_bits, bits); + for_each_rtd_codec_dai(rtd, i, codec_dai) { + pcm_codec = snd_soc_dai_get_pcm_stream(codec_dai, stream); + + if (pcm_codec->sig_bits == 0) { + bits = 0; + break; } - cpu_bits = cpu_dai->driver->playback.sig_bits; - } else { - for_each_rtd_codec_dai(rtd, i, codec_dai) { - if (codec_dai->driver->capture.sig_bits == 0) { - bits = 0; - break; - } - bits = max(codec_dai->driver->capture.sig_bits, bits); - } - cpu_bits = cpu_dai->driver->capture.sig_bits; + bits = max(pcm_codec->sig_bits, bits); } + pcm_cpu = snd_soc_dai_get_pcm_stream(cpu_dai, stream); + cpu_bits = pcm_cpu->sig_bits; + soc_pcm_set_msb(substream, bits); soc_pcm_set_msb(substream, cpu_bits); } From 0c01f6ca8e4cc1e5505bf4657cf77fbfaa7b0bc2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Feb 2020 15:56:41 +0900 Subject: [PATCH 0720/4444] ASoC: soc-pcm: add snd_soc_dai_get_widget() soc-pcm.c has dai_get_widget(), but it can be more generic. This patch renames it to snd_soc_dai_get_widget(), and use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87d0abjca1.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 8 ++++++++ sound/soc/intel/skylake/skl-pcm.c | 10 ++-------- sound/soc/soc-dapm.c | 10 ++-------- sound/soc/soc-pcm.c | 17 ++++------------- 4 files changed, 16 insertions(+), 29 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index c1089194ddf1..92c382690930 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -359,6 +359,14 @@ snd_soc_dai_get_pcm_stream(const struct snd_soc_dai *dai, int stream) &dai->driver->playback : &dai->driver->capture; } +static inline +struct snd_soc_dapm_widget *snd_soc_dai_get_widget( + struct snd_soc_dai *dai, int stream) +{ + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? + dai->playback_widget : dai->capture_widget; +} + static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai, const struct snd_pcm_substream *ss) { diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index b99509675d29..05a9677c5a53 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -112,10 +112,7 @@ static void skl_set_suspend_active(struct snd_pcm_substream *substream, struct snd_soc_dapm_widget *w; struct skl_dev *skl = bus_to_skl(bus); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - w = dai->playback_widget; - else - w = dai->capture_widget; + w = snd_soc_dai_get_widget(dai, substream->stream); if (w->ignore_suspend && enable) skl->supend_active++; @@ -475,10 +472,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, if (!mconfig) return -EIO; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - w = dai->playback_widget; - else - w = dai->capture_widget; + w = snd_soc_dai_get_widget(dai, substream->stream); switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 69eff234b26f..f2e678865480 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2620,10 +2620,7 @@ static int dapm_update_dai_unlocked(struct snd_pcm_substream *substream, struct snd_soc_dapm_widget *w; int ret; - if (dir == SNDRV_PCM_STREAM_PLAYBACK) - w = dai->playback_widget; - else - w = dai->capture_widget; + w = snd_soc_dai_get_widget(dai, dir); if (!w) return 0; @@ -4389,10 +4386,7 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream, struct snd_soc_dapm_widget *w; unsigned int ep; - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - w = dai->playback_widget; - else - w = dai->capture_widget; + w = snd_soc_dai_get_widget(dai, stream); if (w) { dapm_mark_dirty(w, "stream event"); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 6f56526bbb26..e183fabc5b6f 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -82,15 +82,6 @@ static int soc_rtd_trigger(struct snd_soc_pcm_runtime *rtd, return 0; } -static inline -struct snd_soc_dapm_widget *dai_get_widget(struct snd_soc_dai *dai, int stream) -{ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - return dai->playback_widget; - else - return dai->capture_widget; -} - static void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, int stream, int action) { @@ -1242,7 +1233,7 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, if (!be->dai_link->no_pcm) continue; - w = dai_get_widget(be->cpu_dai, stream); + w = snd_soc_dai_get_widget(be->cpu_dai, stream); dev_dbg(card->dev, "ASoC: try BE : %s\n", w ? w->name : "(not set)"); @@ -1251,7 +1242,7 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, return be; for_each_rtd_codec_dai(be, i, dai) { - w = dai_get_widget(dai, stream); + w = snd_soc_dai_get_widget(dai, stream); if (w == widget) return be; @@ -1326,7 +1317,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, unsigned int i; /* is there a valid CPU DAI widget for this BE */ - widget = dai_get_widget(dpcm->be->cpu_dai, stream); + widget = snd_soc_dai_get_widget(dpcm->be->cpu_dai, stream); /* prune the BE if it's no longer in our active list */ if (widget && widget_in_list(list, widget)) @@ -1335,7 +1326,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, /* is there a valid CODEC DAI widget for this BE */ do_prune = 1; for_each_rtd_codec_dai(dpcm->be, i, dai) { - widget = dai_get_widget(dai, stream); + widget = snd_soc_dai_get_widget(dai, stream); /* prune the BE if it's no longer in our active list */ if (widget && widget_in_list(list, widget)) From 580dff3636d08ed12cb5d5db2fd895cbeffd0fd5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Feb 2020 15:56:46 +0900 Subject: [PATCH 0721/4444] ASoC: soc-pcm: merge dpcm_run_new/old_update() into dpcm_fe_runtime_update() soc-pcm has dpcm_run_new/old_update(), but these are used from dpcm_fe_runtime_update() only, and are very verbose functions. This patch disassembles these. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87blpvjc9v.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 35 +++++++---------------------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index e183fabc5b6f..1bf2db1732bf 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2536,37 +2536,12 @@ disconnect: return ret; } -static int dpcm_run_new_update(struct snd_soc_pcm_runtime *fe, int stream) -{ - int ret; - - dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE); - ret = dpcm_run_update_startup(fe, stream); - if (ret < 0) - dev_err(fe->dev, "ASoC: failed to startup some BEs\n"); - dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); - - return ret; -} - -static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream) -{ - int ret; - - dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE); - ret = dpcm_run_update_shutdown(fe, stream); - if (ret < 0) - dev_err(fe->dev, "ASoC: failed to shutdown some BEs\n"); - dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); - - return ret; -} - static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) { struct snd_soc_dapm_widget_list *list; int stream; int count, paths; + int ret; if (!fe->dai_link->dynamic) return 0; @@ -2603,10 +2578,14 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) /* update any playback/capture paths */ count = dpcm_process_paths(fe, stream, &list, new); if (count) { + dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE); if (new) - dpcm_run_new_update(fe, stream); + ret = dpcm_run_update_startup(fe, stream); else - dpcm_run_old_update(fe, stream); + ret = dpcm_run_update_shutdown(fe, stream); + if (ret < 0) + dev_err(fe->dev, "ASoC: failed to shutdown some BEs\n"); + dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); dpcm_clear_pending_state(fe, stream); dpcm_be_disconnect(fe, stream); From 52645e332d227a3d3cd345e97a10d99b7e80fae4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Feb 2020 15:56:52 +0900 Subject: [PATCH 0722/4444] ASoC: soc-pcm: move dpcm_path_put() to soc-pcm.c dpcm_path_put() (A) is calling kfree(*list). The freed list is created by dapm_widget_list_create() (B) which is called from snd_soc_dapm_dai_get_connected_widgets() (C) which is called from dpcm_path_get() (D). (B) dapm_widget_list_create(**list, ...) { ... => *list = kzalloc(); ... } (C) snd_soc_dapm_dai_get_connected_widgets(..., **list, ...) { ... dapm_widget_list_create(list, ...); ... } (D) dpcm_path_get(..., **list) { ... snd_soc_dapm_dai_get_connected_widgets(..., list, ...); ... } (A) dpcm_path_put(**list) { => kfree(*list); } This kind of unbalance code is very difficult to read/understand. To avoid this issue, this patch adds each missing paired function dapm_widget_list_free() for dapm_widget_list_create() (B), and snd_soc_dapm_dai_free_widgets() for snd_soc_dapm_dai_get_connected_widgets() (C). This patch uses these, and moves dpcm_path_put() next to dpcm_path_get(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87a75fjc9q.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 1 + include/sound/soc-dpcm.h | 7 +------ sound/soc/soc-dapm.c | 10 ++++++++++ sound/soc/soc-pcm.c | 5 +++++ 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 9439e75945f6..464b20acd720 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -484,6 +484,7 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, struct snd_soc_dapm_widget_list **list, bool (*custom_stop_condition)(struct snd_soc_dapm_widget *, enum snd_soc_dapm_direction)); +void snd_soc_dapm_dai_free_widgets(struct snd_soc_dapm_widget_list **list); struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm( struct snd_kcontrol *kcontrol); diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index 3e7819d2a6aa..40223577ec4a 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -145,6 +145,7 @@ static inline void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd) int dpcm_path_get(struct snd_soc_pcm_runtime *fe, int stream, struct snd_soc_dapm_widget_list **list_); +void dpcm_path_put(struct snd_soc_dapm_widget_list **list); int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, int stream, struct snd_soc_dapm_widget_list **list, int new); int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream); @@ -158,10 +159,4 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream); int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, int event); -static inline void dpcm_path_put(struct snd_soc_dapm_widget_list **list) -{ - kfree(*list); -} - - #endif diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f2e678865480..8a7d700a0fda 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1105,6 +1105,11 @@ static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget) } } +static void dapm_widget_list_free(struct snd_soc_dapm_widget_list **list) +{ + kfree(*list); +} + static int dapm_widget_list_create(struct snd_soc_dapm_widget_list **list, struct list_head *widgets) { @@ -1310,6 +1315,11 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, return paths; } +void snd_soc_dapm_dai_free_widgets(struct snd_soc_dapm_widget_list **list) +{ + dapm_widget_list_free(list); +} + /* * Handler for regulator supply widget. */ diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 1bf2db1732bf..3b3b32923783 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1302,6 +1302,11 @@ int dpcm_path_get(struct snd_soc_pcm_runtime *fe, return paths; } +void dpcm_path_put(struct snd_soc_dapm_widget_list **list) +{ + snd_soc_dapm_dai_free_widgets(list); +} + static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, struct snd_soc_dapm_widget_list **list_) { From c3212829f812a4ac0c6078978c109c6f1ff882c2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Feb 2020 15:56:57 +0900 Subject: [PATCH 0723/4444] ASoC: soc-pcm: move CONFIG_DEBUG_FS functions to top side This is prepare for CONFIG_DEBUG_FS cleanup Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/878skzjc9k.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 276 ++++++++++++++++++++++---------------------- 1 file changed, 138 insertions(+), 138 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 3b3b32923783..fc98ab87fa45 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -28,6 +28,144 @@ #define DPCM_MAX_BE_USERS 8 +#ifdef CONFIG_DEBUG_FS +static const char *dpcm_state_string(enum snd_soc_dpcm_state state) +{ + switch (state) { + case SND_SOC_DPCM_STATE_NEW: + return "new"; + case SND_SOC_DPCM_STATE_OPEN: + return "open"; + case SND_SOC_DPCM_STATE_HW_PARAMS: + return "hw_params"; + case SND_SOC_DPCM_STATE_PREPARE: + return "prepare"; + case SND_SOC_DPCM_STATE_START: + return "start"; + case SND_SOC_DPCM_STATE_STOP: + return "stop"; + case SND_SOC_DPCM_STATE_SUSPEND: + return "suspend"; + case SND_SOC_DPCM_STATE_PAUSED: + return "paused"; + case SND_SOC_DPCM_STATE_HW_FREE: + return "hw_free"; + case SND_SOC_DPCM_STATE_CLOSE: + return "close"; + } + + return "unknown"; +} + +static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe, + int stream, char *buf, size_t size) +{ + struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params; + struct snd_soc_dpcm *dpcm; + ssize_t offset = 0; + unsigned long flags; + + /* FE state */ + offset += snprintf(buf + offset, size - offset, + "[%s - %s]\n", fe->dai_link->name, + stream ? "Capture" : "Playback"); + + offset += snprintf(buf + offset, size - offset, "State: %s\n", + dpcm_state_string(fe->dpcm[stream].state)); + + if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) && + (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP)) + offset += snprintf(buf + offset, size - offset, + "Hardware Params: " + "Format = %s, Channels = %d, Rate = %d\n", + snd_pcm_format_name(params_format(params)), + params_channels(params), + params_rate(params)); + + /* BEs state */ + offset += snprintf(buf + offset, size - offset, "Backends:\n"); + + if (list_empty(&fe->dpcm[stream].be_clients)) { + offset += snprintf(buf + offset, size - offset, + " No active DSP links\n"); + goto out; + } + + spin_lock_irqsave(&fe->card->dpcm_lock, flags); + for_each_dpcm_be(fe, stream, dpcm) { + struct snd_soc_pcm_runtime *be = dpcm->be; + params = &dpcm->hw_params; + + offset += snprintf(buf + offset, size - offset, + "- %s\n", be->dai_link->name); + + offset += snprintf(buf + offset, size - offset, + " State: %s\n", + dpcm_state_string(be->dpcm[stream].state)); + + if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) && + (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP)) + offset += snprintf(buf + offset, size - offset, + " Hardware Params: " + "Format = %s, Channels = %d, Rate = %d\n", + snd_pcm_format_name(params_format(params)), + params_channels(params), + params_rate(params)); + } + spin_unlock_irqrestore(&fe->card->dpcm_lock, flags); +out: + return offset; +} + +static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct snd_soc_pcm_runtime *fe = file->private_data; + ssize_t out_count = PAGE_SIZE, offset = 0, ret = 0; + int stream; + char *buf; + + buf = kmalloc(out_count, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + for_each_pcm_streams(stream) + if (snd_soc_dai_stream_valid(fe->cpu_dai, stream)) + offset += dpcm_show_state(fe, stream, + buf + offset, + out_count - offset); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, offset); + + kfree(buf); + return ret; +} + +static const struct file_operations dpcm_state_fops = { + .open = simple_open, + .read = dpcm_state_read_file, + .llseek = default_llseek, +}; + +void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd) +{ + if (!rtd->dai_link) + return; + + if (!rtd->dai_link->dynamic) + return; + + if (!rtd->card->debugfs_card_root) + return; + + rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name, + rtd->card->debugfs_card_root); + + debugfs_create_file("state", 0444, rtd->debugfs_dpcm_root, + rtd, &dpcm_state_fops); +} +#endif + static int soc_rtd_startup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_substream *substream) { @@ -2930,141 +3068,3 @@ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe, return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state)); } EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params); - -#ifdef CONFIG_DEBUG_FS -static const char *dpcm_state_string(enum snd_soc_dpcm_state state) -{ - switch (state) { - case SND_SOC_DPCM_STATE_NEW: - return "new"; - case SND_SOC_DPCM_STATE_OPEN: - return "open"; - case SND_SOC_DPCM_STATE_HW_PARAMS: - return "hw_params"; - case SND_SOC_DPCM_STATE_PREPARE: - return "prepare"; - case SND_SOC_DPCM_STATE_START: - return "start"; - case SND_SOC_DPCM_STATE_STOP: - return "stop"; - case SND_SOC_DPCM_STATE_SUSPEND: - return "suspend"; - case SND_SOC_DPCM_STATE_PAUSED: - return "paused"; - case SND_SOC_DPCM_STATE_HW_FREE: - return "hw_free"; - case SND_SOC_DPCM_STATE_CLOSE: - return "close"; - } - - return "unknown"; -} - -static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe, - int stream, char *buf, size_t size) -{ - struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params; - struct snd_soc_dpcm *dpcm; - ssize_t offset = 0; - unsigned long flags; - - /* FE state */ - offset += snprintf(buf + offset, size - offset, - "[%s - %s]\n", fe->dai_link->name, - stream ? "Capture" : "Playback"); - - offset += snprintf(buf + offset, size - offset, "State: %s\n", - dpcm_state_string(fe->dpcm[stream].state)); - - if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) && - (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP)) - offset += snprintf(buf + offset, size - offset, - "Hardware Params: " - "Format = %s, Channels = %d, Rate = %d\n", - snd_pcm_format_name(params_format(params)), - params_channels(params), - params_rate(params)); - - /* BEs state */ - offset += snprintf(buf + offset, size - offset, "Backends:\n"); - - if (list_empty(&fe->dpcm[stream].be_clients)) { - offset += snprintf(buf + offset, size - offset, - " No active DSP links\n"); - goto out; - } - - spin_lock_irqsave(&fe->card->dpcm_lock, flags); - for_each_dpcm_be(fe, stream, dpcm) { - struct snd_soc_pcm_runtime *be = dpcm->be; - params = &dpcm->hw_params; - - offset += snprintf(buf + offset, size - offset, - "- %s\n", be->dai_link->name); - - offset += snprintf(buf + offset, size - offset, - " State: %s\n", - dpcm_state_string(be->dpcm[stream].state)); - - if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) && - (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP)) - offset += snprintf(buf + offset, size - offset, - " Hardware Params: " - "Format = %s, Channels = %d, Rate = %d\n", - snd_pcm_format_name(params_format(params)), - params_channels(params), - params_rate(params)); - } - spin_unlock_irqrestore(&fe->card->dpcm_lock, flags); -out: - return offset; -} - -static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct snd_soc_pcm_runtime *fe = file->private_data; - ssize_t out_count = PAGE_SIZE, offset = 0, ret = 0; - int stream; - char *buf; - - buf = kmalloc(out_count, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - for_each_pcm_streams(stream) - if (snd_soc_dai_stream_valid(fe->cpu_dai, stream)) - offset += dpcm_show_state(fe, stream, - buf + offset, - out_count - offset); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, offset); - - kfree(buf); - return ret; -} - -static const struct file_operations dpcm_state_fops = { - .open = simple_open, - .read = dpcm_state_read_file, - .llseek = default_llseek, -}; - -void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd) -{ - if (!rtd->dai_link) - return; - - if (!rtd->dai_link->dynamic) - return; - - if (!rtd->card->debugfs_card_root) - return; - - rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name, - rtd->card->debugfs_card_root); - - debugfs_create_file("state", 0444, rtd->debugfs_dpcm_root, - rtd, &dpcm_state_fops); -} -#endif From 154dae87e73faa6d56265f22cae16dcdcea3dbb0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Feb 2020 15:57:06 +0900 Subject: [PATCH 0724/4444] ASoC: soc-pcm: add dpcm_create/remove_debugfs_state() soc-pcm.c has implementation which depends on CONFIG_DEBUG_FS. But, we don't want to have random #ifdef. This patch adds dpcm_create/remove_debugfs_state() and care it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/877e0jjc9b.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 51 ++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index fc98ab87fa45..c5cfd88720c2 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -164,6 +164,36 @@ void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd) debugfs_create_file("state", 0444, rtd->debugfs_dpcm_root, rtd, &dpcm_state_fops); } + +static void dpcm_create_debugfs_state(struct snd_soc_dpcm *dpcm, int stream) +{ + char *name; + + name = kasprintf(GFP_KERNEL, "%s:%s", dpcm->be->dai_link->name, + stream ? "capture" : "playback"); + if (name) { + dpcm->debugfs_state = debugfs_create_dir( + name, dpcm->fe->debugfs_dpcm_root); + debugfs_create_u32("state", 0644, dpcm->debugfs_state, + &dpcm->state); + kfree(name); + } +} + +static void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm) +{ + debugfs_remove_recursive(dpcm->debugfs_state); +} + +#else +static inline void dpcm_create_debugfs_state(struct snd_soc_dpcm *dpcm, + int stream) +{ +} + +static inline void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm) +{ +} #endif static int soc_rtd_startup(struct snd_soc_pcm_runtime *rtd, @@ -1254,9 +1284,6 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe, { struct snd_soc_dpcm *dpcm; unsigned long flags; -#ifdef CONFIG_DEBUG_FS - char *name; -#endif /* only add new dpcms */ for_each_dpcm_be(fe, stream, dpcm) { @@ -1281,17 +1308,8 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe, stream ? "capture" : "playback", fe->dai_link->name, stream ? "<-" : "->", be->dai_link->name); -#ifdef CONFIG_DEBUG_FS - name = kasprintf(GFP_KERNEL, "%s:%s", be->dai_link->name, - stream ? "capture" : "playback"); - if (name) { - dpcm->debugfs_state = debugfs_create_dir(name, - fe->debugfs_dpcm_root); - debugfs_create_u32("state", 0644, dpcm->debugfs_state, - &dpcm->state); - kfree(name); - } -#endif + dpcm_create_debugfs_state(dpcm, stream); + return 1; } @@ -1344,9 +1362,8 @@ void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream) /* BEs still alive need new FE */ dpcm_be_reparent(fe, dpcm->be, stream); -#ifdef CONFIG_DEBUG_FS - debugfs_remove_recursive(dpcm->debugfs_state); -#endif + dpcm_remove_debugfs_state(dpcm); + spin_lock_irqsave(&fe->card->dpcm_lock, flags); list_del(&dpcm->list_be); list_del(&dpcm->list_fe); From d2aaa8d8bfba93237ac944ee058fb98e2c2ef983 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 20 Feb 2020 11:49:55 +0200 Subject: [PATCH 0725/4444] ASoC: soc-pcm: fix state tracking error in snd_soc_component_open/close() ASoC component open/close and snd_soc_component_module_get/put are called independently for each component-substream pair, so the logic added in commit dd03907bf129 ("ASoC: soc-pcm: call snd_soc_component_open/close() once") was not sufficient and led to PCM playback and module unload errors. Implement handling of failures directly in soc_pcm_components_open(), so that any successfully opened components are closed upon error with other components. This allows to clean up error handling in soc_pcm_open() without adding more state tracking. Fixes: dd03907bf129 ("ASoC: soc-pcm: call snd_soc_component_open/close() once") Signed-off-by: Kai Vehmanen Tested-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20200220094955.16968-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 7 ++----- sound/soc/soc-component.c | 35 +++++++---------------------------- sound/soc/soc-pcm.c | 27 +++++++++++++++++++++------ 3 files changed, 30 insertions(+), 39 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 1866ecc8e94b..154d02fbbfed 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -147,6 +147,8 @@ struct snd_soc_component { unsigned int active; + unsigned int suspended:1; /* is in suspend PM state */ + struct list_head list; struct list_head card_aux_list; /* for auxiliary bound components */ struct list_head card_list; @@ -180,11 +182,6 @@ struct snd_soc_component { struct dentry *debugfs_root; const char *debugfs_prefix; #endif - - /* bit field */ - unsigned int suspended:1; /* is in suspend PM state */ - unsigned int opened:1; - unsigned int module:1; }; #define for_each_component_dais(component, dai)\ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index ee00c09df5e7..14e175cdeeb8 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -297,55 +297,34 @@ EXPORT_SYMBOL_GPL(snd_soc_component_set_jack); int snd_soc_component_module_get(struct snd_soc_component *component, int upon_open) { - if (component->module) - return 0; - if (component->driver->module_get_upon_open == !!upon_open && !try_module_get(component->dev->driver->owner)) return -ENODEV; - component->module = 1; - return 0; } void snd_soc_component_module_put(struct snd_soc_component *component, int upon_open) { - if (component->module && - component->driver->module_get_upon_open == !!upon_open) + if (component->driver->module_get_upon_open == !!upon_open) module_put(component->dev->driver->owner); - - component->module = 0; } int snd_soc_component_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - int ret = 0; - - if (!component->opened && - component->driver->open) - ret = component->driver->open(component, substream); - - if (ret == 0) - component->opened = 1; - - return ret; + if (component->driver->open) + return component->driver->open(component, substream); + return 0; } int snd_soc_component_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - int ret = 0; - - if (component->opened && - component->driver->close) - ret = component->driver->close(component, substream); - - component->opened = 0; - - return ret; + if (component->driver->close) + return component->driver->close(component, substream); + return 0; } int snd_soc_component_prepare(struct snd_soc_component *component, diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index aff27c8599ef..235baeb2d56a 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -469,28 +469,43 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) static int soc_pcm_components_open(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_component *last = NULL; struct snd_soc_component *component; int i, ret = 0; for_each_rtd_components(rtd, i, component) { + last = component; + ret = snd_soc_component_module_get_when_open(component); if (ret < 0) { dev_err(component->dev, "ASoC: can't get module %s\n", component->name); - return ret; + break; } ret = snd_soc_component_open(component, substream); if (ret < 0) { + snd_soc_component_module_put_when_close(component); dev_err(component->dev, "ASoC: can't open component %s: %d\n", component->name, ret); - return ret; + break; } } - return 0; + if (ret < 0) { + /* rollback on error */ + for_each_rtd_components(rtd, i, component) { + if (component == last) + break; + + snd_soc_component_close(component, substream); + snd_soc_component_module_put_when_close(component); + } + } + + return ret; } static int soc_pcm_components_close(struct snd_pcm_substream *substream) @@ -585,7 +600,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) if (ret < 0) { pr_err("ASoC: %s startup failed: %d\n", rtd->dai_link->name, ret); - goto component_err; + goto rtd_startup_err; } /* startup the audio subsystem */ @@ -681,9 +696,9 @@ cpu_dai_err: snd_soc_dai_shutdown(cpu_dai, substream); soc_rtd_shutdown(rtd, substream); -component_err: +rtd_startup_err: soc_pcm_components_close(substream); - +component_err: mutex_unlock(&rtd->card->pcm_mutex); for_each_rtd_components(rtd, i, component) { From 5c538e09cb19b7d8f5fcdfc8d4e4440d0b9ed799 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Wed, 6 Nov 2019 16:22:45 -0800 Subject: [PATCH 0726/4444] arm64: dts: qcom: sdm845: Add first PCIe controller and PHY Add the GEN2 PCIe controller and PHY found on SDM845. Tested-by: Julien Massot Reviewed-by: Vinod Koul Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20191107002247.1127689-2-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 104 +++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index d42302b8889b..9ac2e85d8181 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -1364,6 +1364,110 @@ interrupts = ; }; + pcie0: pci@1c00000 { + compatible = "qcom,pcie-sdm845", "snps,dw-pcie"; + reg = <0 0x01c00000 0 0x2000>, + <0 0x60000000 0 0xf1d>, + <0 0x60000f20 0 0xa8>, + <0 0x60100000 0 0x100000>; + reg-names = "parf", "dbi", "elbi", "config"; + device_type = "pci"; + linux,pci-domain = <0>; + bus-range = <0x00 0xff>; + num-lanes = <1>; + + #address-cells = <3>; + #size-cells = <2>; + + ranges = <0x01000000 0x0 0x60200000 0 0x60200000 0x0 0x100000>, + <0x02000000 0x0 0x60300000 0 0x60300000 0x0 0xd00000>; + + interrupts = ; + interrupt-names = "msi"; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &intc 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ + <0 0 0 2 &intc 0 150 IRQ_TYPE_LEVEL_HIGH>, /* int_b */ + <0 0 0 3 &intc 0 151 IRQ_TYPE_LEVEL_HIGH>, /* int_c */ + <0 0 0 4 &intc 0 152 IRQ_TYPE_LEVEL_HIGH>; /* int_d */ + + clocks = <&gcc GCC_PCIE_0_PIPE_CLK>, + <&gcc GCC_PCIE_0_AUX_CLK>, + <&gcc GCC_PCIE_0_CFG_AHB_CLK>, + <&gcc GCC_PCIE_0_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_0_SLV_AXI_CLK>, + <&gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>, + <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>; + clock-names = "pipe", + "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a", + "tbu"; + + iommus = <&apps_smmu 0x1c10 0xf>; + iommu-map = <0x0 &apps_smmu 0x1c10 0x1>, + <0x100 &apps_smmu 0x1c11 0x1>, + <0x200 &apps_smmu 0x1c12 0x1>, + <0x300 &apps_smmu 0x1c13 0x1>, + <0x400 &apps_smmu 0x1c14 0x1>, + <0x500 &apps_smmu 0x1c15 0x1>, + <0x600 &apps_smmu 0x1c16 0x1>, + <0x700 &apps_smmu 0x1c17 0x1>, + <0x800 &apps_smmu 0x1c18 0x1>, + <0x900 &apps_smmu 0x1c19 0x1>, + <0xa00 &apps_smmu 0x1c1a 0x1>, + <0xb00 &apps_smmu 0x1c1b 0x1>, + <0xc00 &apps_smmu 0x1c1c 0x1>, + <0xd00 &apps_smmu 0x1c1d 0x1>, + <0xe00 &apps_smmu 0x1c1e 0x1>, + <0xf00 &apps_smmu 0x1c1f 0x1>; + + resets = <&gcc GCC_PCIE_0_BCR>; + reset-names = "pci"; + + power-domains = <&gcc PCIE_0_GDSC>; + + phys = <&pcie0_lane>; + phy-names = "pciephy"; + + status = "disabled"; + }; + + pcie0_phy: phy@1c06000 { + compatible = "qcom,sdm845-qmp-pcie-phy"; + reg = <0 0x01c06000 0 0x18c>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>, + <&gcc GCC_PCIE_0_CFG_AHB_CLK>, + <&gcc GCC_PCIE_0_CLKREF_CLK>, + <&gcc GCC_PCIE_PHY_REFGEN_CLK>; + clock-names = "aux", "cfg_ahb", "ref", "refgen"; + + resets = <&gcc GCC_PCIE_0_PHY_BCR>; + reset-names = "phy"; + + assigned-clocks = <&gcc GCC_PCIE_PHY_REFGEN_CLK>; + assigned-clock-rates = <100000000>; + + status = "disabled"; + + pcie0_lane: lanes@1c06200 { + reg = <0 0x01c06200 0 0x128>, + <0 0x01c06400 0 0x1fc>, + <0 0x01c06800 0 0x218>, + <0 0x01c06600 0 0x70>; + clocks = <&gcc GCC_PCIE_0_PIPE_CLK>; + clock-names = "pipe0"; + + #phy-cells = <0>; + clock-output-names = "pcie_0_pipe_clk"; + }; + }; + ufs_mem_hc: ufshc@1d84000 { compatible = "qcom,sdm845-ufshc", "qcom,ufshc", "jedec,ufs-2.0"; From 42ad231338c14204065cc446d914653ac0afbc26 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Wed, 6 Nov 2019 16:22:46 -0800 Subject: [PATCH 0727/4444] arm64: dts: qcom: sdm845: Add second PCIe PHY and controller Add the second PCIe controller and the associated QHP PHY found on SDM845. Tested-by: Julien Massot Reviewed-by: Vinod Koul Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20191107002247.1127689-3-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 108 +++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index 9ac2e85d8181..0f681cc60094 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -1468,6 +1468,114 @@ }; }; + pcie1: pci@1c08000 { + compatible = "qcom,pcie-sdm845", "snps,dw-pcie"; + reg = <0 0x01c08000 0 0x2000>, + <0 0x40000000 0 0xf1d>, + <0 0x40000f20 0 0xa8>, + <0 0x40100000 0 0x100000>; + reg-names = "parf", "dbi", "elbi", "config"; + device_type = "pci"; + linux,pci-domain = <1>; + bus-range = <0x00 0xff>; + num-lanes = <1>; + + #address-cells = <3>; + #size-cells = <2>; + + ranges = <0x01000000 0x0 0x40200000 0x0 0x40200000 0x0 0x100000>, + <0x02000000 0x0 0x40300000 0x0 0x40300000 0x0 0x1fd00000>; + + interrupts = ; + interrupt-names = "msi"; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &intc 0 434 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ + <0 0 0 2 &intc 0 435 IRQ_TYPE_LEVEL_HIGH>, /* int_b */ + <0 0 0 3 &intc 0 438 IRQ_TYPE_LEVEL_HIGH>, /* int_c */ + <0 0 0 4 &intc 0 439 IRQ_TYPE_LEVEL_HIGH>; /* int_d */ + + clocks = <&gcc GCC_PCIE_1_PIPE_CLK>, + <&gcc GCC_PCIE_1_AUX_CLK>, + <&gcc GCC_PCIE_1_CFG_AHB_CLK>, + <&gcc GCC_PCIE_1_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_1_SLV_AXI_CLK>, + <&gcc GCC_PCIE_1_SLV_Q2A_AXI_CLK>, + <&gcc GCC_PCIE_1_CLKREF_CLK>, + <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>; + clock-names = "pipe", + "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a", + "ref", + "tbu"; + + assigned-clocks = <&gcc GCC_PCIE_1_AUX_CLK>; + assigned-clock-rates = <19200000>; + + iommus = <&apps_smmu 0x1c00 0xf>; + iommu-map = <0x0 &apps_smmu 0x1c00 0x1>, + <0x100 &apps_smmu 0x1c01 0x1>, + <0x200 &apps_smmu 0x1c02 0x1>, + <0x300 &apps_smmu 0x1c03 0x1>, + <0x400 &apps_smmu 0x1c04 0x1>, + <0x500 &apps_smmu 0x1c05 0x1>, + <0x600 &apps_smmu 0x1c06 0x1>, + <0x700 &apps_smmu 0x1c07 0x1>, + <0x800 &apps_smmu 0x1c08 0x1>, + <0x900 &apps_smmu 0x1c09 0x1>, + <0xa00 &apps_smmu 0x1c0a 0x1>, + <0xb00 &apps_smmu 0x1c0b 0x1>, + <0xc00 &apps_smmu 0x1c0c 0x1>, + <0xd00 &apps_smmu 0x1c0d 0x1>, + <0xe00 &apps_smmu 0x1c0e 0x1>, + <0xf00 &apps_smmu 0x1c0f 0x1>; + + resets = <&gcc GCC_PCIE_1_BCR>; + reset-names = "pci"; + + power-domains = <&gcc PCIE_1_GDSC>; + + phys = <&pcie1_lane>; + phy-names = "pciephy"; + + status = "disabled"; + }; + + pcie1_phy: phy@1c0a000 { + compatible = "qcom,sdm845-qhp-pcie-phy"; + reg = <0 0x01c0a000 0 0x800>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>, + <&gcc GCC_PCIE_1_CFG_AHB_CLK>, + <&gcc GCC_PCIE_1_CLKREF_CLK>, + <&gcc GCC_PCIE_PHY_REFGEN_CLK>; + clock-names = "aux", "cfg_ahb", "ref", "refgen"; + + resets = <&gcc GCC_PCIE_1_PHY_BCR>; + reset-names = "phy"; + + assigned-clocks = <&gcc GCC_PCIE_PHY_REFGEN_CLK>; + assigned-clock-rates = <100000000>; + + status = "disabled"; + + pcie1_lane: lanes@1c06200 { + reg = <0 0x01c0a800 0 0x800>, + <0 0x01c0a800 0 0x800>, + <0 0x01c0b800 0 0x400>; + clocks = <&gcc GCC_PCIE_1_PIPE_CLK>; + clock-names = "pipe0"; + + #phy-cells = <0>; + clock-output-names = "pcie_1_pipe_clk"; + }; + }; + ufs_mem_hc: ufshc@1d84000 { compatible = "qcom,sdm845-ufshc", "qcom,ufshc", "jedec,ufs-2.0"; From 4a657c264b785a55d9232588f970bfd3f97cd6da Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Wed, 6 Nov 2019 16:22:47 -0800 Subject: [PATCH 0728/4444] arm64: dts: qcom: db845c: Enable PCIe controllers Enable the two PCIe controllers found on the Dragonboard845c. Tested-by: Julien Massot Reviewed-by: Vinod Koul Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20191107002247.1127689-4-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 91 ++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts index eb77aaa6a819..6e60e81f8db7 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts @@ -364,6 +364,39 @@ firmware-name = "qcom/sdm845/mba.mbn", "qcom/sdm845/modem.mbn"; }; +&pcie0 { + status = "okay"; + perst-gpio = <&tlmm 35 GPIO_ACTIVE_LOW>; + enable-gpio = <&tlmm 134 GPIO_ACTIVE_HIGH>; + + vddpe-3v3-supply = <&pcie0_3p3v_dual>; + + pinctrl-names = "default"; + pinctrl-0 = <&pcie0_default_state>; +}; + +&pcie0_phy { + status = "okay"; + + vdda-phy-supply = <&vreg_l1a_0p875>; + vdda-pll-supply = <&vreg_l26a_1p2>; +}; + +&pcie1 { + status = "okay"; + perst-gpio = <&tlmm 102 GPIO_ACTIVE_LOW>; + + pinctrl-names = "default"; + pinctrl-0 = <&pcie1_default_state>; +}; + +&pcie1_phy { + status = "okay"; + + vdda-phy-supply = <&vreg_l1a_0p875>; + vdda-pll-supply = <&vreg_l26a_1p2>; +}; + &pm8998_gpio { vol_up_pin_a: vol-up-active { pins = "gpio6"; @@ -406,6 +439,31 @@ }; &tlmm { + pcie0_default_state: pcie0-default { + clkreq { + pins = "gpio36"; + function = "pci_e0"; + bias-pull-up; + }; + + reset-n { + pins = "gpio35"; + function = "gpio"; + + drive-strength = <2>; + output-low; + bias-pull-down; + }; + + wake-n { + pins = "gpio37"; + function = "gpio"; + + drive-strength = <2>; + bias-pull-up; + }; + }; + pcie0_pwren_state: pcie0-pwren { pins = "gpio90"; function = "gpio"; @@ -414,6 +472,39 @@ bias-disable; }; + pcie1_default_state: pcie1-default { + perst-n { + pins = "gpio102"; + function = "gpio"; + + drive-strength = <16>; + bias-disable; + }; + + clkreq { + pins = "gpio103"; + function = "pci_e1"; + bias-pull-up; + }; + + wake-n { + pins = "gpio11"; + function = "gpio"; + + drive-strength = <2>; + bias-pull-up; + }; + + reset-n { + pins = "gpio75"; + function = "gpio"; + + drive-strength = <16>; + bias-pull-up; + output-high; + }; + }; + sdc2_default_state: sdc2-default { clk { pins = "sdc2_clk"; From 48a0585b53675be47b1f237efa3d47e5c52430c3 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Wed, 8 Jan 2020 12:26:23 +0900 Subject: [PATCH 0729/4444] arm64: dts: qcom: add Venus firmware node on Cheza Cheza boards require this node to probe, so add it. Reviewed-by: Stanimir Varbanov Signed-off-by: Alexandre Courbot Link: https://lore.kernel.org/r/20200108032623.113921-1-acourbot@chromium.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi | 6 ++++++ arch/arm64/boot/dts/qcom/sdm845.dtsi | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi index a8e9f639a2bb..8d16d016efec 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi @@ -1296,3 +1296,9 @@ ap_ts_i2c: &i2c14 { }; }; }; + +&venus { + video-firmware { + iommus = <&apps_smmu 0x10b2 0x0>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index 0f681cc60094..dbbf2b1b204e 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -2782,7 +2782,7 @@ }; }; - video-codec@aa00000 { + venus: video-codec@aa00000 { compatible = "qcom,sdm845-venus"; reg = <0 0x0aa00000 0 0xff000>; interrupts = ; From f855a9224f1c4cd9109ca1555b922a526928b5d7 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 14 Jan 2020 18:53:14 -0800 Subject: [PATCH 0730/4444] arm64: dts: qcom: pm6150: Add label to pwrkey node Some platforms don't want to use the pmic power key as the power key event. Add a label so platforms can easily reference and mark this node as status = "disabled". Reviewed-by: Douglas Anderson Cc: Kiran Gunda Cc: Rajendra Nayak Cc: Douglas Anderson Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20200115025314.3054-1-swboyd@chromium.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/pm6150.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/pm6150.dtsi b/arch/arm64/boot/dts/qcom/pm6150.dtsi index 23534639f455..57af0b4a384d 100644 --- a/arch/arm64/boot/dts/qcom/pm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/pm6150.dtsi @@ -20,7 +20,7 @@ mode-bootloader = <0x2>; mode-recovery = <0x1>; - pwrkey { + pm6150_pwrkey: pwrkey { compatible = "qcom,pm8941-pwrkey"; interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>; debounce = <15625>; From 8b99dc0922618062a1589ebd74df6108b4f9ac22 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Wed, 8 Jan 2020 13:54:55 +0100 Subject: [PATCH 0731/4444] ARM: dts: qcom: add gpio-ranges property This patch adds the gpio-ranges property to almost all of the Qualcomm ARM platforms that utilize the pinctrl-msm framework. The gpio-ranges property is part of the gpiolib subsystem. As a result, the binding text is available in section "2.1 gpio- and pin-controller interaction" of Documentation/devicetree/bindings/gpio/gpio.txt For more information please see the patch titled: "pinctrl: msm: fix gpio-hog related boot issues" from this series. Reported-by: Sven Eckelmann Tested-by: Sven Eckelmann [ipq4019] Reviewed-by: Bjorn Andersson Reviewed-by: Linus Walleij Signed-off-by: Christian Lamparter Tested-by: Robert Marko [ipq4019] Cc: Luka Perkov Signed-off-by: Robert Marko Link: https://lore.kernel.org/r/20200108125455.308969-1-robert.marko@sartura.hr Signed-off-by: Bjorn Andersson --- arch/arm/boot/dts/qcom-apq8064.dtsi | 1 + arch/arm/boot/dts/qcom-apq8084.dtsi | 1 + arch/arm/boot/dts/qcom-ipq4019.dtsi | 1 + arch/arm/boot/dts/qcom-ipq8064.dtsi | 1 + arch/arm/boot/dts/qcom-mdm9615.dtsi | 1 + arch/arm/boot/dts/qcom-msm8660.dtsi | 1 + arch/arm/boot/dts/qcom-msm8960.dtsi | 1 + arch/arm/boot/dts/qcom-msm8974.dtsi | 1 + 8 files changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi index 8b79b4112ee1..2687c4e890ba 100644 --- a/arch/arm/boot/dts/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi @@ -350,6 +350,7 @@ reg = <0x800000 0x4000>; gpio-controller; + gpio-ranges = <&tlmm_pinmux 0 0 90>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; diff --git a/arch/arm/boot/dts/qcom-apq8084.dtsi b/arch/arm/boot/dts/qcom-apq8084.dtsi index fa1852eed37b..bf6a03506b45 100644 --- a/arch/arm/boot/dts/qcom-apq8084.dtsi +++ b/arch/arm/boot/dts/qcom-apq8084.dtsi @@ -403,6 +403,7 @@ compatible = "qcom,apq8084-pinctrl"; reg = <0xfd510000 0x4000>; gpio-controller; + gpio-ranges = <&tlmm 0 0 147>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; diff --git a/arch/arm/boot/dts/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom-ipq4019.dtsi index 71bb25a8afc0..bfa9ce4c6e69 100644 --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi @@ -201,6 +201,7 @@ compatible = "qcom,ipq4019-pinctrl"; reg = <0x01000000 0x300000>; gpio-controller; + gpio-ranges = <&tlmm 0 0 100>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; diff --git a/arch/arm/boot/dts/qcom-ipq8064.dtsi b/arch/arm/boot/dts/qcom-ipq8064.dtsi index 16c0da97932c..4021f661cd11 100644 --- a/arch/arm/boot/dts/qcom-ipq8064.dtsi +++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi @@ -119,6 +119,7 @@ reg = <0x800000 0x4000>; gpio-controller; + gpio-ranges = <&qcom_pinmux 0 0 69>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; diff --git a/arch/arm/boot/dts/qcom-mdm9615.dtsi b/arch/arm/boot/dts/qcom-mdm9615.dtsi index 356e9535f7a6..347b4f7d7889 100644 --- a/arch/arm/boot/dts/qcom-mdm9615.dtsi +++ b/arch/arm/boot/dts/qcom-mdm9615.dtsi @@ -128,6 +128,7 @@ msmgpio: pinctrl@800000 { compatible = "qcom,mdm9615-pinctrl"; gpio-controller; + gpio-ranges = <&msmgpio 0 0 88>; #gpio-cells = <2>; interrupts = ; interrupt-controller; diff --git a/arch/arm/boot/dts/qcom-msm8660.dtsi b/arch/arm/boot/dts/qcom-msm8660.dtsi index ec5cbc468bd3..480fc08cbe8e 100644 --- a/arch/arm/boot/dts/qcom-msm8660.dtsi +++ b/arch/arm/boot/dts/qcom-msm8660.dtsi @@ -115,6 +115,7 @@ reg = <0x800000 0x4000>; gpio-controller; + gpio-ranges = <&tlmm 0 0 173>; #gpio-cells = <2>; interrupts = <0 16 0x4>; interrupt-controller; diff --git a/arch/arm/boot/dts/qcom-msm8960.dtsi b/arch/arm/boot/dts/qcom-msm8960.dtsi index f2aeaccdc1ad..172ea3c70eac 100644 --- a/arch/arm/boot/dts/qcom-msm8960.dtsi +++ b/arch/arm/boot/dts/qcom-msm8960.dtsi @@ -107,6 +107,7 @@ msmgpio: pinctrl@800000 { compatible = "qcom,msm8960-pinctrl"; gpio-controller; + gpio-ranges = <&msmgpio 0 0 152>; #gpio-cells = <2>; interrupts = <0 16 0x4>; interrupt-controller; diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi index f8e093179c3f..2ea2308d91b3 100644 --- a/arch/arm/boot/dts/qcom-msm8974.dtsi +++ b/arch/arm/boot/dts/qcom-msm8974.dtsi @@ -934,6 +934,7 @@ compatible = "qcom,msm8974-pinctrl"; reg = <0xfd510000 0x4000>; gpio-controller; + gpio-ranges = <&msmgpio 0 0 146>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; From 297177a45b95097ae4f25a6f6d191d592e1bb018 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Wed, 8 Jan 2020 13:54:57 +0100 Subject: [PATCH 0732/4444] ARM64: dts: qcom: add gpio-ranges property This patch adds the gpio-ranges property to almost all of the Qualcomm ARM platforms that utilize the pinctrl-msm framework. The gpio-ranges property is part of the gpiolib subsystem. As a result, the binding text is available in section "2.1 gpio- and pin-controller interaction" of Documentation/devicetree/bindings/gpio/gpio.txt For more information please see the patch titled: "pinctrl: msm: fix gpio-hog related boot issues" from this series. Reported-by: Sven Eckelmann Tested-by: Sven Eckelmann [ipq4019] Reviewed-by: Bjorn Andersson Reviewed-by: Linus Walleij Signed-off-by: Christian Lamparter Tested-by: Robert Marko [ipq4019] Cc: Luka Perkov Signed-off-by: Robert Marko Link: https://lore.kernel.org/r/20200108125455.308969-2-robert.marko@sartura.hr Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/ipq8074.dtsi | 1 + arch/arm64/boot/dts/qcom/msm8916.dtsi | 1 + arch/arm64/boot/dts/qcom/msm8992.dtsi | 1 + arch/arm64/boot/dts/qcom/msm8994.dtsi | 1 + arch/arm64/boot/dts/qcom/msm8996.dtsi | 1 + 5 files changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/ipq8074.dtsi b/arch/arm64/boot/dts/qcom/ipq8074.dtsi index 67ee5f560104..2b31823d3ccd 100644 --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi @@ -21,6 +21,7 @@ reg = <0x1000000 0x300000>; interrupts = ; gpio-controller; + gpio-ranges = <&tlmm 0 0 70>; #gpio-cells = <0x2>; interrupt-controller; #interrupt-cells = <0x2>; diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index cabfa3547d28..7c2ada02e276 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -423,6 +423,7 @@ reg = <0x1000000 0x300000>; interrupts = ; gpio-controller; + gpio-ranges = <&msmgpio 0 0 122>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; diff --git a/arch/arm64/boot/dts/qcom/msm8992.dtsi b/arch/arm64/boot/dts/qcom/msm8992.dtsi index 8be60c08a9ab..2021795c99ad 100644 --- a/arch/arm64/boot/dts/qcom/msm8992.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8992.dtsi @@ -171,6 +171,7 @@ reg = <0xfd510000 0x4000>; interrupts = ; gpio-controller; + gpio-ranges = <&msmgpio 0 0 146>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; diff --git a/arch/arm64/boot/dts/qcom/msm8994.dtsi b/arch/arm64/boot/dts/qcom/msm8994.dtsi index 3932757f78b7..b1c2d7d6a0f2 100644 --- a/arch/arm64/boot/dts/qcom/msm8994.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8994.dtsi @@ -133,6 +133,7 @@ reg = <0xfd510000 0x4000>; interrupts = ; gpio-controller; + gpio-ranges = <&msmgpio 0 0 146>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index 7ae082ea14ea..eaae356a493c 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -695,6 +695,7 @@ reg = <0x01010000 0x300000>; interrupts = ; gpio-controller; + gpio-ranges = <&msmgpio 0 0 150>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; From f8c848134185ffcf8409a8b6398c16584c752a1a Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Mon, 27 Jan 2020 08:23:48 -0800 Subject: [PATCH 0733/4444] arm64: dts: qcom: qcs404: Fix sdhci compat string As per the bindings, the SDHCI controller should have a SoC-specific compatible string in addition to the generic version-based one. Add it. Reviewed-by: Vinod Koul Fixes: 7241ab944da3 ("arm64: dts: qcom: qcs404: Add sdcc1 node") Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20200127082331.1.I402470e4a162d69fde47ee2ea708b15bde9751f9@changeid Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/qcs404.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs404.dtsi b/arch/arm64/boot/dts/qcom/qcs404.dtsi index 4ee1e3d5f123..1eea06435779 100644 --- a/arch/arm64/boot/dts/qcom/qcs404.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs404.dtsi @@ -685,7 +685,7 @@ }; sdcc1: sdcc@7804000 { - compatible = "qcom,sdhci-msm-v5"; + compatible = "qcom,qcs404-sdhci", "qcom,sdhci-msm-v5"; reg = <0x07804000 0x1000>, <0x7805000 0x1000>; reg-names = "hc_mem", "cmdq_mem"; From 0997882f96c784927bcd368dd7e800d3623fc27d Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Mon, 3 Feb 2020 10:31:36 -0800 Subject: [PATCH 0734/4444] arm64: dts: qcom: sdm845: Add the missing clocks on the dispcc We're transitioning over to requiring the Qualcomm Display Clock Controller to specify all the input clocks. Let's add them for sdm845. NOTES: - Until the Linux driver for sdm845's dispcc is updated, these clocks will not actually be used in Linux. It will continue to use global clock names to match things up. - Although the clocks from the DP PHY are required, the DP PHY isn't represented in the dts yet. Apparently the magic for this is just to use <0>. Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20200203103049.v4.3.Ie80fa74e1774f4317d80d70d30ef4b78f16cc8df@changeid Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index dbbf2b1b204e..7a7835bdf630 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -3145,6 +3145,24 @@ dispcc: clock-controller@af00000 { compatible = "qcom,sdm845-dispcc"; reg = <0 0x0af00000 0 0x10000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_DISP_GPLL0_CLK_SRC>, + <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>, + <&dsi0_phy 0>, + <&dsi0_phy 1>, + <&dsi1_phy 0>, + <&dsi1_phy 1>, + <0>, + <0>; + clock-names = "bi_tcxo", + "gcc_disp_gpll0_clk_src", + "gcc_disp_gpll0_div_clk_src", + "dsi0_phy_pll_out_byteclk", + "dsi0_phy_pll_out_dsiclk", + "dsi1_phy_pll_out_byteclk", + "dsi1_phy_pll_out_dsiclk", + "dp_link_clk_divsel_ten", + "dp_vco_divided_clk_src_mux"; #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; From bb2bd9bffb9271c90e3a3e7a791cda0b6332b285 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Mon, 3 Feb 2020 10:31:41 -0800 Subject: [PATCH 0735/4444] arm64: dts: qcom: sdm845: Add missing clocks / fix names on the gpucc We're transitioning over to requiring the Qualcomm GPU Clock Controller to specify all the input clocks. Let's add them for sdm845. As part of this we've decided that the xo clock should be referred to in the bindings as "bi_tcxo". Change the dts. NOTE: Until the Linux driver for sdm845's gpucc is updated, these clocks will not actually be used in Linux. It will continue to use global clock names to match things up. Of course, Linux didn't use the old "xo" clock anyway. Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20200203103049.v4.8.If8596faf02408cef4bb9f52296b911eb9ba49287@changeid Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index 7a7835bdf630..f6b6927010e5 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -2115,8 +2115,12 @@ #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; - clocks = <&rpmhcc RPMH_CXO_CLK>; - clock-names = "xo"; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_GPU_GPLL0_CLK_SRC>, + <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>; + clock-names = "bi_tcxo", + "gcc_gpu_gpll0_clk_src", + "gcc_gpu_gpll0_div_clk_src"; }; stm@6002000 { From af85ef13a5ce5ef5c16160dbefb5c8b360f827c6 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Mon, 3 Feb 2020 10:31:47 -0800 Subject: [PATCH 0736/4444] arm64: dts: qcom: sdm845: Add the missing clock on the videocc We're transitioning over to requiring the Qualcomm Video Clock Controller to specify all the input clocks. Let's add the one input clock for the videocc for sdm845. NOTE: Until the Linux driver for sdm845's video is updated, this clock will not actually be used in Linux. It will continue to use global clock names to match things up. Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20200203103049.v4.14.Id0599319487f075808baba7cba02c4c3c486dc80@changeid Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index f6b6927010e5..061f49faab19 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -2819,6 +2819,8 @@ videocc: clock-controller@ab00000 { compatible = "qcom,sdm845-videocc"; reg = <0 0x0ab00000 0 0x10000>; + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "bi_tcxo"; #clock-cells = <1>; #power-domain-cells = <1>; #reset-cells = <1>; From e07f83544e791de68a561ba4a56eedfb71ad8b83 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 3 Feb 2020 10:31:48 -0800 Subject: [PATCH 0737/4444] arm64: dts: sc7180: Add clock controller nodes Add the display, video & graphics clock controller nodes supported on SC7180. NOTE: the dispcc needs input clocks from various PHYs that aren't in the device tree yet. For now we'll leave these stubbed out with <0>, which is apparently the magic way to do this. These clocks aren't really "optional" and this stubbing out method is apparently the best way to handle it. Signed-off-by: Taniya Das Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20200203103049.v4.15.I1a4b93fb005791e29a9dcf288fc8bd459a555a59@changeid Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sc7180.dtsi | 47 ++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index b6a998adb3d0..2f1b3a1d92ea 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -5,8 +5,11 @@ * Copyright (c) 2019, The Linux Foundation. All rights reserved. */ +#include #include +#include #include +#include #include #include #include @@ -1190,6 +1193,20 @@ status = "disabled"; }; + gpucc: clock-controller@5090000 { + compatible = "qcom,sc7180-gpucc"; + reg = <0 0x05090000 0 0x9000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_GPU_GPLL0_CLK_SRC>, + <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>; + clock-names = "bi_tcxo", + "gcc_gpu_gpll0_clk_src", + "gcc_gpu_gpll0_div_clk_src"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + qspi: spi@88dc000 { compatible = "qcom,qspi-v1"; reg = <0 0x088dc000 0 0x600>; @@ -1302,6 +1319,36 @@ }; }; + videocc: clock-controller@ab00000 { + compatible = "qcom,sc7180-videocc"; + reg = <0 0x0ab00000 0 0x10000>; + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "bi_tcxo"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + dispcc: clock-controller@af00000 { + compatible = "qcom,sc7180-dispcc"; + reg = <0 0x0af00000 0 0x200000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_DISP_GPLL0_CLK_SRC>, + <0>, + <0>, + <0>, + <0>; + clock-names = "bi_tcxo", + "gcc_disp_gpll0_clk_src", + "dsi0_phy_pll_out_byteclk", + "dsi0_phy_pll_out_dsiclk", + "dp_phy_pll_link_clk", + "dp_phy_pll_vco_div_clk"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + pdc: interrupt-controller@b220000 { compatible = "qcom,sc7180-pdc", "qcom,pdc"; reg = <0 0x0b220000 0 0x30000>; From 2f0c17faebde61e7aef0c28914b8c00f98bf0e5f Mon Sep 17 00:00:00 2001 From: Sricharan R Date: Sun, 19 Jan 2020 18:43:19 +0530 Subject: [PATCH 0738/4444] dt-bindings: qcom: Add ipq6018 bindings Document the new ipq6018 SOC/board device tree bindings. Co-developed-by: Selvam Sathappan Periakaruppan Signed-off-by: Selvam Sathappan Periakaruppan Co-developed-by: Sivaprakash Murugesan Signed-off-by: Sivaprakash Murugesan Reviewed-by: Rob Herring Signed-off-by: Sricharan R Link: https://lore.kernel.org/r/1579439601-14810-4-git-send-email-sricharan@codeaurora.org Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/arm/qcom.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml index 5976c0b16b65..64ddae3bd39f 100644 --- a/Documentation/devicetree/bindings/arm/qcom.yaml +++ b/Documentation/devicetree/bindings/arm/qcom.yaml @@ -28,6 +28,7 @@ description: | apq8074 apq8084 apq8096 + ipq6018 ipq8074 mdm9615 msm8916 @@ -41,6 +42,7 @@ description: | The 'board' element must be one of the following strings: cdp + cp01-c1 dragonboard hk01 idp @@ -150,4 +152,10 @@ properties: - enum: - qcom,sc7180-idp - const: qcom,sc7180 + + - items: + - enum: + - qcom,ipq6018-cp01-c1 + - const: qcom,ipq6018 + ... From 1e8277854b49b165daaee1a1f278967239f8c48e Mon Sep 17 00:00:00 2001 From: Sricharan R Date: Sun, 19 Jan 2020 18:43:20 +0530 Subject: [PATCH 0739/4444] arm64: dts: Add ipq6018 SoC and CP01 board support Add initial device tree support for the Qualcomm IPQ6018 SoC and CP01 evaluation board. Co-developed-by: Abhishek Sahu Signed-off-by: Abhishek Sahu Co-developed-by: Sivaprakash Murugesan Signed-off-by: Sivaprakash Murugesan Signed-off-by: Sricharan R Link: https://lore.kernel.org/r/1579439601-14810-5-git-send-email-sricharan@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/Makefile | 1 + arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts | 30 +++ arch/arm64/boot/dts/qcom/ipq6018.dtsi | 217 +++++++++++++++++++ 3 files changed, 248 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts create mode 100644 arch/arm64/boot/dts/qcom/ipq6018.dtsi diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 973c0f079659..204775f3af50 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -2,6 +2,7 @@ dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8096-db820c.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8096-ifc6640.dtb +dtb-$(CONFIG_ARCH_QCOM) += ipq6018-cp01-c1.dtb dtb-$(CONFIG_ARCH_QCOM) += ipq8074-hk01.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-longcheer-l8150.dtb diff --git a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts new file mode 100644 index 000000000000..897b4b293a22 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * IPQ6018 CP01 board device tree source + * + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +/dts-v1/; + +#include "ipq6018.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. IPQ6018/AP-CP01-C1"; + compatible = "qcom,ipq6018-cp01", "qcom,ipq6018"; + + aliases { + serial0 = &blsp1_uart3; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " swiotlb=1"; + }; +}; + +&blsp1_uart3 { + pinctrl-0 = <&serial_3_pins>; + pinctrl-names = "default"; + status = "ok"; +}; diff --git a/arch/arm64/boot/dts/qcom/ipq6018.dtsi b/arch/arm64/boot/dts/qcom/ipq6018.dtsi new file mode 100644 index 000000000000..0fb44e56dd32 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * IPQ6018 SoC device tree source + * + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include +#include + +/ { + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&intc>; + + clocks { + sleep_clk: sleep-clk { + compatible = "fixed-clock"; + clock-frequency = <32000>; + #clock-cells = <0>; + }; + + xo: xo { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + #clock-cells = <0>; + }; + }; + + cpus: cpus { + #address-cells = <1>; + #size-cells = <0>; + + CPU0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0>; + enable-method = "psci"; + next-level-cache = <&L2_0>; + }; + + CPU1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + enable-method = "psci"; + reg = <0x1>; + next-level-cache = <&L2_0>; + }; + + CPU2: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + enable-method = "psci"; + reg = <0x2>; + next-level-cache = <&L2_0>; + }; + + CPU3: cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + enable-method = "psci"; + reg = <0x3>; + next-level-cache = <&L2_0>; + }; + + L2_0: l2-cache { + compatible = "cache"; + cache-level = <0x2>; + }; + }; + + pmuv8: pmu { + compatible = "arm,cortex-a53-pmu"; + interrupts = ; + }; + + psci: psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + tz: tz@48500000 { + reg = <0x0 0x48500000 0x0 0x00200000>; + no-map; + }; + }; + + soc: soc { + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0xffffffff>; + dma-ranges; + compatible = "simple-bus"; + + tlmm: pinctrl@1000000 { + compatible = "qcom,ipq6018-pinctrl"; + reg = <0x01000000 0x300000>; + interrupts = ; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&tlmm 0 80>; + interrupt-controller; + #interrupt-cells = <2>; + + serial_3_pins: serial3-pinmux { + pins = "gpio44", "gpio45"; + function = "blsp2_uart"; + drive-strength = <8>; + bias-pull-down; + }; + }; + + gcc: gcc@1800000 { + compatible = "qcom,gcc-ipq6018"; + reg = <0x01800000 0x80000>; + clocks = <&xo>, <&sleep_clk>; + clock-names = "xo", "sleep_clk"; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + blsp1_uart3: serial@78b1000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x078b1000 0x200>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_UART3_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + status = "disabled"; + }; + + intc: interrupt-controller@b000000 { + compatible = "qcom,msm-qgic2"; + interrupt-controller; + #interrupt-cells = <0x3>; + reg = <0x0b000000 0x1000>, /*GICD*/ + <0x0b002000 0x1000>, /*GICC*/ + <0x0b001000 0x1000>, /*GICH*/ + <0x0b004000 0x1000>; /*GICV*/ + interrupts = ; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + timer@b120000 { + #address-cells = <1>; + #size-cells = <1>; + ranges; + compatible = "arm,armv7-timer-mem"; + reg = <0x0b120000 0x1000>; + clock-frequency = <19200000>; + + frame@b120000 { + frame-number = <0>; + interrupts = , + ; + reg = <0x0b121000 0x1000>, + <0x0b122000 0x1000>; + }; + + frame@b123000 { + frame-number = <1>; + interrupts = ; + reg = <0xb123000 0x1000>; + status = "disabled"; + }; + + frame@b124000 { + frame-number = <2>; + interrupts = ; + reg = <0x0b124000 0x1000>; + status = "disabled"; + }; + + frame@b125000 { + frame-number = <3>; + interrupts = ; + reg = <0x0b125000 0x1000>; + status = "disabled"; + }; + + frame@b126000 { + frame-number = <4>; + interrupts = ; + reg = <0x0b126000 0x1000>; + status = "disabled"; + }; + + frame@b127000 { + frame-number = <5>; + interrupts = ; + reg = <0x0b127000 0x1000>; + status = "disabled"; + }; + + frame@b128000 { + frame-number = <6>; + interrupts = ; + reg = <0x0b128000 0x1000>; + status = "disabled"; + }; + }; + + }; +}; From 05f8740a0e6fcd97fe462c7012dff2eed821b529 Mon Sep 17 00:00:00 2001 From: Pierre-Yves MORDRET Date: Wed, 29 Jan 2020 16:36:21 +0100 Subject: [PATCH 0740/4444] dmaengine: stm32-dma: add suspend/resume power management support Add suspend/resume power management relying on PM Runtime engine. Signed-off-by: Pierre-Yves MORDRET Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200129153628.29329-2-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-dma.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index 5989b0893521..136deabd1aa3 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -1427,7 +1427,39 @@ static int stm32_dma_runtime_resume(struct device *dev) } #endif +#ifdef CONFIG_PM_SLEEP +static int stm32_dma_suspend(struct device *dev) +{ + struct stm32_dma_device *dmadev = dev_get_drvdata(dev); + int id, ret, scr; + + ret = pm_runtime_get_sync(dev); + if (ret < 0) + return ret; + + for (id = 0; id < STM32_DMA_MAX_CHANNELS; id++) { + scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id)); + if (scr & STM32_DMA_SCR_EN) { + dev_warn(dev, "Suspend is prevented by Chan %i\n", id); + return -EBUSY; + } + } + + pm_runtime_put_sync(dev); + + pm_runtime_force_suspend(dev); + + return 0; +} + +static int stm32_dma_resume(struct device *dev) +{ + return pm_runtime_force_resume(dev); +} +#endif + static const struct dev_pm_ops stm32_dma_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(stm32_dma_suspend, stm32_dma_resume) SET_RUNTIME_PM_OPS(stm32_dma_runtime_suspend, stm32_dma_runtime_resume, NULL) }; From 8cf1e0fc50fcc25021567bb2755580504c57c83a Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Wed, 29 Jan 2020 16:36:22 +0100 Subject: [PATCH 0741/4444] dmaengine: stm32-dma: use reset controller only at probe time Remove reset controller reference from device instance since it is used only at probe time. Signed-off-by: Etienne Carriere Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200129153628.29329-3-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-dma.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index 136deabd1aa3..e31414796ec4 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -207,7 +207,6 @@ struct stm32_dma_device { struct dma_device ddev; void __iomem *base; struct clk *clk; - struct reset_control *rst; bool mem2mem; struct stm32_dma_chan chan[STM32_DMA_MAX_CHANNELS]; }; @@ -1275,6 +1274,7 @@ static int stm32_dma_probe(struct platform_device *pdev) struct dma_device *dd; const struct of_device_id *match; struct resource *res; + struct reset_control *rst; int i, ret; match = of_match_device(stm32_dma_of_match, &pdev->dev); @@ -1309,11 +1309,11 @@ static int stm32_dma_probe(struct platform_device *pdev) dmadev->mem2mem = of_property_read_bool(pdev->dev.of_node, "st,mem2mem"); - dmadev->rst = devm_reset_control_get(&pdev->dev, NULL); - if (!IS_ERR(dmadev->rst)) { - reset_control_assert(dmadev->rst); + rst = devm_reset_control_get(&pdev->dev, NULL); + if (!IS_ERR(rst)) { + reset_control_assert(rst); udelay(2); - reset_control_deassert(dmadev->rst); + reset_control_deassert(rst); } dma_cap_set(DMA_SLAVE, dd->cap_mask); From 615eee2c45c8448feca0be4e3ad7723916b90744 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Wed, 29 Jan 2020 16:36:23 +0100 Subject: [PATCH 0742/4444] dmaengine: stm32-dma: driver defers probe for reset Change STM32 DMA driver to defer its probe operation when reset controller is expected but has not been probed yet when DMA device is probed. Changes error traces when failing to get a system resource so that it is not printed on failure with deferred probing. Signed-off-by: Etienne Carriere Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200129153628.29329-4-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-dma.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index e31414796ec4..c8bbe08b8e32 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -1296,8 +1296,10 @@ static int stm32_dma_probe(struct platform_device *pdev) dmadev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(dmadev->clk)) { - dev_err(&pdev->dev, "Error: Missing controller clock\n"); - return PTR_ERR(dmadev->clk); + ret = PTR_ERR(dmadev->clk); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Can't get clock\n"); + return ret; } ret = clk_prepare_enable(dmadev->clk); @@ -1310,7 +1312,11 @@ static int stm32_dma_probe(struct platform_device *pdev) "st,mem2mem"); rst = devm_reset_control_get(&pdev->dev, NULL); - if (!IS_ERR(rst)) { + if (IS_ERR(rst)) { + ret = PTR_ERR(rst); + if (ret == -EPROBE_DEFER) + goto clk_free; + } else { reset_control_assert(rst); udelay(2); reset_control_deassert(rst); @@ -1470,10 +1476,11 @@ static struct platform_driver stm32_dma_driver = { .of_match_table = stm32_dma_of_match, .pm = &stm32_dma_pm_ops, }, + .probe = stm32_dma_probe, }; static int __init stm32_dma_init(void) { - return platform_driver_probe(&stm32_dma_driver, stm32_dma_probe); + return platform_driver_register(&stm32_dma_driver); } subsys_initcall(stm32_dma_init); From 22a0bb297cdca9d02407db603bbed84986ef5c05 Mon Sep 17 00:00:00 2001 From: Pierre-Yves MORDRET Date: Wed, 29 Jan 2020 16:36:24 +0100 Subject: [PATCH 0743/4444] dmaengine: stm32-dma: enable descriptor_reuse Enable client to resubmit already processed descriptors in order to save descriptor creation time. Signed-off-by: Pierre-Yves MORDRET Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200129153628.29329-5-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-dma.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index c8bbe08b8e32..25f7281932bd 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -554,6 +554,7 @@ static void stm32_dma_start_transfer(struct stm32_dma_chan *chan) sg_req = &chan->desc->sg_req[chan->next_sg]; reg = &sg_req->chan_reg; + reg->dma_scr &= ~STM32_DMA_SCR_EN; stm32_dma_write(dmadev, STM32_DMA_SCR(chan->id), reg->dma_scr); stm32_dma_write(dmadev, STM32_DMA_SPAR(chan->id), reg->dma_spar); stm32_dma_write(dmadev, STM32_DMA_SM0AR(chan->id), reg->dma_sm0ar); @@ -1343,6 +1344,7 @@ static int stm32_dma_probe(struct platform_device *pdev) dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); dd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; dd->max_burst = STM32_DMA_MAX_BURST; + dd->descriptor_reuse = true; dd->dev = &pdev->dev; INIT_LIST_HEAD(&dd->channels); From d7a9e42609cab42bf748a66756270652187df084 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Wed, 29 Jan 2020 16:36:25 +0100 Subject: [PATCH 0744/4444] dmaengine: stm32-dma: use dma_set_max_seg_size to set the sg limit This patch adds dma_set_max_seg_size to define sg dma constraint. This constraint may be taken into account by client to scatter/gather its buffer. Signed-off-by: Ludovic Barre Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200129153628.29329-6-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-dma.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index 25f7281932bd..b7e18cfcd439 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -1323,6 +1323,8 @@ static int stm32_dma_probe(struct platform_device *pdev) reset_control_deassert(rst); } + dma_set_max_seg_size(&pdev->dev, STM32_DMA_ALIGNED_MAX_DATA_ITEMS); + dma_cap_set(DMA_SLAVE, dd->cap_mask); dma_cap_set(DMA_PRIVATE, dd->cap_mask); dma_cap_set(DMA_CYCLIC, dd->cap_mask); From 32ce108833a8424c686d9f82db231a6039290d41 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Wed, 29 Jan 2020 16:36:26 +0100 Subject: [PATCH 0745/4444] dmaengine: stm32-dma: add copy_align constraint This patch adds copy_align property in accordance with hardware restriction. Signed-off-by: Ludovic Barre Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200129153628.29329-7-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-dma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index b7e18cfcd439..01a2374ae03a 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -1345,6 +1345,7 @@ static int stm32_dma_probe(struct platform_device *pdev) BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); dd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; + dd->copy_align = DMAENGINE_ALIGN_32_BYTES; dd->max_burst = STM32_DMA_MAX_BURST; dd->descriptor_reuse = true; dd->dev = &pdev->dev; From 409ffc4d990c157f876f105d06e11c1f21444cb7 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Wed, 29 Jan 2020 16:36:27 +0100 Subject: [PATCH 0746/4444] dmaengine: stm32-dma: fix sleeping function called from invalid context This patch fixes BUG: sleeping function called from invalid context in stm32_dma_disable_chan function. The goal of this function is to force channel disable if it has not been disabled by hardware. This consists in clearing STM32_DMA_SCR_EN bit and read it as 0 to ensure the channel is well disabled and the last transfer is over. In previous implementation, the waiting loop was based on a do...while (1) with a call to cond_resched to give the scheduler a chance to run a higher priority process. But in some conditions, stm32_dma_disable_chan can be called while preemption is disabled, on a stm32_dma_stop call for example. So cond_resched must not be used. To avoid this, use readl_relaxed_poll_timeout_atomic to poll STM32_DMA_SCR_EN bit cleared. Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200129153628.29329-8-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-dma.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index 01a2374ae03a..b585e11c2168 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -421,29 +422,19 @@ static void stm32_dma_irq_clear(struct stm32_dma_chan *chan, u32 flags) static int stm32_dma_disable_chan(struct stm32_dma_chan *chan) { struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); - unsigned long timeout = jiffies + msecs_to_jiffies(5000); - u32 dma_scr, id; + u32 dma_scr, id, reg; id = chan->id; - dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id)); + reg = STM32_DMA_SCR(id); + dma_scr = stm32_dma_read(dmadev, reg); if (dma_scr & STM32_DMA_SCR_EN) { dma_scr &= ~STM32_DMA_SCR_EN; - stm32_dma_write(dmadev, STM32_DMA_SCR(id), dma_scr); + stm32_dma_write(dmadev, reg, dma_scr); - do { - dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id)); - dma_scr &= STM32_DMA_SCR_EN; - if (!dma_scr) - break; - - if (time_after_eq(jiffies, timeout)) { - dev_err(chan2dev(chan), "%s: timeout!\n", - __func__); - return -EBUSY; - } - cond_resched(); - } while (1); + return readl_relaxed_poll_timeout_atomic(dmadev->base + reg, + dma_scr, !(dma_scr & STM32_DMA_SCR_EN), + 10, 1000000); } return 0; From d80cbef35bf89b763f06e03bb4ff8f933bf012c5 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Wed, 29 Jan 2020 16:36:28 +0100 Subject: [PATCH 0747/4444] dmaengine: stm32-dma: use vchan_terminate_vdesc() in .terminate_all To avoid race with vchan_complete, use the race free way to terminate running transfer. Move vdesc->node list_del in stm32_dma_start_transfer instead of in stm32_mdma_chan_complete to avoid another race in vchan_dma_desc_free_list. Signed-off-by: Amelie Delaunay Link: https://lore.kernel.org/r/20200129153628.29329-9-amelie.delaunay@st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32-dma.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index b585e11c2168..0ddbaa4b4f0b 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -478,8 +478,10 @@ static int stm32_dma_terminate_all(struct dma_chan *c) spin_lock_irqsave(&chan->vchan.lock, flags); - if (chan->busy) { - stm32_dma_stop(chan); + if (chan->desc) { + vchan_terminate_vdesc(&chan->desc->vdesc); + if (chan->busy) + stm32_dma_stop(chan); chan->desc = NULL; } @@ -535,6 +537,8 @@ static void stm32_dma_start_transfer(struct stm32_dma_chan *chan) if (!vdesc) return; + list_del(&vdesc->node); + chan->desc = to_stm32_dma_desc(vdesc); chan->next_sg = 0; } @@ -613,7 +617,6 @@ static void stm32_dma_handle_chan_done(struct stm32_dma_chan *chan) } else { chan->busy = false; if (chan->next_sg == chan->desc->num_sgs) { - list_del(&chan->desc->vdesc.node); vchan_cookie_complete(&chan->desc->vdesc); chan->desc = NULL; } From 04c2bc2bede12f768227ac2b62b21258dc6b45e8 Mon Sep 17 00:00:00 2001 From: Radhey Shyam Pandey Date: Thu, 30 Jan 2020 18:24:24 +0530 Subject: [PATCH 0748/4444] dmaengine: xilinx_dma: Extend dma_config structure to store max channel count Extend dma_config structure to store the max channel count. This input is used to populate dma device channel nodes at the fixed offset. It serves as a preparatory patch for removing dma channel DT node order dependency, added in the subsequent commit. Signed-off-by: Radhey Shyam Pandey Link: https://lore.kernel.org/r/1580388865-9960-2-git-send-email-radhey.shyam.pandey@xilinx.com Signed-off-by: Vinod Koul --- drivers/dma/xilinx/xilinx_dma.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index 6f1539cad1ee..2281af30beeb 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -125,7 +125,9 @@ #define XILINX_VDMA_ENABLE_VERTICAL_FLIP BIT(0) /* HW specific definitions */ -#define XILINX_DMA_MAX_CHANS_PER_DEVICE 0x20 +#define XILINX_MCDMA_MAX_CHANS_PER_DEVICE 0x20 +#define XILINX_DMA_MAX_CHANS_PER_DEVICE 0x2 +#define XILINX_CDMA_MAX_CHANS_PER_DEVICE 0x1 #define XILINX_DMA_DMAXR_ALL_IRQ_MASK \ (XILINX_DMA_DMASR_FRM_CNT_IRQ | \ @@ -468,6 +470,7 @@ struct xilinx_dma_config { struct clk **tx_clk, struct clk **txs_clk, struct clk **rx_clk, struct clk **rxs_clk); irqreturn_t (*irq_handler)(int irq, void *data); + const int max_channels; }; /** @@ -2939,23 +2942,27 @@ static const struct xilinx_dma_config axidma_config = { .dmatype = XDMA_TYPE_AXIDMA, .clk_init = axidma_clk_init, .irq_handler = xilinx_dma_irq_handler, + .max_channels = XILINX_DMA_MAX_CHANS_PER_DEVICE, }; static const struct xilinx_dma_config aximcdma_config = { .dmatype = XDMA_TYPE_AXIMCDMA, .clk_init = axidma_clk_init, .irq_handler = xilinx_mcdma_irq_handler, + .max_channels = XILINX_MCDMA_MAX_CHANS_PER_DEVICE, }; static const struct xilinx_dma_config axicdma_config = { .dmatype = XDMA_TYPE_CDMA, .clk_init = axicdma_clk_init, .irq_handler = xilinx_dma_irq_handler, + .max_channels = XILINX_CDMA_MAX_CHANS_PER_DEVICE, }; static const struct xilinx_dma_config axivdma_config = { .dmatype = XDMA_TYPE_VDMA, .clk_init = axivdma_clk_init, .irq_handler = xilinx_dma_irq_handler, + .max_channels = XILINX_DMA_MAX_CHANS_PER_DEVICE, }; static const struct of_device_id xilinx_dma_of_ids[] = { From 14ccf0aab46e1888e2f45b6e995c621c70b32651 Mon Sep 17 00:00:00 2001 From: Radhey Shyam Pandey Date: Thu, 30 Jan 2020 18:24:25 +0530 Subject: [PATCH 0749/4444] dmaengine: xilinx_dma: In dma channel probe fix node order dependency In overlay application we noticed that dma channel node probe order is inverted i.e s2mm channel is probed first followed by mm2s channel. The reason for this inversion is fdtoverlay utility which uses a function called fdt_add_subnode(*). It stores the subnodes after the properties, this has the effect of inserting the new subnode before any others and the end result is a reversal. Because of this inverted channel probe order, the node probed first is assigned a '0' index instead of Channel ID should be '0' for tx and '1' for rx and dmatest client using the DT convention fails in dma transfer as channel are swapped. To fix above behavior and make channel assignment index independent of probe order, always assign mm2s channel at '0' index and the s2mm channel at IP specific fixed offset derived from the max_channels count. Signed-off-by: Radhey Shyam Pandey Link: https://lore.kernel.org/r/1580388865-9960-3-git-send-email-radhey.shyam.pandey@xilinx.com Signed-off-by: Vinod Koul --- drivers/dma/xilinx/xilinx_dma.c | 39 ++++++++++++++------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index 2281af30beeb..aecd5a35a296 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -488,16 +488,15 @@ struct xilinx_dma_config { * @txs_clk: DMA mm2s stream clock * @rx_clk: DMA s2mm clock * @rxs_clk: DMA s2mm stream clock - * @nr_channels: Number of channels DMA device supports - * @chan_id: DMA channel identifier + * @s2mm_chan_id: DMA s2mm channel identifier + * @mm2s_chan_id: DMA mm2s channel identifier * @max_buffer_len: Max buffer length - * @s2mm_index: S2MM channel index */ struct xilinx_dma_device { void __iomem *regs; struct device *dev; struct dma_device common; - struct xilinx_dma_chan *chan[XILINX_DMA_MAX_CHANS_PER_DEVICE]; + struct xilinx_dma_chan *chan[XILINX_MCDMA_MAX_CHANS_PER_DEVICE]; u32 flush_on_fsync; bool ext_addr; struct platform_device *pdev; @@ -507,10 +506,9 @@ struct xilinx_dma_device { struct clk *txs_clk; struct clk *rx_clk; struct clk *rxs_clk; - u32 nr_channels; - u32 chan_id; + u32 s2mm_chan_id; + u32 mm2s_chan_id; u32 max_buffer_len; - u32 s2mm_index; }; /* Macros */ @@ -1748,7 +1746,7 @@ static irqreturn_t xilinx_mcdma_irq_handler(int irq, void *data) return IRQ_NONE; if (chan->direction == DMA_DEV_TO_MEM) - chan_offset = chan->xdev->s2mm_index; + chan_offset = chan->xdev->dma_config->max_channels / 2; chan_offset = chan_offset + (chan_id - 1); chan = chan->xdev->chan[chan_offset]; @@ -2734,12 +2732,11 @@ static void xdma_disable_allclks(struct xilinx_dma_device *xdev) * * @xdev: Driver specific device structure * @node: Device node - * @chan_id: DMA Channel id * * Return: '0' on success and failure value on error */ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, - struct device_node *node, int chan_id) + struct device_node *node) { struct xilinx_dma_chan *chan; bool has_dre = false; @@ -2791,8 +2788,8 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, of_device_is_compatible(node, "xlnx,axi-dma-mm2s-channel") || of_device_is_compatible(node, "xlnx,axi-cdma-channel")) { chan->direction = DMA_MEM_TO_DEV; - chan->id = chan_id; - chan->tdest = chan_id; + chan->id = xdev->mm2s_chan_id++; + chan->tdest = chan->id; chan->ctrl_offset = XILINX_DMA_MM2S_CTRL_OFFSET; if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) { @@ -2808,9 +2805,8 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, of_device_is_compatible(node, "xlnx,axi-dma-s2mm-channel")) { chan->direction = DMA_DEV_TO_MEM; - chan->id = chan_id; - xdev->s2mm_index = xdev->nr_channels; - chan->tdest = chan_id - xdev->nr_channels; + chan->id = xdev->s2mm_chan_id++; + chan->tdest = chan->id - xdev->dma_config->max_channels / 2; chan->has_vflip = of_property_read_bool(node, "xlnx,enable-vert-flip"); if (chan->has_vflip) { @@ -2912,9 +2908,7 @@ static int xilinx_dma_child_probe(struct xilinx_dma_device *xdev, dev_warn(xdev->dev, "missing dma-channels property\n"); for (i = 0; i < nr_channels; i++) - xilinx_dma_chan_probe(xdev, node, xdev->chan_id++); - - xdev->nr_channels += nr_channels; + xilinx_dma_chan_probe(xdev, node); return 0; } @@ -2932,7 +2926,7 @@ static struct dma_chan *of_dma_xilinx_xlate(struct of_phandle_args *dma_spec, struct xilinx_dma_device *xdev = ofdma->of_dma_data; int chan_id = dma_spec->args[0]; - if (chan_id >= xdev->nr_channels || !xdev->chan[chan_id]) + if (chan_id >= xdev->dma_config->max_channels || !xdev->chan[chan_id]) return NULL; return dma_get_slave_channel(&xdev->chan[chan_id]->common); @@ -3019,6 +3013,7 @@ static int xilinx_dma_probe(struct platform_device *pdev) /* Retrieve the DMA engine properties from the device tree */ xdev->max_buffer_len = GENMASK(XILINX_DMA_MAX_TRANS_LEN_MAX - 1, 0); + xdev->s2mm_chan_id = xdev->dma_config->max_channels / 2; if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA || xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA) { @@ -3112,7 +3107,7 @@ static int xilinx_dma_probe(struct platform_device *pdev) } if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) { - for (i = 0; i < xdev->nr_channels; i++) + for (i = 0; i < xdev->dma_config->max_channels; i++) if (xdev->chan[i]) xdev->chan[i]->num_frms = num_frames; } @@ -3142,7 +3137,7 @@ static int xilinx_dma_probe(struct platform_device *pdev) disable_clks: xdma_disable_allclks(xdev); error: - for (i = 0; i < xdev->nr_channels; i++) + for (i = 0; i < xdev->dma_config->max_channels; i++) if (xdev->chan[i]) xilinx_dma_chan_remove(xdev->chan[i]); @@ -3164,7 +3159,7 @@ static int xilinx_dma_remove(struct platform_device *pdev) dma_async_device_unregister(&xdev->common); - for (i = 0; i < xdev->nr_channels; i++) + for (i = 0; i < xdev->dma_config->max_channels; i++) if (xdev->chan[i]) xilinx_dma_chan_remove(xdev->chan[i]); From a6e7f19c910068cb54983f36acebedb376f3a9ac Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 23 Jan 2020 14:03:02 +0000 Subject: [PATCH 0750/4444] dmaengine: at_hdmac: Substitute kzalloc with kmalloc All members of the structure are initialized below in the function, there is no need to use kzalloc. Signed-off-by: Tudor Ambarus Acked-by: Ludovic Desroches Link: https://lore.kernel.org/r/20200123140237.125799-1-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 672c73b4a2d4..cad6dcd9cfb5 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1671,7 +1671,7 @@ static struct dma_chan *at_dma_xlate(struct of_phandle_args *dma_spec, dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - atslave = kzalloc(sizeof(*atslave), GFP_KERNEL); + atslave = kmalloc(sizeof(*atslave), GFP_KERNEL); if (!atslave) return NULL; From bbc58394d81110f76586d3053fd5a3a3ad616050 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 23 Jan 2020 14:03:04 +0000 Subject: [PATCH 0751/4444] dmaengine: at_hdmac: Drop locking in at_hdmac_alloc_chan_resources() There is no need for locking in device_alloc_chan_resources(), the DMA core takes care of it by using a dma_list_mutex around the DMA devices. Signed-off-by: Tudor Ambarus Acked-by: Ludovic Desroches Link: https://lore.kernel.org/r/20200123140237.125799-2-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index cad6dcd9cfb5..301bae45cf8d 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1542,10 +1542,8 @@ static int atc_alloc_chan_resources(struct dma_chan *chan) struct at_dma *atdma = to_at_dma(chan->device); struct at_desc *desc; struct at_dma_slave *atslave; - unsigned long flags; int i; u32 cfg; - LIST_HEAD(tmp_list); dev_vdbg(chan2dev(chan), "alloc_chan_resources\n"); @@ -1583,14 +1581,11 @@ static int atc_alloc_chan_resources(struct dma_chan *chan) "Only %d initial descriptors\n", i); break; } - list_add_tail(&desc->desc_node, &tmp_list); + list_add_tail(&desc->desc_node, &atchan->free_list); } - spin_lock_irqsave(&atchan->lock, flags); atchan->descs_allocated = i; - list_splice(&tmp_list, &atchan->free_list); dma_cookie_init(chan); - spin_unlock_irqrestore(&atchan->lock, flags); /* channel parameters */ channel_writel(atchan, CFG, cfg); From ad16bc232dd72f85984c790e07c69009b7c850c8 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 23 Jan 2020 14:03:06 +0000 Subject: [PATCH 0752/4444] dmaengine: at_hdmac: Return err in case the chan is not free at alloc res time Having a list of descriptors allocated for the channel at device_alloc_chan_resources() time is a sign for bad free usage. Return err and add a debug message in case the channel is not free from a previous use. atchan->descs_allocated becomes useless, get rid of it. More, drop the error message in atc_desc_get() because now it would introduce an extra if statement. The callers of atc_desc_get() already print error messages in case the callee fails, no one is hurt. Signed-off-by: Tudor Ambarus Acked-by: Ludovic Desroches Link: https://lore.kernel.org/r/20200123140237.125799-3-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 31 ++++++++----------------------- drivers/dma/at_hdmac_regs.h | 2 -- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 301bae45cf8d..e17b75075904 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -146,17 +146,8 @@ static struct at_desc *atc_desc_get(struct at_dma_chan *atchan) "scanned %u descriptors on freelist\n", i); /* no more descriptor available in initial pool: create one more */ - if (!ret) { + if (!ret) ret = atc_alloc_descriptor(&atchan->chan_common, GFP_ATOMIC); - if (ret) { - spin_lock_irqsave(&atchan->lock, flags); - atchan->descs_allocated++; - spin_unlock_irqrestore(&atchan->lock, flags); - } else { - dev_err(chan2dev(&atchan->chan_common), - "not enough descriptors available\n"); - } - } return ret; } @@ -1553,6 +1544,11 @@ static int atc_alloc_chan_resources(struct dma_chan *chan) return -EIO; } + if (!list_empty(&atchan->free_list)) { + dev_dbg(chan2dev(chan), "can't allocate channel resources (channel not freed from a previous use)\n"); + return -EIO; + } + cfg = ATC_DEFAULT_CFG; atslave = chan->private; @@ -1568,11 +1564,6 @@ static int atc_alloc_chan_resources(struct dma_chan *chan) cfg = atslave->cfg; } - /* have we already been set up? - * reconfigure channel but no need to reallocate descriptors */ - if (!list_empty(&atchan->free_list)) - return atchan->descs_allocated; - /* Allocate initial pool of descriptors */ for (i = 0; i < init_nr_desc_per_channel; i++) { desc = atc_alloc_descriptor(chan, GFP_KERNEL); @@ -1584,17 +1575,15 @@ static int atc_alloc_chan_resources(struct dma_chan *chan) list_add_tail(&desc->desc_node, &atchan->free_list); } - atchan->descs_allocated = i; dma_cookie_init(chan); /* channel parameters */ channel_writel(atchan, CFG, cfg); dev_dbg(chan2dev(chan), - "alloc_chan_resources: allocated %d descriptors\n", - atchan->descs_allocated); + "alloc_chan_resources: allocated %d descriptors\n", i); - return atchan->descs_allocated; + return i; } /** @@ -1608,9 +1597,6 @@ static void atc_free_chan_resources(struct dma_chan *chan) struct at_desc *desc, *_desc; LIST_HEAD(list); - dev_dbg(chan2dev(chan), "free_chan_resources: (descs allocated=%u)\n", - atchan->descs_allocated); - /* ASSERT: channel is idle */ BUG_ON(!list_empty(&atchan->active_list)); BUG_ON(!list_empty(&atchan->queue)); @@ -1623,7 +1609,6 @@ static void atc_free_chan_resources(struct dma_chan *chan) dma_pool_free(atdma->dma_desc_pool, desc, desc->txd.phys); } list_splice_init(&atchan->free_list, &list); - atchan->descs_allocated = 0; atchan->status = 0; /* diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h index fe8a5853ec49..397692e937b3 100644 --- a/drivers/dma/at_hdmac_regs.h +++ b/drivers/dma/at_hdmac_regs.h @@ -243,7 +243,6 @@ enum atc_status { * @active_list: list of descriptors dmaengine is being running on * @queue: list of descriptors ready to be submitted to engine * @free_list: list of descriptors usable by the channel - * @descs_allocated: records the actual size of the descriptor pool */ struct at_dma_chan { struct dma_chan chan_common; @@ -264,7 +263,6 @@ struct at_dma_chan { struct list_head active_list; struct list_head queue; struct list_head free_list; - unsigned int descs_allocated; }; #define channel_readl(atchan, name) \ From ceb2c14c5908565ac49f9b6a5c0d9e93f2099ea0 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 23 Jan 2020 14:03:07 +0000 Subject: [PATCH 0753/4444] dmaengine: at_hdmac: Drop description for a not defined parameter Probably a leftover, drop it. Signed-off-by: Tudor Ambarus Acked-by: Ludovic Desroches Link: https://lore.kernel.org/r/20200123140237.125799-4-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index e17b75075904..44d998bc894b 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1523,7 +1523,6 @@ static void atc_issue_pending(struct dma_chan *chan) /** * atc_alloc_chan_resources - allocate resources for DMA channel * @chan: allocate descriptor resources for this channel - * @client: current client requesting the channel be ready for requests * * return - the number of allocated descriptors */ From 247b4d83d6525d04278333cf201d6e3b066c9ca5 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 23 Jan 2020 14:03:09 +0000 Subject: [PATCH 0754/4444] dmaengine: at_hdmac: Switch atomic allocations to GFP_NOWAIT Avoids sleeping without depleting the emergency pool. The rationale being that in most cases a dma device is either offloading an operation that will automatically fallback to software when the descriptor allocation fails, or we can simply poll and wait for the dma device to release some in use descriptors. Signed-off-by: Tudor Ambarus Acked-by: Ludovic Desroches Link: https://lore.kernel.org/r/20200123140237.125799-5-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 44d998bc894b..8e8e04bd1b28 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -147,7 +147,7 @@ static struct at_desc *atc_desc_get(struct at_dma_chan *atchan) /* no more descriptor available in initial pool: create one more */ if (!ret) - ret = atc_alloc_descriptor(&atchan->chan_common, GFP_ATOMIC); + ret = atc_alloc_descriptor(&atchan->chan_common, GFP_NOWAIT); return ret; } @@ -931,7 +931,7 @@ atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, return NULL; } - vaddr = dma_pool_alloc(atdma->memset_pool, GFP_ATOMIC, &paddr); + vaddr = dma_pool_alloc(atdma->memset_pool, GFP_NOWAIT, &paddr); if (!vaddr) { dev_err(chan2dev(chan), "%s: couldn't allocate buffer\n", __func__); @@ -989,7 +989,7 @@ atc_prep_dma_memset_sg(struct dma_chan *chan, return NULL; } - vaddr = dma_pool_alloc(atdma->memset_pool, GFP_ATOMIC, &paddr); + vaddr = dma_pool_alloc(atdma->memset_pool, GFP_NOWAIT, &paddr); if (!vaddr) { dev_err(chan2dev(chan), "%s: couldn't allocate buffer\n", __func__); From 078a6506141a4ce76bee6c257e9b14f5c606ee4c Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 23 Jan 2020 14:03:11 +0000 Subject: [PATCH 0755/4444] dmaengine: at_hdmac: Fix deadlocks Fix the following deadlocks: 1/ atc_handle_cyclic() and atc_chain_complete() called dmaengine_desc_get_callback_invoke() while wrongly holding the atchan->lock. Clients can set the callback to dmaengine_terminate_sync() which will end up trying to get the same lock, thus a deadlock occurred. 2/ dma_run_dependencies() was called with the atchan->lock held, but the method calls device_issue_pending() which tries to get the same lock, and so a deadlock occurred. The driver must not hold the lock when invoking the callback or when running dependencies. Releasing the spinlock within a called function before calling the callback is not a nice thing to do -> called functions become non-atomic when called within an atomic region. Thus the lock is now taken in the child routines whereever is needed. Signed-off-by: Tudor Ambarus Acked-by: Ludovic Desroches Link: https://lore.kernel.org/r/20200123140237.125799-6-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 74 ++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 8e8e04bd1b28..73a20780744b 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -426,17 +426,19 @@ static int atc_get_bytes_left(struct dma_chan *chan, dma_cookie_t cookie) * atc_chain_complete - finish work for one transaction chain * @atchan: channel we work on * @desc: descriptor at the head of the chain we want do complete - * - * Called with atchan->lock held and bh disabled */ + */ static void atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc) { struct dma_async_tx_descriptor *txd = &desc->txd; struct at_dma *atdma = to_at_dma(atchan->chan_common.device); + unsigned long flags; dev_vdbg(chan2dev(&atchan->chan_common), "descriptor %u complete\n", txd->cookie); + spin_lock_irqsave(&atchan->lock, flags); + /* mark the descriptor as complete for non cyclic cases only */ if (!atc_chan_is_cyclic(atchan)) dma_cookie_complete(txd); @@ -453,16 +455,13 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc) /* move myself to free_list */ list_move(&desc->desc_node, &atchan->free_list); + spin_unlock_irqrestore(&atchan->lock, flags); + dma_descriptor_unmap(txd); /* for cyclic transfers, * no need to replay callback function while stopping */ - if (!atc_chan_is_cyclic(atchan)) { - /* - * The API requires that no submissions are done from a - * callback, so we don't need to drop the lock here - */ + if (!atc_chan_is_cyclic(atchan)) dmaengine_desc_get_callback_invoke(txd, NULL); - } dma_run_dependencies(txd); } @@ -480,9 +479,12 @@ static void atc_complete_all(struct at_dma_chan *atchan) { struct at_desc *desc, *_desc; LIST_HEAD(list); + unsigned long flags; dev_vdbg(chan2dev(&atchan->chan_common), "complete all\n"); + spin_lock_irqsave(&atchan->lock, flags); + /* * Submit queued descriptors ASAP, i.e. before we go through * the completed ones. @@ -494,6 +496,8 @@ static void atc_complete_all(struct at_dma_chan *atchan) /* empty queue list by moving descriptors (if any) to active_list */ list_splice_init(&atchan->queue, &atchan->active_list); + spin_unlock_irqrestore(&atchan->lock, flags); + list_for_each_entry_safe(desc, _desc, &list, desc_node) atc_chain_complete(atchan, desc); } @@ -501,38 +505,44 @@ static void atc_complete_all(struct at_dma_chan *atchan) /** * atc_advance_work - at the end of a transaction, move forward * @atchan: channel where the transaction ended - * - * Called with atchan->lock held and bh disabled */ static void atc_advance_work(struct at_dma_chan *atchan) { + unsigned long flags; + int ret; + dev_vdbg(chan2dev(&atchan->chan_common), "advance_work\n"); - if (atc_chan_is_enabled(atchan)) + spin_lock_irqsave(&atchan->lock, flags); + ret = atc_chan_is_enabled(atchan); + spin_unlock_irqrestore(&atchan->lock, flags); + if (ret) return; if (list_empty(&atchan->active_list) || - list_is_singular(&atchan->active_list)) { - atc_complete_all(atchan); - } else { - atc_chain_complete(atchan, atc_first_active(atchan)); - /* advance work */ - atc_dostart(atchan, atc_first_active(atchan)); - } + list_is_singular(&atchan->active_list)) + return atc_complete_all(atchan); + + atc_chain_complete(atchan, atc_first_active(atchan)); + + /* advance work */ + spin_lock_irqsave(&atchan->lock, flags); + atc_dostart(atchan, atc_first_active(atchan)); + spin_unlock_irqrestore(&atchan->lock, flags); } /** * atc_handle_error - handle errors reported by DMA controller * @atchan: channel where error occurs - * - * Called with atchan->lock held and bh disabled */ static void atc_handle_error(struct at_dma_chan *atchan) { struct at_desc *bad_desc; struct at_desc *child; + unsigned long flags; + spin_lock_irqsave(&atchan->lock, flags); /* * The descriptor currently at the head of the active list is * broked. Since we don't have any way to report errors, we'll @@ -564,6 +574,8 @@ static void atc_handle_error(struct at_dma_chan *atchan) list_for_each_entry(child, &bad_desc->tx_list, desc_node) atc_dump_lli(atchan, &child->lli); + spin_unlock_irqrestore(&atchan->lock, flags); + /* Pretend the descriptor completed successfully */ atc_chain_complete(atchan, bad_desc); } @@ -571,8 +583,6 @@ static void atc_handle_error(struct at_dma_chan *atchan) /** * atc_handle_cyclic - at the end of a period, run callback function * @atchan: channel used for cyclic operations - * - * Called with atchan->lock held and bh disabled */ static void atc_handle_cyclic(struct at_dma_chan *atchan) { @@ -591,17 +601,14 @@ static void atc_handle_cyclic(struct at_dma_chan *atchan) static void atc_tasklet(unsigned long data) { struct at_dma_chan *atchan = (struct at_dma_chan *)data; - unsigned long flags; - spin_lock_irqsave(&atchan->lock, flags); if (test_and_clear_bit(ATC_IS_ERROR, &atchan->status)) - atc_handle_error(atchan); - else if (atc_chan_is_cyclic(atchan)) - atc_handle_cyclic(atchan); - else - atc_advance_work(atchan); + return atc_handle_error(atchan); - spin_unlock_irqrestore(&atchan->lock, flags); + if (atc_chan_is_cyclic(atchan)) + return atc_handle_cyclic(atchan); + + atc_advance_work(atchan); } static irqreturn_t at_dma_interrupt(int irq, void *dev_id) @@ -1437,6 +1444,8 @@ static int atc_terminate_all(struct dma_chan *chan) list_splice_init(&atchan->queue, &list); list_splice_init(&atchan->active_list, &list); + spin_unlock_irqrestore(&atchan->lock, flags); + /* Flush all pending and queued descriptors */ list_for_each_entry_safe(desc, _desc, &list, desc_node) atc_chain_complete(atchan, desc); @@ -1445,8 +1454,6 @@ static int atc_terminate_all(struct dma_chan *chan) /* if channel dedicated to cyclic operations, free it */ clear_bit(ATC_IS_CYCLIC, &atchan->status); - spin_unlock_irqrestore(&atchan->lock, flags); - return 0; } @@ -1507,7 +1514,6 @@ atc_tx_status(struct dma_chan *chan, static void atc_issue_pending(struct dma_chan *chan) { struct at_dma_chan *atchan = to_at_dma_chan(chan); - unsigned long flags; dev_vdbg(chan2dev(chan), "issue_pending\n"); @@ -1515,9 +1521,7 @@ static void atc_issue_pending(struct dma_chan *chan) if (atc_chan_is_cyclic(atchan)) return; - spin_lock_irqsave(&atchan->lock, flags); atc_advance_work(atchan); - spin_unlock_irqrestore(&atchan->lock, flags); } /** From a443e988765b7cdaf9ffa0f3d2d3d9b532668e5d Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 23 Jan 2020 14:03:12 +0000 Subject: [PATCH 0756/4444] dmaengine: at_xdmac: Drop always true check The code in cause is already in the else case of 'if (at_xdmac_chan_is_cyclic(atchan))', drop the redundant check. Signed-off-by: Tudor Ambarus Acked-by: Ludovic Desroches Link: https://lore.kernel.org/r/20200123140237.125799-7-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_xdmac.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c index f71c9f77d405..3d6e84def7a6 100644 --- a/drivers/dma/at_xdmac.c +++ b/drivers/dma/at_xdmac.c @@ -1656,11 +1656,9 @@ static void at_xdmac_tasklet(unsigned long data) at_xdmac_remove_xfer(atchan, desc); spin_unlock(&atchan->lock); - if (!at_xdmac_chan_is_cyclic(atchan)) { - dma_cookie_complete(txd); - if (txd->flags & DMA_PREP_INTERRUPT) - dmaengine_desc_get_callback_invoke(txd, NULL); - } + dma_cookie_complete(txd); + if (txd->flags & DMA_PREP_INTERRUPT) + dmaengine_desc_get_callback_invoke(txd, NULL); dma_run_dependencies(txd); From 387269d04b3d6f76a3a6efd4fb66fa31c12e2508 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 23 Jan 2020 14:03:14 +0000 Subject: [PATCH 0757/4444] dmaengine: at_xdmac: Drop locking in at_xdmac_alloc_chan_resources() There is no need for locking in device_alloc_chan_resources(), the DMA core takes care of it by using a dma_list_mutex around the DMA devices. Signed-off-by: Tudor Ambarus Acked-by: Ludovic Desroches Link: https://lore.kernel.org/r/20200123140237.125799-8-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_xdmac.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c index 3d6e84def7a6..8fb01bc90ba7 100644 --- a/drivers/dma/at_xdmac.c +++ b/drivers/dma/at_xdmac.c @@ -1820,22 +1820,17 @@ static int at_xdmac_alloc_chan_resources(struct dma_chan *chan) struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan); struct at_xdmac_desc *desc; int i; - unsigned long flags; - - spin_lock_irqsave(&atchan->lock, flags); if (at_xdmac_chan_is_enabled(atchan)) { dev_err(chan2dev(chan), "can't allocate channel resources (channel enabled)\n"); - i = -EIO; - goto spin_unlock; + return -EIO; } if (!list_empty(&atchan->free_descs_list)) { dev_err(chan2dev(chan), "can't allocate channel resources (channel not free from a previous use)\n"); - i = -EIO; - goto spin_unlock; + return -EIO; } for (i = 0; i < init_nr_desc_per_channel; i++) { @@ -1852,8 +1847,6 @@ static int at_xdmac_alloc_chan_resources(struct dma_chan *chan) dev_dbg(chan2dev(chan), "%s: allocated %d descriptors\n", __func__, i); -spin_unlock: - spin_unlock_irqrestore(&atchan->lock, flags); return i; } From 8592f2c81ebc494017d574fd8b731be44087a2e9 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 23 Jan 2020 14:03:15 +0000 Subject: [PATCH 0758/4444] dmaengine: at_xdmac: GFP_KERNEL for user that can sleep device_alloc_chan_resources can sleep, use GFP_KERNEL flag. Signed-off-by: Tudor Ambarus Acked-by: Ludovic Desroches Link: https://lore.kernel.org/r/20200123140237.125799-9-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_xdmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c index 8fb01bc90ba7..31321da69ae6 100644 --- a/drivers/dma/at_xdmac.c +++ b/drivers/dma/at_xdmac.c @@ -1834,7 +1834,7 @@ static int at_xdmac_alloc_chan_resources(struct dma_chan *chan) } for (i = 0; i < init_nr_desc_per_channel; i++) { - desc = at_xdmac_alloc_desc(chan, GFP_ATOMIC); + desc = at_xdmac_alloc_desc(chan, GFP_KERNEL); if (!desc) { dev_warn(chan2dev(chan), "only %d descriptors have been allocated\n", i); From 191bd1cad3535a30c2931dc1757e260afe03854b Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 23 Jan 2020 14:03:17 +0000 Subject: [PATCH 0759/4444] dmaengine: at_xdmac: Fix locking in tasklet Tasklets run with all the interrupts enabled. This means that we should replace all the (already present) spin_lock_irqsave() uses in the tasklet with spin_lock_irq() to protect being interrupted by a IRQ which tries to get the same lock (via calls to device_prep_dma_* for example). spin_lock and spin_lock_bh in tasklets are not enough to protect from IRQs, update these to spin_lock_irq(). at_xdmac_advance_work() can be called with all the interrupts enabled (when called from tasklet), or with interrupts disabled (when called from at_xdmac_issue_pending). Move the locking in the callers to be able to use spin_lock_irq() and spin_lock_irqsave() for these cases. Signed-off-by: Tudor Ambarus Acked-by: Ludovic Desroches Link: https://lore.kernel.org/r/20200123140237.125799-10-tudor.ambarus@microchip.com Signed-off-by: Vinod Koul --- drivers/dma/at_xdmac.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c index 31321da69ae6..bb0eaf38b594 100644 --- a/drivers/dma/at_xdmac.c +++ b/drivers/dma/at_xdmac.c @@ -1543,9 +1543,6 @@ static void at_xdmac_remove_xfer(struct at_xdmac_chan *atchan, static void at_xdmac_advance_work(struct at_xdmac_chan *atchan) { struct at_xdmac_desc *desc; - unsigned long flags; - - spin_lock_irqsave(&atchan->lock, flags); /* * If channel is enabled, do nothing, advance_work will be triggered @@ -1559,8 +1556,6 @@ static void at_xdmac_advance_work(struct at_xdmac_chan *atchan) if (!desc->active_xfer) at_xdmac_start_xfer(atchan, desc); } - - spin_unlock_irqrestore(&atchan->lock, flags); } static void at_xdmac_handle_cyclic(struct at_xdmac_chan *atchan) @@ -1596,7 +1591,7 @@ static void at_xdmac_handle_error(struct at_xdmac_chan *atchan) if (atchan->irq_status & AT_XDMAC_CIS_ROIS) dev_err(chan2dev(&atchan->chan), "request overflow error!!!"); - spin_lock_bh(&atchan->lock); + spin_lock_irq(&atchan->lock); /* Channel must be disabled first as it's not done automatically */ at_xdmac_write(atxdmac, AT_XDMAC_GD, atchan->mask); @@ -1607,7 +1602,7 @@ static void at_xdmac_handle_error(struct at_xdmac_chan *atchan) struct at_xdmac_desc, xfer_node); - spin_unlock_bh(&atchan->lock); + spin_unlock_irq(&atchan->lock); /* Print bad descriptor's details if needed */ dev_dbg(chan2dev(&atchan->chan), @@ -1640,21 +1635,21 @@ static void at_xdmac_tasklet(unsigned long data) if (atchan->irq_status & error_mask) at_xdmac_handle_error(atchan); - spin_lock(&atchan->lock); + spin_lock_irq(&atchan->lock); desc = list_first_entry(&atchan->xfers_list, struct at_xdmac_desc, xfer_node); dev_vdbg(chan2dev(&atchan->chan), "%s: desc 0x%p\n", __func__, desc); if (!desc->active_xfer) { dev_err(chan2dev(&atchan->chan), "Xfer not active: exiting"); - spin_unlock(&atchan->lock); + spin_unlock_irq(&atchan->lock); return; } txd = &desc->tx_dma_desc; at_xdmac_remove_xfer(atchan, desc); - spin_unlock(&atchan->lock); + spin_unlock_irq(&atchan->lock); dma_cookie_complete(txd); if (txd->flags & DMA_PREP_INTERRUPT) @@ -1662,7 +1657,9 @@ static void at_xdmac_tasklet(unsigned long data) dma_run_dependencies(txd); + spin_lock_irq(&atchan->lock); at_xdmac_advance_work(atchan); + spin_unlock_irq(&atchan->lock); } } @@ -1723,11 +1720,15 @@ static irqreturn_t at_xdmac_interrupt(int irq, void *dev_id) static void at_xdmac_issue_pending(struct dma_chan *chan) { struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan); + unsigned long flags; dev_dbg(chan2dev(&atchan->chan), "%s\n", __func__); - if (!at_xdmac_chan_is_cyclic(atchan)) + if (!at_xdmac_chan_is_cyclic(atchan)) { + spin_lock_irqsave(&atchan->lock, flags); at_xdmac_advance_work(atchan); + spin_unlock_irqrestore(&atchan->lock, flags); + } return; } From eb0249d50153a8edf2c0cfbf281199813980c8d4 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 10 Feb 2020 11:44:55 +0200 Subject: [PATCH 0760/4444] dmaengine: ti: edma: Support for interleaved mem to mem transfer Add basic interleaved support via EDMA. Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20200210094455.3615-1-peter.ujfalusi@ti.com Signed-off-by: Vinod Koul --- drivers/dma/ti/edma.c | 79 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/drivers/dma/ti/edma.c b/drivers/dma/ti/edma.c index 03a7f647f7b2..2b1fdd438e7f 100644 --- a/drivers/dma/ti/edma.c +++ b/drivers/dma/ti/edma.c @@ -1275,6 +1275,81 @@ static struct dma_async_tx_descriptor *edma_prep_dma_memcpy( return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags); } +static struct dma_async_tx_descriptor * +edma_prep_dma_interleaved(struct dma_chan *chan, + struct dma_interleaved_template *xt, + unsigned long tx_flags) +{ + struct device *dev = chan->device->dev; + struct edma_chan *echan = to_edma_chan(chan); + struct edmacc_param *param; + struct edma_desc *edesc; + size_t src_icg, dst_icg; + int src_bidx, dst_bidx; + + /* Slave mode is not supported */ + if (is_slave_direction(xt->dir)) + return NULL; + + if (xt->frame_size != 1 || xt->numf == 0) + return NULL; + + if (xt->sgl[0].size > SZ_64K || xt->numf > SZ_64K) + return NULL; + + src_icg = dmaengine_get_src_icg(xt, &xt->sgl[0]); + if (src_icg) { + src_bidx = src_icg + xt->sgl[0].size; + } else if (xt->src_inc) { + src_bidx = xt->sgl[0].size; + } else { + dev_err(dev, "%s: SRC constant addressing is not supported\n", + __func__); + return NULL; + } + + dst_icg = dmaengine_get_dst_icg(xt, &xt->sgl[0]); + if (dst_icg) { + dst_bidx = dst_icg + xt->sgl[0].size; + } else if (xt->dst_inc) { + dst_bidx = xt->sgl[0].size; + } else { + dev_err(dev, "%s: DST constant addressing is not supported\n", + __func__); + return NULL; + } + + if (src_bidx > SZ_64K || dst_bidx > SZ_64K) + return NULL; + + edesc = kzalloc(struct_size(edesc, pset, 1), GFP_ATOMIC); + if (!edesc) + return NULL; + + edesc->direction = DMA_MEM_TO_MEM; + edesc->echan = echan; + edesc->pset_nr = 1; + + param = &edesc->pset[0].param; + + param->src = xt->src_start; + param->dst = xt->dst_start; + param->a_b_cnt = xt->numf << 16 | xt->sgl[0].size; + param->ccnt = 1; + param->src_dst_bidx = (dst_bidx << 16) | src_bidx; + param->src_dst_cidx = 0; + + param->opt = EDMA_TCC(EDMA_CHAN_SLOT(echan->ch_num)); + param->opt |= ITCCHEN; + /* Enable transfer complete interrupt if requested */ + if (tx_flags & DMA_PREP_INTERRUPT) + param->opt |= TCINTEN; + else + edesc->polled = true; + + return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags); +} + static struct dma_async_tx_descriptor *edma_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_transfer_direction direction, @@ -1917,7 +1992,9 @@ static void edma_dma_init(struct edma_cc *ecc, bool legacy_mode) "Legacy memcpy is enabled, things might not work\n"); dma_cap_set(DMA_MEMCPY, s_ddev->cap_mask); + dma_cap_set(DMA_INTERLEAVE, m_ddev->cap_mask); s_ddev->device_prep_dma_memcpy = edma_prep_dma_memcpy; + s_ddev->device_prep_interleaved_dma = edma_prep_dma_interleaved; s_ddev->directions = BIT(DMA_MEM_TO_MEM); } @@ -1953,8 +2030,10 @@ static void edma_dma_init(struct edma_cc *ecc, bool legacy_mode) dma_cap_zero(m_ddev->cap_mask); dma_cap_set(DMA_MEMCPY, m_ddev->cap_mask); + dma_cap_set(DMA_INTERLEAVE, m_ddev->cap_mask); m_ddev->device_prep_dma_memcpy = edma_prep_dma_memcpy; + m_ddev->device_prep_interleaved_dma = edma_prep_dma_interleaved; m_ddev->device_alloc_chan_resources = edma_alloc_chan_resources; m_ddev->device_free_chan_resources = edma_free_chan_resources; m_ddev->device_issue_pending = edma_issue_pending; From dda5e35a771043bb5a9e6107fa9f141d8d56b847 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 9 Feb 2020 19:33:40 +0300 Subject: [PATCH 0761/4444] dmaengine: tegra-apb: Implement synchronization hook The ISR tasklet could be kept scheduled after DMA transfer termination, let's add synchronization hook which blocks until tasklet is finished. Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Link: https://lore.kernel.org/r/20200209163356.6439-4-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 3a45079d11ec..b18cbfbab004 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -802,6 +802,13 @@ skip_dma_stop: return 0; } +static void tegra_dma_synchronize(struct dma_chan *dc) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + + tasklet_kill(&tdc->tasklet); +} + static unsigned int tegra_dma_sg_bytes_xferred(struct tegra_dma_channel *tdc, struct tegra_dma_sg_req *sg_req) { @@ -1510,6 +1517,7 @@ static int tegra_dma_probe(struct platform_device *pdev) tdma->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; tdma->dma_dev.device_config = tegra_dma_slave_config; tdma->dma_dev.device_terminate_all = tegra_dma_terminate_all; + tdma->dma_dev.device_synchronize = tegra_dma_synchronize; tdma->dma_dev.device_tx_status = tegra_dma_tx_status; tdma->dma_dev.device_issue_pending = tegra_dma_issue_pending; From 8e84172e372bdca20c305d92d51d33640d2da431 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 9 Feb 2020 19:33:41 +0300 Subject: [PATCH 0762/4444] dmaengine: tegra-apb: Prevent race conditions on channel's freeing It's incorrect to check the channel's "busy" state without taking a lock. That shouldn't cause any real troubles, nevertheless it's always better not to have any race conditions in the code. Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Link: https://lore.kernel.org/r/20200209163356.6439-5-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index b18cbfbab004..81a2b5f4181f 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -1298,8 +1298,7 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc) dev_dbg(tdc2dev(tdc), "Freeing channel %d\n", tdc->id); - if (tdc->busy) - tegra_dma_terminate_all(dc); + tegra_dma_terminate_all(dc); spin_lock_irqsave(&tdc->lock, flags); list_splice_init(&tdc->pending_sg_req, &sg_req_list); From 41ffc423e117782309e3a409d61507bf7b77719c Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 9 Feb 2020 19:33:42 +0300 Subject: [PATCH 0763/4444] dmaengine: tegra-apb: Clean up tasklet releasing There is no need to kill tasklet when driver's probe fails because tasklet can't be scheduled at this time. It is also cleaner to kill tasklet on channel's freeing rather than to kill it on driver's removal, otherwise tasklet could perform a dummy execution after channel's releasing, which isn't very nice. Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Link: https://lore.kernel.org/r/20200209163356.6439-6-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 81a2b5f4181f..f2ef940c4e2a 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -1291,7 +1291,6 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc) struct tegra_dma_sg_req *sg_req; struct list_head dma_desc_list; struct list_head sg_req_list; - unsigned long flags; INIT_LIST_HEAD(&dma_desc_list); INIT_LIST_HEAD(&sg_req_list); @@ -1299,15 +1298,14 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc) dev_dbg(tdc2dev(tdc), "Freeing channel %d\n", tdc->id); tegra_dma_terminate_all(dc); + tasklet_kill(&tdc->tasklet); - spin_lock_irqsave(&tdc->lock, flags); list_splice_init(&tdc->pending_sg_req, &sg_req_list); list_splice_init(&tdc->free_sg_req, &sg_req_list); list_splice_init(&tdc->free_dma_desc, &dma_desc_list); INIT_LIST_HEAD(&tdc->cb_desc); tdc->config_init = false; tdc->isr_handler = NULL; - spin_unlock_irqrestore(&tdc->lock, flags); while (!list_empty(&dma_desc_list)) { dma_desc = list_first_entry(&dma_desc_list, @@ -1546,7 +1544,6 @@ err_irq: struct tegra_dma_channel *tdc = &tdma->channels[i]; free_irq(tdc->irq, tdc); - tasklet_kill(&tdc->tasklet); } pm_runtime_disable(&pdev->dev); @@ -1566,7 +1563,6 @@ static int tegra_dma_remove(struct platform_device *pdev) for (i = 0; i < tdma->chip_data->nr_channels; ++i) { tdc = &tdma->channels[i]; free_irq(tdc->irq, tdc); - tasklet_kill(&tdc->tasklet); } pm_runtime_disable(&pdev->dev); From c55c745e6f2696889dae10425abcaf32e878d93a Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 9 Feb 2020 19:33:43 +0300 Subject: [PATCH 0764/4444] dmaengine: tegra-apb: Use devm_platform_ioremap_resource Use devm_platform_ioremap_resource to keep code cleaner a tad. Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Link: https://lore.kernel.org/r/20200209163356.6439-7-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index f2ef940c4e2a..4468ded15780 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -1406,8 +1406,7 @@ static int tegra_dma_probe(struct platform_device *pdev) tdma->chip_data = cdata; platform_set_drvdata(pdev, tdma); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - tdma->base_addr = devm_ioremap_resource(&pdev->dev, res); + tdma->base_addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(tdma->base_addr)) return PTR_ERR(tdma->base_addr); From 2cd3d13cb4aa7371f3e945cecc57506769936541 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 9 Feb 2020 19:33:44 +0300 Subject: [PATCH 0765/4444] dmaengine: tegra-apb: Use devm_request_irq Use resource-managed variant of request_irq for brevity. Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Link: https://lore.kernel.org/r/20200209163356.6439-8-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 4468ded15780..9dc1fc236941 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -182,7 +182,6 @@ struct tegra_dma_channel { char name[12]; bool config_init; int id; - int irq; void __iomem *chan_addr; spinlock_t lock; bool busy; @@ -1384,7 +1383,6 @@ static const struct tegra_dma_chip_data tegra148_dma_chip_data = { static int tegra_dma_probe(struct platform_device *pdev) { - struct resource *res; struct tegra_dma *tdma; int ret; int i; @@ -1450,25 +1448,27 @@ static int tegra_dma_probe(struct platform_device *pdev) INIT_LIST_HEAD(&tdma->dma_dev.channels); for (i = 0; i < cdata->nr_channels; i++) { struct tegra_dma_channel *tdc = &tdma->channels[i]; + int irq; tdc->chan_addr = tdma->base_addr + TEGRA_APBDMA_CHANNEL_BASE_ADD_OFFSET + (i * cdata->channel_reg_size); - res = platform_get_resource(pdev, IORESOURCE_IRQ, i); - if (!res) { - ret = -EINVAL; + irq = platform_get_irq(pdev, i); + if (irq < 0) { + ret = irq; dev_err(&pdev->dev, "No irq resource for chan %d\n", i); - goto err_irq; + goto err_pm_disable; } - tdc->irq = res->start; + snprintf(tdc->name, sizeof(tdc->name), "apbdma.%d", i); - ret = request_irq(tdc->irq, tegra_dma_isr, 0, tdc->name, tdc); + ret = devm_request_irq(&pdev->dev, irq, tegra_dma_isr, 0, + tdc->name, tdc); if (ret) { dev_err(&pdev->dev, "request_irq failed with err %d channel %d\n", ret, i); - goto err_irq; + goto err_pm_disable; } tdc->dma_chan.device = &tdma->dma_dev; @@ -1521,7 +1521,7 @@ static int tegra_dma_probe(struct platform_device *pdev) if (ret < 0) { dev_err(&pdev->dev, "Tegra20 APB DMA driver registration failed %d\n", ret); - goto err_irq; + goto err_pm_disable; } ret = of_dma_controller_register(pdev->dev.of_node, @@ -1538,13 +1538,7 @@ static int tegra_dma_probe(struct platform_device *pdev) err_unregister_dma_dev: dma_async_device_unregister(&tdma->dma_dev); -err_irq: - while (--i >= 0) { - struct tegra_dma_channel *tdc = &tdma->channels[i]; - - free_irq(tdc->irq, tdc); - } - +err_pm_disable: pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) tegra_dma_runtime_suspend(&pdev->dev); @@ -1554,16 +1548,9 @@ err_irq: static int tegra_dma_remove(struct platform_device *pdev) { struct tegra_dma *tdma = platform_get_drvdata(pdev); - int i; - struct tegra_dma_channel *tdc; dma_async_device_unregister(&tdma->dma_dev); - for (i = 0; i < tdma->chip_data->nr_channels; ++i) { - tdc = &tdma->channels[i]; - free_irq(tdc->irq, tdc); - } - pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) tegra_dma_runtime_suspend(&pdev->dev); From 3964293aecf9c600962c01a924475a205a715b68 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 9 Feb 2020 19:33:45 +0300 Subject: [PATCH 0766/4444] dmaengine: tegra-apb: Fix coding style problems This patch fixes few dozens of coding style problems reported by checkpatch and prettifies code where makes sense. Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Link: https://lore.kernel.org/r/20200209163356.6439-9-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 279 ++++++++++++++++++---------------- 1 file changed, 146 insertions(+), 133 deletions(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 9dc1fc236941..4cc01a82d983 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -59,7 +59,7 @@ #define TEGRA_APBDMA_STATUS_COUNT_MASK 0xFFFC #define TEGRA_APBDMA_CHAN_CSRE 0x00C -#define TEGRA_APBDMA_CHAN_CSRE_PAUSE (1 << 31) +#define TEGRA_APBDMA_CHAN_CSRE_PAUSE BIT(31) /* AHB memory address */ #define TEGRA_APBDMA_CHAN_AHBPTR 0x010 @@ -120,21 +120,21 @@ struct tegra_dma; * @support_separate_wcount_reg: Support separate word count register. */ struct tegra_dma_chip_data { - int nr_channels; - int channel_reg_size; - int max_dma_count; + unsigned int nr_channels; + unsigned int channel_reg_size; + unsigned int max_dma_count; bool support_channel_pause; bool support_separate_wcount_reg; }; /* DMA channel registers */ struct tegra_dma_channel_regs { - unsigned long csr; - unsigned long ahb_ptr; - unsigned long apb_ptr; - unsigned long ahb_seq; - unsigned long apb_seq; - unsigned long wcount; + u32 csr; + u32 ahb_ptr; + u32 apb_ptr; + u32 ahb_seq; + u32 apb_seq; + u32 wcount; }; /* @@ -168,7 +168,7 @@ struct tegra_dma_desc { struct list_head node; struct list_head tx_list; struct list_head cb_node; - int cb_count; + unsigned int cb_count; }; struct tegra_dma_channel; @@ -181,7 +181,7 @@ struct tegra_dma_channel { struct dma_chan dma_chan; char name[12]; bool config_init; - int id; + unsigned int id; void __iomem *chan_addr; spinlock_t lock; bool busy; @@ -201,7 +201,7 @@ struct tegra_dma_channel { /* Channel-slave specific configuration */ unsigned int slave_id; struct dma_slave_config dma_sconfig; - struct tegra_dma_channel_regs channel_reg; + struct tegra_dma_channel_regs channel_reg; }; /* tegra_dma: Tegra DMA specific information */ @@ -239,7 +239,7 @@ static inline u32 tdma_read(struct tegra_dma *tdma, u32 reg) } static inline void tdc_write(struct tegra_dma_channel *tdc, - u32 reg, u32 val) + u32 reg, u32 val) { writel(val, tdc->chan_addr + reg); } @@ -254,8 +254,8 @@ static inline struct tegra_dma_channel *to_tegra_dma_chan(struct dma_chan *dc) return container_of(dc, struct tegra_dma_channel, dma_chan); } -static inline struct tegra_dma_desc *txd_to_tegra_dma_desc( - struct dma_async_tx_descriptor *td) +static inline struct tegra_dma_desc * +txd_to_tegra_dma_desc(struct dma_async_tx_descriptor *td) { return container_of(td, struct tegra_dma_desc, txd); } @@ -270,8 +270,7 @@ static int tegra_dma_runtime_suspend(struct device *dev); static int tegra_dma_runtime_resume(struct device *dev); /* Get DMA desc from free list, if not there then allocate it. */ -static struct tegra_dma_desc *tegra_dma_desc_get( - struct tegra_dma_channel *tdc) +static struct tegra_dma_desc *tegra_dma_desc_get(struct tegra_dma_channel *tdc) { struct tegra_dma_desc *dma_desc; unsigned long flags; @@ -298,11 +297,12 @@ static struct tegra_dma_desc *tegra_dma_desc_get( dma_async_tx_descriptor_init(&dma_desc->txd, &tdc->dma_chan); dma_desc->txd.tx_submit = tegra_dma_tx_submit; dma_desc->txd.flags = 0; + return dma_desc; } static void tegra_dma_desc_put(struct tegra_dma_channel *tdc, - struct tegra_dma_desc *dma_desc) + struct tegra_dma_desc *dma_desc) { unsigned long flags; @@ -313,29 +313,29 @@ static void tegra_dma_desc_put(struct tegra_dma_channel *tdc, spin_unlock_irqrestore(&tdc->lock, flags); } -static struct tegra_dma_sg_req *tegra_dma_sg_req_get( - struct tegra_dma_channel *tdc) +static struct tegra_dma_sg_req * +tegra_dma_sg_req_get(struct tegra_dma_channel *tdc) { - struct tegra_dma_sg_req *sg_req = NULL; + struct tegra_dma_sg_req *sg_req; unsigned long flags; spin_lock_irqsave(&tdc->lock, flags); if (!list_empty(&tdc->free_sg_req)) { - sg_req = list_first_entry(&tdc->free_sg_req, - typeof(*sg_req), node); + sg_req = list_first_entry(&tdc->free_sg_req, typeof(*sg_req), + node); list_del(&sg_req->node); spin_unlock_irqrestore(&tdc->lock, flags); return sg_req; } spin_unlock_irqrestore(&tdc->lock, flags); - sg_req = kzalloc(sizeof(struct tegra_dma_sg_req), GFP_NOWAIT); + sg_req = kzalloc(sizeof(*sg_req), GFP_NOWAIT); return sg_req; } static int tegra_dma_slave_config(struct dma_chan *dc, - struct dma_slave_config *sconfig) + struct dma_slave_config *sconfig) { struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); @@ -352,11 +352,12 @@ static int tegra_dma_slave_config(struct dma_chan *dc, tdc->slave_id = sconfig->slave_id; } tdc->config_init = true; + return 0; } static void tegra_dma_global_pause(struct tegra_dma_channel *tdc, - bool wait_for_burst_complete) + bool wait_for_burst_complete) { struct tegra_dma *tdma = tdc->tdma; @@ -391,13 +392,13 @@ out: } static void tegra_dma_pause(struct tegra_dma_channel *tdc, - bool wait_for_burst_complete) + bool wait_for_burst_complete) { struct tegra_dma *tdma = tdc->tdma; if (tdma->chip_data->support_channel_pause) { tdc_write(tdc, TEGRA_APBDMA_CHAN_CSRE, - TEGRA_APBDMA_CHAN_CSRE_PAUSE); + TEGRA_APBDMA_CHAN_CSRE_PAUSE); if (wait_for_burst_complete) udelay(TEGRA_APBDMA_BURST_COMPLETE_TIME); } else { @@ -409,17 +410,15 @@ static void tegra_dma_resume(struct tegra_dma_channel *tdc) { struct tegra_dma *tdma = tdc->tdma; - if (tdma->chip_data->support_channel_pause) { + if (tdma->chip_data->support_channel_pause) tdc_write(tdc, TEGRA_APBDMA_CHAN_CSRE, 0); - } else { + else tegra_dma_global_resume(tdc); - } } static void tegra_dma_stop(struct tegra_dma_channel *tdc) { - u32 csr; - u32 status; + u32 csr, status; /* Disable interrupts */ csr = tdc_read(tdc, TEGRA_APBDMA_CHAN_CSR); @@ -440,7 +439,7 @@ static void tegra_dma_stop(struct tegra_dma_channel *tdc) } static void tegra_dma_start(struct tegra_dma_channel *tdc, - struct tegra_dma_sg_req *sg_req) + struct tegra_dma_sg_req *sg_req) { struct tegra_dma_channel_regs *ch_regs = &sg_req->ch_regs; @@ -454,11 +453,11 @@ static void tegra_dma_start(struct tegra_dma_channel *tdc, /* Start DMA */ tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, - ch_regs->csr | TEGRA_APBDMA_CSR_ENB); + ch_regs->csr | TEGRA_APBDMA_CSR_ENB); } static void tegra_dma_configure_for_next(struct tegra_dma_channel *tdc, - struct tegra_dma_sg_req *nsg_req) + struct tegra_dma_sg_req *nsg_req) { unsigned long status; @@ -492,9 +491,9 @@ static void tegra_dma_configure_for_next(struct tegra_dma_channel *tdc, tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, nsg_req->ch_regs.ahb_ptr); if (tdc->tdma->chip_data->support_separate_wcount_reg) tdc_write(tdc, TEGRA_APBDMA_CHAN_WCOUNT, - nsg_req->ch_regs.wcount); + nsg_req->ch_regs.wcount); tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, - nsg_req->ch_regs.csr | TEGRA_APBDMA_CSR_ENB); + nsg_req->ch_regs.csr | TEGRA_APBDMA_CSR_ENB); nsg_req->configured = true; nsg_req->words_xferred = 0; @@ -508,8 +507,7 @@ static void tdc_start_head_req(struct tegra_dma_channel *tdc) if (list_empty(&tdc->pending_sg_req)) return; - sg_req = list_first_entry(&tdc->pending_sg_req, - typeof(*sg_req), node); + sg_req = list_first_entry(&tdc->pending_sg_req, typeof(*sg_req), node); tegra_dma_start(tdc, sg_req); sg_req->configured = true; sg_req->words_xferred = 0; @@ -518,34 +516,35 @@ static void tdc_start_head_req(struct tegra_dma_channel *tdc) static void tdc_configure_next_head_desc(struct tegra_dma_channel *tdc) { - struct tegra_dma_sg_req *hsgreq; - struct tegra_dma_sg_req *hnsgreq; + struct tegra_dma_sg_req *hsgreq, *hnsgreq; if (list_empty(&tdc->pending_sg_req)) return; hsgreq = list_first_entry(&tdc->pending_sg_req, typeof(*hsgreq), node); if (!list_is_last(&hsgreq->node, &tdc->pending_sg_req)) { - hnsgreq = list_first_entry(&hsgreq->node, - typeof(*hnsgreq), node); + hnsgreq = list_first_entry(&hsgreq->node, typeof(*hnsgreq), + node); tegra_dma_configure_for_next(tdc, hnsgreq); } } -static inline int get_current_xferred_count(struct tegra_dma_channel *tdc, - struct tegra_dma_sg_req *sg_req, unsigned long status) +static inline unsigned int +get_current_xferred_count(struct tegra_dma_channel *tdc, + struct tegra_dma_sg_req *sg_req, + unsigned long status) { return sg_req->req_len - (status & TEGRA_APBDMA_STATUS_COUNT_MASK) - 4; } static void tegra_dma_abort_all(struct tegra_dma_channel *tdc) { - struct tegra_dma_sg_req *sgreq; struct tegra_dma_desc *dma_desc; + struct tegra_dma_sg_req *sgreq; while (!list_empty(&tdc->pending_sg_req)) { - sgreq = list_first_entry(&tdc->pending_sg_req, - typeof(*sgreq), node); + sgreq = list_first_entry(&tdc->pending_sg_req, typeof(*sgreq), + node); list_move_tail(&sgreq->node, &tdc->free_sg_req); if (sgreq->last_sg) { dma_desc = sgreq->dma_desc; @@ -555,7 +554,7 @@ static void tegra_dma_abort_all(struct tegra_dma_channel *tdc) /* Add in cb list if it is not there. */ if (!dma_desc->cb_count) list_add_tail(&dma_desc->cb_node, - &tdc->cb_desc); + &tdc->cb_desc); dma_desc->cb_count++; } } @@ -563,9 +562,10 @@ static void tegra_dma_abort_all(struct tegra_dma_channel *tdc) } static bool handle_continuous_head_request(struct tegra_dma_channel *tdc, - struct tegra_dma_sg_req *last_sg_req, bool to_terminate) + struct tegra_dma_sg_req *last_sg_req, + bool to_terminate) { - struct tegra_dma_sg_req *hsgreq = NULL; + struct tegra_dma_sg_req *hsgreq; if (list_empty(&tdc->pending_sg_req)) { dev_err(tdc2dev(tdc), "DMA is running without req\n"); @@ -589,14 +589,15 @@ static bool handle_continuous_head_request(struct tegra_dma_channel *tdc, /* Configure next request */ if (!to_terminate) tdc_configure_next_head_desc(tdc); + return true; } static void handle_once_dma_done(struct tegra_dma_channel *tdc, - bool to_terminate) + bool to_terminate) { - struct tegra_dma_sg_req *sgreq; struct tegra_dma_desc *dma_desc; + struct tegra_dma_sg_req *sgreq; tdc->busy = false; sgreq = list_first_entry(&tdc->pending_sg_req, typeof(*sgreq), node); @@ -622,10 +623,10 @@ static void handle_once_dma_done(struct tegra_dma_channel *tdc, } static void handle_cont_sngl_cycle_dma_done(struct tegra_dma_channel *tdc, - bool to_terminate) + bool to_terminate) { - struct tegra_dma_sg_req *sgreq; struct tegra_dma_desc *dma_desc; + struct tegra_dma_sg_req *sgreq; bool st; sgreq = list_first_entry(&tdc->pending_sg_req, typeof(*sgreq), node); @@ -657,13 +658,13 @@ static void tegra_dma_tasklet(unsigned long data) struct tegra_dma_channel *tdc = (struct tegra_dma_channel *)data; struct dmaengine_desc_callback cb; struct tegra_dma_desc *dma_desc; + unsigned int cb_count; unsigned long flags; - int cb_count; spin_lock_irqsave(&tdc->lock, flags); while (!list_empty(&tdc->cb_desc)) { - dma_desc = list_first_entry(&tdc->cb_desc, - typeof(*dma_desc), cb_node); + dma_desc = list_first_entry(&tdc->cb_desc, typeof(*dma_desc), + cb_node); list_del(&dma_desc->cb_node); dmaengine_desc_get_callback(&dma_desc->txd, &cb); cb_count = dma_desc->cb_count; @@ -681,8 +682,8 @@ static void tegra_dma_tasklet(unsigned long data) static irqreturn_t tegra_dma_isr(int irq, void *dev_id) { struct tegra_dma_channel *tdc = dev_id; - unsigned long status; unsigned long flags; + u32 status; spin_lock_irqsave(&tdc->lock, flags); @@ -697,8 +698,9 @@ static irqreturn_t tegra_dma_isr(int irq, void *dev_id) } spin_unlock_irqrestore(&tdc->lock, flags); - dev_info(tdc2dev(tdc), - "Interrupt already served status 0x%08lx\n", status); + dev_info(tdc2dev(tdc), "Interrupt already served status 0x%08x\n", + status); + return IRQ_NONE; } @@ -714,6 +716,7 @@ static dma_cookie_t tegra_dma_tx_submit(struct dma_async_tx_descriptor *txd) cookie = dma_cookie_assign(&dma_desc->txd); list_splice_tail_init(&dma_desc->tx_list, &tdc->pending_sg_req); spin_unlock_irqrestore(&tdc->lock, flags); + return cookie; } @@ -747,11 +750,10 @@ end: static int tegra_dma_terminate_all(struct dma_chan *dc) { struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); - struct tegra_dma_sg_req *sgreq; struct tegra_dma_desc *dma_desc; + struct tegra_dma_sg_req *sgreq; unsigned long flags; - unsigned long status; - unsigned long wcount; + u32 status, wcount; bool was_busy; spin_lock_irqsave(&tdc->lock, flags); @@ -781,8 +783,8 @@ static int tegra_dma_terminate_all(struct dma_chan *dc) tegra_dma_stop(tdc); if (!list_empty(&tdc->pending_sg_req) && was_busy) { - sgreq = list_first_entry(&tdc->pending_sg_req, - typeof(*sgreq), node); + sgreq = list_first_entry(&tdc->pending_sg_req, typeof(*sgreq), + node); sgreq->dma_desc->bytes_transferred += get_current_xferred_count(tdc, sgreq, wcount); } @@ -792,12 +794,13 @@ skip_dma_stop: tegra_dma_abort_all(tdc); while (!list_empty(&tdc->cb_desc)) { - dma_desc = list_first_entry(&tdc->cb_desc, - typeof(*dma_desc), cb_node); + dma_desc = list_first_entry(&tdc->cb_desc, typeof(*dma_desc), + cb_node); list_del(&dma_desc->cb_node); dma_desc->cb_count = 0; } spin_unlock_irqrestore(&tdc->lock, flags); + return 0; } @@ -811,7 +814,7 @@ static void tegra_dma_synchronize(struct dma_chan *dc) static unsigned int tegra_dma_sg_bytes_xferred(struct tegra_dma_channel *tdc, struct tegra_dma_sg_req *sg_req) { - unsigned long status, wcount = 0; + u32 status, wcount = 0; if (!list_is_first(&sg_req->node, &tdc->pending_sg_req)) return 0; @@ -868,7 +871,8 @@ static unsigned int tegra_dma_sg_bytes_xferred(struct tegra_dma_channel *tdc, } static enum dma_status tegra_dma_tx_status(struct dma_chan *dc, - dma_cookie_t cookie, struct dma_tx_state *txstate) + dma_cookie_t cookie, + struct dma_tx_state *txstate) { struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); struct tegra_dma_desc *dma_desc; @@ -915,11 +919,12 @@ found: trace_tegra_dma_tx_status(&tdc->dma_chan, cookie, txstate); spin_unlock_irqrestore(&tdc->lock, flags); + return ret; } -static inline int get_bus_width(struct tegra_dma_channel *tdc, - enum dma_slave_buswidth slave_bw) +static inline unsigned int get_bus_width(struct tegra_dma_channel *tdc, + enum dma_slave_buswidth slave_bw) { switch (slave_bw) { case DMA_SLAVE_BUSWIDTH_1_BYTE: @@ -932,16 +937,17 @@ static inline int get_bus_width(struct tegra_dma_channel *tdc, return TEGRA_APBDMA_APBSEQ_BUS_WIDTH_64; default: dev_warn(tdc2dev(tdc), - "slave bw is not supported, using 32bits\n"); + "slave bw is not supported, using 32bits\n"); return TEGRA_APBDMA_APBSEQ_BUS_WIDTH_32; } } -static inline int get_burst_size(struct tegra_dma_channel *tdc, - u32 burst_size, enum dma_slave_buswidth slave_bw, int len) +static inline unsigned int get_burst_size(struct tegra_dma_channel *tdc, + u32 burst_size, + enum dma_slave_buswidth slave_bw, + u32 len) { - int burst_byte; - int burst_ahb_width; + unsigned int burst_byte, burst_ahb_width; /* * burst_size from client is in terms of the bus_width. @@ -968,9 +974,12 @@ static inline int get_burst_size(struct tegra_dma_channel *tdc, } static int get_transfer_param(struct tegra_dma_channel *tdc, - enum dma_transfer_direction direction, unsigned long *apb_addr, - unsigned long *apb_seq, unsigned long *csr, unsigned int *burst_size, - enum dma_slave_buswidth *slave_bw) + enum dma_transfer_direction direction, + u32 *apb_addr, + u32 *apb_seq, + u32 *csr, + unsigned int *burst_size, + enum dma_slave_buswidth *slave_bw) { switch (direction) { case DMA_MEM_TO_DEV: @@ -991,13 +1000,15 @@ static int get_transfer_param(struct tegra_dma_channel *tdc, default: dev_err(tdc2dev(tdc), "DMA direction is not supported\n"); - return -EINVAL; + break; } + return -EINVAL; } static void tegra_dma_prep_wcount(struct tegra_dma_channel *tdc, - struct tegra_dma_channel_regs *ch_regs, u32 len) + struct tegra_dma_channel_regs *ch_regs, + u32 len) { u32 len_field = (len - 4) & 0xFFFC; @@ -1007,20 +1018,23 @@ static void tegra_dma_prep_wcount(struct tegra_dma_channel *tdc, ch_regs->csr |= len_field; } -static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg( - struct dma_chan *dc, struct scatterlist *sgl, unsigned int sg_len, - enum dma_transfer_direction direction, unsigned long flags, - void *context) +static struct dma_async_tx_descriptor * +tegra_dma_prep_slave_sg(struct dma_chan *dc, + struct scatterlist *sgl, + unsigned int sg_len, + enum dma_transfer_direction direction, + unsigned long flags, + void *context) { struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); - struct tegra_dma_desc *dma_desc; - unsigned int i; - struct scatterlist *sg; - unsigned long csr, ahb_seq, apb_ptr, apb_seq; - struct list_head req_list; - struct tegra_dma_sg_req *sg_req = NULL; - u32 burst_size; + struct tegra_dma_sg_req *sg_req = NULL; + u32 csr, ahb_seq, apb_ptr, apb_seq; enum dma_slave_buswidth slave_bw; + struct tegra_dma_desc *dma_desc; + struct list_head req_list; + struct scatterlist *sg; + unsigned int burst_size; + unsigned int i; if (!tdc->config_init) { dev_err(tdc2dev(tdc), "DMA channel is not configured\n"); @@ -1032,7 +1046,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg( } if (get_transfer_param(tdc, direction, &apb_ptr, &apb_seq, &csr, - &burst_size, &slave_bw) < 0) + &burst_size, &slave_bw) < 0) return NULL; INIT_LIST_HEAD(&req_list); @@ -1078,7 +1092,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg( len = sg_dma_len(sg); if ((len & 3) || (mem & 3) || - (len > tdc->tdma->chip_data->max_dma_count)) { + len > tdc->tdma->chip_data->max_dma_count) { dev_err(tdc2dev(tdc), "DMA length/memory address is not supported\n"); tegra_dma_desc_put(tdc, dma_desc); @@ -1130,20 +1144,21 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg( return &dma_desc->txd; } -static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( - struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_len, - size_t period_len, enum dma_transfer_direction direction, - unsigned long flags) +static struct dma_async_tx_descriptor * +tegra_dma_prep_dma_cyclic(struct dma_chan *dc, dma_addr_t buf_addr, + size_t buf_len, + size_t period_len, + enum dma_transfer_direction direction, + unsigned long flags) { struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); - struct tegra_dma_desc *dma_desc = NULL; struct tegra_dma_sg_req *sg_req = NULL; - unsigned long csr, ahb_seq, apb_ptr, apb_seq; - int len; - size_t remain_len; - dma_addr_t mem = buf_addr; - u32 burst_size; + u32 csr, ahb_seq, apb_ptr, apb_seq; enum dma_slave_buswidth slave_bw; + struct tegra_dma_desc *dma_desc; + dma_addr_t mem = buf_addr; + unsigned int burst_size; + size_t len, remain_len; if (!buf_len || !period_len) { dev_err(tdc2dev(tdc), "Invalid buffer/period len\n"); @@ -1177,13 +1192,13 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( len = period_len; if ((len & 3) || (buf_addr & 3) || - (len > tdc->tdma->chip_data->max_dma_count)) { + len > tdc->tdma->chip_data->max_dma_count) { dev_err(tdc2dev(tdc), "Req len/mem address is not correct\n"); return NULL; } if (get_transfer_param(tdc, direction, &apb_ptr, &apb_seq, &csr, - &burst_size, &slave_bw) < 0) + &burst_size, &slave_bw) < 0) return NULL; ahb_seq = TEGRA_APBDMA_AHBSEQ_INTR_ENB; @@ -1307,8 +1322,8 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc) tdc->isr_handler = NULL; while (!list_empty(&dma_desc_list)) { - dma_desc = list_first_entry(&dma_desc_list, - typeof(*dma_desc), node); + dma_desc = list_first_entry(&dma_desc_list, typeof(*dma_desc), + node); list_del(&dma_desc->node); kfree(dma_desc); } @@ -1327,8 +1342,8 @@ static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec, struct of_dma *ofdma) { struct tegra_dma *tdma = ofdma->of_dma_data; - struct dma_chan *chan; struct tegra_dma_channel *tdc; + struct dma_chan *chan; if (dma_spec->args[0] > TEGRA_APBDMA_CSR_REQ_SEL_MASK) { dev_err(tdma->dev, "Invalid slave id: %d\n", dma_spec->args[0]); @@ -1383,20 +1398,16 @@ static const struct tegra_dma_chip_data tegra148_dma_chip_data = { static int tegra_dma_probe(struct platform_device *pdev) { - struct tegra_dma *tdma; - int ret; - int i; const struct tegra_dma_chip_data *cdata; + struct tegra_dma *tdma; + unsigned int i; + size_t size; + int ret; cdata = of_device_get_match_data(&pdev->dev); - if (!cdata) { - dev_err(&pdev->dev, "Error: No device match data found\n"); - return -ENODEV; - } + size = struct_size(tdma, channels, cdata->nr_channels); - tdma = devm_kzalloc(&pdev->dev, - struct_size(tdma, channels, cdata->nr_channels), - GFP_KERNEL); + tdma = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); if (!tdma) return -ENOMEM; @@ -1428,10 +1439,8 @@ static int tegra_dma_probe(struct platform_device *pdev) else ret = pm_runtime_get_sync(&pdev->dev); - if (ret < 0) { - pm_runtime_disable(&pdev->dev); - return ret; - } + if (ret < 0) + goto err_pm_disable; /* Reset DMA controller */ reset_control_assert(tdma->rst); @@ -1474,13 +1483,13 @@ static int tegra_dma_probe(struct platform_device *pdev) tdc->dma_chan.device = &tdma->dma_dev; dma_cookie_init(&tdc->dma_chan); list_add_tail(&tdc->dma_chan.device_node, - &tdma->dma_dev.channels); + &tdma->dma_dev.channels); tdc->tdma = tdma; tdc->id = i; tdc->slave_id = TEGRA_APBDMA_SLAVE_ID_INVALID; tasklet_init(&tdc->tasklet, tegra_dma_tasklet, - (unsigned long)tdc); + (unsigned long)tdc); spin_lock_init(&tdc->lock); INIT_LIST_HEAD(&tdc->pending_sg_req); @@ -1532,16 +1541,19 @@ static int tegra_dma_probe(struct platform_device *pdev) goto err_unregister_dma_dev; } - dev_info(&pdev->dev, "Tegra20 APB DMA driver register %d channels\n", - cdata->nr_channels); + dev_info(&pdev->dev, "Tegra20 APB DMA driver registered %u channels\n", + cdata->nr_channels); + return 0; err_unregister_dma_dev: dma_async_device_unregister(&tdma->dma_dev); + err_pm_disable: pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) tegra_dma_runtime_suspend(&pdev->dev); + return ret; } @@ -1561,7 +1573,7 @@ static int tegra_dma_remove(struct platform_device *pdev) static int tegra_dma_runtime_suspend(struct device *dev) { struct tegra_dma *tdma = dev_get_drvdata(dev); - int i; + unsigned int i; tdma->reg_gen = tdma_read(tdma, TEGRA_APBDMA_GENERAL); for (i = 0; i < tdma->chip_data->nr_channels; i++) { @@ -1590,7 +1602,8 @@ static int tegra_dma_runtime_suspend(struct device *dev) static int tegra_dma_runtime_resume(struct device *dev) { struct tegra_dma *tdma = dev_get_drvdata(dev); - int i, ret; + unsigned int i; + int ret; ret = clk_prepare_enable(tdma->dma_clk); if (ret < 0) { @@ -1618,7 +1631,7 @@ static int tegra_dma_runtime_resume(struct device *dev) tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBSEQ, ch_reg->ahb_seq); tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, ch_reg->ahb_ptr); tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, - (ch_reg->csr & ~TEGRA_APBDMA_CSR_ENB)); + ch_reg->csr & ~TEGRA_APBDMA_CSR_ENB); } return 0; From 14c63abfab4ac0cef7a3ddfecfe51617ac929b3c Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 9 Feb 2020 19:33:46 +0300 Subject: [PATCH 0767/4444] dmaengine: tegra-apb: Remove unneeded initialization of tdc->config_init There is no need to re-initialize the already initialized variables. The tdc->config_init=false after driver's probe and after channel's freeing, so there is no need to re-initialize it on the channel's allocation. Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Link: https://lore.kernel.org/r/20200209163356.6439-10-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 4cc01a82d983..49b2d3c1f935 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -1288,7 +1288,6 @@ static int tegra_dma_alloc_chan_resources(struct dma_chan *dc) int ret; dma_cookie_init(&tdc->dma_chan); - tdc->config_init = false; ret = pm_runtime_get_sync(tdma->dev); if (ret < 0) From a75013a5a173c7b595de716314dd40091cb75f90 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 9 Feb 2020 19:33:47 +0300 Subject: [PATCH 0768/4444] dmaengine: tegra-apb: Remove assumptions about unavailable runtime PM The runtime PM is always available on all Tegra SoCs since the commit 40b2bb1b132a ("ARM: tegra: enforce PM requirement"), so there is no need to handle the case of unavailable RPM in the code anymore. Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Link: https://lore.kernel.org/r/20200209163356.6439-11-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 49b2d3c1f935..4d909a79839f 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -1433,11 +1433,8 @@ static int tegra_dma_probe(struct platform_device *pdev) spin_lock_init(&tdma->global_lock); pm_runtime_enable(&pdev->dev); - if (!pm_runtime_enabled(&pdev->dev)) - ret = tegra_dma_runtime_resume(&pdev->dev); - else - ret = pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) goto err_pm_disable; @@ -1550,8 +1547,6 @@ err_unregister_dma_dev: err_pm_disable: pm_runtime_disable(&pdev->dev); - if (!pm_runtime_status_suspended(&pdev->dev)) - tegra_dma_runtime_suspend(&pdev->dev); return ret; } @@ -1561,10 +1556,7 @@ static int tegra_dma_remove(struct platform_device *pdev) struct tegra_dma *tdma = platform_get_drvdata(pdev); dma_async_device_unregister(&tdma->dma_dev); - pm_runtime_disable(&pdev->dev); - if (!pm_runtime_status_suspended(&pdev->dev)) - tegra_dma_runtime_suspend(&pdev->dev); return 0; } From d8396c0576c6919a60bdb573ab3cd5947243d140 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 9 Feb 2020 19:33:48 +0300 Subject: [PATCH 0769/4444] dmaengine: tegra-apb: Remove duplicated pending_sg_req checks There are few place in the code which check whether pending_sg_req list is empty despite of the check already being done. Let's remove the duplicated checks to keep code clean. Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Link: https://lore.kernel.org/r/20200209163356.6439-12-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 4d909a79839f..8d655715da68 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -504,9 +504,6 @@ static void tdc_start_head_req(struct tegra_dma_channel *tdc) { struct tegra_dma_sg_req *sg_req; - if (list_empty(&tdc->pending_sg_req)) - return; - sg_req = list_first_entry(&tdc->pending_sg_req, typeof(*sg_req), node); tegra_dma_start(tdc, sg_req); sg_req->configured = true; @@ -518,9 +515,6 @@ static void tdc_configure_next_head_desc(struct tegra_dma_channel *tdc) { struct tegra_dma_sg_req *hsgreq, *hnsgreq; - if (list_empty(&tdc->pending_sg_req)) - return; - hsgreq = list_first_entry(&tdc->pending_sg_req, typeof(*hsgreq), node); if (!list_is_last(&hsgreq->node, &tdc->pending_sg_req)) { hnsgreq = list_first_entry(&hsgreq->node, typeof(*hnsgreq), @@ -567,12 +561,6 @@ static bool handle_continuous_head_request(struct tegra_dma_channel *tdc, { struct tegra_dma_sg_req *hsgreq; - if (list_empty(&tdc->pending_sg_req)) { - dev_err(tdc2dev(tdc), "DMA is running without req\n"); - tegra_dma_stop(tdc); - return false; - } - /* * Check that head req on list should be in flight. * If it is not in flight then abort transfer as From 84a3f375eea984652bc2889c6b0a1ca7f849eefa Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 9 Feb 2020 19:33:49 +0300 Subject: [PATCH 0770/4444] dmaengine: tegra-apb: Keep clock enabled only during of DMA transfer It's a bit impractical to enable hardware's clock at the time of DMA channel's allocation because most of DMA client drivers allocate DMA channel at the time of the driver's probing, and thus, DMA clock is kept always-enabled in practice, defeating the whole purpose of runtime PM. Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Link: https://lore.kernel.org/r/20200209163356.6439-13-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 36 ++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 8d655715da68..652b63c85df3 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -569,6 +569,7 @@ static bool handle_continuous_head_request(struct tegra_dma_channel *tdc, hsgreq = list_first_entry(&tdc->pending_sg_req, typeof(*hsgreq), node); if (!hsgreq->configured) { tegra_dma_stop(tdc); + pm_runtime_put(tdc->tdma->dev); dev_err(tdc2dev(tdc), "Error in DMA transfer, aborting DMA\n"); tegra_dma_abort_all(tdc); return false; @@ -604,9 +605,14 @@ static void handle_once_dma_done(struct tegra_dma_channel *tdc, list_add_tail(&sgreq->node, &tdc->free_sg_req); /* Do not start DMA if it is going to be terminate */ - if (to_terminate || list_empty(&tdc->pending_sg_req)) + if (to_terminate) return; + if (list_empty(&tdc->pending_sg_req)) { + pm_runtime_put(tdc->tdma->dev); + return; + } + tdc_start_head_req(tdc); } @@ -712,6 +718,7 @@ static void tegra_dma_issue_pending(struct dma_chan *dc) { struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); unsigned long flags; + int err; spin_lock_irqsave(&tdc->lock, flags); if (list_empty(&tdc->pending_sg_req)) { @@ -719,6 +726,12 @@ static void tegra_dma_issue_pending(struct dma_chan *dc) goto end; } if (!tdc->busy) { + err = pm_runtime_get_sync(tdc->tdma->dev); + if (err < 0) { + dev_err(tdc2dev(tdc), "Failed to enable DMA\n"); + goto end; + } + tdc_start_head_req(tdc); /* Continuous single mode: Configure next req */ @@ -778,6 +791,8 @@ static int tegra_dma_terminate_all(struct dma_chan *dc) } tegra_dma_resume(tdc); + pm_runtime_put(tdc->tdma->dev); + skip_dma_stop: tegra_dma_abort_all(tdc); @@ -1272,22 +1287,15 @@ tegra_dma_prep_dma_cyclic(struct dma_chan *dc, dma_addr_t buf_addr, static int tegra_dma_alloc_chan_resources(struct dma_chan *dc) { struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); - struct tegra_dma *tdma = tdc->tdma; - int ret; dma_cookie_init(&tdc->dma_chan); - ret = pm_runtime_get_sync(tdma->dev); - if (ret < 0) - return ret; - return 0; } static void tegra_dma_free_chan_resources(struct dma_chan *dc) { struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); - struct tegra_dma *tdma = tdc->tdma; struct tegra_dma_desc *dma_desc; struct tegra_dma_sg_req *sg_req; struct list_head dma_desc_list; @@ -1320,7 +1328,6 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc) list_del(&sg_req->node); kfree(sg_req); } - pm_runtime_put(tdma->dev); tdc->slave_id = TEGRA_APBDMA_SLAVE_ID_INVALID; } @@ -1420,6 +1427,11 @@ static int tegra_dma_probe(struct platform_device *pdev) spin_lock_init(&tdma->global_lock); + ret = clk_prepare(tdma->dma_clk); + if (ret) + return ret; + + pm_runtime_irq_safe(&pdev->dev); pm_runtime_enable(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev); @@ -1535,6 +1547,7 @@ err_unregister_dma_dev: err_pm_disable: pm_runtime_disable(&pdev->dev); + clk_unprepare(tdma->dma_clk); return ret; } @@ -1545,6 +1558,7 @@ static int tegra_dma_remove(struct platform_device *pdev) dma_async_device_unregister(&tdma->dma_dev); pm_runtime_disable(&pdev->dev); + clk_unprepare(tdma->dma_clk); return 0; } @@ -1573,7 +1587,7 @@ static int tegra_dma_runtime_suspend(struct device *dev) TEGRA_APBDMA_CHAN_WCOUNT); } - clk_disable_unprepare(tdma->dma_clk); + clk_disable(tdma->dma_clk); return 0; } @@ -1584,7 +1598,7 @@ static int tegra_dma_runtime_resume(struct device *dev) unsigned int i; int ret; - ret = clk_prepare_enable(tdma->dma_clk); + ret = clk_enable(tdma->dma_clk); if (ret < 0) { dev_err(dev, "clk_enable failed: %d\n", ret); return ret; From dcb394b6b5fb7fdaac258115ec77e8faff19d2b9 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 9 Feb 2020 19:33:50 +0300 Subject: [PATCH 0771/4444] dmaengine: tegra-apb: Clean up suspend-resume It is enough to check whether hardware is busy on suspend and to reset it across of suspend-resume because: 1. Channel's configuration is fully re-programmed on each DMA transfer anyways. 2. Context save-restore of an active channel won't end up well without pausing transfer prior to the context's saving, but note that every channel shall be idling at the time of suspend, so save-restore is not needed at all. 3. The only case where context save-restore may be useful is when channel is in a paused state during suspend. But channel's pausing could be supported only on Tegra114+ and this functionality wasn't implemented by the driver for years now because there is no need for it in upstream kernel. Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Link: https://lore.kernel.org/r/20200209163356.6439-14-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 134 +++++++++++++++++----------------- 1 file changed, 68 insertions(+), 66 deletions(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 652b63c85df3..fd1cfe205826 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -221,9 +221,6 @@ struct tegra_dma { */ u32 global_pause_count; - /* Some register need to be cache before suspend */ - u32 reg_gen; - /* Last member of the structure */ struct tegra_dma_channel channels[0]; }; @@ -1390,6 +1387,36 @@ static const struct tegra_dma_chip_data tegra148_dma_chip_data = { .support_separate_wcount_reg = true, }; +static int tegra_dma_init_hw(struct tegra_dma *tdma) +{ + int err; + + err = reset_control_assert(tdma->rst); + if (err) { + dev_err(tdma->dev, "failed to assert reset: %d\n", err); + return err; + } + + err = clk_enable(tdma->dma_clk); + if (err) { + dev_err(tdma->dev, "failed to enable clk: %d\n", err); + return err; + } + + /* reset DMA controller */ + udelay(2); + reset_control_deassert(tdma->rst); + + /* enable global DMA registers */ + tdma_write(tdma, TEGRA_APBDMA_GENERAL, TEGRA_APBDMA_GENERAL_ENABLE); + tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0); + tdma_write(tdma, TEGRA_APBDMA_IRQ_MASK_SET, 0xFFFFFFFF); + + clk_disable(tdma->dma_clk); + + return 0; +} + static int tegra_dma_probe(struct platform_device *pdev) { const struct tegra_dma_chip_data *cdata; @@ -1431,25 +1458,13 @@ static int tegra_dma_probe(struct platform_device *pdev) if (ret) return ret; + ret = tegra_dma_init_hw(tdma); + if (ret) + goto err_clk_unprepare; + pm_runtime_irq_safe(&pdev->dev); pm_runtime_enable(&pdev->dev); - ret = pm_runtime_get_sync(&pdev->dev); - if (ret < 0) - goto err_pm_disable; - - /* Reset DMA controller */ - reset_control_assert(tdma->rst); - udelay(2); - reset_control_deassert(tdma->rst); - - /* Enable global DMA registers */ - tdma_write(tdma, TEGRA_APBDMA_GENERAL, TEGRA_APBDMA_GENERAL_ENABLE); - tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0); - tdma_write(tdma, TEGRA_APBDMA_IRQ_MASK_SET, 0xFFFFFFFFul); - - pm_runtime_put(&pdev->dev); - INIT_LIST_HEAD(&tdma->dma_dev.channels); for (i = 0; i < cdata->nr_channels; i++) { struct tegra_dma_channel *tdc = &tdma->channels[i]; @@ -1547,6 +1562,8 @@ err_unregister_dma_dev: err_pm_disable: pm_runtime_disable(&pdev->dev); + +err_clk_unprepare: clk_unprepare(tdma->dma_clk); return ret; @@ -1566,26 +1583,6 @@ static int tegra_dma_remove(struct platform_device *pdev) static int tegra_dma_runtime_suspend(struct device *dev) { struct tegra_dma *tdma = dev_get_drvdata(dev); - unsigned int i; - - tdma->reg_gen = tdma_read(tdma, TEGRA_APBDMA_GENERAL); - for (i = 0; i < tdma->chip_data->nr_channels; i++) { - struct tegra_dma_channel *tdc = &tdma->channels[i]; - struct tegra_dma_channel_regs *ch_reg = &tdc->channel_reg; - - /* Only save the state of DMA channels that are in use */ - if (!tdc->config_init) - continue; - - ch_reg->csr = tdc_read(tdc, TEGRA_APBDMA_CHAN_CSR); - ch_reg->ahb_ptr = tdc_read(tdc, TEGRA_APBDMA_CHAN_AHBPTR); - ch_reg->apb_ptr = tdc_read(tdc, TEGRA_APBDMA_CHAN_APBPTR); - ch_reg->ahb_seq = tdc_read(tdc, TEGRA_APBDMA_CHAN_AHBSEQ); - ch_reg->apb_seq = tdc_read(tdc, TEGRA_APBDMA_CHAN_APBSEQ); - if (tdma->chip_data->support_separate_wcount_reg) - ch_reg->wcount = tdc_read(tdc, - TEGRA_APBDMA_CHAN_WCOUNT); - } clk_disable(tdma->dma_clk); @@ -1595,46 +1592,51 @@ static int tegra_dma_runtime_suspend(struct device *dev) static int tegra_dma_runtime_resume(struct device *dev) { struct tegra_dma *tdma = dev_get_drvdata(dev); + + return clk_enable(tdma->dma_clk); +} + +static int __maybe_unused tegra_dma_dev_suspend(struct device *dev) +{ + struct tegra_dma *tdma = dev_get_drvdata(dev); + unsigned long flags; unsigned int i; - int ret; - - ret = clk_enable(tdma->dma_clk); - if (ret < 0) { - dev_err(dev, "clk_enable failed: %d\n", ret); - return ret; - } - - tdma_write(tdma, TEGRA_APBDMA_GENERAL, tdma->reg_gen); - tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0); - tdma_write(tdma, TEGRA_APBDMA_IRQ_MASK_SET, 0xFFFFFFFFul); + bool busy; for (i = 0; i < tdma->chip_data->nr_channels; i++) { struct tegra_dma_channel *tdc = &tdma->channels[i]; - struct tegra_dma_channel_regs *ch_reg = &tdc->channel_reg; - /* Only restore the state of DMA channels that are in use */ - if (!tdc->config_init) - continue; + tasklet_kill(&tdc->tasklet); - if (tdma->chip_data->support_separate_wcount_reg) - tdc_write(tdc, TEGRA_APBDMA_CHAN_WCOUNT, - ch_reg->wcount); - tdc_write(tdc, TEGRA_APBDMA_CHAN_APBSEQ, ch_reg->apb_seq); - tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, ch_reg->apb_ptr); - tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBSEQ, ch_reg->ahb_seq); - tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, ch_reg->ahb_ptr); - tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, - ch_reg->csr & ~TEGRA_APBDMA_CSR_ENB); + spin_lock_irqsave(&tdc->lock, flags); + busy = tdc->busy; + spin_unlock_irqrestore(&tdc->lock, flags); + + if (busy) { + dev_err(tdma->dev, "channel %u busy\n", i); + return -EBUSY; + } } - return 0; + return pm_runtime_force_suspend(dev); +} + +static int __maybe_unused tegra_dma_dev_resume(struct device *dev) +{ + struct tegra_dma *tdma = dev_get_drvdata(dev); + int err; + + err = tegra_dma_init_hw(tdma); + if (err) + return err; + + return pm_runtime_force_resume(dev); } static const struct dev_pm_ops tegra_dma_dev_pm_ops = { SET_RUNTIME_PM_OPS(tegra_dma_runtime_suspend, tegra_dma_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + SET_SYSTEM_SLEEP_PM_OPS(tegra_dma_dev_suspend, tegra_dma_dev_resume) }; static const struct of_device_id tegra_dma_of_match[] = { From 16e2b3e24bf14480304b34c989cc3b0be2b26288 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 9 Feb 2020 19:33:51 +0300 Subject: [PATCH 0772/4444] dmaengine: tegra-apb: Add missing of_dma_controller_free The DMA controller shall be released on driver's removal. Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Link: https://lore.kernel.org/r/20200209163356.6439-15-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index fd1cfe205826..043e58272caa 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -1573,6 +1573,7 @@ static int tegra_dma_remove(struct platform_device *pdev) { struct tegra_dma *tdma = platform_get_drvdata(pdev); + of_dma_controller_free(pdev->dev.of_node); dma_async_device_unregister(&tdma->dma_dev); pm_runtime_disable(&pdev->dev); clk_unprepare(tdma->dma_clk); From 703b70f4dc3d22b4ab587e0ca424b974a4489db4 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 9 Feb 2020 19:33:52 +0300 Subject: [PATCH 0773/4444] dmaengine: tegra-apb: Allow to compile as a loadable kernel module The driver's removal was fixed by a recent commit and module load/unload is working well now, tested on Tegra30. Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Link: https://lore.kernel.org/r/20200209163356.6439-16-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 5142da401db3..98daf3aafdcc 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -616,7 +616,7 @@ config TXX9_DMAC integrated in chips such as the Toshiba TX4927/38/39. config TEGRA20_APB_DMA - bool "NVIDIA Tegra20 APB DMA support" + tristate "NVIDIA Tegra20 APB DMA support" depends on ARCH_TEGRA select DMA_ENGINE help From 3962a245099637503a879b0b1c089895694406b5 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 9 Feb 2020 19:33:53 +0300 Subject: [PATCH 0774/4444] dmaengine: tegra-apb: Remove MODULE_ALIAS Tegra APB DMA driver is an Open Firmware driver, so it uses OF alias naming scheme which overrides MODULE_ALIAS, meaning that MODULE_ALIAS does nothing and could be removed safely. Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Link: https://lore.kernel.org/r/20200209163356.6439-17-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 043e58272caa..85a37152a66d 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -1670,7 +1670,6 @@ static struct platform_driver tegra_dmac_driver = { module_platform_driver(tegra_dmac_driver); -MODULE_ALIAS("platform:tegra20-apbdma"); MODULE_DESCRIPTION("NVIDIA Tegra APB DMA Controller driver"); MODULE_AUTHOR("Laxman Dewangan "); MODULE_LICENSE("GPL v2"); From 6c41ac96ad9217fe2a6f31c9dcc31b97365b21f6 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 9 Feb 2020 19:33:54 +0300 Subject: [PATCH 0775/4444] dmaengine: tegra-apb: Support COMPILE_TEST There is nothing arch-specific in the driver's code, so let's enable compile-testing for the driver. Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Link: https://lore.kernel.org/r/20200209163356.6439-18-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 98daf3aafdcc..7fc725d928b2 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -617,7 +617,7 @@ config TXX9_DMAC config TEGRA20_APB_DMA tristate "NVIDIA Tegra20 APB DMA support" - depends on ARCH_TEGRA + depends on ARCH_TEGRA || COMPILE_TEST select DMA_ENGINE help Support for the NVIDIA Tegra20 APB DMA controller driver. The From f261f1cd91efe36e932996efddaa7efffbb62831 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 9 Feb 2020 19:33:55 +0300 Subject: [PATCH 0776/4444] dmaengine: tegra-apb: Remove unused function argument Remove unused function argument from handle_continuous_head_request(). Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Link: https://lore.kernel.org/r/20200209163356.6439-19-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 85a37152a66d..3265eb8e5d91 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -553,7 +553,6 @@ static void tegra_dma_abort_all(struct tegra_dma_channel *tdc) } static bool handle_continuous_head_request(struct tegra_dma_channel *tdc, - struct tegra_dma_sg_req *last_sg_req, bool to_terminate) { struct tegra_dma_sg_req *hsgreq; @@ -638,7 +637,7 @@ static void handle_cont_sngl_cycle_dma_done(struct tegra_dma_channel *tdc, if (!list_is_last(&sgreq->node, &tdc->pending_sg_req)) { list_move_tail(&sgreq->node, &tdc->pending_sg_req); sgreq->configured = false; - st = handle_continuous_head_request(tdc, sgreq, to_terminate); + st = handle_continuous_head_request(tdc, to_terminate); if (!st) dma_desc->dma_status = DMA_ERROR; } From 01b66a7521274c1f208010db49af2a3d8e274400 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 9 Feb 2020 19:33:56 +0300 Subject: [PATCH 0777/4444] dmaengine: tegra-apb: Improve error message about DMA underflow Technically it is possible that DMA could be misconfigured in a way that cyclic DMA transfer is processed slower than it takes to complete the cycle and in this case the DMA is getting aborted with a not very informative message about the problem, let's improve it. Suggested-by: Jon Hunter Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Link: https://lore.kernel.org/r/20200209163356.6439-20-digetx@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 3265eb8e5d91..f1ff836abeaf 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -566,7 +566,7 @@ static bool handle_continuous_head_request(struct tegra_dma_channel *tdc, if (!hsgreq->configured) { tegra_dma_stop(tdc); pm_runtime_put(tdc->tdma->dev); - dev_err(tdc2dev(tdc), "Error in DMA transfer, aborting DMA\n"); + dev_err(tdc2dev(tdc), "DMA transfer underflow, aborting DMA\n"); tegra_dma_abort_all(tdc); return false; } From 4ae7a3c3d7d31260f690d8d658f0365f3eca67a2 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 10 Feb 2020 10:55:59 +0100 Subject: [PATCH 0778/4444] arm64: dts: allwinner: h5: Fix PMU compatible The commit c35a516a4618 ("arm64: dts: allwinner: H5: Add PMU node") introduced support for the PMU found on the Allwinner H5. However, the binding only allows for a single compatible, while the patch was adding two. Make sure we follow the binding. Fixes: c35a516a4618 ("arm64: dts: allwinner: H5: Add PMU node") Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi index 9893aa64dd0b..4462a68c0681 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi @@ -38,8 +38,7 @@ }; pmu { - compatible = "arm,cortex-a53-pmu", - "arm,armv8-pmuv3"; + compatible = "arm,cortex-a53-pmu"; interrupts = , , , From 4c7eeb9af3e41ae7d840977119c58f3bbb3f4f59 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 10 Feb 2020 10:56:00 +0100 Subject: [PATCH 0779/4444] arm64: dts: allwinner: h6: Fix PMU compatible The commit 7aa9b9eb7d6a ("arm64: dts: allwinner: H6: Add PMU mode") introduced support for the PMU found on the Allwinner H6. However, the binding only allows for a single compatible, while the patch was adding two. Make sure we follow the binding. Fixes: 7aa9b9eb7d6a ("arm64: dts: allwinner: H6: Add PMU mode") Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index 41b58ffa8596..967249e58811 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -70,8 +70,7 @@ }; pmu { - compatible = "arm,cortex-a53-pmu", - "arm,armv8-pmuv3"; + compatible = "arm,cortex-a53-pmu"; interrupts = , , , From 7ad9f3d0cb2f2b886c068f99e791bd41ceb0677a Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Mon, 24 Feb 2020 17:54:46 +0100 Subject: [PATCH 0780/4444] ARM: dts: sun8i-h3: Add thermal trip points/cooling maps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enables passive cooling by down-regulating CPU voltage and frequency. For trip points, I used a slightly lowered values from the BSP code. The critical temperature of 110°C from BSP code seemed like a lot, so I rounded it off to 100°C. The critical trip point value is 30°C above the maximum recommended ambient temperature (70°C) for the SoC from the datasheet, so there's some headroom even at such a high ambient temperature. Signed-off-by: Ondrej Jirman Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-h3.dtsi | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi index 20217e2ca4d3..e83aa6866e7e 100644 --- a/arch/arm/boot/dts/sun8i-h3.dtsi +++ b/arch/arm/boot/dts/sun8i-h3.dtsi @@ -41,6 +41,7 @@ */ #include "sunxi-h3-h5.dtsi" +#include / { cpu0_opp_table: opp_table0 { @@ -227,6 +228,30 @@ polling-delay-passive = <0>; polling-delay = <0>; thermal-sensors = <&ths 0>; + + trips { + cpu_hot_trip: cpu-hot { + temperature = <80000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_very_hot_trip: cpu-very-hot { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + cpu-hot-limit { + trip = <&cpu_hot_trip>; + cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; }; }; From 87bf7a5fba68b0ab3b34fbb06b5aa6cbb9dcc9a1 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Mon, 24 Feb 2020 17:54:17 +0100 Subject: [PATCH 0781/4444] ARM: dts: sun8i-a83t: Add thermal trip points/cooling maps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enables passive cooling by down-regulating CPU voltage and frequency. For the trip points, I used values from the BSP code directly. The critical trip point value is 30°C above the maximum recommended ambient temperature (70°C) for the SoC from the datasheet, so there's some headroom even at such a high ambient temperature. Signed-off-by: Ondrej Jirman Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-a83t.dtsi | 60 +++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi index 74ac7ee9383c..53c2b6a836f2 100644 --- a/arch/arm/boot/dts/sun8i-a83t.dtsi +++ b/arch/arm/boot/dts/sun8i-a83t.dtsi @@ -72,7 +72,7 @@ #cooling-cells = <2>; }; - cpu@1 { + cpu1: cpu@1 { compatible = "arm,cortex-a7"; device_type = "cpu"; clocks = <&ccu CLK_C0CPUX>; @@ -83,7 +83,7 @@ #cooling-cells = <2>; }; - cpu@2 { + cpu2: cpu@2 { compatible = "arm,cortex-a7"; device_type = "cpu"; clocks = <&ccu CLK_C0CPUX>; @@ -94,7 +94,7 @@ #cooling-cells = <2>; }; - cpu@3 { + cpu3: cpu@3 { compatible = "arm,cortex-a7"; device_type = "cpu"; clocks = <&ccu CLK_C0CPUX>; @@ -116,7 +116,7 @@ #cooling-cells = <2>; }; - cpu@101 { + cpu101: cpu@101 { compatible = "arm,cortex-a7"; device_type = "cpu"; clocks = <&ccu CLK_C1CPUX>; @@ -127,7 +127,7 @@ #cooling-cells = <2>; }; - cpu@102 { + cpu102: cpu@102 { compatible = "arm,cortex-a7"; device_type = "cpu"; clocks = <&ccu CLK_C1CPUX>; @@ -138,7 +138,7 @@ #cooling-cells = <2>; }; - cpu@103 { + cpu103: cpu@103 { compatible = "arm,cortex-a7"; device_type = "cpu"; clocks = <&ccu CLK_C1CPUX>; @@ -1188,12 +1188,60 @@ polling-delay-passive = <0>; polling-delay = <0>; thermal-sensors = <&ths 0>; + + trips { + cpu0_hot: cpu-hot { + temperature = <80000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu0_very_hot: cpu-very-hot { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + cpu-hot-limit { + trip = <&cpu0_hot>; + cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; cpu1_thermal: cpu1-thermal { polling-delay-passive = <0>; polling-delay = <0>; thermal-sensors = <&ths 1>; + + trips { + cpu1_hot: cpu-hot { + temperature = <80000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu1_very_hot: cpu-very-hot { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + cpu-hot-limit { + trip = <&cpu1_hot>; + cooling-device = <&cpu100 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu101 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu102 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu103 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpu_thermal: gpu-thermal { From 2140b66b5d3ecf6c7c0fa9dc5eebb41855765ace Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 14 Jan 2020 18:08:35 -0600 Subject: [PATCH 0782/4444] soundwire: bus: fix race condition with probe_complete signaling The driver probe takes care of basic initialization and is invoked when a Slave becomes attached, after a match between the Slave DevID registers and ACPI/DT entries. The update_status callback is invoked when a Slave state changes, e.g. when it is assigned a non-zero Device Number and it reports with an ATTACHED/ALERT state. The state change detection is usually hardware-based and based on the SoundWire frame rate (e.g. double-digit microseconds) while the probe is a pure software operation, which may involve a kernel module load. In corner cases, it's possible that the state changes before the probe completes. This patch suggests the use of wait_for_completion to avoid races on startup, so that the update_status callback does not rely on invalid pointers/data structures. Signed-off-by: Rander Wang Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200115000844.14695-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/bus.c | 25 ++++++++++++++++++++++--- drivers/soundwire/bus.h | 1 + drivers/soundwire/bus_type.c | 5 +++++ drivers/soundwire/slave.c | 2 ++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 6106577fb3ed..4980dfd6f3a3 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -970,10 +970,29 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) static int sdw_update_slave_status(struct sdw_slave *slave, enum sdw_slave_status status) { - if (slave->ops && slave->ops->update_status) - return slave->ops->update_status(slave, status); + unsigned long time; - return 0; + if (!slave->probed) { + /* + * the slave status update is typically handled in an + * interrupt thread, which can race with the driver + * probe, e.g. when a module needs to be loaded. + * + * make sure the probe is complete before updating + * status. + */ + time = wait_for_completion_timeout(&slave->probe_complete, + msecs_to_jiffies(DEFAULT_PROBE_TIMEOUT)); + if (!time) { + dev_err(&slave->dev, "Probe not complete, timed out\n"); + return -ETIMEDOUT; + } + } + + if (!slave->ops || !slave->ops->update_status) + return 0; + + return slave->ops->update_status(slave, status); } /** diff --git a/drivers/soundwire/bus.h b/drivers/soundwire/bus.h index cb482da914da..acb8d11a4c84 100644 --- a/drivers/soundwire/bus.h +++ b/drivers/soundwire/bus.h @@ -5,6 +5,7 @@ #define __SDW_BUS_H #define DEFAULT_BANK_SWITCH_TIMEOUT 3000 +#define DEFAULT_PROBE_TIMEOUT 2000 #if IS_ENABLED(CONFIG_ACPI) int sdw_acpi_find_slaves(struct sdw_bus *bus); diff --git a/drivers/soundwire/bus_type.c b/drivers/soundwire/bus_type.c index 4a465f55039f..17f096dd6806 100644 --- a/drivers/soundwire/bus_type.c +++ b/drivers/soundwire/bus_type.c @@ -110,6 +110,11 @@ static int sdw_drv_probe(struct device *dev) slave->bus->clk_stop_timeout = max_t(u32, slave->bus->clk_stop_timeout, slave->prop.clk_stop_timeout); + slave->probed = true; + complete(&slave->probe_complete); + + dev_dbg(dev, "probe complete\n"); + return 0; } diff --git a/drivers/soundwire/slave.c b/drivers/soundwire/slave.c index 19919975bb6d..08db0488e02d 100644 --- a/drivers/soundwire/slave.c +++ b/drivers/soundwire/slave.c @@ -47,6 +47,8 @@ static int sdw_slave_add(struct sdw_bus *bus, slave->bus = bus; slave->status = SDW_SLAVE_UNATTACHED; slave->dev_num = 0; + init_completion(&slave->probe_complete); + slave->probed = false; mutex_lock(&bus->bus_lock); list_add_tail(&slave->node, &bus->slaves); From fb9469e54fa7a7b6a8137c40ae66c41b8d0ab175 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 14 Jan 2020 18:08:36 -0600 Subject: [PATCH 0783/4444] soundwire: bus: fix race condition with enumeration_complete signaling This patch adds the signaling needed for Slave drivers to wait until the enumeration completes so that race conditions when issuing read/write commands are avoided. The calls for wait_for_completion() will be added in codec drivers in follow-up patches. The order between init_completion() and complete() is deterministic, the Slave is marked as UNATTACHED either during a Master-initiated HardReset, or when the hardware detects the Slave no longer reports as ATTACHED. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200115000844.14695-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/bus.c | 20 ++++++++++++++++++++ drivers/soundwire/slave.c | 1 + 2 files changed, 21 insertions(+) diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 4980dfd6f3a3..a2267c3a1d2d 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -610,6 +610,26 @@ static void sdw_modify_slave_status(struct sdw_slave *slave, enum sdw_slave_status status) { mutex_lock(&slave->bus->bus_lock); + + dev_vdbg(&slave->dev, + "%s: changing status slave %d status %d new status %d\n", + __func__, slave->dev_num, slave->status, status); + + if (status == SDW_SLAVE_UNATTACHED) { + dev_dbg(&slave->dev, + "%s: initializing completion for Slave %d\n", + __func__, slave->dev_num); + + init_completion(&slave->enumeration_complete); + + } else if ((status == SDW_SLAVE_ATTACHED) && + (slave->status == SDW_SLAVE_UNATTACHED)) { + dev_dbg(&slave->dev, + "%s: signaling completion for Slave %d\n", + __func__, slave->dev_num); + + complete(&slave->enumeration_complete); + } slave->status = status; mutex_unlock(&slave->bus->bus_lock); } diff --git a/drivers/soundwire/slave.c b/drivers/soundwire/slave.c index 08db0488e02d..e767a78066ee 100644 --- a/drivers/soundwire/slave.c +++ b/drivers/soundwire/slave.c @@ -46,6 +46,7 @@ static int sdw_slave_add(struct sdw_bus *bus, slave->dev.of_node = of_node_get(to_of_node(fwnode)); slave->bus = bus; slave->status = SDW_SLAVE_UNATTACHED; + init_completion(&slave->enumeration_complete); slave->dev_num = 0; init_completion(&slave->probe_complete); slave->probed = false; From a90def0681270eb58496825b8861aa9ffca6abce Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 14 Jan 2020 18:08:37 -0600 Subject: [PATCH 0784/4444] soundwire: bus: fix race condition with initialization_complete signaling Waiting for the enumeration to be complete may not be enough for a Slave driver, there is a possible race condition between resume operations and initializations handled in an interrupt thread, which can results in settings not being fully restored after system or pm_runtime resume. This patch builds on the changes added for enumeration_complete, init_completion() is called when the Slave device becomes UNATTACHED, as done with enumeration_complete. The difference with the enumeration_complete case is that complete() is signaled after the Slave device is fully initialized after the .update_status() callback is called. A Slave device driver can decide to wait on either of the two complete() cases, depending on its initialization code and requirements. Signed-off-by: Rander Wang Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200115000844.14695-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/bus.c | 8 ++++++++ drivers/soundwire/slave.c | 1 + 2 files changed, 9 insertions(+) diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index a2267c3a1d2d..ea04cf5f5bdc 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -621,6 +621,7 @@ static void sdw_modify_slave_status(struct sdw_slave *slave, __func__, slave->dev_num); init_completion(&slave->enumeration_complete); + init_completion(&slave->initialization_complete); } else if ((status == SDW_SLAVE_ATTACHED) && (slave->status == SDW_SLAVE_UNATTACHED)) { @@ -1025,6 +1026,7 @@ int sdw_handle_slave_status(struct sdw_bus *bus, { enum sdw_slave_status prev_status; struct sdw_slave *slave; + bool attached_initializing; int i, ret = 0; /* first check if any Slaves fell off the bus */ @@ -1070,6 +1072,8 @@ int sdw_handle_slave_status(struct sdw_bus *bus, if (!slave) continue; + attached_initializing = false; + switch (status[i]) { case SDW_SLAVE_UNATTACHED: if (slave->status == SDW_SLAVE_UNATTACHED) @@ -1096,6 +1100,8 @@ int sdw_handle_slave_status(struct sdw_bus *bus, if (prev_status == SDW_SLAVE_ALERT) break; + attached_initializing = true; + ret = sdw_initialize_slave(slave); if (ret) dev_err(bus->dev, @@ -1114,6 +1120,8 @@ int sdw_handle_slave_status(struct sdw_bus *bus, if (ret) dev_err(slave->bus->dev, "Update Slave status failed:%d\n", ret); + if (attached_initializing) + complete(&slave->initialization_complete); } return ret; diff --git a/drivers/soundwire/slave.c b/drivers/soundwire/slave.c index e767a78066ee..aace57fae7f8 100644 --- a/drivers/soundwire/slave.c +++ b/drivers/soundwire/slave.c @@ -47,6 +47,7 @@ static int sdw_slave_add(struct sdw_bus *bus, slave->bus = bus; slave->status = SDW_SLAVE_UNATTACHED; init_completion(&slave->enumeration_complete); + init_completion(&slave->initialization_complete); slave->dev_num = 0; init_completion(&slave->probe_complete); slave->probed = false; From 60ee9be2557124aa007e6e12e78def2f55d1b64b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 14 Jan 2020 18:08:38 -0600 Subject: [PATCH 0785/4444] soundwire: bus: add PM/no-PM versions of read/write functions Add support for pm_runtime with the appropriate error checks for sdw_write/read functions, e.g. when pm_runtime is not supported. Also expose internal functions without pm_runtime support, which are required to perform any sort of suspend/resume operation, as well as any enumeration tasks. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200115000844.14695-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/bus.c | 70 +++++++++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 17 deletions(-) diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index ea04cf5f5bdc..c525b9b50453 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -317,14 +317,15 @@ int sdw_fill_msg(struct sdw_msg *msg, struct sdw_slave *slave, return 0; } -/** - * sdw_nread() - Read "n" contiguous SDW Slave registers - * @slave: SDW Slave - * @addr: Register address - * @count: length - * @val: Buffer for values to be read +/* + * Read/Write IO functions. + * no_pm versions can only be called by the bus, e.g. while enumerating or + * handling suspend-resume sequences. + * all clients need to use the pm versions */ -int sdw_nread(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) + +static int +sdw_nread_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) { struct sdw_msg msg; int ret; @@ -334,11 +335,48 @@ int sdw_nread(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) if (ret < 0) return ret; - ret = pm_runtime_get_sync(slave->bus->dev); + return sdw_transfer(slave->bus, &msg); +} + +static int +sdw_nwrite_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) +{ + struct sdw_msg msg; + int ret; + + ret = sdw_fill_msg(&msg, slave, addr, count, + slave->dev_num, SDW_MSG_FLAG_WRITE, val); if (ret < 0) return ret; - ret = sdw_transfer(slave->bus, &msg); + return sdw_transfer(slave->bus, &msg); +} + +static int sdw_write_no_pm(struct sdw_slave *slave, u32 addr, u8 value) +{ + return sdw_nwrite_no_pm(slave, addr, 1, &value); +} + +/** + * sdw_nread() - Read "n" contiguous SDW Slave registers + * @slave: SDW Slave + * @addr: Register address + * @count: length + * @val: Buffer for values to be read + */ +int sdw_nread(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) +{ + int ret; + + ret = pm_runtime_get_sync(slave->bus->dev); + if (ret < 0 && ret != -EACCES) { + pm_runtime_put_noidle(slave->bus->dev); + return ret; + } + + ret = sdw_nread_no_pm(slave, addr, count, val); + + pm_runtime_mark_last_busy(slave->bus->dev); pm_runtime_put(slave->bus->dev); return ret; @@ -354,19 +392,17 @@ EXPORT_SYMBOL(sdw_nread); */ int sdw_nwrite(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) { - struct sdw_msg msg; int ret; - ret = sdw_fill_msg(&msg, slave, addr, count, - slave->dev_num, SDW_MSG_FLAG_WRITE, val); - if (ret < 0) - return ret; - ret = pm_runtime_get_sync(slave->bus->dev); - if (ret < 0) + if (ret < 0 && ret != -EACCES) { + pm_runtime_put_noidle(slave->bus->dev); return ret; + } - ret = sdw_transfer(slave->bus, &msg); + ret = sdw_nwrite_no_pm(slave, addr, count, val); + + pm_runtime_mark_last_busy(slave->bus->dev); pm_runtime_put(slave->bus->dev); return ret; From d300de4f2d5108ac5f73601190ee4e3806f37c0b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 14 Jan 2020 18:08:39 -0600 Subject: [PATCH 0786/4444] soundwire: bus: write Slave Device Number without runtime_pm While handling the Device0, we can safely use sdw_write_no_pm. This move will also helps us track that all other usages of sdw_write() happen when the Slave is already enumerated. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200115000844.14695-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index c525b9b50453..dfe27e3ca815 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -522,7 +522,7 @@ static int sdw_assign_device_num(struct sdw_slave *slave) dev_num = slave->dev_num; slave->dev_num = 0; - ret = sdw_write(slave, SDW_SCP_DEVNUMBER, dev_num); + ret = sdw_write_no_pm(slave, SDW_SCP_DEVNUMBER, dev_num); if (ret < 0) { dev_err(&slave->dev, "Program device_num %d failed: %d\n", dev_num, ret); From 3ab2ca405a08c34c9b8b54a02b6d0e29821e73c8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 14 Jan 2020 18:08:40 -0600 Subject: [PATCH 0787/4444] soundwire: bus: add helper to clear Slave status to UNATTACHED When resuming with a bus reset, we need to re-enumerate and restart from UNATTACHED. The helper added in this patch helps implement a more robust state machine avoiding race conditions on resume. The unattach request is stored and will be used by Slave drivers, if needed: Intel validation exposed a corner case where the Slave device may transition to D3 when streaming stops, but streaming restarts before the Master transitions to D3. In that case, the Slave status was not cleared as UNATTACHED by the Master resuming, and the wait_for_completion will time out. When the slave resumes, it can check if a Master-initiated re-enumeration and initialization took place and skip the wait_for_completion() if there is no reason to wait. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200115000844.14695-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/bus.c | 27 +++++++++++++++++++++++++++ drivers/soundwire/bus.h | 8 ++++++++ 2 files changed, 35 insertions(+) diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index dfe27e3ca815..57dec61142e5 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -1163,3 +1163,30 @@ int sdw_handle_slave_status(struct sdw_bus *bus, return ret; } EXPORT_SYMBOL(sdw_handle_slave_status); + +void sdw_clear_slave_status(struct sdw_bus *bus, u32 request) +{ + struct sdw_slave *slave; + int i; + + /* Check all non-zero devices */ + for (i = 1; i <= SDW_MAX_DEVICES; i++) { + mutex_lock(&bus->bus_lock); + if (test_bit(i, bus->assigned) == false) { + mutex_unlock(&bus->bus_lock); + continue; + } + mutex_unlock(&bus->bus_lock); + + slave = sdw_get_slave(bus, i); + if (!slave) + continue; + + if (slave->status != SDW_SLAVE_UNATTACHED) + sdw_modify_slave_status(slave, SDW_SLAVE_UNATTACHED); + + /* keep track of request, used in pm_runtime resume */ + slave->unattach_request = request; + } +} +EXPORT_SYMBOL(sdw_clear_slave_status); diff --git a/drivers/soundwire/bus.h b/drivers/soundwire/bus.h index acb8d11a4c84..204204a26db8 100644 --- a/drivers/soundwire/bus.h +++ b/drivers/soundwire/bus.h @@ -165,4 +165,12 @@ sdw_update(struct sdw_slave *slave, u32 addr, u8 mask, u8 val) return sdw_write(slave, addr, tmp); } +/* + * At the moment we only track Master-initiated hw_reset. + * Additional fields can be added as needed + */ +#define SDW_UNATTACH_REQUEST_MASTER_RESET BIT(0) + +void sdw_clear_slave_status(struct sdw_bus *bus, u32 request); + #endif /* __SDW_BUS_H */ From dff70572e9a3a1a01d9dbc2279faa784d95f41b6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 14 Jan 2020 18:08:41 -0600 Subject: [PATCH 0788/4444] soundwire: bus: disable pm_runtime in sdw_slave_delete Before removing the slave device, disable pm_runtime to prevent any race condition with the resume being executed after the bus and slave devices are removed. Since this pm_runtime_disable() is handled in common routines, implementations of Slave drivers do not need to call it in their .remove() routine. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200115000844.14695-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/bus.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 57dec61142e5..33bb273454cf 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -113,6 +113,8 @@ static int sdw_delete_slave(struct device *dev, void *data) struct sdw_slave *slave = dev_to_sdw_dev(dev); struct sdw_bus *bus = slave->bus; + pm_runtime_disable(dev); + sdw_slave_debugfs_exit(slave); mutex_lock(&bus->bus_lock); From aa79293517b395c6094a382779c911689e8c9a8b Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Tue, 14 Jan 2020 18:08:42 -0600 Subject: [PATCH 0789/4444] soundwire: bus: fix io error when processing alert event There are two types of io errors when processing alert event. a) the Master detects an ALERT status for e.g. a jack event and invokes the implementation-defined function in the Slave driver to check the jack status. At this time the codec is just suspended, so io registers can't be accessed. b) when waking up from clock stop mode1 state, where the bus needs a complete re-enumeration, Slave registers can't be accessed until the enumeration is complete. This patch resumes the Slave device and waits for initialization complete when processing slave alert event, so that registers on the Slave can be accessed without timeouts or io errors. Signed-off-by: Rander Wang Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200115000844.14695-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/bus.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 33bb273454cf..23bc24c8e9d1 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -890,12 +890,19 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) sdw_modify_slave_status(slave, SDW_SLAVE_ALERT); + ret = pm_runtime_get_sync(&slave->dev); + if (ret < 0 && ret != -EACCES) { + dev_err(&slave->dev, "Failed to resume device: %d\n", ret); + pm_runtime_put_noidle(slave->bus->dev); + return ret; + } + /* Read Instat 1, Instat 2 and Instat 3 registers */ ret = sdw_read(slave, SDW_SCP_INT1); if (ret < 0) { dev_err(slave->bus->dev, "SDW_SCP_INT1 read failed:%d\n", ret); - return ret; + goto io_err; } buf = ret; @@ -903,7 +910,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) if (ret < 0) { dev_err(slave->bus->dev, "SDW_SCP_INT2/3 read failed:%d\n", ret); - return ret; + goto io_err; } do { @@ -983,7 +990,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) if (ret < 0) { dev_err(slave->bus->dev, "SDW_SCP_INT1 write failed:%d\n", ret); - return ret; + goto io_err; } /* @@ -994,7 +1001,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) if (ret < 0) { dev_err(slave->bus->dev, "SDW_SCP_INT1 read failed:%d\n", ret); - return ret; + goto io_err; } _buf = ret; @@ -1002,7 +1009,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) if (ret < 0) { dev_err(slave->bus->dev, "SDW_SCP_INT2/3 read failed:%d\n", ret); - return ret; + goto io_err; } /* Make sure no interrupts are pending */ @@ -1023,6 +1030,10 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) if (count == SDW_READ_INTR_CLEAR_RETRY) dev_warn(slave->bus->dev, "Reached MAX_RETRY on alert read\n"); +io_err: + pm_runtime_mark_last_busy(&slave->dev); + pm_runtime_put_autosuspend(&slave->dev); + return ret; } From 0231453bc08f63584545dda1c05d61b19755d3a9 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Tue, 14 Jan 2020 18:08:43 -0600 Subject: [PATCH 0790/4444] soundwire: bus: add clock stop helpers SoundWire supports two clock stop modes. Add support to handle the clock stop modes and add pm_runtime calls in the bus. Credits: this patch is based on an earlier internal contribution by Vinod Koul, Sanyog Kale, Shreyas Nc and Hardik Shah. Signed-off-by: Bard Liao Signed-off-by: Rander Wang Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200115000844.14695-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/bus.c | 332 ++++++++++++++++++++++++++++++++++ include/linux/soundwire/sdw.h | 24 +++ 2 files changed, 356 insertions(+) diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 23bc24c8e9d1..3395abd2ed39 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -2,6 +2,7 @@ // Copyright(c) 2015-17 Intel Corporation. #include +#include #include #include #include @@ -359,6 +360,52 @@ static int sdw_write_no_pm(struct sdw_slave *slave, u32 addr, u8 value) return sdw_nwrite_no_pm(slave, addr, 1, &value); } +static int +sdw_bread_no_pm(struct sdw_bus *bus, u16 dev_num, u32 addr) +{ + struct sdw_msg msg; + u8 buf; + int ret; + + ret = sdw_fill_msg(&msg, NULL, addr, 1, dev_num, + SDW_MSG_FLAG_READ, &buf); + if (ret) + return ret; + + ret = sdw_transfer(bus, &msg); + if (ret < 0) + return ret; + else + return buf; +} + +static int +sdw_bwrite_no_pm(struct sdw_bus *bus, u16 dev_num, u32 addr, u8 value) +{ + struct sdw_msg msg; + int ret; + + ret = sdw_fill_msg(&msg, NULL, addr, 1, dev_num, + SDW_MSG_FLAG_WRITE, &value); + if (ret) + return ret; + + return sdw_transfer(bus, &msg); +} + +static int +sdw_read_no_pm(struct sdw_slave *slave, u32 addr) +{ + u8 buf; + int ret; + + ret = sdw_nread_no_pm(slave, addr, 1, &buf); + if (ret < 0) + return ret; + else + return buf; +} + /** * sdw_nread() - Read "n" contiguous SDW Slave registers * @slave: SDW Slave @@ -673,6 +720,291 @@ static void sdw_modify_slave_status(struct sdw_slave *slave, mutex_unlock(&slave->bus->bus_lock); } +static enum sdw_clk_stop_mode sdw_get_clk_stop_mode(struct sdw_slave *slave) +{ + enum sdw_clk_stop_mode mode; + + /* + * Query for clock stop mode if Slave implements + * ops->get_clk_stop_mode, else read from property. + */ + if (slave->ops && slave->ops->get_clk_stop_mode) { + mode = slave->ops->get_clk_stop_mode(slave); + } else { + if (slave->prop.clk_stop_mode1) + mode = SDW_CLK_STOP_MODE1; + else + mode = SDW_CLK_STOP_MODE0; + } + + return mode; +} + +static int sdw_slave_clk_stop_callback(struct sdw_slave *slave, + enum sdw_clk_stop_mode mode, + enum sdw_clk_stop_type type) +{ + int ret; + + if (slave->ops && slave->ops->clk_stop) { + ret = slave->ops->clk_stop(slave, mode, type); + if (ret < 0) { + dev_err(&slave->dev, + "Clk Stop type =%d failed: %d\n", type, ret); + return ret; + } + } + + return 0; +} + +static int sdw_slave_clk_stop_prepare(struct sdw_slave *slave, + enum sdw_clk_stop_mode mode, + bool prepare) +{ + bool wake_en; + u32 val = 0; + int ret; + + wake_en = slave->prop.wake_capable; + + if (prepare) { + val = SDW_SCP_SYSTEMCTRL_CLK_STP_PREP; + + if (mode == SDW_CLK_STOP_MODE1) + val |= SDW_SCP_SYSTEMCTRL_CLK_STP_MODE1; + + if (wake_en) + val |= SDW_SCP_SYSTEMCTRL_WAKE_UP_EN; + } else { + val = sdw_read_no_pm(slave, SDW_SCP_SYSTEMCTRL); + + val &= ~(SDW_SCP_SYSTEMCTRL_CLK_STP_PREP); + } + + ret = sdw_write_no_pm(slave, SDW_SCP_SYSTEMCTRL, val); + + if (ret != 0) + dev_err(&slave->dev, + "Clock Stop prepare failed for slave: %d", ret); + + return ret; +} + +static int sdw_bus_wait_for_clk_prep_deprep(struct sdw_bus *bus, u16 dev_num) +{ + int retry = bus->clk_stop_timeout; + int val; + + do { + val = sdw_bread_no_pm(bus, dev_num, SDW_SCP_STAT) & + SDW_SCP_STAT_CLK_STP_NF; + if (!val) { + dev_info(bus->dev, "clock stop prep/de-prep done slave:%d", + dev_num); + return 0; + } + + usleep_range(1000, 1500); + retry--; + } while (retry); + + dev_err(bus->dev, "clock stop prep/de-prep failed slave:%d", + dev_num); + + return -ETIMEDOUT; +} + +/** + * sdw_bus_prep_clk_stop: prepare Slave(s) for clock stop + * + * @bus: SDW bus instance + * + * Query Slave for clock stop mode and prepare for that mode. + */ +int sdw_bus_prep_clk_stop(struct sdw_bus *bus) +{ + enum sdw_clk_stop_mode slave_mode; + bool simple_clk_stop = true; + struct sdw_slave *slave; + bool is_slave = false; + int ret = 0; + + /* + * In order to save on transition time, prepare + * each Slave and then wait for all Slave(s) to be + * prepared for clock stop. + */ + list_for_each_entry(slave, &bus->slaves, node) { + if (!slave->dev_num) + continue; + + /* Identify if Slave(s) are available on Bus */ + is_slave = true; + + if (slave->status != SDW_SLAVE_ATTACHED && + slave->status != SDW_SLAVE_ALERT) + continue; + + slave_mode = sdw_get_clk_stop_mode(slave); + slave->curr_clk_stop_mode = slave_mode; + + ret = sdw_slave_clk_stop_callback(slave, slave_mode, + SDW_CLK_PRE_PREPARE); + if (ret < 0) { + dev_err(&slave->dev, + "pre-prepare failed:%d", ret); + return ret; + } + + ret = sdw_slave_clk_stop_prepare(slave, + slave_mode, true); + if (ret < 0) { + dev_err(&slave->dev, + "pre-prepare failed:%d", ret); + return ret; + } + + if (slave_mode == SDW_CLK_STOP_MODE1) + simple_clk_stop = false; + } + + if (is_slave && !simple_clk_stop) { + ret = sdw_bus_wait_for_clk_prep_deprep(bus, + SDW_BROADCAST_DEV_NUM); + if (ret < 0) + return ret; + } + + /* Inform slaves that prep is done */ + list_for_each_entry(slave, &bus->slaves, node) { + if (!slave->dev_num) + continue; + + if (slave->status != SDW_SLAVE_ATTACHED && + slave->status != SDW_SLAVE_ALERT) + continue; + + slave_mode = slave->curr_clk_stop_mode; + + if (slave_mode == SDW_CLK_STOP_MODE1) { + ret = sdw_slave_clk_stop_callback(slave, + slave_mode, + SDW_CLK_POST_PREPARE); + + if (ret < 0) { + dev_err(&slave->dev, + "post-prepare failed:%d", ret); + } + } + } + + return ret; +} +EXPORT_SYMBOL(sdw_bus_prep_clk_stop); + +/** + * sdw_bus_clk_stop: stop bus clock + * + * @bus: SDW bus instance + * + * After preparing the Slaves for clock stop, stop the clock by broadcasting + * write to SCP_CTRL register. + */ +int sdw_bus_clk_stop(struct sdw_bus *bus) +{ + int ret; + + /* + * broadcast clock stop now, attached Slaves will ACK this, + * unattached will ignore + */ + ret = sdw_bwrite_no_pm(bus, SDW_BROADCAST_DEV_NUM, + SDW_SCP_CTRL, SDW_SCP_CTRL_CLK_STP_NOW); + if (ret < 0) { + dev_err(bus->dev, + "ClockStopNow Broadcast message failed %d", ret); + return ret; + } + + return 0; +} +EXPORT_SYMBOL(sdw_bus_clk_stop); + +/** + * sdw_bus_exit_clk_stop: Exit clock stop mode + * + * @bus: SDW bus instance + * + * This De-prepares the Slaves by exiting Clock Stop Mode 0. For the Slaves + * exiting Clock Stop Mode 1, they will be de-prepared after they enumerate + * back. + */ +int sdw_bus_exit_clk_stop(struct sdw_bus *bus) +{ + enum sdw_clk_stop_mode mode; + bool simple_clk_stop = true; + struct sdw_slave *slave; + bool is_slave = false; + int ret; + + /* + * In order to save on transition time, de-prepare + * each Slave and then wait for all Slave(s) to be + * de-prepared after clock resume. + */ + list_for_each_entry(slave, &bus->slaves, node) { + if (!slave->dev_num) + continue; + + /* Identify if Slave(s) are available on Bus */ + is_slave = true; + + if (slave->status != SDW_SLAVE_ATTACHED && + slave->status != SDW_SLAVE_ALERT) + continue; + + mode = slave->curr_clk_stop_mode; + + if (mode == SDW_CLK_STOP_MODE1) { + simple_clk_stop = false; + continue; + } + + ret = sdw_slave_clk_stop_callback(slave, mode, + SDW_CLK_PRE_DEPREPARE); + if (ret < 0) + dev_warn(&slave->dev, + "clk stop deprep failed:%d", ret); + + ret = sdw_slave_clk_stop_prepare(slave, mode, + false); + + if (ret < 0) + dev_warn(&slave->dev, + "clk stop deprep failed:%d", ret); + } + + if (is_slave && !simple_clk_stop) + sdw_bus_wait_for_clk_prep_deprep(bus, SDW_BROADCAST_DEV_NUM); + + list_for_each_entry(slave, &bus->slaves, node) { + if (!slave->dev_num) + continue; + + if (slave->status != SDW_SLAVE_ATTACHED && + slave->status != SDW_SLAVE_ALERT) + continue; + + mode = slave->curr_clk_stop_mode; + sdw_slave_clk_stop_callback(slave, mode, + SDW_CLK_POST_DEPREPARE); + } + + return 0; +} +EXPORT_SYMBOL(sdw_bus_exit_clk_stop); + int sdw_configure_dpn_intr(struct sdw_slave *slave, int port, bool enable, int mask) { diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index b451bb622335..b8427df034ce 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -79,6 +79,21 @@ enum sdw_slave_status { SDW_SLAVE_RESERVED = 3, }; +/** + * enum sdw_clk_stop_type: clock stop operations + * + * @SDW_CLK_PRE_PREPARE: pre clock stop prepare + * @SDW_CLK_POST_PREPARE: post clock stop prepare + * @SDW_CLK_PRE_DEPREPARE: pre clock stop de-prepare + * @SDW_CLK_POST_DEPREPARE: post clock stop de-prepare + */ +enum sdw_clk_stop_type { + SDW_CLK_PRE_PREPARE = 0, + SDW_CLK_POST_PREPARE, + SDW_CLK_PRE_DEPREPARE, + SDW_CLK_POST_DEPREPARE, +}; + /** * enum sdw_command_response - Command response as defined by SDW spec * @SDW_CMD_OK: cmd was successful @@ -533,6 +548,11 @@ struct sdw_slave_ops { int (*port_prep)(struct sdw_slave *slave, struct sdw_prepare_ch *prepare_ch, enum sdw_port_prep_ops pre_ops); + int (*get_clk_stop_mode)(struct sdw_slave *slave); + int (*clk_stop)(struct sdw_slave *slave, + enum sdw_clk_stop_mode mode, + enum sdw_clk_stop_type type); + }; /** @@ -575,6 +595,7 @@ struct sdw_slave { #endif struct list_head node; struct completion *port_ready; + enum sdw_clk_stop_mode curr_clk_stop_mode; u16 dev_num; u16 dev_num_sticky; bool probed; @@ -892,6 +913,9 @@ int sdw_prepare_stream(struct sdw_stream_runtime *stream); int sdw_enable_stream(struct sdw_stream_runtime *stream); int sdw_disable_stream(struct sdw_stream_runtime *stream); int sdw_deprepare_stream(struct sdw_stream_runtime *stream); +int sdw_bus_prep_clk_stop(struct sdw_bus *bus); +int sdw_bus_clk_stop(struct sdw_bus *bus); +int sdw_bus_exit_clk_stop(struct sdw_bus *bus); /* messaging and data APIs */ From dde73538c9a5f537fe1d6ae4a563507343ec6587 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 14 Jan 2020 18:08:44 -0600 Subject: [PATCH 0791/4444] soundwire: bus: don't treat CMD_IGNORED as error on ClockStop If a SoundWire link is enabled, but there are no Slave devices exposed in firmware tables for this link, or no Slaves in ATTACHED or ALERT mode, the CMD_IGNORED/-ENODATA error code on a broadcast write is perfectly legit. Filter this case to report errors and let the caller deal with the CMD_IGNORED case. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200115000844.14695-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/bus.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 3395abd2ed39..13887713f311 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -922,8 +922,12 @@ int sdw_bus_clk_stop(struct sdw_bus *bus) ret = sdw_bwrite_no_pm(bus, SDW_BROADCAST_DEV_NUM, SDW_SCP_CTRL, SDW_SCP_CTRL_CLK_STP_NOW); if (ret < 0) { - dev_err(bus->dev, - "ClockStopNow Broadcast message failed %d", ret); + if (ret == -ENODATA) + dev_dbg(bus->dev, + "ClockStopNow Broadcast msg ignored %d", ret); + else + dev_err(bus->dev, + "ClockStopNow Broadcast msg failed %d", ret); return ret; } From 3d5f7d9f6a38ddcc105ebfb23b640630bbabba65 Mon Sep 17 00:00:00 2001 From: Vidya Sagar Date: Mon, 17 Feb 2020 17:40:32 +0530 Subject: [PATCH 0792/4444] PCI: endpoint: Add core init notifying feature Add a new feature core_init_notifier for cores that can notify about their availability for initialization. Signed-off-by: Vidya Sagar Signed-off-by: Lorenzo Pieralisi Acked-by: Kishon Vijay Abraham I --- include/linux/pci-epc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h index ccaf6e3fa931..9ffe6bd081ae 100644 --- a/include/linux/pci-epc.h +++ b/include/linux/pci-epc.h @@ -120,6 +120,7 @@ struct pci_epc { */ struct pci_epc_features { unsigned int linkup_notifier : 1; + unsigned int core_init_notifier : 1; unsigned int msi_capable : 1; unsigned int msix_capable : 1; u8 reserved_bar; From e966f7390da935e2b5aa0b2248d2d1265f937369 Mon Sep 17 00:00:00 2001 From: Vidya Sagar Date: Mon, 17 Feb 2020 17:40:33 +0530 Subject: [PATCH 0793/4444] PCI: dwc: Refactor core initialization code for EP mode Split core initialization code for EP mode into two, one that doesn't touch core registers and the other that touches core registers. The latter would be called/skipped based on the EPC feature 'core_init_notifier'. In platforms where this is skipped, it would be called indirectly through hooks from the endpoint function driver. Signed-off-by: Vidya Sagar Signed-off-by: Lorenzo Pieralisi Acked-by: Kishon Vijay Abraham I --- .../pci/controller/dwc/pcie-designware-ep.c | 72 +++++++++++-------- drivers/pci/controller/dwc/pcie-designware.h | 6 ++ 2 files changed, 50 insertions(+), 28 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index cfeccd7e9fff..84a102df9f62 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -492,19 +492,53 @@ static unsigned int dw_pcie_ep_find_ext_capability(struct dw_pcie *pci, int cap) return 0; } +int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep) +{ + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + unsigned int offset; + unsigned int nbars; + u8 hdr_type; + u32 reg; + int i; + + hdr_type = dw_pcie_readb_dbi(pci, PCI_HEADER_TYPE); + if (hdr_type != PCI_HEADER_TYPE_NORMAL) { + dev_err(pci->dev, + "PCIe controller is not set to EP mode (hdr_type:0x%x)!\n", + hdr_type); + return -EIO; + } + + ep->msi_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSI); + + ep->msix_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSIX); + + offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR); + if (offset) { + reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL); + nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >> + PCI_REBAR_CTRL_NBAR_SHIFT; + + dw_pcie_dbi_ro_wr_en(pci); + for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL) + dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, 0x0); + dw_pcie_dbi_ro_wr_dis(pci); + } + + dw_pcie_setup(pci); + + return 0; +} + int dw_pcie_ep_init(struct dw_pcie_ep *ep) { - int i; int ret; - u32 reg; void *addr; - u8 hdr_type; - unsigned int nbars; - unsigned int offset; struct pci_epc *epc; struct dw_pcie *pci = to_dw_pcie_from_ep(ep); struct device *dev = pci->dev; struct device_node *np = dev->of_node; + const struct pci_epc_features *epc_features; if (!pci->dbi_base || !pci->dbi_base2) { dev_err(dev, "dbi_base/dbi_base2 is not populated\n"); @@ -563,13 +597,6 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) if (ep->ops->ep_init) ep->ops->ep_init(ep); - hdr_type = dw_pcie_readb_dbi(pci, PCI_HEADER_TYPE); - if (hdr_type != PCI_HEADER_TYPE_NORMAL) { - dev_err(pci->dev, "PCIe controller is not set to EP mode (hdr_type:0x%x)!\n", - hdr_type); - return -EIO; - } - ret = of_property_read_u8(np, "max-functions", &epc->max_functions); if (ret < 0) epc->max_functions = 1; @@ -587,23 +614,12 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) dev_err(dev, "Failed to reserve memory for MSI/MSI-X\n"); return -ENOMEM; } - ep->msi_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSI); - ep->msix_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSIX); - - offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR); - if (offset) { - reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL); - nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >> - PCI_REBAR_CTRL_NBAR_SHIFT; - - dw_pcie_dbi_ro_wr_en(pci); - for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL) - dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, 0x0); - dw_pcie_dbi_ro_wr_dis(pci); + if (ep->ops->get_features) { + epc_features = ep->ops->get_features(ep); + if (epc_features->core_init_notifier) + return 0; } - dw_pcie_setup(pci); - - return 0; + return dw_pcie_ep_init_complete(ep); } diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index a22ea5982817..b67b7f756bc2 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -411,6 +411,7 @@ static inline int dw_pcie_allocate_domains(struct pcie_port *pp) #ifdef CONFIG_PCIE_DW_EP void dw_pcie_ep_linkup(struct dw_pcie_ep *ep); int dw_pcie_ep_init(struct dw_pcie_ep *ep); +int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep); void dw_pcie_ep_exit(struct dw_pcie_ep *ep); int dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep, u8 func_no); int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, @@ -428,6 +429,11 @@ static inline int dw_pcie_ep_init(struct dw_pcie_ep *ep) return 0; } +static inline int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep) +{ + return 0; +} + static inline void dw_pcie_ep_exit(struct dw_pcie_ep *ep) { } From 0ef22dcf0c1871888c4c0ee46a9d9c494f2fe997 Mon Sep 17 00:00:00 2001 From: Vidya Sagar Date: Mon, 17 Feb 2020 17:40:34 +0530 Subject: [PATCH 0794/4444] PCI: endpoint: Add notification for core init completion Add support to send notifications to EPF from EPC once the core registers initialization is complete. Signed-off-by: Vidya Sagar Signed-off-by: Lorenzo Pieralisi Acked-by: Kishon Vijay Abraham I --- drivers/pci/endpoint/pci-epc-core.c | 19 ++++++++++++++++++- include/linux/pci-epc.h | 1 + include/linux/pci-epf.h | 5 +++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index dc1c673534e0..0d22a377a0cf 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -540,10 +540,27 @@ void pci_epc_linkup(struct pci_epc *epc) if (!epc || IS_ERR(epc)) return; - atomic_notifier_call_chain(&epc->notifier, 0, NULL); + atomic_notifier_call_chain(&epc->notifier, LINK_UP, NULL); } EXPORT_SYMBOL_GPL(pci_epc_linkup); +/** + * pci_epc_init_notify() - Notify the EPF device that EPC device's core + * initialization is completed. + * @epc: the EPC device whose core initialization is completeds + * + * Invoke to Notify the EPF device that the EPC device's initialization + * is completed. + */ +void pci_epc_init_notify(struct pci_epc *epc) +{ + if (!epc || IS_ERR(epc)) + return; + + atomic_notifier_call_chain(&epc->notifier, CORE_INIT, NULL); +} +EXPORT_SYMBOL_GPL(pci_epc_init_notify); + /** * pci_epc_destroy() - destroy the EPC device * @epc: the EPC device that has to be destroyed diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h index 9ffe6bd081ae..0d7e91bad91e 100644 --- a/include/linux/pci-epc.h +++ b/include/linux/pci-epc.h @@ -165,6 +165,7 @@ void devm_pci_epc_destroy(struct device *dev, struct pci_epc *epc); void pci_epc_destroy(struct pci_epc *epc); int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf); void pci_epc_linkup(struct pci_epc *epc); +void pci_epc_init_notify(struct pci_epc *epc); void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf); int pci_epc_write_header(struct pci_epc *epc, u8 func_no, struct pci_epf_header *hdr); diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h index bcdf4f07bde7..0c628e30c582 100644 --- a/include/linux/pci-epf.h +++ b/include/linux/pci-epf.h @@ -15,6 +15,11 @@ struct pci_epf; +enum pci_notify_event { + CORE_INIT, + LINK_UP, +}; + enum pci_barno { BAR_0, BAR_1, From ac37dde721776463f866ba5c93986af19a6b73b9 Mon Sep 17 00:00:00 2001 From: Vidya Sagar Date: Mon, 17 Feb 2020 17:40:35 +0530 Subject: [PATCH 0795/4444] PCI: dwc: Add API to notify core initialization completion Add a new API dw_pcie_ep_init_notify() to let platform drivers call it when the core is available for initialization. Signed-off-by: Vidya Sagar Signed-off-by: Lorenzo Pieralisi Acked-by: Kishon Vijay Abraham I --- drivers/pci/controller/dwc/pcie-designware-ep.c | 7 +++++++ drivers/pci/controller/dwc/pcie-designware.h | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index 84a102df9f62..dfbb806c25bf 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -19,6 +19,13 @@ void dw_pcie_ep_linkup(struct dw_pcie_ep *ep) pci_epc_linkup(epc); } +void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep) +{ + struct pci_epc *epc = ep->epc; + + pci_epc_init_notify(epc); +} + static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar, int flags) { diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index b67b7f756bc2..aa98fbd50807 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -412,6 +412,7 @@ static inline int dw_pcie_allocate_domains(struct pcie_port *pp) void dw_pcie_ep_linkup(struct dw_pcie_ep *ep); int dw_pcie_ep_init(struct dw_pcie_ep *ep); int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep); +void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep); void dw_pcie_ep_exit(struct dw_pcie_ep *ep); int dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep, u8 func_no); int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, @@ -434,6 +435,10 @@ static inline int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep) return 0; } +static inline void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep) +{ +} + static inline void dw_pcie_ep_exit(struct dw_pcie_ep *ep) { } From f5e056e1e46fcbb5f74ce560792aeb7d57ce79e6 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 19 Nov 2019 11:36:40 +0000 Subject: [PATCH 0796/4444] ASoC: Intel: mrfld: fix incorrect check on p->sink The check on p->sink looks bogus, I believe it should be p->source since the following code blocks are related to p->source. Fix this by replacing p->sink with p->source. Fixes: 24c8d14192cc ("ASoC: Intel: mrfld: add DSP core controls") Signed-off-by: Colin Ian King Addresses-Coverity: ("Copy-paste error") Link: https://lore.kernel.org/r/20191119113640.166940-1-colin.king@canonical.com Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst-atom-controls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c index baef461a99f1..f883c9340eee 100644 --- a/sound/soc/intel/atom/sst-atom-controls.c +++ b/sound/soc/intel/atom/sst-atom-controls.c @@ -1333,7 +1333,7 @@ int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute) dai->capture_widget->name); w = dai->capture_widget; snd_soc_dapm_widget_for_each_source_path(w, p) { - if (p->connected && !p->connected(w, p->sink)) + if (p->connected && !p->connected(w, p->source)) continue; if (p->connect && p->source->power && From 9779542003719b971d901c27f4af0d69e86026e5 Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Tue, 25 Feb 2020 10:31:02 +0100 Subject: [PATCH 0797/4444] gpiolib: export gpiochip_get_desc The function was currently used internal by the gpiolib. Since commit 56cc3af4e8c8 ("pinctrl: da9062: add driver support") it is also used by drivers so we need to export the symbol. Signed-off-by: Marco Felsch Link: https://lore.kernel.org/r/20200225093102.10964-1-m.felsch@pengutronix.de Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 753283486037..1dbd0e6d240b 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -149,6 +149,7 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, return &gdev->descs[hwnum]; } +EXPORT_SYMBOL_GPL(gpiochip_get_desc); /** * desc_to_gpio - convert a GPIO descriptor to the integer namespace From 5c2614e995de07b41eb355155eb5e0e3d593718b Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Fri, 21 Feb 2020 19:35:28 +0000 Subject: [PATCH 0798/4444] dt-bindings: ARM: Add recent Cortex/Neoverse CPUs The CPU group has been busy since we last updated these bindings... Add definitions for all the new Cortex-A and Neoverse cores now available. Signed-off-by: Robin Murphy Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/arm/cpus.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/cpus.yaml b/Documentation/devicetree/bindings/arm/cpus.yaml index 765af3cbd11f..f61a5a13fb42 100644 --- a/Documentation/devicetree/bindings/arm/cpus.yaml +++ b/Documentation/devicetree/bindings/arm/cpus.yaml @@ -123,11 +123,18 @@ properties: - arm,cortex-a12 - arm,cortex-a15 - arm,cortex-a17 + - arm,cortex-a32 + - arm,cortex-a34 + - arm,cortex-a35 - arm,cortex-a53 - arm,cortex-a55 - arm,cortex-a57 + - arm,cortex-a65 - arm,cortex-a72 - arm,cortex-a73 + - arm,cortex-a75 + - arm,cortex-a76 + - arm,cortex-a77 - arm,cortex-m0 - arm,cortex-m0+ - arm,cortex-m1 @@ -136,6 +143,8 @@ properties: - arm,cortex-r4 - arm,cortex-r5 - arm,cortex-r7 + - arm,neoverse-e1 + - arm,neoverse-n1 - brcm,brahma-b15 - brcm,brahma-b53 - brcm,vulcan From 05f9e9f7c9f477362b5adaa194a33270102abb5b Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Fri, 21 Feb 2020 19:35:29 +0000 Subject: [PATCH 0799/4444] dt-bindings: ARM: Add recent Cortex/Neoverse PMUs Add new PMU definitions to correspond with the CPU bindings. Signed-off-by: Robin Murphy Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/arm/pmu.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/pmu.yaml b/Documentation/devicetree/bindings/arm/pmu.yaml index 52ae094ce330..cc52195d0e9e 100644 --- a/Documentation/devicetree/bindings/arm/pmu.yaml +++ b/Documentation/devicetree/bindings/arm/pmu.yaml @@ -21,11 +21,20 @@ properties: - enum: - apm,potenza-pmu - arm,armv8-pmuv3 + - arm,neoverse-n1-pmu + - arm,neoverse-e1-pmu + - arm,cortex-a77-pmu + - arm,cortex-a76-pmu + - arm,cortex-a75-pmu - arm,cortex-a73-pmu - arm,cortex-a72-pmu + - arm,cortex-a65-pmu - arm,cortex-a57-pmu + - arm,cortex-a55-pmu - arm,cortex-a53-pmu - arm,cortex-a35-pmu + - arm,cortex-a34-pmu + - arm,cortex-a32-pmu - arm,cortex-a17-pmu - arm,cortex-a15-pmu - arm,cortex-a12-pmu From a8e446e49765bb680ac7681ab334d5baf9d25722 Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Fri, 21 Feb 2020 19:35:30 +0000 Subject: [PATCH 0800/4444] dt-bindings: ARM: Clean up PMU compatible list The "alpha by vendor, reverse-alpha by model" sorting of compatibles that we seem to have ended up with is decidedly odd. Make it less so. Also copy the comment from the generic "arm,armv8" CPU binding to help clarify that the "arm,armv8-pmuv3" binding is rather intended to be a counterpart to that, for describing implementations without a specific microarchitecture like the AEMv8 software model. Signed-off-by: Robin Murphy Signed-off-by: Rob Herring --- .../devicetree/bindings/arm/pmu.yaml | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/pmu.yaml b/Documentation/devicetree/bindings/arm/pmu.yaml index cc52195d0e9e..97df36d301c9 100644 --- a/Documentation/devicetree/bindings/arm/pmu.yaml +++ b/Documentation/devicetree/bindings/arm/pmu.yaml @@ -20,36 +20,36 @@ properties: items: - enum: - apm,potenza-pmu - - arm,armv8-pmuv3 - - arm,neoverse-n1-pmu - - arm,neoverse-e1-pmu - - arm,cortex-a77-pmu - - arm,cortex-a76-pmu - - arm,cortex-a75-pmu - - arm,cortex-a73-pmu - - arm,cortex-a72-pmu - - arm,cortex-a65-pmu - - arm,cortex-a57-pmu - - arm,cortex-a55-pmu - - arm,cortex-a53-pmu - - arm,cortex-a35-pmu - - arm,cortex-a34-pmu - - arm,cortex-a32-pmu - - arm,cortex-a17-pmu - - arm,cortex-a15-pmu - - arm,cortex-a12-pmu - - arm,cortex-a9-pmu - - arm,cortex-a8-pmu - - arm,cortex-a7-pmu - - arm,cortex-a5-pmu - - arm,arm11mpcore-pmu - - arm,arm1176-pmu + - arm,armv8-pmuv3 # Only for s/w models - arm,arm1136-pmu + - arm,arm1176-pmu + - arm,arm11mpcore-pmu + - arm,cortex-a5-pmu + - arm,cortex-a7-pmu + - arm,cortex-a8-pmu + - arm,cortex-a9-pmu + - arm,cortex-a12-pmu + - arm,cortex-a15-pmu + - arm,cortex-a17-pmu + - arm,cortex-a32-pmu + - arm,cortex-a34-pmu + - arm,cortex-a35-pmu + - arm,cortex-a53-pmu + - arm,cortex-a55-pmu + - arm,cortex-a57-pmu + - arm,cortex-a65-pmu + - arm,cortex-a72-pmu + - arm,cortex-a73-pmu + - arm,cortex-a75-pmu + - arm,cortex-a76-pmu + - arm,cortex-a77-pmu + - arm,neoverse-e1-pmu + - arm,neoverse-n1-pmu - brcm,vulcan-pmu - cavium,thunder-pmu + - qcom,krait-pmu - qcom,scorpion-pmu - qcom,scorpion-mp-pmu - - qcom,krait-pmu interrupts: # Don't know how many CPUs, so no constraints to specify From 632c99084052aef1c9dcfe43d2720306026d6d21 Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Mon, 24 Feb 2020 10:02:32 -0800 Subject: [PATCH 0801/4444] of: of_reserved_mem: Increase limit on number of reserved regions Certain SoCs need to support a large amount of reserved memory regions. For example, Qualcomm's SM8150 SoC requires that 20 regions of memory be reserved for a variety of reasons (e.g. loading a peripheral subsystem's firmware image into a particular space). When adding more reserved memory regions to cater to different usecases, the remaining number of reserved memory regions--12 to be exact--becomes too small. Thus, double the existing limit of reserved memory regions. Signed-off-by: Patrick Daly Signed-off-by: Isaac J. Manjarres Signed-off-by: Rob Herring --- drivers/of/of_reserved_mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 6bd610ee2cd7..1a84bc0d5fa8 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -22,7 +22,7 @@ #include #include -#define MAX_RESERVED_REGIONS 32 +#define MAX_RESERVED_REGIONS 64 static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; static int reserved_mem_count; From 05642cf7289c5562e5939d2ee8a0529d310010b8 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Tue, 7 Jan 2020 09:16:40 +0000 Subject: [PATCH 0802/4444] powerpc/32: don't restore r0, r6-r8 on exception entry path after trace_hardirqs_off() Since commit b86fb88855ea ("powerpc/32: implement fast entry for syscalls on non BOOKE") and commit 1a4b739bbb4f ("powerpc/32: implement fast entry for syscalls on BOOKE"), syscalls don't use the exception entry path anymore. It is therefore pointless to restore r0 and r6-r8 after calling trace_hardirqs_off(). In the meantime, drop the '2:' label which is unused and misleading. Signed-off-by: Christophe Leroy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/d2c6dc65d27e83964eb05f16a126161ab6455eea.1578388585.git.christophe.leroy@c-s.fr --- arch/powerpc/kernel/entry_32.S | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index ad000cbb5252..afab378c3d28 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -246,9 +246,8 @@ reenable_mmu: * r3 can be different from GPR3(r1) at this point, r9 and r11 * contains the old MSR and handler address respectively, * r4 & r5 can contain page fault arguments that need to be passed - * along as well. r12, CCR, CTR, XER etc... are left clobbered as - * they aren't useful past this point (aren't syscall arguments), - * the rest is restored from the exception frame. + * along as well. r0, r6-r8, r12, CCR, CTR, XER etc... are left + * clobbered as they aren't useful past this point. */ stwu r1,-32(r1) @@ -262,16 +261,12 @@ reenable_mmu: * lockdep */ 1: bl trace_hardirqs_off -2: lwz r5,24(r1) + lwz r5,24(r1) lwz r4,20(r1) lwz r3,16(r1) lwz r11,12(r1) lwz r9,8(r1) addi r1,r1,32 - lwz r0,GPR0(r1) - lwz r6,GPR6(r1) - lwz r7,GPR7(r1) - lwz r8,GPR8(r1) mtctr r11 mtlr r9 bctr /* jump to handler */ From 0b1c524caaae2428b20e714297243e5551251eb5 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Thu, 9 Jan 2020 08:25:25 +0000 Subject: [PATCH 0803/4444] powerpc/32: refactor pmd_offset(pud_offset(pgd_offset... At several places pmd pointer is retrieved through the same action: pmd = pmd_offset(pud_offset(pgd_offset(mm, addr), addr), addr); or pmd = pmd_offset(pud_offset(pgd_offset_k(addr), addr), addr); Refactor this by implementing two helpers pmd_ptr() and pmd_ptr_k() This will help when adding the p4d level. Signed-off-by: Christophe Leroy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/7b065c5be35726af4066cab238ee35cabceda1fa.1578558199.git.christophe.leroy@c-s.fr --- arch/powerpc/include/asm/pgtable.h | 12 ++++++++++++ arch/powerpc/mm/book3s32/mmu.c | 2 +- arch/powerpc/mm/book3s32/tlb.c | 4 ++-- arch/powerpc/mm/kasan/kasan_init_32.c | 8 ++++---- arch/powerpc/mm/mem.c | 3 +-- arch/powerpc/mm/nohash/40x.c | 4 ++-- arch/powerpc/mm/pgtable_32.c | 2 +- 7 files changed, 23 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index 8cc543ed114c..22bf7bb666a7 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h @@ -41,6 +41,18 @@ struct mm_struct; #ifndef __ASSEMBLY__ +#ifdef CONFIG_PPC32 +static inline pmd_t *pmd_ptr(struct mm_struct *mm, unsigned long va) +{ + return pmd_offset(pud_offset(pgd_offset(mm, va), va), va); +} + +static inline pmd_t *pmd_ptr_k(unsigned long va) +{ + return pmd_offset(pud_offset(pgd_offset_k(va), va), va); +} +#endif + #include /* Keep these as a macros to avoid include dependency mess */ diff --git a/arch/powerpc/mm/book3s32/mmu.c b/arch/powerpc/mm/book3s32/mmu.c index 0a1c65a2c565..c225b0397ffd 100644 --- a/arch/powerpc/mm/book3s32/mmu.c +++ b/arch/powerpc/mm/book3s32/mmu.c @@ -312,7 +312,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea) if (!Hash) return; - pmd = pmd_offset(pud_offset(pgd_offset(mm, ea), ea), ea); + pmd = pmd_ptr(mm, ea); if (!pmd_none(*pmd)) add_hash_page(mm->context.id, ea, pmd_val(*pmd)); } diff --git a/arch/powerpc/mm/book3s32/tlb.c b/arch/powerpc/mm/book3s32/tlb.c index 724c0490fb17..dc9039a170aa 100644 --- a/arch/powerpc/mm/book3s32/tlb.c +++ b/arch/powerpc/mm/book3s32/tlb.c @@ -90,7 +90,7 @@ static void flush_range(struct mm_struct *mm, unsigned long start, if (start >= end) return; end = (end - 1) | ~PAGE_MASK; - pmd = pmd_offset(pud_offset(pgd_offset(mm, start), start), start); + pmd = pmd_ptr(mm, start); for (;;) { pmd_end = ((start + PGDIR_SIZE) & PGDIR_MASK) - 1; if (pmd_end > end) @@ -148,7 +148,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) return; } mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm; - pmd = pmd_offset(pud_offset(pgd_offset(mm, vmaddr), vmaddr), vmaddr); + pmd = pmd_ptr(mm, vmaddr); if (!pmd_none(*pmd)) flush_hash_pages(mm->context.id, vmaddr, pmd_val(*pmd), 1); } diff --git a/arch/powerpc/mm/kasan/kasan_init_32.c b/arch/powerpc/mm/kasan/kasan_init_32.c index 16dd95bd0749..b195d085970a 100644 --- a/arch/powerpc/mm/kasan/kasan_init_32.c +++ b/arch/powerpc/mm/kasan/kasan_init_32.c @@ -36,7 +36,7 @@ static int __init kasan_init_shadow_page_tables(unsigned long k_start, unsigned unsigned long k_cur, k_next; pte_t *new = NULL; - pmd = pmd_offset(pud_offset(pgd_offset_k(k_start), k_start), k_start); + pmd = pmd_ptr_k(k_start); for (k_cur = k_start; k_cur != k_end; k_cur = k_next, pmd++) { k_next = pgd_addr_end(k_cur, k_end); @@ -78,7 +78,7 @@ static int __init kasan_init_region(void *start, size_t size) block = memblock_alloc(k_end - k_start, PAGE_SIZE); for (k_cur = k_start & PAGE_MASK; k_cur < k_end; k_cur += PAGE_SIZE) { - pmd_t *pmd = pmd_offset(pud_offset(pgd_offset_k(k_cur), k_cur), k_cur); + pmd_t *pmd = pmd_ptr_k(k_cur); void *va = block + k_cur - k_start; pte_t pte = pfn_pte(PHYS_PFN(__pa(va)), PAGE_KERNEL); @@ -102,7 +102,7 @@ static void __init kasan_remap_early_shadow_ro(void) kasan_populate_pte(kasan_early_shadow_pte, prot); for (k_cur = k_start & PAGE_MASK; k_cur < k_end; k_cur += PAGE_SIZE) { - pmd_t *pmd = pmd_offset(pud_offset(pgd_offset_k(k_cur), k_cur), k_cur); + pmd_t *pmd = pmd_ptr_k(k_cur); pte_t *ptep = pte_offset_kernel(pmd, k_cur); if ((pte_val(*ptep) & PTE_RPN_MASK) != pa) @@ -202,7 +202,7 @@ void __init kasan_early_init(void) unsigned long addr = KASAN_SHADOW_START; unsigned long end = KASAN_SHADOW_END; unsigned long next; - pmd_t *pmd = pmd_offset(pud_offset(pgd_offset_k(addr), addr), addr); + pmd_t *pmd = pmd_ptr_k(addr); BUILD_BUG_ON(KASAN_SHADOW_START & ~PGDIR_MASK); diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index ef7b1119b2e2..b7325bb4c890 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -69,8 +69,7 @@ EXPORT_SYMBOL(kmap_prot); static inline pte_t *virt_to_kpte(unsigned long vaddr) { - return pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), - vaddr), vaddr), vaddr); + return pte_offset_kernel(pmd_ptr_k(vaddr), vaddr); } #endif diff --git a/arch/powerpc/mm/nohash/40x.c b/arch/powerpc/mm/nohash/40x.c index f348104eb461..82862723ab42 100644 --- a/arch/powerpc/mm/nohash/40x.c +++ b/arch/powerpc/mm/nohash/40x.c @@ -104,7 +104,7 @@ unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top) pmd_t *pmdp; unsigned long val = p | _PMD_SIZE_16M | _PAGE_EXEC | _PAGE_HWWRITE; - pmdp = pmd_offset(pud_offset(pgd_offset_k(v), v), v); + pmdp = pmd_ptr_k(v); *pmdp++ = __pmd(val); *pmdp++ = __pmd(val); *pmdp++ = __pmd(val); @@ -119,7 +119,7 @@ unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top) pmd_t *pmdp; unsigned long val = p | _PMD_SIZE_4M | _PAGE_EXEC | _PAGE_HWWRITE; - pmdp = pmd_offset(pud_offset(pgd_offset_k(v), v), v); + pmdp = pmd_ptr_k(v); *pmdp = __pmd(val); v += LARGE_PAGE_SIZE_4M; diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index 5fb90edd865e..d90c166bb6e5 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c @@ -63,7 +63,7 @@ int __ref map_kernel_page(unsigned long va, phys_addr_t pa, pgprot_t prot) int err = -ENOMEM; /* Use upper 10 bits of VA to index the first level map */ - pd = pmd_offset(pud_offset(pgd_offset_k(va), va), va); + pd = pmd_ptr_k(va); /* Use middle 10 bits of VA to index the second-level map */ if (likely(slab_is_available())) pg = pte_alloc_kernel(pd, va); From 2efc7c085f05870eda6f29ac71eeb83f3bd54415 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Thu, 9 Jan 2020 08:25:26 +0000 Subject: [PATCH 0804/4444] powerpc/32: drop get_pteptr() Commit 8d30c14cab30 ("powerpc/mm: Rework I$/D$ coherency (v3)") and commit 90ac19a8b21b ("[POWERPC] Abolish iopa(), mm_ptov(), io_block_mapping() from arch/powerpc") removed the use of get_pteptr() outside of mm/pgtable_32.c In mm/pgtable_32.c, the only user of get_pteptr() is change_page_attr() which operates on kernel context and on lowmem pages only. Make virt_to_kpte() available outside of mm/mem.c and use it instead of get_pteptr(), and drop get_pteptr() Signed-off-by: Christophe Leroy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/788378c6c3ba5c5298caab7c7f95e6c3c88244b8.1578558199.git.christophe.leroy@c-s.fr --- arch/powerpc/include/asm/pgtable.h | 5 ++++ arch/powerpc/mm/mem.c | 5 ---- arch/powerpc/mm/pgtable_32.c | 39 ++---------------------------- 3 files changed, 7 insertions(+), 42 deletions(-) diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index 22bf7bb666a7..b80bfd41828d 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h @@ -51,6 +51,11 @@ static inline pmd_t *pmd_ptr_k(unsigned long va) { return pmd_offset(pud_offset(pgd_offset_k(va), va), va); } + +static inline pte_t *virt_to_kpte(unsigned long vaddr) +{ + return pte_offset_kernel(pmd_ptr_k(vaddr), vaddr); +} #endif #include diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index b7325bb4c890..4f852d2a62f5 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -66,11 +66,6 @@ pte_t *kmap_pte; EXPORT_SYMBOL(kmap_pte); pgprot_t kmap_prot; EXPORT_SYMBOL(kmap_prot); - -static inline pte_t *virt_to_kpte(unsigned long vaddr) -{ - return pte_offset_kernel(pmd_ptr_k(vaddr), vaddr); -} #endif pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index d90c166bb6e5..f62de06e3d07 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c @@ -121,44 +121,9 @@ void __init mapin_ram(void) } } -/* Scan the real Linux page tables and return a PTE pointer for - * a virtual address in a context. - * Returns true (1) if PTE was found, zero otherwise. The pointer to - * the PTE pointer is unmodified if PTE is not found. - */ -static int -get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp) -{ - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - int retval = 0; - - pgd = pgd_offset(mm, addr & PAGE_MASK); - if (pgd) { - pud = pud_offset(pgd, addr & PAGE_MASK); - if (pud && pud_present(*pud)) { - pmd = pmd_offset(pud, addr & PAGE_MASK); - if (pmd_present(*pmd)) { - pte = pte_offset_map(pmd, addr & PAGE_MASK); - if (pte) { - retval = 1; - *ptep = pte; - if (pmdp) - *pmdp = pmd; - /* XXX caller needs to do pte_unmap, yuck */ - } - } - } - } - return(retval); -} - static int __change_page_attr_noflush(struct page *page, pgprot_t prot) { pte_t *kpte; - pmd_t *kpmd; unsigned long address; BUG_ON(PageHighMem(page)); @@ -166,10 +131,10 @@ static int __change_page_attr_noflush(struct page *page, pgprot_t prot) if (v_block_mapped(address)) return 0; - if (!get_pteptr(&init_mm, address, &kpte, &kpmd)) + kpte = virt_to_kpte(address); + if (!kpte) return -EINVAL; __set_pte_at(&init_mm, address, kpte, mk_pte(page, prot), 0); - pte_unmap(kpte); return 0; } From 59986527f55b711048f1c8c3ac3020bbd0c32341 Mon Sep 17 00:00:00 2001 From: Sricharan R Date: Sun, 19 Jan 2020 18:43:21 +0530 Subject: [PATCH 0805/4444] arm64: defconfig: Enable qcom ipq6018 clock and pinctrl These configs are required for booting kernel in qcom ipq6018 boards. Reviewed-by: Bjorn Andersson Signed-off-by: Sricharan R Link: https://lore.kernel.org/r/1579439601-14810-6-git-send-email-sricharan@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/configs/defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index fca2b43affb7..a650b87d2d4b 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -413,6 +413,7 @@ CONFIG_PINCTRL_IMX8MN=y CONFIG_PINCTRL_IMX8MQ=y CONFIG_PINCTRL_IMX8QXP=y CONFIG_PINCTRL_IPQ8074=y +CONFIG_PINCTRL_IPQ6018=y CONFIG_PINCTRL_MSM8916=y CONFIG_PINCTRL_MSM8994=y CONFIG_PINCTRL_MSM8996=y @@ -726,6 +727,7 @@ CONFIG_QCOM_CLK_APCS_MSM8916=y CONFIG_QCOM_CLK_SMD_RPM=y CONFIG_QCOM_CLK_RPMH=y CONFIG_IPQ_GCC_8074=y +CONFIG_IPQ_GCC_6018=y CONFIG_MSM_GCC_8916=y CONFIG_MSM_GCC_8994=y CONFIG_MSM_MMCC_8996=y From 71f873169a80729f1b5efeae88e84b5beafa73cb Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Tue, 7 Jan 2020 16:15:24 +0530 Subject: [PATCH 0806/4444] arm64: dts: qcom: sc7180: Add dynamic CPU power coefficients Add dynamic power coefficients for Silver and Gold CPUs on SC7180 SoC. Signed-off-by: Rajendra Nayak Link: https://lore.kernel.org/r/1578393926-5052-1-git-send-email-rnayak@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sc7180.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index 2f1b3a1d92ea..8ebfa2e2741d 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -89,6 +89,7 @@ compatible = "arm,armv8"; reg = <0x0 0x0>; enable-method = "psci"; + dynamic-power-coefficient = <100>; next-level-cache = <&L2_0>; #cooling-cells = <2>; qcom,freq-domain = <&cpufreq_hw 0>; @@ -106,6 +107,7 @@ compatible = "arm,armv8"; reg = <0x0 0x100>; enable-method = "psci"; + dynamic-power-coefficient = <100>; next-level-cache = <&L2_100>; #cooling-cells = <2>; qcom,freq-domain = <&cpufreq_hw 0>; @@ -120,6 +122,7 @@ compatible = "arm,armv8"; reg = <0x0 0x200>; enable-method = "psci"; + dynamic-power-coefficient = <100>; next-level-cache = <&L2_200>; #cooling-cells = <2>; qcom,freq-domain = <&cpufreq_hw 0>; @@ -134,6 +137,7 @@ compatible = "arm,armv8"; reg = <0x0 0x300>; enable-method = "psci"; + dynamic-power-coefficient = <100>; next-level-cache = <&L2_300>; #cooling-cells = <2>; qcom,freq-domain = <&cpufreq_hw 0>; @@ -148,6 +152,7 @@ compatible = "arm,armv8"; reg = <0x0 0x400>; enable-method = "psci"; + dynamic-power-coefficient = <100>; next-level-cache = <&L2_400>; #cooling-cells = <2>; qcom,freq-domain = <&cpufreq_hw 0>; @@ -162,6 +167,7 @@ compatible = "arm,armv8"; reg = <0x0 0x500>; enable-method = "psci"; + dynamic-power-coefficient = <100>; next-level-cache = <&L2_500>; #cooling-cells = <2>; qcom,freq-domain = <&cpufreq_hw 0>; @@ -176,6 +182,7 @@ compatible = "arm,armv8"; reg = <0x0 0x600>; enable-method = "psci"; + dynamic-power-coefficient = <405>; next-level-cache = <&L2_600>; #cooling-cells = <2>; qcom,freq-domain = <&cpufreq_hw 1>; @@ -190,6 +197,7 @@ compatible = "arm,armv8"; reg = <0x0 0x700>; enable-method = "psci"; + dynamic-power-coefficient = <405>; next-level-cache = <&L2_700>; #cooling-cells = <2>; qcom,freq-domain = <&cpufreq_hw 1>; From e7bb680f917d019c6be660b77139ea5d75ccb8b0 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Tue, 7 Jan 2020 16:15:25 +0530 Subject: [PATCH 0807/4444] arm64: dts: qcom: sc7180: Add CPU capacity values Specify the relative CPU capacity of all SC7180 cpu cores. Signed-off-by: Rajendra Nayak Link: https://lore.kernel.org/r/1578393926-5052-2-git-send-email-rnayak@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sc7180.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index 8ebfa2e2741d..c754b4bf3273 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -89,6 +89,7 @@ compatible = "arm,armv8"; reg = <0x0 0x0>; enable-method = "psci"; + capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; next-level-cache = <&L2_0>; #cooling-cells = <2>; @@ -107,6 +108,7 @@ compatible = "arm,armv8"; reg = <0x0 0x100>; enable-method = "psci"; + capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; next-level-cache = <&L2_100>; #cooling-cells = <2>; @@ -122,6 +124,7 @@ compatible = "arm,armv8"; reg = <0x0 0x200>; enable-method = "psci"; + capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; next-level-cache = <&L2_200>; #cooling-cells = <2>; @@ -137,6 +140,7 @@ compatible = "arm,armv8"; reg = <0x0 0x300>; enable-method = "psci"; + capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; next-level-cache = <&L2_300>; #cooling-cells = <2>; @@ -152,6 +156,7 @@ compatible = "arm,armv8"; reg = <0x0 0x400>; enable-method = "psci"; + capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; next-level-cache = <&L2_400>; #cooling-cells = <2>; @@ -167,6 +172,7 @@ compatible = "arm,armv8"; reg = <0x0 0x500>; enable-method = "psci"; + capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; next-level-cache = <&L2_500>; #cooling-cells = <2>; @@ -182,6 +188,7 @@ compatible = "arm,armv8"; reg = <0x0 0x600>; enable-method = "psci"; + capacity-dmips-mhz = <1740>; dynamic-power-coefficient = <405>; next-level-cache = <&L2_600>; #cooling-cells = <2>; @@ -197,6 +204,7 @@ compatible = "arm,armv8"; reg = <0x0 0x700>; enable-method = "psci"; + capacity-dmips-mhz = <1740>; dynamic-power-coefficient = <405>; next-level-cache = <&L2_700>; #cooling-cells = <2>; From 83e5e33eaba2df888cfd5a2cd9319c0637ebc93d Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Tue, 7 Jan 2020 16:15:26 +0530 Subject: [PATCH 0808/4444] arm64: dts: qcom: sc7180: Add CPU topology SC7180 has 2 big cores and 6 LITTLE ones in a single cluster with shared L3. Signed-off-by: Rajendra Nayak Link: https://lore.kernel.org/r/1578393926-5052-3-git-send-email-rnayak@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sc7180.dtsi | 36 ++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index c754b4bf3273..97cfc113c9b3 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -214,6 +214,42 @@ next-level-cache = <&L3_0>; }; }; + + cpu-map { + cluster0 { + core0 { + cpu = <&CPU0>; + }; + + core1 { + cpu = <&CPU1>; + }; + + core2 { + cpu = <&CPU2>; + }; + + core3 { + cpu = <&CPU3>; + }; + + core4 { + cpu = <&CPU4>; + }; + + core5 { + cpu = <&CPU5>; + }; + + core6 { + cpu = <&CPU6>; + }; + + core7 { + cpu = <&CPU7>; + }; + }; + }; }; memory@80000000 { From 0e4621a4711a56a223f9f41e1c82a41882c7af1d Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Tue, 14 Jan 2020 18:23:33 +0530 Subject: [PATCH 0809/4444] arm64: dts: sc7180: Add Venus video codec DT node This adds Venus video codec DT node for sc7180. Reviewed-by: Stanimir Varbanov Signed-off-by: Dikshita Agarwal Link: https://lore.kernel.org/r/1579006416-11599-2-git-send-email-dikshita@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sc7180.dtsi | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index 97cfc113c9b3..127be85bbfd7 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -78,6 +78,11 @@ reg = <0x0 0x80900000 0x0 0x200000>; no-map; }; + + venus_mem: memory@8f600000 { + reg = <0 0x8f600000 0 0x500000>; + no-map; + }; }; cpus { @@ -1401,6 +1406,32 @@ #power-domain-cells = <1>; }; + venus: video-codec@aa00000 { + compatible = "qcom,sc7180-venus"; + reg = <0 0x0aa00000 0 0xff000>; + interrupts = ; + power-domains = <&videocc VENUS_GDSC>, + <&videocc VCODEC0_GDSC>; + power-domain-names = "venus", "vcodec0"; + clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>, + <&videocc VIDEO_CC_VENUS_AHB_CLK>, + <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>, + <&videocc VIDEO_CC_VCODEC0_CORE_CLK>, + <&videocc VIDEO_CC_VCODEC0_AXI_CLK>; + clock-names = "core", "iface", "bus", + "vcodec0_core", "vcodec0_bus"; + iommus = <&apps_smmu 0x0c00 0x60>; + memory-region = <&venus_mem>; + + video-decoder { + compatible = "venus-decoder"; + }; + + video-encoder { + compatible = "venus-encoder"; + }; + }; + pdc: interrupt-controller@b220000 { compatible = "qcom,sc7180-pdc", "qcom,pdc"; reg = <0 0x0b220000 0 0x30000>; From 2fefa8a169747c5a1d280633521b01d920ce24a9 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Tue, 14 Jan 2020 18:23:36 +0530 Subject: [PATCH 0810/4444] arm64: dts: sc7180: Add Venus firmware subnode This adds Venus firmware subnode for non-TZ platform. Reviewed-by: Stanimir Varbanov Signed-off-by: Dikshita Agarwal Link: https://lore.kernel.org/r/1579006416-11599-5-git-send-email-dikshita@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sc7180-idp.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sc7180-idp.dts b/arch/arm64/boot/dts/qcom/sc7180-idp.dts index 38ca36bd722d..043c9b9b5024 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-idp.dts +++ b/arch/arm64/boot/dts/qcom/sc7180-idp.dts @@ -321,6 +321,12 @@ vdda-pll-supply = <&vreg_l4a_0p8>; }; +&venus { + video-firmware { + iommus = <&apps_smmu 0x0c42 0x0>; + }; +}; + /* PINCTRL - additions to nodes defined in sc7180.dtsi */ &qspi_clk { From 129ff51d8edc4db7df821b36343f6a29580ccd26 Mon Sep 17 00:00:00 2001 From: Sandeep Maheswaram Date: Wed, 12 Feb 2020 16:51:28 +0530 Subject: [PATCH 0811/4444] arm64: dts: qcom: sc7180: Correct qmp phy reset entries The phy reset entries were incorrect.so swapped them. Reviewed-by: Matthias Kaehlcke Signed-off-by: Sandeep Maheswaram Link: https://lore.kernel.org/r/1581506488-26881-5-git-send-email-sanm@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sc7180.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index 127be85bbfd7..7cebc1fad7e0 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -1306,8 +1306,8 @@ <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>; clock-names = "aux", "cfg_ahb", "ref", "com_aux"; - resets = <&gcc GCC_USB3_DP_PHY_PRIM_BCR>, - <&gcc GCC_USB3_PHY_PRIM_BCR>; + resets = <&gcc GCC_USB3_PHY_PRIM_BCR>, + <&gcc GCC_USB3_DP_PHY_PRIM_BCR>; reset-names = "phy", "common"; usb_1_ssphy: phy@88e9200 { From a3db7ad1af49c73fce5feb419c03351ee28e3db9 Mon Sep 17 00:00:00 2001 From: Harigovindan P Date: Tue, 4 Feb 2020 19:45:07 +0530 Subject: [PATCH 0812/4444] arm64: dts: sc7180: add display dt nodes Add display, DSI hardware DT nodes for sc7180. Tested-by: Douglas Anderson Reviewed-by: Douglas Anderson Co-developed-by: Kalyan Thota Signed-off-by: Kalyan Thota Signed-off-by: Harigovindan P Link: https://lore.kernel.org/r/1580825707-27115-1-git-send-email-harigovi@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sc7180.dtsi | 136 ++++++++++++++++++++++++++- 1 file changed, 134 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index 7cebc1fad7e0..253274d5f04c 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -1386,13 +1386,145 @@ #power-domain-cells = <1>; }; + mdss: mdss@ae00000 { + compatible = "qcom,sc7180-mdss"; + reg = <0 0x0ae00000 0 0x1000>; + reg-names = "mdss"; + + power-domains = <&dispcc MDSS_GDSC>; + + clocks = <&gcc GCC_DISP_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>; + clock-names = "iface", "bus", "ahb", "core"; + + assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>; + assigned-clock-rates = <300000000>; + + interrupts = ; + interrupt-controller; + #interrupt-cells = <1>; + + iommus = <&apps_smmu 0x800 0x2>; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + status = "disabled"; + + mdp: mdp@ae01000 { + compatible = "qcom,sc7180-dpu"; + reg = <0 0x0ae01000 0 0x8f000>, + <0 0x0aeb0000 0 0x2008>; + reg-names = "mdp", "vbif"; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_ROT_CLK>, + <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>, + <&dispcc DISP_CC_MDSS_VSYNC_CLK>; + clock-names = "iface", "rot", "lut", "core", + "vsync"; + assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>, + <&dispcc DISP_CC_MDSS_VSYNC_CLK>; + assigned-clock-rates = <300000000>, + <19200000>; + + interrupt-parent = <&mdss>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dpu_intf1_out: endpoint { + remote-endpoint = <&dsi0_in>; + }; + }; + }; + }; + + dsi0: dsi@ae94000 { + compatible = "qcom,mdss-dsi-ctrl"; + reg = <0 0x0ae94000 0 0x400>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <4 IRQ_TYPE_LEVEL_HIGH>; + + clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>, + <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>, + <&dispcc DISP_CC_MDSS_PCLK0_CLK>, + <&dispcc DISP_CC_MDSS_ESC0_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>; + clock-names = "byte", + "byte_intf", + "pixel", + "core", + "iface", + "bus"; + + phys = <&dsi_phy>; + phy-names = "dsi"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dsi0_in: endpoint { + remote-endpoint = <&dpu_intf1_out>; + }; + }; + + port@1 { + reg = <1>; + dsi0_out: endpoint { + }; + }; + }; + }; + + dsi_phy: dsi-phy@ae94400 { + compatible = "qcom,dsi-phy-10nm"; + reg = <0 0x0ae94400 0 0x200>, + <0 0x0ae94600 0 0x280>, + <0 0x0ae94a00 0 0x1e0>; + reg-names = "dsi_phy", + "dsi_phy_lane", + "dsi_pll"; + + #clock-cells = <1>; + #phy-cells = <0>; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&rpmhcc RPMH_CXO_CLK>; + clock-names = "iface", "ref"; + + status = "disabled"; + }; + }; + dispcc: clock-controller@af00000 { compatible = "qcom,sc7180-dispcc"; reg = <0 0x0af00000 0 0x200000>; clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GCC_DISP_GPLL0_CLK_SRC>, - <0>, - <0>, + <&dsi_phy 0>, + <&dsi_phy 1>, <0>, <0>; clock-names = "bi_tcxo", From d3a9ad1163a8b71833a023328b9773969edb8392 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 8 Nov 2019 18:42:34 -0800 Subject: [PATCH 0813/4444] arm64: defconfig: Enable Qualcomm SDM845 display and gpu clocks Enable the drivers for the display and gpu clock controllers on Qualcomm SDM845, needed in order to get these features working. These drivers provides power-domains and can as such not be compiled as modules. Acked-by: Will Deacon Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20191109024234.1757452-1-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- arch/arm64/configs/defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index a650b87d2d4b..0d8ee75cccb8 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -734,6 +734,8 @@ CONFIG_MSM_MMCC_8996=y CONFIG_MSM_GCC_8998=y CONFIG_QCS_GCC_404=y CONFIG_SDM_GCC_845=y +CONFIG_SDM_GPUCC_845=y +CONFIG_SDM_DISPCC_845=y CONFIG_SM_GCC_8150=y CONFIG_QCOM_HFPLL=y CONFIG_HWSPINLOCK=y From eb751d9f1fb1cfcd8c2164af8b06ce3180b9efae Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 25 Feb 2020 11:00:39 -0600 Subject: [PATCH 0814/4444] soundwire: cadence: remove useless prototypes These prototypes are no longer used, remove. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200225170041.23644-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/cadence_master.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/soundwire/cadence_master.h b/drivers/soundwire/cadence_master.h index 001457cbe5ad..2de1b2493ffc 100644 --- a/drivers/soundwire/cadence_master.h +++ b/drivers/soundwire/cadence_master.h @@ -148,20 +148,12 @@ int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns, bool state); void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root); #endif -int sdw_cdns_get_stream(struct sdw_cdns *cdns, - struct sdw_cdns_streams *stream, - u32 ch, u32 dir); struct sdw_cdns_pdi *sdw_cdns_alloc_pdi(struct sdw_cdns *cdns, struct sdw_cdns_streams *stream, u32 ch, u32 dir, int dai_id); void sdw_cdns_config_stream(struct sdw_cdns *cdns, u32 ch, u32 dir, struct sdw_cdns_pdi *pdi); -int sdw_cdns_pcm_set_stream(struct snd_soc_dai *dai, - void *stream, int direction); -int sdw_cdns_pdm_set_stream(struct snd_soc_dai *dai, - void *stream, int direction); - enum sdw_command_response cdns_reset_page_addr(struct sdw_bus *bus, unsigned int dev_num); From 2c6cff682d6681fb1cdb03b3cdbbecd3fb0e4c89 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 25 Feb 2020 11:00:41 -0600 Subject: [PATCH 0815/4444] soundwire: add helper macros for devID fields Move bit extractors to macros, so that the definitions can be used by other drivers parsing the MIPI definitions extracted from firmware tables (ACPI or DT). Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200225170041.23644-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/bus.c | 21 +++++---------------- include/linux/soundwire/sdw.h | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 6106577fb3ed..ab35b09e7231 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -504,22 +504,11 @@ void sdw_extract_slave_id(struct sdw_bus *bus, { dev_dbg(bus->dev, "SDW Slave Addr: %llx\n", addr); - /* - * Spec definition - * Register Bit Contents - * DevId_0 [7:4] 47:44 sdw_version - * DevId_0 [3:0] 43:40 unique_id - * DevId_1 39:32 mfg_id [15:8] - * DevId_2 31:24 mfg_id [7:0] - * DevId_3 23:16 part_id [15:8] - * DevId_4 15:08 part_id [7:0] - * DevId_5 07:00 class_id - */ - id->sdw_version = (addr >> 44) & GENMASK(3, 0); - id->unique_id = (addr >> 40) & GENMASK(3, 0); - id->mfg_id = (addr >> 24) & GENMASK(15, 0); - id->part_id = (addr >> 8) & GENMASK(15, 0); - id->class_id = addr & GENMASK(7, 0); + id->sdw_version = SDW_VERSION(addr); + id->unique_id = SDW_UNIQUE_ID(addr); + id->mfg_id = SDW_MFG_ID(addr); + id->part_id = SDW_PART_ID(addr); + id->class_id = SDW_CLASS_ID(addr); dev_dbg(bus->dev, "SDW Slave class_id %x, part_id %x, mfg_id %x, unique_id %x, version %x\n", diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index b451bb622335..56273c5c1f6b 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -424,6 +424,29 @@ struct sdw_slave_id { __u8 sdw_version:4; }; +/* + * Helper macros to extract the MIPI-defined IDs + * + * Spec definition + * Register Bit Contents + * DevId_0 [7:4] 47:44 sdw_version + * DevId_0 [3:0] 43:40 unique_id + * DevId_1 39:32 mfg_id [15:8] + * DevId_2 31:24 mfg_id [7:0] + * DevId_3 23:16 part_id [15:8] + * DevId_4 15:08 part_id [7:0] + * DevId_5 07:00 class_id + * + * The MIPI DisCo for SoundWire defines in addition the link_id as bits 51:48 + */ + +#define SDW_DISCO_LINK_ID(adr) (((adr) >> 48) & GENMASK(3, 0)) +#define SDW_VERSION(adr) (((adr) >> 44) & GENMASK(3, 0)) +#define SDW_UNIQUE_ID(adr) (((adr) >> 40) & GENMASK(3, 0)) +#define SDW_MFG_ID(adr) (((adr) >> 24) & GENMASK(15, 0)) +#define SDW_PART_ID(adr) (((adr) >> 8) & GENMASK(15, 0)) +#define SDW_CLASS_ID(adr) ((adr) & GENMASK(7, 0)) + /** * struct sdw_slave_intr_status - Slave interrupt status * @control_port: control port status From 5e50ee27d4a52a817ab152128c48690ec7c5cdf1 Mon Sep 17 00:00:00 2001 From: Vidya Sagar Date: Mon, 17 Feb 2020 17:40:36 +0530 Subject: [PATCH 0816/4444] PCI: pci-epf-test: Add support to defer core initialization Add support to defer core initialization for the endpoint mode of operation. This would enable support for implementations where the core initialization needs to be deferred until the PCIe reference clock is available from the host system. Signed-off-by: Vidya Sagar [lorenzo.pieralisi@arm.com: commit log] Signed-off-by: Lorenzo Pieralisi Acked-by: Kishon Vijay Abraham I --- drivers/pci/endpoint/functions/pci-epf-test.c | 118 ++++++++++++------ 1 file changed, 77 insertions(+), 41 deletions(-) diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index bddff15052cc..be04c6220265 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -360,18 +360,6 @@ reset_handler: msecs_to_jiffies(1)); } -static int pci_epf_test_notifier(struct notifier_block *nb, unsigned long val, - void *data) -{ - struct pci_epf *epf = container_of(nb, struct pci_epf, nb); - struct pci_epf_test *epf_test = epf_get_drvdata(epf); - - queue_delayed_work(kpcitest_workqueue, &epf_test->cmd_handler, - msecs_to_jiffies(1)); - - return NOTIFY_OK; -} - static void pci_epf_test_unbind(struct pci_epf *epf) { struct pci_epf_test *epf_test = epf_get_drvdata(epf); @@ -428,6 +416,78 @@ static int pci_epf_test_set_bar(struct pci_epf *epf) return 0; } +static int pci_epf_test_core_init(struct pci_epf *epf) +{ + struct pci_epf_header *header = epf->header; + const struct pci_epc_features *epc_features; + struct pci_epc *epc = epf->epc; + struct device *dev = &epf->dev; + bool msix_capable = false; + bool msi_capable = true; + int ret; + + epc_features = pci_epc_get_features(epc, epf->func_no); + if (epc_features) { + msix_capable = epc_features->msix_capable; + msi_capable = epc_features->msi_capable; + } + + ret = pci_epc_write_header(epc, epf->func_no, header); + if (ret) { + dev_err(dev, "Configuration header write failed\n"); + return ret; + } + + ret = pci_epf_test_set_bar(epf); + if (ret) + return ret; + + if (msi_capable) { + ret = pci_epc_set_msi(epc, epf->func_no, epf->msi_interrupts); + if (ret) { + dev_err(dev, "MSI configuration failed\n"); + return ret; + } + } + + if (msix_capable) { + ret = pci_epc_set_msix(epc, epf->func_no, epf->msix_interrupts); + if (ret) { + dev_err(dev, "MSI-X configuration failed\n"); + return ret; + } + } + + return 0; +} + +static int pci_epf_test_notifier(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct pci_epf *epf = container_of(nb, struct pci_epf, nb); + struct pci_epf_test *epf_test = epf_get_drvdata(epf); + int ret; + + switch (val) { + case CORE_INIT: + ret = pci_epf_test_core_init(epf); + if (ret) + return NOTIFY_BAD; + break; + + case LINK_UP: + queue_delayed_work(kpcitest_workqueue, &epf_test->cmd_handler, + msecs_to_jiffies(1)); + break; + + default: + dev_err(&epf->dev, "Invalid EPF test notifier event\n"); + return NOTIFY_BAD; + } + + return NOTIFY_OK; +} + static int pci_epf_test_alloc_space(struct pci_epf *epf) { struct pci_epf_test *epf_test = epf_get_drvdata(epf); @@ -496,14 +556,11 @@ static int pci_epf_test_bind(struct pci_epf *epf) { int ret; struct pci_epf_test *epf_test = epf_get_drvdata(epf); - struct pci_epf_header *header = epf->header; const struct pci_epc_features *epc_features; enum pci_barno test_reg_bar = BAR_0; struct pci_epc *epc = epf->epc; - struct device *dev = &epf->dev; bool linkup_notifier = false; - bool msix_capable = false; - bool msi_capable = true; + bool core_init_notifier = false; if (WARN_ON_ONCE(!epc)) return -EINVAL; @@ -511,8 +568,7 @@ static int pci_epf_test_bind(struct pci_epf *epf) epc_features = pci_epc_get_features(epc, epf->func_no); if (epc_features) { linkup_notifier = epc_features->linkup_notifier; - msix_capable = epc_features->msix_capable; - msi_capable = epc_features->msi_capable; + core_init_notifier = epc_features->core_init_notifier; test_reg_bar = pci_epc_get_first_free_bar(epc_features); pci_epf_configure_bar(epf, epc_features); } @@ -520,34 +576,14 @@ static int pci_epf_test_bind(struct pci_epf *epf) epf_test->test_reg_bar = test_reg_bar; epf_test->epc_features = epc_features; - ret = pci_epc_write_header(epc, epf->func_no, header); - if (ret) { - dev_err(dev, "Configuration header write failed\n"); - return ret; - } - ret = pci_epf_test_alloc_space(epf); if (ret) return ret; - ret = pci_epf_test_set_bar(epf); - if (ret) - return ret; - - if (msi_capable) { - ret = pci_epc_set_msi(epc, epf->func_no, epf->msi_interrupts); - if (ret) { - dev_err(dev, "MSI configuration failed\n"); + if (!core_init_notifier) { + ret = pci_epf_test_core_init(epf); + if (ret) return ret; - } - } - - if (msix_capable) { - ret = pci_epc_set_msix(epc, epf->func_no, epf->msix_interrupts); - if (ret) { - dev_err(dev, "MSI-X configuration failed\n"); - return ret; - } } if (linkup_notifier) { From 19e5cef058a0089af4148d79af4658245a6952d2 Mon Sep 17 00:00:00 2001 From: Kamel Bouhara Date: Wed, 15 Jan 2020 13:54:17 +0200 Subject: [PATCH 0817/4444] dt-bindings: i2c: at91: document optional bus recovery properties The at91 I2C controller can support bus recovery by re-assigning SCL and SDA to gpios. Add the optional pinctrl and gpio properties to do so. Signed-off-by: Kamel Bouhara [codrin.ciubotariu@microchip.com: rebased] Signed-off-by: Codrin Ciubotariu Reviewed-by: Rob Herring Acked-by: Ludovic Desroches Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-at91.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/i2c/i2c-at91.txt b/Documentation/devicetree/bindings/i2c/i2c-at91.txt index d4bad86107b8..96c914e048f5 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-at91.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-at91.txt @@ -28,8 +28,13 @@ Optional properties: "atmel,sama5d4-i2c", "atmel,sama5d2-i2c", "microchip,sam9x60-i2c". +- scl-gpios: specify the gpio related to SCL pin +- sda-gpios: specify the gpio related to SDA pin +- pinctrl: add extra pinctrl to configure i2c pins to gpio function for i2c + bus recovery, call it "gpio" state - Child nodes conforming to i2c bus binding + Examples : i2c0: i2c@fff84000 { @@ -64,6 +69,11 @@ i2c0: i2c@f8034600 { clocks = <&flx0>; atmel,fifo-size = <16>; i2c-sda-hold-time-ns = <336>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c0>; + pinctrl-1 = <&pinctrl_i2c0_gpio>; + sda-gpios = <&pioA 30 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioA 31 GPIO_ACTIVE_HIGH>; wm8731: wm8731@1a { compatible = "wm8731"; From d3d3fdcc4c90fed42b400999721a5b535a310533 Mon Sep 17 00:00:00 2001 From: Kamel Bouhara Date: Wed, 15 Jan 2020 13:54:18 +0200 Subject: [PATCH 0818/4444] i2c: at91: implement i2c bus recovery Implement i2c bus recovery when slaves devices might hold SDA low. In this case re-assign SCL/SDA to gpios and issue 9 dummy clock pulses until the slave release SDA. Signed-off-by: Kamel Bouhara Signed-off-by: Codrin Ciubotariu Acked-by: Ludovic Desroches Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-at91-master.c | 78 ++++++++++++++++++++++++++++ drivers/i2c/busses/i2c-at91.h | 4 ++ 2 files changed, 82 insertions(+) diff --git a/drivers/i2c/busses/i2c-at91-master.c b/drivers/i2c/busses/i2c-at91-master.c index 7a862e00b475..0aba51a7df32 100644 --- a/drivers/i2c/busses/i2c-at91-master.c +++ b/drivers/i2c/busses/i2c-at91-master.c @@ -18,11 +18,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -478,6 +480,7 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) unsigned long time_left; bool has_unre_flag = dev->pdata->has_unre_flag; bool has_alt_cmd = dev->pdata->has_alt_cmd; + struct i2c_bus_recovery_info *rinfo = &dev->rinfo; /* * WARNING: the TXCOMP bit in the Status Register is NOT a clear on @@ -637,6 +640,13 @@ error: at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_THRCLR | AT91_TWI_LOCKCLR); } + + if (rinfo->get_sda && !(rinfo->get_sda(&dev->adapter))) { + dev_dbg(dev->dev, + "SDA is down; clear bus using gpio\n"); + i2c_recover_bus(&dev->adapter); + } + return ret; } @@ -806,6 +816,70 @@ error: return ret; } +static void at91_prepare_twi_recovery(struct i2c_adapter *adap) +{ + struct at91_twi_dev *dev = i2c_get_adapdata(adap); + + pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_gpio); +} + +static void at91_unprepare_twi_recovery(struct i2c_adapter *adap) +{ + struct at91_twi_dev *dev = i2c_get_adapdata(adap); + + pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_default); +} + +static int at91_init_twi_recovery_info(struct platform_device *pdev, + struct at91_twi_dev *dev) +{ + struct i2c_bus_recovery_info *rinfo = &dev->rinfo; + + dev->pinctrl = devm_pinctrl_get(&pdev->dev); + if (!dev->pinctrl || IS_ERR(dev->pinctrl)) { + dev_info(dev->dev, "can't get pinctrl, bus recovery not supported\n"); + return PTR_ERR(dev->pinctrl); + } + + dev->pinctrl_pins_default = pinctrl_lookup_state(dev->pinctrl, + PINCTRL_STATE_DEFAULT); + dev->pinctrl_pins_gpio = pinctrl_lookup_state(dev->pinctrl, + "gpio"); + rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN); + if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl", + GPIOD_OUT_HIGH_OPEN_DRAIN); + if (PTR_ERR(rinfo->scl_gpiod) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + if (IS_ERR(rinfo->sda_gpiod) || + IS_ERR(rinfo->scl_gpiod) || + IS_ERR(dev->pinctrl_pins_default) || + IS_ERR(dev->pinctrl_pins_gpio)) { + dev_info(&pdev->dev, "recovery information incomplete\n"); + if (!IS_ERR(rinfo->sda_gpiod)) { + gpiod_put(rinfo->sda_gpiod); + rinfo->sda_gpiod = NULL; + } + if (!IS_ERR(rinfo->scl_gpiod)) { + gpiod_put(rinfo->scl_gpiod); + rinfo->scl_gpiod = NULL; + } + return -EINVAL; + } + + dev_info(&pdev->dev, "using scl, sda for recovery\n"); + + rinfo->prepare_recovery = at91_prepare_twi_recovery; + rinfo->unprepare_recovery = at91_unprepare_twi_recovery; + rinfo->recover_bus = i2c_generic_scl_recovery; + dev->adapter.bus_recovery_info = rinfo; + + return 0; +} + int at91_twi_probe_master(struct platform_device *pdev, u32 phy_addr, struct at91_twi_dev *dev) { @@ -838,6 +912,10 @@ int at91_twi_probe_master(struct platform_device *pdev, "i2c-analog-filter"); at91_calc_twi_clock(dev); + rc = at91_init_twi_recovery_info(pdev, dev); + if (rc == -EPROBE_DEFER) + return rc; + dev->adapter.algo = &at91_twi_algorithm; dev->adapter.quirks = &at91_twi_quirks; diff --git a/drivers/i2c/busses/i2c-at91.h b/drivers/i2c/busses/i2c-at91.h index 977a67bc0f88..f57a6cab96b4 100644 --- a/drivers/i2c/busses/i2c-at91.h +++ b/drivers/i2c/busses/i2c-at91.h @@ -151,6 +151,10 @@ struct at91_twi_dev { u32 fifo_size; struct at91_twi_dma dma; bool slave_detected; + struct i2c_bus_recovery_info rinfo; + struct pinctrl *pinctrl; + struct pinctrl_state *pinctrl_pins_default; + struct pinctrl_state *pinctrl_pins_gpio; #ifdef CONFIG_I2C_AT91_SLAVE_EXPERIMENTAL unsigned smr; struct i2c_client *slave; From 3a5ee18d2a32bda6b9a1260136f6805848e3839d Mon Sep 17 00:00:00 2001 From: Stefan Lengfeld Date: Mon, 20 Jan 2020 10:36:50 +0100 Subject: [PATCH 0819/4444] i2c: imx: implement master_xfer_atomic callback Rework the read and write code paths in the driver to support operation in atomic contexts. To achieve this, the driver must not rely on IRQs and not call schedule(), e.g. via a sleep routine, in these cases. With this patch the driver supports normal operation, DMA transfers and now the polling mode or also called sleep-free or IRQ-less operation. It makes the code not simpler or easier to read, but atomic I2C transfers are needed on some hardware configurations, e.g. to trigger reboots on an external PMIC chip. Signed-off-by: Stefan Lengfeld [m.felsch@pengutronix.de: integrate https://patchwork.ozlabs.org/patch/1085943/ review feedback] [m.felsch@pengutronix.de: adapt commit message] Signed-off-by: Marco Felsch Acked-by: Oleksij Rempel Reviewed-by: Stefan Agner Tested-by: Stefan Lengfeld Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-imx.c | 146 +++++++++++++++++++++++++---------- 1 file changed, 105 insertions(+), 41 deletions(-) diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index a3b61336fe55..79d5b37fd8a1 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -414,7 +415,7 @@ static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx) dma->chan_using = NULL; } -static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) +static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool atomic) { unsigned long orig_jiffies = jiffies; unsigned int temp; @@ -444,15 +445,37 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) "<%s> I2C bus is busy\n", __func__); return -ETIMEDOUT; } - schedule(); + if (atomic) + udelay(100); + else + schedule(); } return 0; } -static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx) +static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx, bool atomic) { - wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10); + if (atomic) { + void __iomem *addr = i2c_imx->base + (IMX_I2C_I2SR << i2c_imx->hwdata->regshift); + unsigned int regval; + + /* + * The formula for the poll timeout is documented in the RM + * Rev.5 on page 1878: + * T_min = 10/F_scl + * Set the value hard as it is done for the non-atomic use-case. + * Use 10 kHz for the calculation since this is the minimum + * allowed SMBus frequency. Also add an offset of 100us since it + * turned out that the I2SR_IIF bit isn't set correctly within + * the minimum timeout in polling mode. + */ + readb_poll_timeout_atomic(addr, regval, regval & I2SR_IIF, 5, 1000 + 100); + i2c_imx->i2csr = regval; + imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR); + } else { + wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10); + } if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) { dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__); @@ -530,7 +553,7 @@ static int i2c_imx_clk_notifier_call(struct notifier_block *nb, return NOTIFY_OK; } -static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) +static int i2c_imx_start(struct imx_i2c_struct *i2c_imx, bool atomic) { unsigned int temp = 0; int result; @@ -543,23 +566,29 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode, i2c_imx, IMX_I2C_I2CR); /* Wait controller to be stable */ - usleep_range(50, 150); + if (atomic) + udelay(50); + else + usleep_range(50, 150); /* Start I2C transaction */ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); temp |= I2CR_MSTA; imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); - result = i2c_imx_bus_busy(i2c_imx, 1); + result = i2c_imx_bus_busy(i2c_imx, 1, atomic); if (result) return result; temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK; + if (atomic) + temp &= ~I2CR_IIEN; /* Disable interrupt */ + temp &= ~I2CR_DMAEN; imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); return result; } -static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) +static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx, bool atomic) { unsigned int temp = 0; @@ -581,7 +610,7 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) } if (!i2c_imx->stopped) - i2c_imx_bus_busy(i2c_imx, 0); + i2c_imx_bus_busy(i2c_imx, 0, atomic); /* Disable I2C controller */ temp = i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN, @@ -662,7 +691,7 @@ static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx, /* The last data byte must be transferred by the CPU. */ imx_i2c_write_reg(msgs->buf[msgs->len-1], i2c_imx, IMX_I2C_I2DR); - result = i2c_imx_trx_complete(i2c_imx); + result = i2c_imx_trx_complete(i2c_imx, false); if (result) return result; @@ -721,7 +750,7 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx, msgs->buf[msgs->len-2] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* read n byte data */ - result = i2c_imx_trx_complete(i2c_imx); + result = i2c_imx_trx_complete(i2c_imx, false); if (result) return result; @@ -734,7 +763,7 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx, temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); temp &= ~(I2CR_MSTA | I2CR_MTX); imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); - i2c_imx_bus_busy(i2c_imx, 0); + i2c_imx_bus_busy(i2c_imx, 0, false); } else { /* * For i2c master receiver repeat restart operation like: @@ -752,7 +781,8 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx, return 0; } -static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) +static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, + bool atomic) { int i, result; @@ -761,7 +791,7 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) /* write slave address */ imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR); - result = i2c_imx_trx_complete(i2c_imx); + result = i2c_imx_trx_complete(i2c_imx, atomic); if (result) return result; result = i2c_imx_acked(i2c_imx); @@ -775,7 +805,7 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) "<%s> write byte: B%d=0x%X\n", __func__, i, msgs->buf[i]); imx_i2c_write_reg(msgs->buf[i], i2c_imx, IMX_I2C_I2DR); - result = i2c_imx_trx_complete(i2c_imx); + result = i2c_imx_trx_complete(i2c_imx, atomic); if (result) return result; result = i2c_imx_acked(i2c_imx); @@ -785,7 +815,8 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) return 0; } -static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bool is_lastmsg) +static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, + bool is_lastmsg, bool atomic) { int i, result; unsigned int temp; @@ -798,7 +829,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo /* write slave address */ imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR); - result = i2c_imx_trx_complete(i2c_imx); + result = i2c_imx_trx_complete(i2c_imx, atomic); if (result) return result; result = i2c_imx_acked(i2c_imx); @@ -831,7 +862,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo for (i = 0; i < msgs->len; i++) { u8 len = 0; - result = i2c_imx_trx_complete(i2c_imx); + result = i2c_imx_trx_complete(i2c_imx, atomic); if (result) return result; /* @@ -859,7 +890,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); temp &= ~(I2CR_MSTA | I2CR_MTX); imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); - i2c_imx_bus_busy(i2c_imx, 0); + i2c_imx_bus_busy(i2c_imx, 0, atomic); } else { /* * For i2c master receiver repeat restart operation like: @@ -890,8 +921,8 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo return 0; } -static int i2c_imx_xfer(struct i2c_adapter *adapter, - struct i2c_msg *msgs, int num) +static int i2c_imx_xfer_common(struct i2c_adapter *adapter, + struct i2c_msg *msgs, int num, bool atomic) { unsigned int i, temp; int result; @@ -900,16 +931,16 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - result = pm_runtime_get_sync(i2c_imx->adapter.dev.parent); - if (result < 0) - goto out; - /* Start I2C transfer */ - result = i2c_imx_start(i2c_imx); + result = i2c_imx_start(i2c_imx, atomic); if (result) { - if (i2c_imx->adapter.bus_recovery_info) { + /* + * Bus recovery uses gpiod_get_value_cansleep() which is not + * allowed within atomic context. + */ + if (!atomic && i2c_imx->adapter.bus_recovery_info) { i2c_recover_bus(&i2c_imx->adapter); - result = i2c_imx_start(i2c_imx); + result = i2c_imx_start(i2c_imx, atomic); } } @@ -927,7 +958,7 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); temp |= I2CR_RSTA; imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); - result = i2c_imx_bus_busy(i2c_imx, 1); + result = i2c_imx_bus_busy(i2c_imx, 1, atomic); if (result) goto fail0; } @@ -951,13 +982,14 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, (temp & I2SR_SRW ? 1 : 0), (temp & I2SR_IIF ? 1 : 0), (temp & I2SR_RXAK ? 1 : 0)); #endif - if (msgs[i].flags & I2C_M_RD) - result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg); - else { - if (i2c_imx->dma && msgs[i].len >= DMA_THRESHOLD) + if (msgs[i].flags & I2C_M_RD) { + result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg, atomic); + } else { + if (!atomic && + i2c_imx->dma && msgs[i].len >= DMA_THRESHOLD) result = i2c_imx_dma_write(i2c_imx, &msgs[i]); else - result = i2c_imx_write(i2c_imx, &msgs[i]); + result = i2c_imx_write(i2c_imx, &msgs[i], atomic); } if (result) goto fail0; @@ -965,18 +997,49 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, fail0: /* Stop I2C transfer */ - i2c_imx_stop(i2c_imx); + i2c_imx_stop(i2c_imx, atomic); - pm_runtime_mark_last_busy(i2c_imx->adapter.dev.parent); - pm_runtime_put_autosuspend(i2c_imx->adapter.dev.parent); - -out: dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__, (result < 0) ? "error" : "success msg", (result < 0) ? result : num); return (result < 0) ? result : num; } +static int i2c_imx_xfer(struct i2c_adapter *adapter, + struct i2c_msg *msgs, int num) +{ + struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter); + int result; + + result = pm_runtime_get_sync(i2c_imx->adapter.dev.parent); + if (result < 0) + return result; + + result = i2c_imx_xfer_common(adapter, msgs, num, false); + + pm_runtime_mark_last_busy(i2c_imx->adapter.dev.parent); + pm_runtime_put_autosuspend(i2c_imx->adapter.dev.parent); + + return result; +} + +static int i2c_imx_xfer_atomic(struct i2c_adapter *adapter, + struct i2c_msg *msgs, int num) +{ + struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter); + int result; + + result = clk_enable(i2c_imx->clk); + if (result) + return result; + + result = i2c_imx_xfer_common(adapter, msgs, num, true); + + clk_disable(i2c_imx->clk); + + return result; +} + static void i2c_imx_prepare_recovery(struct i2c_adapter *adap) { struct imx_i2c_struct *i2c_imx; @@ -1049,8 +1112,9 @@ static u32 i2c_imx_func(struct i2c_adapter *adapter) } static const struct i2c_algorithm i2c_imx_algo = { - .master_xfer = i2c_imx_xfer, - .functionality = i2c_imx_func, + .master_xfer = i2c_imx_xfer, + .master_xfer_atomic = i2c_imx_xfer_atomic, + .functionality = i2c_imx_func, }; static int i2c_imx_probe(struct platform_device *pdev) From 419be8e1dfed5afa497ca320e1b65954820b48c2 Mon Sep 17 00:00:00 2001 From: Alain Volmat Date: Mon, 3 Feb 2020 18:52:08 +0100 Subject: [PATCH 0820/4444] i2c: stm32f7: allow controller to be wakeup-source Allow the i2c-stm32f7 controller to become a wakeup-source of the system. In such case, when a slave is registered to the I2C controller, receiving a I2C message targeting that registered slave address wakes up the suspended system. In order to be able to wake-up, the I2C controller DT node must have the property wakeup-source defined and a slave must be registered. Signed-off-by: Alain Volmat Reviewed-by: Pierre-Yves MORDRET Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-stm32f7.c | 107 +++++++++++++++++++++++++------ 1 file changed, 86 insertions(+), 21 deletions(-) diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index 5c3e8ac6ad92..378956ac6d1d 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,7 @@ /* STM32F7 I2C control 1 */ #define STM32F7_I2C_CR1_PECEN BIT(23) +#define STM32F7_I2C_CR1_WUPEN BIT(18) #define STM32F7_I2C_CR1_SBC BIT(16) #define STM32F7_I2C_CR1_RXDMAEN BIT(15) #define STM32F7_I2C_CR1_TXDMAEN BIT(14) @@ -301,6 +303,7 @@ struct stm32f7_i2c_msg { * @dma: dma data * @use_dma: boolean to know if dma is used in the current transfer * @regmap: holds SYSCFG phandle for Fast Mode Plus bits + * @wakeup_src: boolean to know if the device is a wakeup source */ struct stm32f7_i2c_dev { struct i2c_adapter adap; @@ -323,6 +326,7 @@ struct stm32f7_i2c_dev { struct stm32_i2c_dma *dma; bool use_dma; struct regmap *regmap; + bool wakeup_src; }; /* @@ -1691,6 +1695,24 @@ pm_free: return ret; } +static void stm32f7_i2c_enable_wakeup(struct stm32f7_i2c_dev *i2c_dev, + bool enable) +{ + void __iomem *base = i2c_dev->base; + u32 mask = STM32F7_I2C_CR1_WUPEN; + + if (!i2c_dev->wakeup_src) + return; + + if (enable) { + device_set_wakeup_enable(i2c_dev->dev, true); + stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask); + } else { + device_set_wakeup_enable(i2c_dev->dev, false); + stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, mask); + } +} + static int stm32f7_i2c_reg_slave(struct i2c_client *slave) { struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(slave->adapter); @@ -1717,6 +1739,9 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave) if (ret < 0) return ret; + if (!stm32f7_i2c_is_slave_registered(i2c_dev)) + stm32f7_i2c_enable_wakeup(i2c_dev, true); + if (id == 0) { /* Configure Own Address 1 */ oar1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR1); @@ -1758,6 +1783,9 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave) ret = 0; pm_free: + if (!stm32f7_i2c_is_slave_registered(i2c_dev)) + stm32f7_i2c_enable_wakeup(i2c_dev, false); + pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); @@ -1791,8 +1819,10 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave) i2c_dev->slave[id] = NULL; - if (!(stm32f7_i2c_is_slave_registered(i2c_dev))) + if (!stm32f7_i2c_is_slave_registered(i2c_dev)) { stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_ALL_IRQ_MASK); + stm32f7_i2c_enable_wakeup(i2c_dev, false); + } pm_runtime_mark_last_busy(i2c_dev->dev); pm_runtime_put_autosuspend(i2c_dev->dev); @@ -1879,6 +1909,9 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) return irq_error ? : -ENOENT; } + i2c_dev->wakeup_src = of_property_read_bool(pdev->dev.of_node, + "wakeup-source"); + i2c_dev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(i2c_dev->clk)) { dev_err(&pdev->dev, "Error: Missing controller clock\n"); @@ -1985,6 +2018,16 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) goto clk_free; } + if (i2c_dev->wakeup_src) { + device_set_wakeup_capable(i2c_dev->dev, true); + + ret = dev_pm_set_wake_irq(i2c_dev->dev, irq_event); + if (ret) { + dev_err(i2c_dev->dev, "Failed to set wake up irq\n"); + goto clr_wakeup_capable; + } + } + platform_set_drvdata(pdev, i2c_dev); pm_runtime_set_autosuspend_delay(i2c_dev->dev, @@ -2014,6 +2057,13 @@ pm_disable: pm_runtime_set_suspended(i2c_dev->dev); pm_runtime_dont_use_autosuspend(i2c_dev->dev); + if (i2c_dev->wakeup_src) + dev_pm_clear_wake_irq(i2c_dev->dev); + +clr_wakeup_capable: + if (i2c_dev->wakeup_src) + device_set_wakeup_capable(i2c_dev->dev, false); + if (i2c_dev->dma) { stm32_i2c_dma_free(i2c_dev->dma); i2c_dev->dma = NULL; @@ -2032,6 +2082,15 @@ static int stm32f7_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&i2c_dev->adap); pm_runtime_get_sync(i2c_dev->dev); + if (i2c_dev->wakeup_src) { + dev_pm_clear_wake_irq(i2c_dev->dev); + /* + * enforce that wakeup is disabled and that the device + * is marked as non wakeup capable + */ + device_init_wakeup(i2c_dev->dev, false); + } + pm_runtime_put_noidle(i2c_dev->dev); pm_runtime_disable(i2c_dev->dev); pm_runtime_set_suspended(i2c_dev->dev); @@ -2073,8 +2132,8 @@ static int __maybe_unused stm32f7_i2c_runtime_resume(struct device *dev) return 0; } -static int __maybe_unused -stm32f7_i2c_regs_backup(struct stm32f7_i2c_dev *i2c_dev) +#ifdef CONFIG_PM_SLEEP +static int stm32f7_i2c_regs_backup(struct stm32f7_i2c_dev *i2c_dev) { int ret; struct stm32f7_i2c_regs *backup_regs = &i2c_dev->backup_regs; @@ -2095,8 +2154,7 @@ stm32f7_i2c_regs_backup(struct stm32f7_i2c_dev *i2c_dev) return ret; } -static int __maybe_unused -stm32f7_i2c_regs_restore(struct stm32f7_i2c_dev *i2c_dev) +static int stm32f7_i2c_regs_restore(struct stm32f7_i2c_dev *i2c_dev) { u32 cr1; int ret; @@ -2127,41 +2185,48 @@ stm32f7_i2c_regs_restore(struct stm32f7_i2c_dev *i2c_dev) return ret; } -static int __maybe_unused stm32f7_i2c_suspend(struct device *dev) +static int stm32f7_i2c_suspend(struct device *dev) { struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); int ret; i2c_mark_adapter_suspended(&i2c_dev->adap); - ret = stm32f7_i2c_regs_backup(i2c_dev); - if (ret < 0) { - i2c_mark_adapter_resumed(&i2c_dev->adap); - return ret; - } - pinctrl_pm_select_sleep_state(dev); - pm_runtime_force_suspend(dev); + if (!device_may_wakeup(dev) && !dev->power.wakeup_path) { + ret = stm32f7_i2c_regs_backup(i2c_dev); + if (ret < 0) { + i2c_mark_adapter_resumed(&i2c_dev->adap); + return ret; + } + + pinctrl_pm_select_sleep_state(dev); + pm_runtime_force_suspend(dev); + } return 0; } -static int __maybe_unused stm32f7_i2c_resume(struct device *dev) +static int stm32f7_i2c_resume(struct device *dev) { struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev); int ret; - ret = pm_runtime_force_resume(dev); - if (ret < 0) - return ret; - pinctrl_pm_select_default_state(dev); + if (!device_may_wakeup(dev) && !dev->power.wakeup_path) { + ret = pm_runtime_force_resume(dev); + if (ret < 0) + return ret; + pinctrl_pm_select_default_state(dev); + + ret = stm32f7_i2c_regs_restore(i2c_dev); + if (ret < 0) + return ret; + } - ret = stm32f7_i2c_regs_restore(i2c_dev); - if (ret < 0) - return ret; i2c_mark_adapter_resumed(&i2c_dev->adap); return 0; } +#endif static const struct dev_pm_ops stm32f7_i2c_pm_ops = { SET_RUNTIME_PM_OPS(stm32f7_i2c_runtime_suspend, From f01adfabbfc4a62a9750cae3abcdf848029ee300 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 30 Jan 2020 21:23:12 +0100 Subject: [PATCH 0821/4444] i2c: dev: keep sorting of includes Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 2ea4585d18c5..ffd381e4afd2 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -15,6 +15,7 @@ /* The I2C_RDWR ioctl code is written by Kolja Waschk */ #include +#include #include #include #include @@ -27,7 +28,6 @@ #include #include #include -#include /* * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a From 604f3956524a6a53c1e3dd27b4b685b664d181ec Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Thu, 26 Dec 2019 17:27:17 -0800 Subject: [PATCH 0822/4444] PCI: qcom: Fix the fixup of PCI_VENDOR_ID_QCOM There exists non-bridge PCIe devices with PCI_VENDOR_ID_QCOM, so limit the fixup to only affect the relevant PCIe bridges. Fixes: 322f03436692 ("PCI: qcom: Use default config space read function") Signed-off-by: Bjorn Andersson Signed-off-by: Lorenzo Pieralisi Acked-by: Stanimir Varbanov Cc: stable@vger.kernel.org # v5.2+ --- drivers/pci/controller/dwc/pcie-qcom.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 5ea527a6bd9f..138e1a2d21cc 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -1439,7 +1439,13 @@ static void qcom_fixup_class(struct pci_dev *dev) { dev->class = PCI_CLASS_BRIDGE_PCI << 8; } -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, PCI_ANY_ID, qcom_fixup_class); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0101, qcom_fixup_class); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0104, qcom_fixup_class); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0106, qcom_fixup_class); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0107, qcom_fixup_class); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0302, qcom_fixup_class); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x1000, qcom_fixup_class); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x1001, qcom_fixup_class); static struct platform_driver qcom_pcie_driver = { .probe = qcom_pcie_probe, From bc36dfffd5f3f19edcf85954d93eb0bc45875c37 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 24 Feb 2020 12:52:17 +0100 Subject: [PATCH 0823/4444] ext2: Silence lockdep warning about reclaim under xattr_sem Lockdep complains about a chain: sb_internal#2 --> &ei->xattr_sem#2 --> fs_reclaim and shrink_dentry_list -> ext2_evict_inode -> ext2_xattr_delete_inode -> down_write(ei->xattr_sem) creating a locking cycle in the reclaim path. This is however a false positive because when we are in ext2_evict_inode() we are the only holder of the inode reference and nobody else should touch xattr_sem of that inode. So we cannot ever block on acquiring the xattr_sem in the reclaim path. Silence the lockdep warning by using down_write_trylock() in ext2_xattr_delete_inode() to not create false locking dependency. Reported-by: "J. R. Okajima" Reviewed-by: Ritesh Harjani Signed-off-by: Jan Kara --- fs/ext2/xattr.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index 0456bc990b5e..9ad07c7ef0b3 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -790,7 +790,15 @@ ext2_xattr_delete_inode(struct inode *inode) struct buffer_head *bh = NULL; struct ext2_sb_info *sbi = EXT2_SB(inode->i_sb); - down_write(&EXT2_I(inode)->xattr_sem); + /* + * We are the only ones holding inode reference. The xattr_sem should + * better be unlocked! We could as well just not acquire xattr_sem at + * all but this makes the code more futureproof. OTOH we need trylock + * here to avoid false-positive warning from lockdep about reclaim + * circular dependency. + */ + if (WARN_ON_ONCE(!down_write_trylock(&EXT2_I(inode)->xattr_sem))) + return; if (!EXT2_I(inode)->i_file_acl) goto cleanup; From c7896490dd1a4e6b346e8a475e4a433356362770 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 7 Jan 2020 15:10:28 +0100 Subject: [PATCH 0824/4444] leds: ns2: Absorb platform data Nothing in the kernel includes the external header so just push the contents into the ns2 leds driver. If someone wants to use platform data or board files to describe this device they should be able to do so using GPIO machine descriptors but in any case device tree should be the way forward for these systems in all cases I can think of, and the driver already supports that. Cc: Simon Guinot Cc: Vincent Donnefort Signed-off-by: Linus Walleij Tested-by: Simon Guinot Signed-off-by: Pavel Machek --- drivers/leds/leds-ns2.c | 30 +++++++++++++-- .../linux/platform_data/leds-kirkwood-ns2.h | 38 ------------------- 2 files changed, 27 insertions(+), 41 deletions(-) delete mode 100644 include/linux/platform_data/leds-kirkwood-ns2.h diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index 7c500dfdcfa3..6d37dda12c39 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c @@ -12,14 +12,38 @@ #include #include #include -#include +#include #include #include -#include #include -#include #include "leds.h" +enum ns2_led_modes { + NS_V2_LED_OFF, + NS_V2_LED_ON, + NS_V2_LED_SATA, +}; + +struct ns2_led_modval { + enum ns2_led_modes mode; + int cmd_level; + int slow_level; +}; + +struct ns2_led { + const char *name; + const char *default_trigger; + unsigned cmd; + unsigned slow; + int num_modes; + struct ns2_led_modval *modval; +}; + +struct ns2_led_platform_data { + int num_leds; + struct ns2_led *leds; +}; + /* * The Network Space v2 dual-GPIO LED is wired to a CPLD. Three different LED * modes are available: off, on and SATA activity blinking. The LED modes are diff --git a/include/linux/platform_data/leds-kirkwood-ns2.h b/include/linux/platform_data/leds-kirkwood-ns2.h deleted file mode 100644 index eb8a6860e816..000000000000 --- a/include/linux/platform_data/leds-kirkwood-ns2.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Platform data structure for Network Space v2 LED driver - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#ifndef __LEDS_KIRKWOOD_NS2_H -#define __LEDS_KIRKWOOD_NS2_H - -enum ns2_led_modes { - NS_V2_LED_OFF, - NS_V2_LED_ON, - NS_V2_LED_SATA, -}; - -struct ns2_led_modval { - enum ns2_led_modes mode; - int cmd_level; - int slow_level; -}; - -struct ns2_led { - const char *name; - const char *default_trigger; - unsigned cmd; - unsigned slow; - int num_modes; - struct ns2_led_modval *modval; -}; - -struct ns2_led_platform_data { - int num_leds; - struct ns2_led *leds; -}; - -#endif /* __LEDS_KIRKWOOD_NS2_H */ From ccbbb117c17eaf108216830bdd1e85a551ccc031 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 7 Jan 2020 15:10:29 +0100 Subject: [PATCH 0825/4444] leds: ns2: Convert to GPIO descriptors This converts the NS2 LED driver to use GPIO descriptors. We take care to request the GPIOs "as is" which is what the current driver goes to lengths to achieve, then we use GPIOs throughout. As the nodes for each LED does not have any corresponding device, we need to use the DT-specific accessors to get these GPIO descriptors from the device tree. Cc: Vincent Donnefort Signed-off-by: Linus Walleij Tested-by: Simon Guinot Signed-off-by: Pavel Machek --- drivers/leds/leds-ns2.c | 73 +++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 42 deletions(-) diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index 6d37dda12c39..538ca5755602 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c @@ -33,8 +33,8 @@ struct ns2_led_modval { struct ns2_led { const char *name; const char *default_trigger; - unsigned cmd; - unsigned slow; + struct gpio_desc *cmd; + struct gpio_desc *slow; int num_modes; struct ns2_led_modval *modval; }; @@ -53,8 +53,8 @@ struct ns2_led_platform_data { struct ns2_led_data { struct led_classdev cdev; - unsigned int cmd; - unsigned int slow; + struct gpio_desc *cmd; + struct gpio_desc *slow; bool can_sleep; unsigned char sata; /* True when SATA mode active. */ rwlock_t rw_lock; /* Lock GPIOs. */ @@ -70,8 +70,8 @@ static int ns2_led_get_mode(struct ns2_led_data *led_dat, int cmd_level; int slow_level; - cmd_level = gpio_get_value_cansleep(led_dat->cmd); - slow_level = gpio_get_value_cansleep(led_dat->slow); + cmd_level = gpiod_get_value_cansleep(led_dat->cmd); + slow_level = gpiod_get_value_cansleep(led_dat->slow); for (i = 0; i < led_dat->num_modes; i++) { if (cmd_level == led_dat->modval[i].cmd_level && @@ -104,15 +104,15 @@ static void ns2_led_set_mode(struct ns2_led_data *led_dat, write_lock_irqsave(&led_dat->rw_lock, flags); if (!led_dat->can_sleep) { - gpio_set_value(led_dat->cmd, - led_dat->modval[i].cmd_level); - gpio_set_value(led_dat->slow, - led_dat->modval[i].slow_level); + gpiod_set_value(led_dat->cmd, + led_dat->modval[i].cmd_level); + gpiod_set_value(led_dat->slow, + led_dat->modval[i].slow_level); goto exit_unlock; } - gpio_set_value_cansleep(led_dat->cmd, led_dat->modval[i].cmd_level); - gpio_set_value_cansleep(led_dat->slow, led_dat->modval[i].slow_level); + gpiod_set_value_cansleep(led_dat->cmd, led_dat->modval[i].cmd_level); + gpiod_set_value_cansleep(led_dat->slow, led_dat->modval[i].slow_level); exit_unlock: write_unlock_irqrestore(&led_dat->rw_lock, flags); @@ -200,26 +200,6 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat, int ret; enum ns2_led_modes mode; - ret = devm_gpio_request_one(&pdev->dev, template->cmd, - gpio_get_value_cansleep(template->cmd) ? - GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW, - template->name); - if (ret) { - dev_err(&pdev->dev, "%s: failed to setup command GPIO\n", - template->name); - return ret; - } - - ret = devm_gpio_request_one(&pdev->dev, template->slow, - gpio_get_value_cansleep(template->slow) ? - GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW, - template->name); - if (ret) { - dev_err(&pdev->dev, "%s: failed to setup slow GPIO\n", - template->name); - return ret; - } - rwlock_init(&led_dat->rw_lock); led_dat->cdev.name = template->name; @@ -229,8 +209,8 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat, led_dat->cdev.groups = ns2_led_groups; led_dat->cmd = template->cmd; led_dat->slow = template->slow; - led_dat->can_sleep = gpio_cansleep(led_dat->cmd) | - gpio_cansleep(led_dat->slow); + led_dat->can_sleep = gpiod_cansleep(led_dat->cmd) | + gpiod_cansleep(led_dat->slow); if (led_dat->can_sleep) led_dat->cdev.brightness_set_blocking = ns2_led_set_blocking; else @@ -285,17 +265,26 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata) const char *string; int i, num_modes; struct ns2_led_modval *modval; + struct gpio_desc *gd; - ret = of_get_named_gpio(child, "cmd-gpio", 0); - if (ret < 0) - goto err_node_put; - led->cmd = ret; - ret = of_get_named_gpio(child, "slow-gpio", 0); - if (ret < 0) - goto err_node_put; - led->slow = ret; ret = of_property_read_string(child, "label", &string); led->name = (ret == 0) ? string : child->name; + + gd = gpiod_get_from_of_node(child, "cmd-gpio", 0, + GPIOD_ASIS, led->name); + if (IS_ERR(gd)) { + ret = PTR_ERR(gd); + goto err_node_put; + } + led->cmd = gd; + gd = gpiod_get_from_of_node(child, "slow-gpio", 0, + GPIOD_ASIS, led->name); + if (IS_ERR(gd)) { + ret = PTR_ERR(gd); + goto err_node_put; + } + led->slow = gd; + ret = of_property_read_string(child, "linux,default-trigger", &string); if (ret == 0) From 877a50b8729994a701aac7b2092381bad2c6c145 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 8 Jan 2020 01:53:22 +0000 Subject: [PATCH 0826/4444] leds: leds-bd2802: remove set but not used variable 'pdata' Fixes gcc '-Wunused-but-set-variable' warning: drivers/leds/leds-bd2802.c: In function 'bd2802_probe': drivers/leds/leds-bd2802.c:663:35: warning: variable 'pdata' set but not used [-Wunused-but-set-variable] commit 4c3718f9d6a6 ("leds: bd2802: Convert to use GPIO descriptors") left behind this unused variable. Signed-off-by: YueHaibing Reviewed-by: Linus Walleij Signed-off-by: Pavel Machek --- drivers/leds/leds-bd2802.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index bd61a823d0ca..8bbaef5a2986 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c @@ -660,7 +660,6 @@ static int bd2802_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct bd2802_led *led; - struct bd2802_led_platform_data *pdata; int ret, i; led = devm_kzalloc(&client->dev, sizeof(struct bd2802_led), GFP_KERNEL); @@ -668,7 +667,6 @@ static int bd2802_probe(struct i2c_client *client, return -ENOMEM; led->client = client; - pdata = led->pdata = dev_get_platdata(&client->dev); i2c_set_clientdata(client, led); /* From 238415f76084080f3085e72ead4b76775d21fc46 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 19 Feb 2020 16:37:45 +0100 Subject: [PATCH 0827/4444] dt-bindings: example-schema: Drop double quotes around URLs It is no longer needed to wrap URLs in double quotes. Signed-off-by: Geert Uytterhoeven Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/example-schema.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/example-schema.yaml b/Documentation/devicetree/bindings/example-schema.yaml index 4ddcf709cc3c..62811a1b5058 100644 --- a/Documentation/devicetree/bindings/example-schema.yaml +++ b/Documentation/devicetree/bindings/example-schema.yaml @@ -7,9 +7,9 @@ # $id is a unique identifier based on the filename. There may or may not be a # file present at the URL. -$id: "http://devicetree.org/schemas/example-schema.yaml#" +$id: http://devicetree.org/schemas/example-schema.yaml# # $schema is the meta-schema this schema should be validated with. -$schema: "http://devicetree.org/meta-schemas/core.yaml#" +$schema: http://devicetree.org/meta-schemas/core.yaml# title: An example schema annotated with jsonschema details From 8acbbddcf9913149ef47b20f487289da02c4a291 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 19 Feb 2020 16:41:46 +0100 Subject: [PATCH 0828/4444] dt-bindings: ata: rcar-sata: Convert to json-schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert the Renesas R-Car Serial-ATA Device Tree binding documentation to json-schema. While at it: - Remove the deprecated "renesas,rcar-sata" compatible value, - Add "iommus", "power-domains", and "resets" properties, - Update the example. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Signed-off-by: Rob Herring --- .../bindings/ata/renesas,rcar-sata.yaml | 71 +++++++++++++++++++ .../devicetree/bindings/ata/sata_rcar.txt | 36 ---------- 2 files changed, 71 insertions(+), 36 deletions(-) create mode 100644 Documentation/devicetree/bindings/ata/renesas,rcar-sata.yaml delete mode 100644 Documentation/devicetree/bindings/ata/sata_rcar.txt diff --git a/Documentation/devicetree/bindings/ata/renesas,rcar-sata.yaml b/Documentation/devicetree/bindings/ata/renesas,rcar-sata.yaml new file mode 100644 index 000000000000..7b69831060d8 --- /dev/null +++ b/Documentation/devicetree/bindings/ata/renesas,rcar-sata.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/ata/renesas,rcar-sata.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Renesas R-Car Serial-ATA Interface + +maintainers: + - Geert Uytterhoeven + +properties: + compatible: + oneOf: + - items: + - enum: + - renesas,sata-r8a7779 # R-Car H1 + - items: + - enum: + - renesas,sata-r8a7790-es1 # R-Car H2 ES1 + - renesas,sata-r8a7790 # R-Car H2 other than ES1 + - renesas,sata-r8a7791 # R-Car M2-W + - renesas,sata-r8a7793 # R-Car M2-N + - const: renesas,rcar-gen2-sata # generic R-Car Gen2 + - items: + - enum: + - renesas,sata-r8a774b1 # RZ/G2N + - renesas,sata-r8a7795 # R-Car H3 + - renesas,sata-r8a77965 # R-Car M3-N + - const: renesas,rcar-gen3-sata # generic R-Car Gen3 or RZ/G2 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + iommus: + maxItems: 1 + + power-domains: + maxItems: 1 + + resets: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + +additionalProperties: false + +examples: + - | + #include + #include + #include + + sata@ee300000 { + compatible = "renesas,sata-r8a7791", "renesas,rcar-gen2-sata"; + reg = <0xee300000 0x200000>; + interrupts = ; + clocks = <&cpg CPG_MOD 815>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; + resets = <&cpg 815>; + }; diff --git a/Documentation/devicetree/bindings/ata/sata_rcar.txt b/Documentation/devicetree/bindings/ata/sata_rcar.txt deleted file mode 100644 index a2fbdc91570d..000000000000 --- a/Documentation/devicetree/bindings/ata/sata_rcar.txt +++ /dev/null @@ -1,36 +0,0 @@ -* Renesas R-Car SATA - -Required properties: -- compatible : should contain one or more of the following: - - "renesas,sata-r8a774b1" for RZ/G2N - - "renesas,sata-r8a7779" for R-Car H1 - - "renesas,sata-r8a7790-es1" for R-Car H2 ES1 - - "renesas,sata-r8a7790" for R-Car H2 other than ES1 - - "renesas,sata-r8a7791" for R-Car M2-W - - "renesas,sata-r8a7793" for R-Car M2-N - - "renesas,sata-r8a7795" for R-Car H3 - - "renesas,sata-r8a77965" for R-Car M3-N - - "renesas,rcar-gen2-sata" for a generic R-Car Gen2 - compatible device - - "renesas,rcar-gen3-sata" for a generic R-Car Gen3 or - RZ/G2 compatible device - - "renesas,rcar-sata" is deprecated - - When compatible with the generic version nodes - must list the SoC-specific version corresponding - to the platform first followed by the generic - version. - -- reg : address and length of the SATA registers; -- interrupts : must consist of one interrupt specifier. -- clocks : must contain a reference to the functional clock. - -Example: - -sata0: sata@ee300000 { - compatible = "renesas,sata-r8a7791", "renesas,rcar-gen2-sata"; - reg = <0 0xee300000 0 0x2000>; - interrupt-parent = <&gic>; - interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&mstp8_clks R8A7791_CLK_SATA0>; -}; From 2f7afc343d49eea0bf88ea5fc8cb3afc392356c3 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Wed, 19 Feb 2020 21:52:50 -0800 Subject: [PATCH 0829/4444] of: property: Add device link support for power-domains and hwlocks Add support for creating device links out of more DT properties. To: lkml To: John Stultz To: Rob Herring Cc: "Rafael J. Wysocki" Cc: Kevin Hilman Cc: Ulf Hansson Cc: Pavel Machek Cc: Len Brown Cc: Todd Kjos Cc: Bjorn Andersson Cc: Liam Girdwood Cc: Mark Brown Cc: Greg Kroah-Hartman Cc: linux-pm@vger.kernel.org Signed-off-by: Saravana Kannan Tested-by: John Stultz Signed-off-by: Rob Herring --- drivers/of/property.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/of/property.c b/drivers/of/property.c index e851c57a15b0..d977c11decda 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -1204,6 +1204,8 @@ DEFINE_SIMPLE_PROP(mboxes, "mboxes", "#mbox-cells") DEFINE_SIMPLE_PROP(io_channels, "io-channel", "#io-channel-cells") DEFINE_SIMPLE_PROP(interrupt_parent, "interrupt-parent", NULL) DEFINE_SIMPLE_PROP(dmas, "dmas", "#dma-cells") +DEFINE_SIMPLE_PROP(power_domains, "power-domains", "#power-domain-cells") +DEFINE_SIMPLE_PROP(hwlocks, "hwlocks", "#hwlock-cells") DEFINE_SUFFIX_PROP(regulators, "-supply", NULL) DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells") DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells") @@ -1226,6 +1228,8 @@ static const struct supplier_bindings of_supplier_bindings[] = { { .parse_prop = parse_io_channels, }, { .parse_prop = parse_interrupt_parent, }, { .parse_prop = parse_dmas, }, + { .parse_prop = parse_power_domains, }, + { .parse_prop = parse_hwlocks, }, { .parse_prop = parse_regulators, }, { .parse_prop = parse_gpio, }, { .parse_prop = parse_gpios, }, From f4056e705b2ef7f123a188f6aee23ade70e7d793 Mon Sep 17 00:00:00 2001 From: Frank Rowand Date: Thu, 20 Feb 2020 12:40:20 -0600 Subject: [PATCH 0830/4444] of: unittest: add overlay gpio test to catch gpio hog problem Geert reports that gpio hog nodes are not properly processed when the gpio hog node is added via an overlay reply and provides an RFC patch to fix the problem [1]. Add a unittest that shows the problem. Unittest will report "1 failed" test before applying Geert's RFC patch and "0 failed" after applying Geert's RFC patch. [1] https://lore.kernel.org/linux-devicetree/20191230133852.5890-1-geert+renesas@glider.be/ Signed-off-by: Frank Rowand Signed-off-by: Rob Herring --- drivers/of/unittest-data/Makefile | 8 +- drivers/of/unittest-data/overlay_gpio_01.dts | 23 ++ drivers/of/unittest-data/overlay_gpio_02a.dts | 16 ++ drivers/of/unittest-data/overlay_gpio_02b.dts | 16 ++ drivers/of/unittest-data/overlay_gpio_03.dts | 23 ++ drivers/of/unittest-data/overlay_gpio_04a.dts | 16 ++ drivers/of/unittest-data/overlay_gpio_04b.dts | 16 ++ drivers/of/unittest.c | 253 ++++++++++++++++++ 8 files changed, 370 insertions(+), 1 deletion(-) create mode 100644 drivers/of/unittest-data/overlay_gpio_01.dts create mode 100644 drivers/of/unittest-data/overlay_gpio_02a.dts create mode 100644 drivers/of/unittest-data/overlay_gpio_02b.dts create mode 100644 drivers/of/unittest-data/overlay_gpio_03.dts create mode 100644 drivers/of/unittest-data/overlay_gpio_04a.dts create mode 100644 drivers/of/unittest-data/overlay_gpio_04b.dts diff --git a/drivers/of/unittest-data/Makefile b/drivers/of/unittest-data/Makefile index 9b6807065827..009f4045c8e4 100644 --- a/drivers/of/unittest-data/Makefile +++ b/drivers/of/unittest-data/Makefile @@ -21,7 +21,13 @@ obj-$(CONFIG_OF_OVERLAY) += overlay.dtb.o \ overlay_bad_add_dup_prop.dtb.o \ overlay_bad_phandle.dtb.o \ overlay_bad_symbol.dtb.o \ - overlay_base.dtb.o + overlay_base.dtb.o \ + overlay_gpio_01.dtb.o \ + overlay_gpio_02a.dtb.o \ + overlay_gpio_02b.dtb.o \ + overlay_gpio_03.dtb.o \ + overlay_gpio_04a.dtb.o \ + overlay_gpio_04b.dtb.o # enable creation of __symbols__ node DTC_FLAGS_overlay += -@ diff --git a/drivers/of/unittest-data/overlay_gpio_01.dts b/drivers/of/unittest-data/overlay_gpio_01.dts new file mode 100644 index 000000000000..699ff104ae10 --- /dev/null +++ b/drivers/of/unittest-data/overlay_gpio_01.dts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; +/plugin/; + +&unittest_test_bus { + #address-cells = <1>; + #size-cells = <0>; + gpio@0 { + compatible = "unittest-gpio"; + reg = <0>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <2>; + gpio-line-names = "line-A", "line-B"; + + line-b { + gpio-hog; + gpios = <2 0>; + input; + line-name = "line-B-input"; + }; + }; +}; diff --git a/drivers/of/unittest-data/overlay_gpio_02a.dts b/drivers/of/unittest-data/overlay_gpio_02a.dts new file mode 100644 index 000000000000..ec59aff6ed47 --- /dev/null +++ b/drivers/of/unittest-data/overlay_gpio_02a.dts @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; +/plugin/; + +&unittest_test_bus { + #address-cells = <1>; + #size-cells = <0>; + gpio@2 { + compatible = "unittest-gpio"; + reg = <2>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <2>; + gpio-line-names = "line-A", "line-B"; + }; +}; diff --git a/drivers/of/unittest-data/overlay_gpio_02b.dts b/drivers/of/unittest-data/overlay_gpio_02b.dts new file mode 100644 index 000000000000..43ce111d41ce --- /dev/null +++ b/drivers/of/unittest-data/overlay_gpio_02b.dts @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; +/plugin/; + +&unittest_test_bus { + #address-cells = <1>; + #size-cells = <0>; + gpio@2 { + line-a { + gpio-hog; + gpios = <1 0>; + input; + line-name = "line-A-input"; + }; + }; +}; diff --git a/drivers/of/unittest-data/overlay_gpio_03.dts b/drivers/of/unittest-data/overlay_gpio_03.dts new file mode 100644 index 000000000000..6e0312340a1b --- /dev/null +++ b/drivers/of/unittest-data/overlay_gpio_03.dts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; +/plugin/; + +&unittest_test_bus { + #address-cells = <1>; + #size-cells = <0>; + gpio@3 { + compatible = "unittest-gpio"; + reg = <3>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <2>; + gpio-line-names = "line-A", "line-B", "line-C", "line-D"; + + line-d { + gpio-hog; + gpios = <4 0>; + input; + line-name = "line-D-input"; + }; + }; +}; diff --git a/drivers/of/unittest-data/overlay_gpio_04a.dts b/drivers/of/unittest-data/overlay_gpio_04a.dts new file mode 100644 index 000000000000..7b1e04ebfa7a --- /dev/null +++ b/drivers/of/unittest-data/overlay_gpio_04a.dts @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; +/plugin/; + +&unittest_test_bus { + #address-cells = <1>; + #size-cells = <0>; + gpio@4 { + compatible = "unittest-gpio"; + reg = <4>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <2>; + gpio-line-names = "line-A", "line-B", "line-C", "line-D"; + }; +}; diff --git a/drivers/of/unittest-data/overlay_gpio_04b.dts b/drivers/of/unittest-data/overlay_gpio_04b.dts new file mode 100644 index 000000000000..a14e95c6699a --- /dev/null +++ b/drivers/of/unittest-data/overlay_gpio_04b.dts @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; +/plugin/; + +&unittest_test_bus { + #address-cells = <1>; + #size-cells = <0>; + gpio@4 { + line-c { + gpio-hog; + gpios = <3 0>; + input; + line-name = "line-C-input"; + }; + }; +}; diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 68b87587b2ef..6059bb363097 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -24,6 +24,7 @@ #include #include +#include #include @@ -46,6 +47,97 @@ static struct unittest_results { failed; \ }) +/* + * Expected message may have a message level other than KERN_INFO. + * Print the expected message only if the current loglevel will allow + * the actual message to print. + */ +#define EXPECT_BEGIN(level, fmt, ...) \ + printk(level pr_fmt("EXPECT \\ : ") fmt, ##__VA_ARGS__) + +#define EXPECT_END(level, fmt, ...) \ + printk(level pr_fmt("EXPECT / : ") fmt, ##__VA_ARGS__) + +struct unittest_gpio_dev { + struct gpio_chip chip; +}; + +static int unittest_gpio_chip_request_count; +static int unittest_gpio_probe_count; +static int unittest_gpio_probe_pass_count; + +static int unittest_gpio_chip_request(struct gpio_chip *chip, unsigned int offset) +{ + unittest_gpio_chip_request_count++; + + pr_debug("%s(): %s %d %d\n", __func__, chip->label, offset, + unittest_gpio_chip_request_count); + return 0; +} + +static int unittest_gpio_probe(struct platform_device *pdev) +{ + struct unittest_gpio_dev *devptr; + int ret; + + unittest_gpio_probe_count++; + + devptr = kzalloc(sizeof(*devptr), GFP_KERNEL); + if (!devptr) + return -ENOMEM; + + platform_set_drvdata(pdev, devptr); + + devptr->chip.of_node = pdev->dev.of_node; + devptr->chip.label = "of-unittest-gpio"; + devptr->chip.base = -1; /* dynamic allocation */ + devptr->chip.ngpio = 5; + devptr->chip.request = unittest_gpio_chip_request; + + ret = gpiochip_add_data(&devptr->chip, NULL); + + unittest(!ret, + "gpiochip_add_data() for node @%pOF failed, ret = %d\n", devptr->chip.of_node, ret); + + if (!ret) + unittest_gpio_probe_pass_count++; + return ret; +} + +static int unittest_gpio_remove(struct platform_device *pdev) +{ + struct unittest_gpio_dev *gdev = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; + struct device_node *np = pdev->dev.of_node; + + dev_dbg(dev, "%s for node @%pOF\n", __func__, np); + + if (!gdev) + return -EINVAL; + + if (gdev->chip.base != -1) + gpiochip_remove(&gdev->chip); + + platform_set_drvdata(pdev, NULL); + kfree(pdev); + + return 0; +} + +static const struct of_device_id unittest_gpio_id[] = { + { .compatible = "unittest-gpio", }, + {} +}; + +static struct platform_driver unittest_gpio_driver = { + .probe = unittest_gpio_probe, + .remove = unittest_gpio_remove, + .driver = { + .name = "unittest-gpio", + .of_match_table = of_match_ptr(unittest_gpio_id), + }, +}; + static void __init of_unittest_find_node_by_name(void) { struct device_node *np; @@ -2183,6 +2275,153 @@ static inline void of_unittest_overlay_i2c_15(void) { } #endif +static void __init of_unittest_overlay_gpio(void) +{ + int chip_request_count; + int probe_pass_count; + int ret; + + /* + * tests: apply overlays before registering driver + * Similar to installing a driver as a module, the + * driver is registered after applying the overlays. + * + * - apply overlay_gpio_01 + * - apply overlay_gpio_02a + * - apply overlay_gpio_02b + * - register driver + * + * register driver will result in + * - probe and processing gpio hog for overlay_gpio_01 + * - probe for overlay_gpio_02a + * - processing gpio for overlay_gpio_02b + */ + + probe_pass_count = unittest_gpio_probe_pass_count; + chip_request_count = unittest_gpio_chip_request_count; + + /* + * overlay_gpio_01 contains gpio node and child gpio hog node + * overlay_gpio_02a contains gpio node + * overlay_gpio_02b contains child gpio hog node + */ + + unittest(overlay_data_apply("overlay_gpio_01", NULL), + "Adding overlay 'overlay_gpio_01' failed\n"); + + unittest(overlay_data_apply("overlay_gpio_02a", NULL), + "Adding overlay 'overlay_gpio_02a' failed\n"); + + unittest(overlay_data_apply("overlay_gpio_02b", NULL), + "Adding overlay 'overlay_gpio_02b' failed\n"); + + /* + * messages are the result of the probes, after the + * driver is registered + */ + + EXPECT_BEGIN(KERN_INFO, + "GPIO line <> (line-B-input) hogged as input\n"); + + EXPECT_BEGIN(KERN_INFO, + "GPIO line <> (line-A-input) hogged as input\n"); + + ret = platform_driver_register(&unittest_gpio_driver); + if (unittest(ret == 0, "could not register unittest gpio driver\n")) + return; + + EXPECT_END(KERN_INFO, + "GPIO line <> (line-A-input) hogged as input\n"); + EXPECT_END(KERN_INFO, + "GPIO line <> (line-B-input) hogged as input\n"); + + unittest(probe_pass_count + 2 == unittest_gpio_probe_pass_count, + "unittest_gpio_probe() failed or not called\n"); + + unittest(chip_request_count + 2 == unittest_gpio_chip_request_count, + "unittest_gpio_chip_request() called %d times (expected 1 time)\n", + unittest_gpio_chip_request_count - chip_request_count); + + /* + * tests: apply overlays after registering driver + * + * Similar to a driver built-in to the kernel, the + * driver is registered before applying the overlays. + * + * overlay_gpio_03 contains gpio node and child gpio hog node + * + * - apply overlay_gpio_03 + * + * apply overlay will result in + * - probe and processing gpio hog. + */ + + probe_pass_count = unittest_gpio_probe_pass_count; + chip_request_count = unittest_gpio_chip_request_count; + + EXPECT_BEGIN(KERN_INFO, + "GPIO line <> (line-D-input) hogged as input\n"); + + /* overlay_gpio_03 contains gpio node and child gpio hog node */ + + unittest(overlay_data_apply("overlay_gpio_03", NULL), + "Adding overlay 'overlay_gpio_03' failed\n"); + + EXPECT_END(KERN_INFO, + "GPIO line <> (line-D-input) hogged as input\n"); + + unittest(probe_pass_count + 1 == unittest_gpio_probe_pass_count, + "unittest_gpio_probe() failed or not called\n"); + + unittest(chip_request_count + 1 == unittest_gpio_chip_request_count, + "unittest_gpio_chip_request() called %d times (expected 1 time)\n", + unittest_gpio_chip_request_count - chip_request_count); + + /* + * overlay_gpio_04a contains gpio node + * + * - apply overlay_gpio_04a + * + * apply the overlay will result in + * - probe for overlay_gpio_04a + */ + + probe_pass_count = unittest_gpio_probe_pass_count; + chip_request_count = unittest_gpio_chip_request_count; + + /* overlay_gpio_04a contains gpio node */ + + unittest(overlay_data_apply("overlay_gpio_04a", NULL), + "Adding overlay 'overlay_gpio_04a' failed\n"); + + unittest(probe_pass_count + 1 == unittest_gpio_probe_pass_count, + "unittest_gpio_probe() failed or not called\n"); + + /* + * overlay_gpio_04b contains child gpio hog node + * + * - apply overlay_gpio_04b + * + * apply the overlay will result in + * - processing gpio for overlay_gpio_04b + */ + + EXPECT_BEGIN(KERN_INFO, + "GPIO line <> (line-C-input) hogged as input\n"); + + /* overlay_gpio_04b contains child gpio hog node */ + + unittest(overlay_data_apply("overlay_gpio_04b", NULL), + "Adding overlay 'overlay_gpio_04b' failed\n"); + + EXPECT_END(KERN_INFO, + "GPIO line <> (line-C-input) hogged as input\n"); + + unittest(chip_request_count + 1 == unittest_gpio_chip_request_count, + "unittest_gpio_chip_request() called %d times (expected 1 time)\n", + unittest_gpio_chip_request_count - chip_request_count); +} + static void __init of_unittest_overlay(void) { struct device_node *bus_np = NULL; @@ -2242,6 +2481,8 @@ static void __init of_unittest_overlay(void) of_unittest_overlay_i2c_cleanup(); #endif + of_unittest_overlay_gpio(); + of_unittest_destroy_tracked_overlays(); out: @@ -2295,6 +2536,12 @@ OVERLAY_INFO_EXTERN(overlay_11); OVERLAY_INFO_EXTERN(overlay_12); OVERLAY_INFO_EXTERN(overlay_13); OVERLAY_INFO_EXTERN(overlay_15); +OVERLAY_INFO_EXTERN(overlay_gpio_01); +OVERLAY_INFO_EXTERN(overlay_gpio_02a); +OVERLAY_INFO_EXTERN(overlay_gpio_02b); +OVERLAY_INFO_EXTERN(overlay_gpio_03); +OVERLAY_INFO_EXTERN(overlay_gpio_04a); +OVERLAY_INFO_EXTERN(overlay_gpio_04b); OVERLAY_INFO_EXTERN(overlay_bad_add_dup_node); OVERLAY_INFO_EXTERN(overlay_bad_add_dup_prop); OVERLAY_INFO_EXTERN(overlay_bad_phandle); @@ -2319,6 +2566,12 @@ static struct overlay_info overlays[] = { OVERLAY_INFO(overlay_12, 0), OVERLAY_INFO(overlay_13, 0), OVERLAY_INFO(overlay_15, 0), + OVERLAY_INFO(overlay_gpio_01, 0), + OVERLAY_INFO(overlay_gpio_02a, 0), + OVERLAY_INFO(overlay_gpio_02b, 0), + OVERLAY_INFO(overlay_gpio_03, 0), + OVERLAY_INFO(overlay_gpio_04a, 0), + OVERLAY_INFO(overlay_gpio_04b, 0), OVERLAY_INFO(overlay_bad_add_dup_node, -EINVAL), OVERLAY_INFO(overlay_bad_add_dup_prop, -EINVAL), OVERLAY_INFO(overlay_bad_phandle, -EINVAL), From 0ac1743979408a4999f32b777ce71f40fac040fa Mon Sep 17 00:00:00 2001 From: Frank Rowand Date: Thu, 20 Feb 2020 12:40:21 -0600 Subject: [PATCH 0831/4444] of: unittest: annotate warnings triggered by unittest Some tests in the devicetree unittests result in printk messages from the code being tested. It can be difficult to determine whether the messages are the result of unittest or are potentially reporting bugs that should be fixed. The most recent example of a person asking whether to be concerned about these messages is [1]. Add annotations for all messages triggered by unittests, except KERN_DEBUG messages. (KERN_DEBUG is a special case due to the possible interaction of CONFIG_DYNAMIC_DEBUG.) The format of the annotations is expected to change when unittests are converted to use the kunit infrastructure when the broader testing community has an opportunity to discuss the implementation of annotations of test triggered messages. [1] https://lore.kernel.org/r/6021ac63-b5e0-ed3d-f964-7c6ef579cd68@huawei.com Signed-off-by: Frank Rowand Signed-off-by: Rob Herring --- drivers/of/unittest.c | 377 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 346 insertions(+), 31 deletions(-) diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 6059bb363097..96ae8a762a9e 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -51,6 +51,9 @@ static struct unittest_results { * Expected message may have a message level other than KERN_INFO. * Print the expected message only if the current loglevel will allow * the actual message to print. + * + * Do not use EXPECT_BEGIN() or EXPECT_END() for messages generated by + * pr_debug(). */ #define EXPECT_BEGIN(level, fmt, ...) \ printk(level pr_fmt("EXPECT \\ : ") fmt, ##__VA_ARGS__) @@ -536,29 +539,77 @@ static void __init of_unittest_parse_phandle_with_args(void) /* Check for missing cells property */ memset(&args, 0, sizeof(args)); + + EXPECT_BEGIN(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-a: could not get #phandle-cells-missing for /testcase-data/phandle-tests/provider1"); + rc = of_parse_phandle_with_args(np, "phandle-list", "#phandle-cells-missing", 0, &args); + + EXPECT_END(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-a: could not get #phandle-cells-missing for /testcase-data/phandle-tests/provider1"); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + + EXPECT_BEGIN(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-a: could not get #phandle-cells-missing for /testcase-data/phandle-tests/provider1"); + rc = of_count_phandle_with_args(np, "phandle-list", "#phandle-cells-missing"); + + EXPECT_END(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-a: could not get #phandle-cells-missing for /testcase-data/phandle-tests/provider1"); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); /* Check for bad phandle in list */ memset(&args, 0, sizeof(args)); + + EXPECT_BEGIN(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-a: could not find phandle"); + rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle", "#phandle-cells", 0, &args); + + EXPECT_END(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-a: could not find phandle"); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + + EXPECT_BEGIN(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-a: could not find phandle"); + rc = of_count_phandle_with_args(np, "phandle-list-bad-phandle", "#phandle-cells"); + + EXPECT_END(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-a: could not find phandle"); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); /* Check for incorrectly formed argument list */ memset(&args, 0, sizeof(args)); + + EXPECT_BEGIN(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-a: #phandle-cells = 3 found -1"); + rc = of_parse_phandle_with_args(np, "phandle-list-bad-args", "#phandle-cells", 1, &args); + + EXPECT_END(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-a: #phandle-cells = 3 found -1"); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + + EXPECT_BEGIN(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-a: #phandle-cells = 3 found -1"); + rc = of_count_phandle_with_args(np, "phandle-list-bad-args", "#phandle-cells"); + + EXPECT_END(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-a: #phandle-cells = 3 found -1"); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); } @@ -669,20 +720,41 @@ static void __init of_unittest_parse_phandle_with_args_map(void) /* Check for missing cells,map,mask property */ memset(&args, 0, sizeof(args)); + + EXPECT_BEGIN(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-b: could not get #phandle-missing-cells for /testcase-data/phandle-tests/provider1"); + rc = of_parse_phandle_with_args_map(np, "phandle-list", "phandle-missing", 0, &args); + EXPECT_END(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-b: could not get #phandle-missing-cells for /testcase-data/phandle-tests/provider1"); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); /* Check for bad phandle in list */ memset(&args, 0, sizeof(args)); + + EXPECT_BEGIN(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-b: could not find phandle"); + rc = of_parse_phandle_with_args_map(np, "phandle-list-bad-phandle", "phandle", 0, &args); + EXPECT_END(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-b: could not find phandle"); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); /* Check for incorrectly formed argument list */ memset(&args, 0, sizeof(args)); + + EXPECT_BEGIN(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-b: #phandle-cells = 2 found -1"); + rc = of_parse_phandle_with_args_map(np, "phandle-list-bad-args", "phandle", 1, &args); + EXPECT_END(KERN_INFO, + "OF: /testcase-data/phandle-tests/consumer-b: #phandle-cells = 2 found -1"); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); } @@ -1213,7 +1285,15 @@ static void __init of_unittest_platform_populate(void) np = of_find_node_by_path("/testcase-data/testcase-device2"); pdev = of_find_device_by_node(np); unittest(pdev, "device 2 creation failed\n"); + + EXPECT_BEGIN(KERN_INFO, + "platform testcase-data:testcase-device2: IRQ index 0 not found"); + irq = platform_get_irq(pdev, 0); + + EXPECT_END(KERN_INFO, + "platform testcase-data:testcase-device2: IRQ index 0 not found"); + unittest(irq < 0 && irq != -EPROBE_DEFER, "device parsing error failed - %d\n", irq); } @@ -1417,6 +1497,9 @@ static int __init unittest_data_add(void) return 0; } + EXPECT_BEGIN(KERN_INFO, + "Duplicate name in testcase-data, renamed to \"duplicate-name#1\""); + /* attach the sub-tree to live tree */ np = unittest_data_node->child; while (np) { @@ -1427,6 +1510,9 @@ static int __init unittest_data_add(void) np = next; } + EXPECT_END(KERN_INFO, + "Duplicate name in testcase-data, renamed to \"duplicate-name#1\""); + of_overlay_mutex_unlock(); return 0; @@ -1769,8 +1855,18 @@ static int __init of_unittest_apply_revert_overlay_check(int overlay_nr, /* test activation of device */ static void __init of_unittest_overlay_0(void) { + int ret; + + EXPECT_BEGIN(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest0/status"); + /* device should enable */ - if (of_unittest_apply_overlay_check(0, 0, 0, 1, PDEV_OVERLAY)) + ret = of_unittest_apply_overlay_check(0, 0, 0, 1, PDEV_OVERLAY); + + EXPECT_END(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest0/status"); + + if (ret) return; unittest(1, "overlay test %d passed\n", 0); @@ -1779,28 +1875,58 @@ static void __init of_unittest_overlay_0(void) /* test deactivation of device */ static void __init of_unittest_overlay_1(void) { + int ret; + + EXPECT_BEGIN(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest1/status"); + /* device should disable */ - if (of_unittest_apply_overlay_check(1, 1, 1, 0, PDEV_OVERLAY)) + ret = of_unittest_apply_overlay_check(1, 1, 1, 0, PDEV_OVERLAY); + + EXPECT_END(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest1/status"); + + if (ret) return; unittest(1, "overlay test %d passed\n", 1); + } /* test activation of device */ static void __init of_unittest_overlay_2(void) { - /* device should enable */ - if (of_unittest_apply_overlay_check(2, 2, 0, 1, PDEV_OVERLAY)) - return; + int ret; + EXPECT_BEGIN(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest2/status"); + + /* device should enable */ + ret = of_unittest_apply_overlay_check(2, 2, 0, 1, PDEV_OVERLAY); + + EXPECT_END(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest2/status"); + + if (ret) + return; unittest(1, "overlay test %d passed\n", 2); } /* test deactivation of device */ static void __init of_unittest_overlay_3(void) { + int ret; + + EXPECT_BEGIN(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest3/status"); + /* device should disable */ - if (of_unittest_apply_overlay_check(3, 3, 1, 0, PDEV_OVERLAY)) + ret = of_unittest_apply_overlay_check(3, 3, 1, 0, PDEV_OVERLAY); + + EXPECT_END(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest3/status"); + + if (ret) return; unittest(1, "overlay test %d passed\n", 3); @@ -1819,8 +1945,18 @@ static void __init of_unittest_overlay_4(void) /* test overlay apply/revert sequence */ static void __init of_unittest_overlay_5(void) { + int ret; + + EXPECT_BEGIN(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest5/status"); + /* device should disable */ - if (of_unittest_apply_revert_overlay_check(5, 5, 0, 1, PDEV_OVERLAY)) + ret = of_unittest_apply_revert_overlay_check(5, 5, 0, 1, PDEV_OVERLAY); + + EXPECT_END(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest5/status"); + + if (ret) return; unittest(1, "overlay test %d passed\n", 5); @@ -1834,6 +1970,8 @@ static void __init of_unittest_overlay_6(void) int before = 0, after = 1; const char *overlay_name; + int ret; + /* unittest device must be in before state */ for (i = 0; i < 2; i++) { if (of_unittest_device_exists(unittest_nr + i, PDEV_OVERLAY) @@ -1848,18 +1986,41 @@ static void __init of_unittest_overlay_6(void) } /* apply the overlays */ - for (i = 0; i < 2; i++) { - overlay_name = overlay_name_from_nr(overlay_nr + i); + EXPECT_BEGIN(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest6/status"); - if (!overlay_data_apply(overlay_name, &ovcs_id)) { - unittest(0, "could not apply overlay \"%s\"\n", - overlay_name); + overlay_name = overlay_name_from_nr(overlay_nr + 0); + + ret = overlay_data_apply(overlay_name, &ovcs_id); + + if (!ret) { + unittest(0, "could not apply overlay \"%s\"\n", overlay_name); return; - } - ov_id[i] = ovcs_id; - of_unittest_track_overlay(ov_id[i]); } + ov_id[0] = ovcs_id; + of_unittest_track_overlay(ov_id[0]); + + EXPECT_END(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest6/status"); + + EXPECT_BEGIN(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest7/status"); + + overlay_name = overlay_name_from_nr(overlay_nr + 1); + + ret = overlay_data_apply(overlay_name, &ovcs_id); + + if (!ret) { + unittest(0, "could not apply overlay \"%s\"\n", overlay_name); + return; + } + ov_id[1] = ovcs_id; + of_unittest_track_overlay(ov_id[1]); + + EXPECT_END(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest7/status"); + for (i = 0; i < 2; i++) { /* unittest device must be in after state */ @@ -1900,6 +2061,7 @@ static void __init of_unittest_overlay_6(void) } unittest(1, "overlay test %d passed\n", 6); + } /* test overlay application in sequence */ @@ -1908,26 +2070,65 @@ static void __init of_unittest_overlay_8(void) int i, ov_id[2], ovcs_id; int overlay_nr = 8, unittest_nr = 8; const char *overlay_name; + int ret; /* we don't care about device state in this test */ + EXPECT_BEGIN(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest8/status"); + + overlay_name = overlay_name_from_nr(overlay_nr + 0); + + ret = overlay_data_apply(overlay_name, &ovcs_id); + if (!ret) + unittest(0, "could not apply overlay \"%s\"\n", overlay_name); + + EXPECT_END(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest8/status"); + + if (!ret) + return; + + ov_id[0] = ovcs_id; + of_unittest_track_overlay(ov_id[0]); + + overlay_name = overlay_name_from_nr(overlay_nr + 1); + + EXPECT_BEGIN(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest8/property-foo"); + /* apply the overlays */ - for (i = 0; i < 2; i++) { + ret = overlay_data_apply(overlay_name, &ovcs_id); - overlay_name = overlay_name_from_nr(overlay_nr + i); + EXPECT_END(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/test-unittest8/property-foo"); - if (!overlay_data_apply(overlay_name, &ovcs_id)) { - unittest(0, "could not apply overlay \"%s\"\n", - overlay_name); - return; - } - ov_id[i] = ovcs_id; - of_unittest_track_overlay(ov_id[i]); + if (!ret) { + unittest(0, "could not apply overlay \"%s\"\n", overlay_name); + return; } + ov_id[1] = ovcs_id; + of_unittest_track_overlay(ov_id[1]); + /* now try to remove first overlay (it should fail) */ ovcs_id = ov_id[0]; - if (!of_overlay_remove(&ovcs_id)) { + + EXPECT_BEGIN(KERN_INFO, + "OF: overlay: node_overlaps_later_cs: #6 overlaps with #7 @/testcase-data/overlay-node/test-bus/test-unittest8"); + + EXPECT_BEGIN(KERN_INFO, + "OF: overlay: overlay #6 is not topmost"); + + ret = of_overlay_remove(&ovcs_id); + + EXPECT_END(KERN_INFO, + "OF: overlay: overlay #6 is not topmost"); + + EXPECT_END(KERN_INFO, + "OF: overlay: node_overlaps_later_cs: #6 overlaps with #7 @/testcase-data/overlay-node/test-bus/test-unittest8"); + + if (!ret) { unittest(0, "%s was destroyed @\"%s\"\n", overlay_name_from_nr(overlay_nr + 0), unittest_path(unittest_nr, @@ -1959,6 +2160,7 @@ static void __init of_unittest_overlay_10(void) /* device should disable */ ret = of_unittest_apply_overlay_check(10, 10, 0, 1, PDEV_OVERLAY); + if (unittest(ret == 0, "overlay test %d failed; overlay application\n", 10)) return; @@ -1982,6 +2184,7 @@ static void __init of_unittest_overlay_11(void) /* device should disable */ ret = of_unittest_apply_revert_overlay_check(11, 11, 0, 1, PDEV_OVERLAY); + unittest(ret == 0, "overlay test %d failed; overlay apply\n", 11); } @@ -2212,12 +2415,21 @@ static int of_unittest_overlay_i2c_init(void) return ret; ret = platform_driver_register(&unittest_i2c_bus_driver); + if (unittest(ret == 0, "could not register unittest i2c bus driver\n")) return ret; #if IS_BUILTIN(CONFIG_I2C_MUX) + + EXPECT_BEGIN(KERN_INFO, + "i2c i2c-1: Added multiplexed i2c bus 2"); + ret = i2c_add_driver(&unittest_i2c_mux_driver); + + EXPECT_END(KERN_INFO, + "i2c i2c-1: Added multiplexed i2c bus 2"); + if (unittest(ret == 0, "could not register unittest i2c mux driver\n")) return ret; @@ -2237,8 +2449,18 @@ static void of_unittest_overlay_i2c_cleanup(void) static void __init of_unittest_overlay_i2c_12(void) { + int ret; + /* device should enable */ - if (of_unittest_apply_overlay_check(12, 12, 0, 1, I2C_OVERLAY)) + EXPECT_BEGIN(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest12/status"); + + ret = of_unittest_apply_overlay_check(12, 12, 0, 1, I2C_OVERLAY); + + EXPECT_END(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest12/status"); + + if (ret) return; unittest(1, "overlay test %d passed\n", 12); @@ -2247,8 +2469,18 @@ static void __init of_unittest_overlay_i2c_12(void) /* test deactivation of device */ static void __init of_unittest_overlay_i2c_13(void) { + int ret; + + EXPECT_BEGIN(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest13/status"); + /* device should disable */ - if (of_unittest_apply_overlay_check(13, 13, 1, 0, I2C_OVERLAY)) + ret = of_unittest_apply_overlay_check(13, 13, 1, 0, I2C_OVERLAY); + + EXPECT_END(KERN_INFO, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest13/status"); + + if (ret) return; unittest(1, "overlay test %d passed\n", 13); @@ -2261,8 +2493,18 @@ static void of_unittest_overlay_i2c_14(void) static void __init of_unittest_overlay_i2c_15(void) { + int ret; + /* device should enable */ - if (of_unittest_apply_overlay_check(15, 15, 0, 1, I2C_OVERLAY)) + EXPECT_BEGIN(KERN_INFO, + "i2c i2c-1: Added multiplexed i2c bus 3"); + + ret = of_unittest_apply_overlay_check(15, 15, 0, 1, I2C_OVERLAY); + + EXPECT_END(KERN_INFO, + "i2c i2c-1: Added multiplexed i2c bus 3"); + + if (ret) return; unittest(1, "overlay test %d passed\n", 15); @@ -2723,6 +2965,7 @@ static __init void of_unittest_overlay_high_level(void) struct device_node *overlay_base_symbols; struct device_node **pprev; struct property *prop; + int ret; if (!overlay_base_root) { unittest(0, "overlay_base_root not initialized\n"); @@ -2837,15 +3080,86 @@ static __init void of_unittest_overlay_high_level(void) /* now do the normal overlay usage test */ - unittest(overlay_data_apply("overlay", NULL), - "Adding overlay 'overlay' failed\n"); + EXPECT_BEGIN(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/substation@100/status"); + EXPECT_BEGIN(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/fairway-1/status"); + EXPECT_BEGIN(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/fairway-1/ride@100/track@30/incline-up"); + EXPECT_BEGIN(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/fairway-1/ride@100/track@40/incline-up"); + EXPECT_BEGIN(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/lights@40000/status"); + EXPECT_BEGIN(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/lights@40000/color"); + EXPECT_BEGIN(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/lights@40000/rate"); + EXPECT_BEGIN(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/hvac_2"); + EXPECT_BEGIN(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/ride_200"); + EXPECT_BEGIN(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/ride_200_left"); + EXPECT_BEGIN(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/ride_200_right"); + + ret = overlay_data_apply("overlay", NULL); + + EXPECT_END(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/ride_200_right"); + EXPECT_END(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/ride_200_left"); + EXPECT_END(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/ride_200"); + EXPECT_END(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/hvac_2"); + EXPECT_END(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/lights@40000/rate"); + EXPECT_END(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/lights@40000/color"); + EXPECT_END(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/lights@40000/status"); + EXPECT_END(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/fairway-1/ride@100/track@40/incline-up"); + EXPECT_END(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/fairway-1/ride@100/track@30/incline-up"); + EXPECT_END(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/fairway-1/status"); + EXPECT_END(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/substation@100/status"); + + unittest(ret, "Adding overlay 'overlay' failed\n"); + + EXPECT_BEGIN(KERN_ERR, + "OF: overlay: ERROR: multiple fragments add and/or delete node /testcase-data-2/substation@100/motor-1/controller"); + EXPECT_BEGIN(KERN_ERR, + "OF: overlay: ERROR: multiple fragments add, update, and/or delete property /testcase-data-2/substation@100/motor-1/controller/name"); unittest(overlay_data_apply("overlay_bad_add_dup_node", NULL), "Adding overlay 'overlay_bad_add_dup_node' failed\n"); + EXPECT_END(KERN_ERR, + "OF: overlay: ERROR: multiple fragments add, update, and/or delete property /testcase-data-2/substation@100/motor-1/controller/name"); + EXPECT_END(KERN_ERR, + "OF: overlay: ERROR: multiple fragments add and/or delete node /testcase-data-2/substation@100/motor-1/controller"); + + EXPECT_BEGIN(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/substation@100/motor-1/rpm_avail"); + EXPECT_BEGIN(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/substation@100/motor-1/rpm_avail"); + EXPECT_BEGIN(KERN_ERR, + "OF: overlay: ERROR: multiple fragments add, update, and/or delete property /testcase-data-2/substation@100/motor-1/rpm_avail"); + unittest(overlay_data_apply("overlay_bad_add_dup_prop", NULL), "Adding overlay 'overlay_bad_add_dup_prop' failed\n"); + EXPECT_END(KERN_ERR, + "OF: overlay: ERROR: multiple fragments add, update, and/or delete property /testcase-data-2/substation@100/motor-1/rpm_avail"); + EXPECT_END(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/substation@100/motor-1/rpm_avail"); + EXPECT_END(KERN_ERR, + "OF: overlay: WARNING: memory leak will occur if overlay removed, property: /testcase-data-2/substation@100/motor-1/rpm_avail"); + unittest(overlay_data_apply("overlay_bad_phandle", NULL), "Adding overlay 'overlay_bad_phandle' failed\n"); @@ -2869,6 +3183,8 @@ static int __init of_unittest(void) struct device_node *np; int res; + pr_info("start of unittest - you will see error messages\n"); + /* adding data for unittest */ if (IS_ENABLED(CONFIG_UML)) @@ -2887,7 +3203,6 @@ static int __init of_unittest(void) } of_node_put(np); - pr_info("start of unittest - you will see error messages\n"); of_unittest_check_tree_linkage(); of_unittest_check_phandles(); of_unittest_find_node_by_name(); From 4f325e8c83e752b84d2c10b9234c5518c198e15e Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 21 Feb 2020 11:11:36 +0900 Subject: [PATCH 0832/4444] dt-bindings: serial: Convert UniPhier UART to json-schema Convert the UniPhier UART binding to DT schema format. Signed-off-by: Masahiro Yamada Signed-off-by: Rob Herring --- .../serial/socionext,uniphier-uart.yaml | 46 +++++++++++++++++++ .../bindings/serial/uniphier-uart.txt | 22 --------- 2 files changed, 46 insertions(+), 22 deletions(-) create mode 100644 Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml delete mode 100644 Documentation/devicetree/bindings/serial/uniphier-uart.txt diff --git a/Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml b/Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml new file mode 100644 index 000000000000..09a30300850c --- /dev/null +++ b/Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/serial/socionext,uniphier-uart.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: UniPhier UART controller + +maintainers: + - Masahiro Yamada + +properties: + compatible: + const: socionext,uniphier-uart + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + minItems: 1 + + auto-flow-control: + description: enable automatic flow control support. + $ref: /schemas/types.yaml#/definitions/flag + +required: + - compatible + - reg + - interrupts + - clocks + +examples: + - | + aliases { + serial0 = &serial0; + }; + + serial0: serial@54006800 { + compatible = "socionext,uniphier-uart"; + reg = <0x54006800 0x40>; + interrupts = <0 33 4>; + clocks = <&uart_clk>; + }; diff --git a/Documentation/devicetree/bindings/serial/uniphier-uart.txt b/Documentation/devicetree/bindings/serial/uniphier-uart.txt deleted file mode 100644 index 7a1bf02bb869..000000000000 --- a/Documentation/devicetree/bindings/serial/uniphier-uart.txt +++ /dev/null @@ -1,22 +0,0 @@ -UniPhier UART controller - -Required properties: -- compatible: should be "socionext,uniphier-uart". -- reg: offset and length of the register set for the device. -- interrupts: a single interrupt specifier. -- clocks: phandle to the input clock. - -Optional properties: --auto-flow-control: enable automatic flow control support. - -Example: - aliases { - serial0 = &serial0; - }; - - serial0: serial@54006800 { - compatible = "socionext,uniphier-uart"; - reg = <0x54006800 0x40>; - interrupts = <0 33 4>; - clocks = <&uart_clk>; - }; From b279cac91583a75295b4fa1ba5f6591683b69fb4 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 21 Feb 2020 11:55:33 +0900 Subject: [PATCH 0833/4444] dt-bindings: i2c: Convert UniPhier I2C controller to json-schema Convert the UniPhier I2C controller (FIFO-less) binding to DT schema format. There are two types of I2C controllers used on the UniPhier platform. This is the legacy one without FIFO support, which is used on the sLD8 SoC or older. Signed-off-by: Masahiro Yamada Signed-off-by: Rob Herring --- .../devicetree/bindings/i2c/i2c-uniphier.txt | 25 ---------- .../bindings/i2c/socionext,uniphier-i2c.yaml | 50 +++++++++++++++++++ 2 files changed, 50 insertions(+), 25 deletions(-) delete mode 100644 Documentation/devicetree/bindings/i2c/i2c-uniphier.txt create mode 100644 Documentation/devicetree/bindings/i2c/socionext,uniphier-i2c.yaml diff --git a/Documentation/devicetree/bindings/i2c/i2c-uniphier.txt b/Documentation/devicetree/bindings/i2c/i2c-uniphier.txt deleted file mode 100644 index 26f9d95b3436..000000000000 --- a/Documentation/devicetree/bindings/i2c/i2c-uniphier.txt +++ /dev/null @@ -1,25 +0,0 @@ -UniPhier I2C controller (FIFO-less) - -Required properties: -- compatible: should be "socionext,uniphier-i2c". -- #address-cells: should be 1. -- #size-cells: should be 0. -- reg: offset and length of the register set for the device. -- interrupts: a single interrupt specifier. -- clocks: phandle to the input clock. - -Optional properties: -- clock-frequency: desired I2C bus frequency in Hz. The maximum supported - value is 400000. Defaults to 100000 if not specified. - -Examples: - - i2c0: i2c@58400000 { - compatible = "socionext,uniphier-i2c"; - reg = <0x58400000 0x40>; - #address-cells = <1>; - #size-cells = <0>; - interrupts = <0 41 1>; - clocks = <&i2c_clk>; - clock-frequency = <100000>; - }; diff --git a/Documentation/devicetree/bindings/i2c/socionext,uniphier-i2c.yaml b/Documentation/devicetree/bindings/i2c/socionext,uniphier-i2c.yaml new file mode 100644 index 000000000000..ef998def554e --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/socionext,uniphier-i2c.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/socionext,uniphier-i2c.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: UniPhier I2C controller (FIFO-less) + +maintainers: + - Masahiro Yamada + +allOf: + - $ref: /schemas/i2c/i2c-controller.yaml# + +properties: + compatible: + const: socionext,uniphier-i2c + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-frequency: + minimum: 100000 + maximum: 400000 + +required: + - compatible + - reg + - "#address-cells" + - "#size-cells" + - interrupts + - clocks + +examples: + - | + i2c0: i2c@58400000 { + compatible = "socionext,uniphier-i2c"; + reg = <0x58400000 0x40>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0 41 1>; + clocks = <&i2c_clk>; + clock-frequency = <100000>; + }; From 4abfe6f04d93e4aac202007486266bd1a904cc43 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 21 Feb 2020 11:55:34 +0900 Subject: [PATCH 0834/4444] dt-bindings: i2c: Convert UniPhier FI2C controller to json-schema Convert the UniPhier FIFO-builtin I2C (a.k.a. FIFO) controller binding to DT schema format. There are two types of I2C controllers used on the UniPhier platform. This is the new one with FIFO support, which is used on the Pro4 SoC or newer. Signed-off-by: Masahiro Yamada Signed-off-by: Rob Herring --- .../bindings/i2c/i2c-uniphier-f.txt | 25 ---------- .../bindings/i2c/socionext,uniphier-fi2c.yaml | 50 +++++++++++++++++++ 2 files changed, 50 insertions(+), 25 deletions(-) delete mode 100644 Documentation/devicetree/bindings/i2c/i2c-uniphier-f.txt create mode 100644 Documentation/devicetree/bindings/i2c/socionext,uniphier-fi2c.yaml diff --git a/Documentation/devicetree/bindings/i2c/i2c-uniphier-f.txt b/Documentation/devicetree/bindings/i2c/i2c-uniphier-f.txt deleted file mode 100644 index 27fc6f8c798b..000000000000 --- a/Documentation/devicetree/bindings/i2c/i2c-uniphier-f.txt +++ /dev/null @@ -1,25 +0,0 @@ -UniPhier I2C controller (FIFO-builtin) - -Required properties: -- compatible: should be "socionext,uniphier-fi2c". -- #address-cells: should be 1. -- #size-cells: should be 0. -- reg: offset and length of the register set for the device. -- interrupts: a single interrupt specifier. -- clocks: phandle to the input clock. - -Optional properties: -- clock-frequency: desired I2C bus frequency in Hz. The maximum supported - value is 400000. Defaults to 100000 if not specified. - -Examples: - - i2c0: i2c@58780000 { - compatible = "socionext,uniphier-fi2c"; - reg = <0x58780000 0x80>; - #address-cells = <1>; - #size-cells = <0>; - interrupts = <0 41 4>; - clocks = <&i2c_clk>; - clock-frequency = <100000>; - }; diff --git a/Documentation/devicetree/bindings/i2c/socionext,uniphier-fi2c.yaml b/Documentation/devicetree/bindings/i2c/socionext,uniphier-fi2c.yaml new file mode 100644 index 000000000000..15abc022968e --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/socionext,uniphier-fi2c.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/socionext,uniphier-fi2c.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: UniPhier I2C controller (FIFO-builtin) + +maintainers: + - Masahiro Yamada + +allOf: + - $ref: /schemas/i2c/i2c-controller.yaml# + +properties: + compatible: + const: socionext,uniphier-fi2c + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-frequency: + minimum: 100000 + maximum: 400000 + +required: + - compatible + - reg + - "#address-cells" + - "#size-cells" + - interrupts + - clocks + +examples: + - | + i2c0: i2c@58780000 { + compatible = "socionext,uniphier-fi2c"; + reg = <0x58780000 0x80>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0 41 4>; + clocks = <&i2c_clk>; + clock-frequency = <100000>; + }; From 76afa64374a79c22b2dab61aebef99a967783bf0 Mon Sep 17 00:00:00 2001 From: Shreyas NC Date: Tue, 25 Feb 2020 21:39:12 +0800 Subject: [PATCH 0835/4444] ASoC: Add initial support for multiple CPU DAIs ASoC core supports multiple codec DAIs but supports only a CPU DAI. To support multiple cpu DAIs, add cpu_dai and num_cpu_dai in snd_soc_dai_link and snd_soc_pcm_runtime structures similar to support for codec_dai. This is intended as a preparatory patch to eventually support the unification of the Codec and CPU DAI. Inline with multiple codec DAI approach, add support to allocate, init, bind and probe multiple cpu_dai on init if driver specifies that. Also add support to loop over multiple cpu_dai during suspend and resume. This is intended as a preparatory patch to eventually unify the CPU and Codec DAI into DAI components. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Signed-off-by: Kuninori Morimoto Signed-off-by: Shreyas NC Link: https://lore.kernel.org/r/20200225133917.21314-2-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- include/sound/soc.h | 15 ++++ sound/soc/soc-core.c | 168 +++++++++++++++++++++++-------------------- 2 files changed, 106 insertions(+), 77 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 8a2266676b2d..81e5d17be935 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -855,6 +855,11 @@ struct snd_soc_dai_link { ((platform) = &link->platforms[i]); \ (i)++) +#define for_each_link_cpus(link, i, cpu) \ + for ((i) = 0; \ + ((i) < link->num_cpus) && ((cpu) = &link->cpus[i]); \ + (i)++) + /* * Sample 1 : Single CPU/Codec/Platform * @@ -1132,6 +1137,9 @@ struct snd_soc_pcm_runtime { struct snd_soc_dai **codec_dais; unsigned int num_codecs; + struct snd_soc_dai **cpu_dais; + unsigned int num_cpus; + struct delayed_work delayed_work; void (*close_delayed_work_func)(struct snd_soc_pcm_runtime *rtd); #ifdef CONFIG_DEBUG_FS @@ -1159,6 +1167,13 @@ struct snd_soc_pcm_runtime { #define for_each_rtd_codec_dai_rollback(rtd, i, dai) \ for (; (--(i) >= 0) && ((dai) = rtd->codec_dais[i]);) +#define for_each_rtd_cpu_dai(rtd, i, dai)\ + for ((i) = 0; \ + ((i) < rtd->num_cpus) && ((dai) = rtd->cpu_dais[i]); \ + (i)++) +#define for_each_rtd_cpu_dai_rollback(rtd, i, dai) \ + for (; (--(i) >= 0) && ((dai) = rtd->cpu_dais[i]);) + void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd); /* mixer control */ diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 518b652cf872..f2cfbf182f49 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -483,6 +483,14 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( if (!rtd->codec_dais) goto free_rtd; + /* + * for rtd->cpu_dais + */ + rtd->cpu_dais = devm_kcalloc(dev, dai_link->num_cpus, + sizeof(struct snd_soc_dai *), + GFP_KERNEL); + if (!rtd->cpu_dais) + goto free_rtd; /* * rtd remaining settings */ @@ -833,7 +841,7 @@ static int soc_dai_link_sanity_check(struct snd_soc_card *card, struct snd_soc_dai_link *link) { int i; - struct snd_soc_dai_link_component *codec, *platform; + struct snd_soc_dai_link_component *cpu, *codec, *platform; for_each_link_codecs(link, i, codec) { /* @@ -882,44 +890,38 @@ static int soc_dai_link_sanity_check(struct snd_soc_card *card, return -EPROBE_DEFER; } - /* FIXME */ - if (link->num_cpus > 1) { - dev_err(card->dev, - "ASoC: multi cpu is not yet supported %s\n", - link->name); - return -EINVAL; - } + for_each_link_cpus(link, i, cpu) { + /* + * CPU device may be specified by either name or OF node, but + * can be left unspecified, and will be matched based on DAI + * name alone.. + */ + if (cpu->name && cpu->of_node) { + dev_err(card->dev, + "ASoC: Neither/both cpu name/of_node are set for %s\n", + link->name); + return -EINVAL; + } - /* - * CPU device may be specified by either name or OF node, but - * can be left unspecified, and will be matched based on DAI - * name alone.. - */ - if (link->cpus->name && link->cpus->of_node) { - dev_err(card->dev, - "ASoC: Neither/both cpu name/of_node are set for %s\n", - link->name); - return -EINVAL; - } + /* + * Defer card registration if cpu dai component is not added to + * component list. + */ + if ((cpu->of_node || cpu->name) && + !soc_find_component(cpu)) + return -EPROBE_DEFER; - /* - * Defer card registration if cpu dai component is not added to - * component list. - */ - if ((link->cpus->of_node || link->cpus->name) && - !soc_find_component(link->cpus)) - return -EPROBE_DEFER; - - /* - * At least one of CPU DAI name or CPU device name/node must be - * specified - */ - if (!link->cpus->dai_name && - !(link->cpus->name || link->cpus->of_node)) { - dev_err(card->dev, - "ASoC: Neither cpu_dai_name nor cpu_name/of_node are set for %s\n", - link->name); - return -EINVAL; + /* + * At least one of CPU DAI name or CPU device name/node must be + * specified + */ + if (!cpu->dai_name && + !(cpu->name || cpu->of_node)) { + dev_err(card->dev, + "ASoC: Neither cpu_dai_name nor cpu_name/of_node are set for %s\n", + link->name); + return -EINVAL; + } } return 0; @@ -962,7 +964,7 @@ int snd_soc_add_pcm_runtime(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) { struct snd_soc_pcm_runtime *rtd; - struct snd_soc_dai_link_component *codec, *platform; + struct snd_soc_dai_link_component *codec, *platform, *cpu; struct snd_soc_component *component; int i, ret; @@ -987,14 +989,19 @@ int snd_soc_add_pcm_runtime(struct snd_soc_card *card, if (!rtd) return -ENOMEM; - /* FIXME: we need multi CPU support in the future */ - rtd->cpu_dai = snd_soc_find_dai(dai_link->cpus); - if (!rtd->cpu_dai) { - dev_info(card->dev, "ASoC: CPU DAI %s not registered\n", - dai_link->cpus->dai_name); - goto _err_defer; + rtd->num_cpus = dai_link->num_cpus; + for_each_link_cpus(dai_link, i, cpu) { + rtd->cpu_dais[i] = snd_soc_find_dai(cpu); + if (!rtd->cpu_dais[i]) { + dev_info(card->dev, "ASoC: CPU DAI %s not registered\n", + cpu->dai_name); + goto _err_defer; + } + snd_soc_rtd_add_component(rtd, rtd->cpu_dais[i]->component); } - snd_soc_rtd_add_component(rtd, rtd->cpu_dai->component); + + /* Single cpu links expect cpu and cpu_dai in runtime data */ + rtd->cpu_dai = rtd->cpu_dais[0]; /* Find CODEC from registered CODECs */ rtd->num_codecs = dai_link->num_codecs; @@ -1114,7 +1121,8 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, dai_link->stream_name, ret); return ret; } - ret = soc_dai_pcm_new(&cpu_dai, 1, rtd); + ret = soc_dai_pcm_new(rtd->cpu_dais, + rtd->num_cpus, rtd); if (ret < 0) return ret; ret = soc_dai_pcm_new(rtd->codec_dais, @@ -1306,6 +1314,7 @@ static void soc_remove_link_dais(struct snd_soc_card *card) { int i; struct snd_soc_dai *codec_dai; + struct snd_soc_dai *cpu_dai; struct snd_soc_pcm_runtime *rtd; int order; @@ -1315,14 +1324,15 @@ static void soc_remove_link_dais(struct snd_soc_card *card) for_each_rtd_codec_dai(rtd, i, codec_dai) soc_remove_dai(codec_dai, order); - soc_remove_dai(rtd->cpu_dai, order); + for_each_rtd_cpu_dai(rtd, i, cpu_dai) + soc_remove_dai(cpu_dai, order); } } } static int soc_probe_link_dais(struct snd_soc_card *card) { - struct snd_soc_dai *codec_dai; + struct snd_soc_dai *codec_dai, *cpu_dai; struct snd_soc_pcm_runtime *rtd; int i, order, ret; @@ -1333,9 +1343,12 @@ static int soc_probe_link_dais(struct snd_soc_card *card) "ASoC: probe %s dai link %d late %d\n", card->name, rtd->num, order); - ret = soc_probe_dai(rtd->cpu_dai, order); - if (ret) - return ret; + /* probe the CPU DAI */ + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + ret = soc_probe_dai(cpu_dai, order); + if (ret) + return ret; + } /* probe the CODEC DAI */ for_each_rtd_codec_dai(rtd, i, codec_dai) { @@ -1467,8 +1480,9 @@ static void soc_remove_aux_devices(struct snd_soc_card *card) int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, unsigned int dai_fmt) { - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; + unsigned int inv_dai_fmt; unsigned int i; int ret; @@ -1485,33 +1499,33 @@ int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, * Flip the polarity for the "CPU" end of a CODEC<->CODEC link * the component which has non_legacy_dai_naming is Codec */ - if (cpu_dai->component->driver->non_legacy_dai_naming) { - unsigned int inv_dai_fmt; - - inv_dai_fmt = dai_fmt & ~SND_SOC_DAIFMT_MASTER_MASK; - switch (dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - inv_dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; - break; - case SND_SOC_DAIFMT_CBM_CFS: - inv_dai_fmt |= SND_SOC_DAIFMT_CBS_CFM; - break; - case SND_SOC_DAIFMT_CBS_CFM: - inv_dai_fmt |= SND_SOC_DAIFMT_CBM_CFS; - break; - case SND_SOC_DAIFMT_CBS_CFS: - inv_dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; - break; - } - - dai_fmt = inv_dai_fmt; + inv_dai_fmt = dai_fmt & ~SND_SOC_DAIFMT_MASTER_MASK; + switch (dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + inv_dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; + break; + case SND_SOC_DAIFMT_CBM_CFS: + inv_dai_fmt |= SND_SOC_DAIFMT_CBS_CFM; + break; + case SND_SOC_DAIFMT_CBS_CFM: + inv_dai_fmt |= SND_SOC_DAIFMT_CBM_CFS; + break; + case SND_SOC_DAIFMT_CBS_CFS: + inv_dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; + break; } + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + unsigned int fmt = dai_fmt; - ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt); - if (ret != 0 && ret != -ENOTSUPP) { - dev_warn(cpu_dai->dev, - "ASoC: Failed to set DAI format: %d\n", ret); - return ret; + if (cpu_dai->component->driver->non_legacy_dai_naming) + fmt = inv_dai_fmt; + + ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + if (ret != 0 && ret != -ENOTSUPP) { + dev_warn(cpu_dai->dev, + "ASoC: Failed to set DAI format: %d\n", ret); + return ret; + } } return 0; From 19bdcc7aeed4169820be6a683c422fc06d030136 Mon Sep 17 00:00:00 2001 From: Shreyas NC Date: Tue, 25 Feb 2020 21:39:13 +0800 Subject: [PATCH 0836/4444] ASoC: Add multiple CPU DAI support for PCM ops Add support in PCM operations to invoke multiple cpu dais as we do for multiple codec dais. Also the symmetry calculations are updated to reflect multiple cpu dais. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Signed-off-by: Kuninori Morimoto Signed-off-by: Shreyas NC Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20200225133917.21314-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 396 +++++++++++++++++++++++++++++--------------- 1 file changed, 261 insertions(+), 135 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 4c27c77206f1..44694e65fc4a 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -253,18 +253,22 @@ static int soc_rtd_trigger(struct snd_soc_pcm_runtime *rtd, static void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, int stream, int action) { - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; int i; lockdep_assert_held(&rtd->card->pcm_mutex); - cpu_dai->stream_active[stream] += action; + for_each_rtd_cpu_dai(rtd, i, cpu_dai) + cpu_dai->stream_active[stream] += action; + for_each_rtd_codec_dai(rtd, i, codec_dai) codec_dai->stream_active[stream] += action; - cpu_dai->active += action; - cpu_dai->component->active += action; + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + cpu_dai->active += action; + cpu_dai->component->active += action; + } for_each_rtd_codec_dai(rtd, i, codec_dai) { codec_dai->active += action; codec_dai->component->active += action; @@ -434,7 +438,7 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; unsigned int rate, channels, sample_bits, symmetry, i; @@ -443,40 +447,60 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, sample_bits = snd_pcm_format_physical_width(params_format(params)); /* reject unmatched parameters when applying symmetry */ - symmetry = cpu_dai->driver->symmetric_rates || - rtd->dai_link->symmetric_rates; + symmetry = rtd->dai_link->symmetric_rates; + + for_each_rtd_cpu_dai(rtd, i, cpu_dai) + symmetry |= cpu_dai->driver->symmetric_rates; for_each_rtd_codec_dai(rtd, i, codec_dai) symmetry |= codec_dai->driver->symmetric_rates; - if (symmetry && cpu_dai->rate && cpu_dai->rate != rate) { - dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n", - cpu_dai->rate, rate); - return -EINVAL; + if (symmetry) { + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + if (cpu_dai->rate && cpu_dai->rate != rate) { + dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n", + cpu_dai->rate, rate); + return -EINVAL; + } + } } - symmetry = cpu_dai->driver->symmetric_channels || - rtd->dai_link->symmetric_channels; + symmetry = rtd->dai_link->symmetric_channels; + + for_each_rtd_cpu_dai(rtd, i, cpu_dai) + symmetry |= cpu_dai->driver->symmetric_channels; for_each_rtd_codec_dai(rtd, i, codec_dai) symmetry |= codec_dai->driver->symmetric_channels; - if (symmetry && cpu_dai->channels && cpu_dai->channels != channels) { - dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n", - cpu_dai->channels, channels); - return -EINVAL; + if (symmetry) { + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + if (cpu_dai->channels && + cpu_dai->channels != channels) { + dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n", + cpu_dai->channels, channels); + return -EINVAL; + } + } } - symmetry = cpu_dai->driver->symmetric_samplebits || - rtd->dai_link->symmetric_samplebits; + symmetry = rtd->dai_link->symmetric_samplebits; + + for_each_rtd_cpu_dai(rtd, i, cpu_dai) + symmetry |= cpu_dai->driver->symmetric_samplebits; for_each_rtd_codec_dai(rtd, i, codec_dai) symmetry |= codec_dai->driver->symmetric_samplebits; - if (symmetry && cpu_dai->sample_bits && cpu_dai->sample_bits != sample_bits) { - dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n", - cpu_dai->sample_bits, sample_bits); - return -EINVAL; + if (symmetry) { + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + if (cpu_dai->sample_bits && + cpu_dai->sample_bits != sample_bits) { + dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n", + cpu_dai->sample_bits, sample_bits); + return -EINVAL; + } + } } return 0; @@ -485,14 +509,20 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai_driver *cpu_driver = rtd->cpu_dai->driver; struct snd_soc_dai_link *link = rtd->dai_link; struct snd_soc_dai *codec_dai; + struct snd_soc_dai *cpu_dai; unsigned int symmetry, i; - symmetry = cpu_driver->symmetric_rates || link->symmetric_rates || - cpu_driver->symmetric_channels || link->symmetric_channels || - cpu_driver->symmetric_samplebits || link->symmetric_samplebits; + symmetry = link->symmetric_rates || + link->symmetric_channels || + link->symmetric_samplebits; + + for_each_rtd_cpu_dai(rtd, i, cpu_dai) + symmetry = symmetry || + cpu_dai->driver->symmetric_rates || + cpu_dai->driver->symmetric_channels || + cpu_dai->driver->symmetric_samplebits; for_each_rtd_codec_dai(rtd, i, codec_dai) symmetry = symmetry || @@ -520,12 +550,12 @@ static void soc_pcm_set_msb(struct snd_pcm_substream *substream, int bits) static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; struct snd_soc_pcm_stream *pcm_codec, *pcm_cpu; int stream = substream->stream; int i; - unsigned int bits = 0, cpu_bits; + unsigned int bits = 0, cpu_bits = 0; for_each_rtd_codec_dai(rtd, i, codec_dai) { pcm_codec = snd_soc_dai_get_pcm_stream(codec_dai, stream); @@ -537,8 +567,15 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) bits = max(pcm_codec->sig_bits, bits); } - pcm_cpu = snd_soc_dai_get_pcm_stream(cpu_dai, stream); - cpu_bits = pcm_cpu->sig_bits; + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + pcm_cpu = snd_soc_dai_get_pcm_stream(cpu_dai, stream); + + if (pcm_cpu->sig_bits == 0) { + cpu_bits = 0; + break; + } + cpu_bits = max(pcm_cpu->sig_bits, cpu_bits); + } soc_pcm_set_msb(substream, bits); soc_pcm_set_msb(substream, cpu_bits); @@ -550,18 +587,32 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) struct snd_pcm_hardware *hw = &runtime->hw; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai; + struct snd_soc_dai *cpu_dai; struct snd_soc_pcm_stream *codec_stream; struct snd_soc_pcm_stream *cpu_stream; unsigned int chan_min = 0, chan_max = UINT_MAX; + unsigned int cpu_chan_min = 0, cpu_chan_max = UINT_MAX; unsigned int rate_min = 0, rate_max = UINT_MAX; - unsigned int rates = UINT_MAX; + unsigned int cpu_rate_min = 0, cpu_rate_max = UINT_MAX; + unsigned int rates = UINT_MAX, cpu_rates = UINT_MAX; u64 formats = ULLONG_MAX; int stream = substream->stream; int i; - cpu_stream = snd_soc_dai_get_pcm_stream(rtd->cpu_dai, stream); + /* first calculate min/max only for CPUs in the DAI link */ + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + cpu_stream = snd_soc_dai_get_pcm_stream(cpu_dai, stream); - /* first calculate min/max only for CODECs in the DAI link */ + cpu_chan_min = max(cpu_chan_min, cpu_stream->channels_min); + cpu_chan_max = min(cpu_chan_max, cpu_stream->channels_max); + cpu_rate_min = max(cpu_rate_min, cpu_stream->rate_min); + cpu_rate_max = min_not_zero(cpu_rate_max, cpu_stream->rate_max); + formats &= cpu_stream->formats; + cpu_rates = snd_pcm_rate_mask_intersect(cpu_stream->rates, + cpu_rates); + } + + /* second calculate min/max only for CODECs in the DAI link */ for_each_rtd_codec_dai(rtd, i, codec_dai) { /* @@ -589,27 +640,28 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) /* * chan min/max cannot be enforced if there are multiple CODEC DAIs - * connected to a single CPU DAI, use CPU DAI's directly and let + * connected to CPU DAI(s), use CPU DAI's directly and let * channel allocation be fixed up later */ if (rtd->num_codecs > 1) { - chan_min = cpu_stream->channels_min; - chan_max = cpu_stream->channels_max; + chan_min = cpu_chan_min; + chan_max = cpu_chan_max; } - hw->channels_min = max(chan_min, cpu_stream->channels_min); - hw->channels_max = min(chan_max, cpu_stream->channels_max); + /* finally find a intersection between CODECs and CPUs */ + hw->channels_min = max(chan_min, cpu_chan_min); + hw->channels_max = min(chan_max, cpu_chan_max); if (hw->formats) - hw->formats &= formats & cpu_stream->formats; + hw->formats &= formats; else - hw->formats = formats & cpu_stream->formats; - hw->rates = snd_pcm_rate_mask_intersect(rates, cpu_stream->rates); + hw->formats = formats; + hw->rates = snd_pcm_rate_mask_intersect(rates, cpu_rates); snd_pcm_limit_hw_rates(runtime); - hw->rate_min = max(hw->rate_min, cpu_stream->rate_min); + hw->rate_min = max(hw->rate_min, cpu_rate_min); hw->rate_min = max(hw->rate_min, rate_min); - hw->rate_max = min_not_zero(hw->rate_max, cpu_stream->rate_max); + hw->rate_max = min_not_zero(hw->rate_max, cpu_rate_max); hw->rate_max = min_not_zero(hw->rate_max, rate_max); } @@ -681,7 +733,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; int i; @@ -689,9 +741,11 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) snd_soc_runtime_deactivate(rtd, substream->stream); - snd_soc_dai_digital_mute(cpu_dai, 1, substream->stream); + for_each_rtd_cpu_dai(rtd, i, cpu_dai) + snd_soc_dai_digital_mute(cpu_dai, 1, substream->stream); - snd_soc_dai_shutdown(cpu_dai, substream); + for_each_rtd_cpu_dai(rtd, i, cpu_dai) + snd_soc_dai_shutdown(cpu_dai, substream); for_each_rtd_codec_dai(rtd, i, codec_dai) snd_soc_dai_shutdown(codec_dai, substream); @@ -726,9 +780,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; const char *codec_dai_name = "multicodec"; + const char *cpu_dai_name = "multicpu"; int i, ret = 0; for_each_rtd_components(rtd, i, component) @@ -751,11 +806,13 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) } /* startup the audio subsystem */ - ret = snd_soc_dai_startup(cpu_dai, substream); - if (ret < 0) { - dev_err(cpu_dai->dev, "ASoC: can't open interface %s: %d\n", - cpu_dai->name, ret); - goto cpu_dai_err; + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + ret = snd_soc_dai_startup(cpu_dai, substream); + if (ret < 0) { + dev_err(cpu_dai->dev, "ASoC: can't open interface %s: %d\n", + cpu_dai->name, ret); + goto cpu_dai_err; + } } for_each_rtd_codec_dai(rtd, i, codec_dai) { @@ -783,34 +840,39 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) if (rtd->num_codecs == 1) codec_dai_name = rtd->codec_dai->name; + if (rtd->num_cpus == 1) + cpu_dai_name = rtd->cpu_dai->name; + if (soc_pcm_has_symmetry(substream)) runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; ret = -EINVAL; if (!runtime->hw.rates) { printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n", - codec_dai_name, cpu_dai->name); + codec_dai_name, cpu_dai_name); goto config_err; } if (!runtime->hw.formats) { printk(KERN_ERR "ASoC: %s <-> %s No matching formats\n", - codec_dai_name, cpu_dai->name); + codec_dai_name, cpu_dai_name); goto config_err; } if (!runtime->hw.channels_min || !runtime->hw.channels_max || runtime->hw.channels_min > runtime->hw.channels_max) { printk(KERN_ERR "ASoC: %s <-> %s No matching channels\n", - codec_dai_name, cpu_dai->name); + codec_dai_name, cpu_dai_name); goto config_err; } soc_pcm_apply_msb(substream); /* Symmetry only applies if we've already got an active stream. */ - if (cpu_dai->active) { - ret = soc_pcm_apply_symmetry(substream, cpu_dai); - if (ret != 0) - goto config_err; + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + if (cpu_dai->active) { + ret = soc_pcm_apply_symmetry(substream, cpu_dai); + if (ret != 0) + goto config_err; + } } for_each_rtd_codec_dai(rtd, i, codec_dai) { @@ -822,7 +884,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) } pr_debug("ASoC: %s <-> %s info:\n", - codec_dai_name, cpu_dai->name); + codec_dai_name, cpu_dai_name); pr_debug("ASoC: rate mask 0x%x\n", runtime->hw.rates); pr_debug("ASoC: min ch %d max ch %d\n", runtime->hw.channels_min, runtime->hw.channels_max); @@ -840,7 +902,8 @@ config_err: for_each_rtd_codec_dai(rtd, i, codec_dai) snd_soc_dai_shutdown(codec_dai, substream); cpu_dai_err: - snd_soc_dai_shutdown(cpu_dai, substream); + for_each_rtd_cpu_dai(rtd, i, cpu_dai) + snd_soc_dai_shutdown(cpu_dai, substream); soc_rtd_shutdown(rtd, substream); rtd_startup_err: @@ -879,7 +942,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; int i, ret = 0; @@ -911,11 +974,13 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) } } - ret = snd_soc_dai_prepare(cpu_dai, substream); - if (ret < 0) { - dev_err(cpu_dai->dev, - "ASoC: cpu DAI prepare error: %d\n", ret); - goto out; + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + ret = snd_soc_dai_prepare(cpu_dai, substream); + if (ret < 0) { + dev_err(cpu_dai->dev, + "ASoC: cpu DAI prepare error: %d\n", ret); + goto out; + } } /* cancel any delayed stream shutdown that is pending */ @@ -931,7 +996,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) for_each_rtd_codec_dai(rtd, i, codec_dai) snd_soc_dai_digital_mute(codec_dai, 0, substream->stream); - snd_soc_dai_digital_mute(cpu_dai, 0, substream->stream); + for_each_rtd_cpu_dai(rtd, i, cpu_dai) + snd_soc_dai_digital_mute(cpu_dai, 0, substream->stream); out: mutex_unlock(&rtd->card->pcm_mutex); @@ -978,7 +1044,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; int i, ret = 0; @@ -1042,17 +1108,19 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, snd_soc_dapm_update_dai(substream, &codec_params, codec_dai); } - ret = snd_soc_dai_hw_params(cpu_dai, substream, params); - if (ret < 0) - goto interface_err; + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + ret = snd_soc_dai_hw_params(cpu_dai, substream, params); + if (ret < 0) + goto interface_err; - /* store the parameters for each DAIs */ - cpu_dai->rate = params_rate(params); - cpu_dai->channels = params_channels(params); - cpu_dai->sample_bits = - snd_pcm_format_physical_width(params_format(params)); + /* store the parameters for each DAI */ + cpu_dai->rate = params_rate(params); + cpu_dai->channels = params_channels(params); + cpu_dai->sample_bits = + snd_pcm_format_physical_width(params_format(params)); - snd_soc_dapm_update_dai(substream, params, cpu_dai); + snd_soc_dapm_update_dai(substream, params, cpu_dai); + } for_each_rtd_components(rtd, i, component) { ret = snd_soc_component_hw_params(component, substream, params); @@ -1072,10 +1140,14 @@ out: component_err: soc_pcm_components_hw_free(substream, component); - snd_soc_dai_hw_free(cpu_dai, substream); - cpu_dai->rate = 0; + i = rtd->num_cpus; interface_err: + for_each_rtd_cpu_dai_rollback(rtd, i, cpu_dai) { + snd_soc_dai_hw_free(cpu_dai, substream); + cpu_dai->rate = 0; + } + i = rtd->num_codecs; codec_err: @@ -1099,7 +1171,7 @@ codec_err: static int soc_pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; int i; @@ -1107,10 +1179,12 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); /* clear the corresponding DAIs parameters when going to be inactive */ - if (cpu_dai->active == 1) { - cpu_dai->rate = 0; - cpu_dai->channels = 0; - cpu_dai->sample_bits = 0; + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + if (cpu_dai->active == 1) { + cpu_dai->rate = 0; + cpu_dai->channels = 0; + cpu_dai->sample_bits = 0; + } } for_each_rtd_codec_dai(rtd, i, codec_dai) { @@ -1146,7 +1220,8 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) snd_soc_dai_hw_free(codec_dai, substream); } - snd_soc_dai_hw_free(cpu_dai, substream); + for_each_rtd_cpu_dai(rtd, i, cpu_dai) + snd_soc_dai_hw_free(cpu_dai, substream); mutex_unlock(&rtd->card->pcm_mutex); return 0; @@ -1156,7 +1231,7 @@ static int soc_pcm_trigger_start(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; int i, ret; @@ -1170,9 +1245,11 @@ static int soc_pcm_trigger_start(struct snd_pcm_substream *substream, int cmd) return ret; } - ret = snd_soc_dai_trigger(cpu_dai, substream, cmd); - if (ret < 0) - return ret; + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + ret = snd_soc_dai_trigger(cpu_dai, substream, cmd); + if (ret < 0) + return ret; + } for_each_rtd_codec_dai(rtd, i, codec_dai) { ret = snd_soc_dai_trigger(codec_dai, substream, cmd); @@ -1187,7 +1264,7 @@ static int soc_pcm_trigger_stop(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; int i, ret; @@ -1197,9 +1274,11 @@ static int soc_pcm_trigger_stop(struct snd_pcm_substream *substream, int cmd) return ret; } - ret = snd_soc_dai_trigger(cpu_dai, substream, cmd); - if (ret < 0) - return ret; + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + ret = snd_soc_dai_trigger(cpu_dai, substream, cmd); + if (ret < 0) + return ret; + } for_each_rtd_components(rtd, i, component) { ret = snd_soc_component_trigger(component, substream, cmd); @@ -1240,7 +1319,7 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; int i, ret; @@ -1250,9 +1329,11 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, return ret; } - ret = snd_soc_dai_bespoke_trigger(cpu_dai, substream, cmd); - if (ret < 0) - return ret; + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + ret = snd_soc_dai_bespoke_trigger(cpu_dai, substream, cmd); + if (ret < 0) + return ret; + } return 0; } @@ -1264,12 +1345,13 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t offset = 0; snd_pcm_sframes_t delay = 0; snd_pcm_sframes_t codec_delay = 0; + snd_pcm_sframes_t cpu_delay = 0; int i; /* clearing the previous total delay */ @@ -1280,7 +1362,11 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) /* base delay if assigned in pointer callback */ delay = runtime->delay; - delay += snd_soc_dai_delay(cpu_dai, substream); + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + cpu_delay = max(cpu_delay, + snd_soc_dai_delay(cpu_dai, substream)); + } + delay += cpu_delay; for_each_rtd_codec_dai(rtd, i, codec_dai) { codec_delay = max(codec_delay, @@ -1403,13 +1489,15 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, if (!be->dai_link->no_pcm) continue; - w = snd_soc_dai_get_widget(be->cpu_dai, stream); + for_each_rtd_cpu_dai(be, i, dai) { + w = snd_soc_dai_get_widget(dai, stream); - dev_dbg(card->dev, "ASoC: try BE : %s\n", - w ? w->name : "(not set)"); + dev_dbg(card->dev, "ASoC: try BE : %s\n", + w ? w->name : "(not set)"); - if (w == widget) - return be; + if (w == widget) + return be; + } for_each_rtd_codec_dai(be, i, dai) { w = snd_soc_dai_get_widget(dai, stream); @@ -1492,10 +1580,18 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, unsigned int i; /* is there a valid CPU DAI widget for this BE */ - widget = snd_soc_dai_get_widget(dpcm->be->cpu_dai, stream); + do_prune = 1; + for_each_rtd_cpu_dai(dpcm->be, i, dai) { + widget = snd_soc_dai_get_widget(dai, stream); - /* prune the BE if it's no longer in our active list */ - if (widget && widget_in_list(list, widget)) + /* + * The BE is pruned only if none of the cpu_dai + * widgets are in the active list. + */ + if (widget && widget_in_list(list, widget)) + do_prune = 0; + } + if (!do_prune) continue; /* is there a valid CODEC DAI widget for this BE */ @@ -1792,11 +1888,17 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *be = dpcm->be; struct snd_soc_pcm_stream *codec_stream; struct snd_soc_pcm_stream *cpu_stream; + struct snd_soc_dai *dai; + int i; - cpu_stream = snd_soc_dai_get_pcm_stream(be->cpu_dai, stream); + for_each_rtd_cpu_dai(be, i, dai) { + cpu_stream = snd_soc_dai_get_pcm_stream(dai, stream); - *channels_min = max(*channels_min, cpu_stream->channels_min); - *channels_max = min(*channels_max, cpu_stream->channels_max); + *channels_min = max(*channels_min, + cpu_stream->channels_min); + *channels_max = min(*channels_max, + cpu_stream->channels_max); + } /* * chan min/max cannot be enforced if there are multiple CODEC @@ -1837,11 +1939,15 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, struct snd_soc_dai *dai; int i; - cpu_stream = snd_soc_dai_get_pcm_stream(be->cpu_dai, stream); + for_each_rtd_cpu_dai(be, i, dai) { + cpu_stream = snd_soc_dai_get_pcm_stream(dai, stream); - *rate_min = max(*rate_min, cpu_stream->rate_min); - *rate_max = min_not_zero(*rate_max, cpu_stream->rate_max); - *rates = snd_pcm_rate_mask_intersect(*rates, cpu_stream->rates); + *rate_min = max(*rate_min, cpu_stream->rate_min); + *rate_max = min_not_zero(*rate_max, + cpu_stream->rate_max); + *rates = snd_pcm_rate_mask_intersect(*rates, + cpu_stream->rates); + } for_each_rtd_codec_dai(be, i, dai) { /* @@ -1866,13 +1972,17 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver; + struct snd_soc_dai *cpu_dai; + struct snd_soc_dai_driver *cpu_dai_drv; + int i; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dpcm_init_runtime_hw(runtime, &cpu_dai_drv->playback); - else - dpcm_init_runtime_hw(runtime, &cpu_dai_drv->capture); + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + cpu_dai_drv = cpu_dai->driver; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dpcm_init_runtime_hw(runtime, &cpu_dai_drv->playback); + else + dpcm_init_runtime_hw(runtime, &cpu_dai_drv->capture); + } dpcm_runtime_merge_format(substream, &runtime->hw.formats); dpcm_runtime_merge_chan(substream, &runtime->hw.channels_min, @@ -1909,18 +2019,21 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, { struct snd_soc_dpcm *dpcm; struct snd_soc_pcm_runtime *fe = fe_substream->private_data; - struct snd_soc_dai *fe_cpu_dai = fe->cpu_dai; + struct snd_soc_dai *fe_cpu_dai; int err; + int i; /* apply symmetry for FE */ if (soc_pcm_has_symmetry(fe_substream)) fe_substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; - /* Symmetry only applies if we've got an active stream. */ - if (fe_cpu_dai->active) { - err = soc_pcm_apply_symmetry(fe_substream, fe_cpu_dai); - if (err < 0) - return err; + for_each_rtd_cpu_dai (fe, i, fe_cpu_dai) { + /* Symmetry only applies if we've got an active stream. */ + if (fe_cpu_dai->active) { + err = soc_pcm_apply_symmetry(fe_substream, fe_cpu_dai); + if (err < 0) + return err; + } } /* apply symmetry for BE */ @@ -1930,6 +2043,7 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, snd_soc_dpcm_get_substream(be, stream); struct snd_soc_pcm_runtime *rtd; struct snd_soc_dai *codec_dai; + struct snd_soc_dai *cpu_dai; int i; /* A backend may not have the requested substream */ @@ -1944,11 +2058,13 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, be_substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; /* Symmetry only applies if we've got an active stream. */ - if (rtd->cpu_dai->active) { - err = soc_pcm_apply_symmetry(fe_substream, - rtd->cpu_dai); - if (err < 0) - return err; + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + if (cpu_dai->active) { + err = soc_pcm_apply_symmetry(fe_substream, + cpu_dai); + if (err < 0) + return err; + } } for_each_rtd_codec_dai(rtd, i, codec_dai) { @@ -2863,7 +2979,7 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) { struct snd_soc_dai *codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai; struct snd_soc_component *component; struct snd_pcm *pcm; char new_name[64]; @@ -2881,6 +2997,16 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; for_each_rtd_codec_dai(rtd, i, codec_dai) { + if (rtd->num_cpus == 1) { + cpu_dai = rtd->cpu_dais[0]; + } else if (rtd->num_cpus == rtd->num_codecs) { + cpu_dai = rtd->cpu_dais[i]; + } else { + dev_err(rtd->card->dev, + "N cpus to M codecs link is not supported yet\n"); + return -EINVAL; + } + if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && snd_soc_dai_stream_valid(cpu_dai, cpu_playback)) playback = 1; @@ -3001,7 +3127,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) out: dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", (rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name, - cpu_dai->name); + (rtd->num_cpus > 1) ? "multicpu" : rtd->cpu_dai->name); return ret; } From 6c4b13b51aa36aab023dd0bf24bf5582c9ba091e Mon Sep 17 00:00:00 2001 From: Shreyas NC Date: Tue, 25 Feb 2020 21:39:14 +0800 Subject: [PATCH 0837/4444] ASoC: Add dapm_add_valid_dai_widget helper Adding a helper to connect widget for a specific cpu and codec dai The helper will help dapm_connect_dai_link_widgets() to reduce indents. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Signed-off-by: Kuninori Morimoto Signed-off-by: Shreyas NC Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20200225133917.21314-4-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 113 +++++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 53 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 58c318c9debb..539a1eaebeac 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -4277,16 +4277,15 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card) return 0; } -static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, - struct snd_soc_pcm_runtime *rtd) +static void dapm_add_valid_dai_widget(struct snd_soc_card *card, + struct snd_soc_pcm_runtime *rtd, + struct snd_soc_dai *codec_dai, + struct snd_soc_dai *cpu_dai) { - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct snd_soc_dai *codec_dai; struct snd_soc_dapm_widget *playback = NULL, *capture = NULL; struct snd_soc_dapm_widget *codec, *playback_cpu, *capture_cpu; struct snd_pcm_substream *substream; struct snd_pcm_str *streams = rtd->pcm->streams; - int i; if (rtd->dai_link->params) { playback_cpu = cpu_dai->capture_widget; @@ -4298,67 +4297,75 @@ static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, capture_cpu = capture; } - for_each_rtd_codec_dai(rtd, i, codec_dai) { - /* connect BE DAI playback if widgets are valid */ - codec = codec_dai->playback_widget; + /* connect BE DAI playback if widgets are valid */ + codec = codec_dai->playback_widget; - if (playback_cpu && codec) { - if (!playback) { - substream = streams[SNDRV_PCM_STREAM_PLAYBACK].substream; - playback = snd_soc_dapm_new_dai(card, substream, - "playback"); - if (IS_ERR(playback)) { - dev_err(rtd->dev, - "ASoC: Failed to create DAI %s: %ld\n", - codec_dai->name, - PTR_ERR(playback)); - continue; - } - - snd_soc_dapm_add_path(&card->dapm, playback_cpu, - playback, NULL, NULL); + if (playback_cpu && codec) { + if (!playback) { + substream = streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + playback = snd_soc_dapm_new_dai(card, substream, + "playback"); + if (IS_ERR(playback)) { + dev_err(rtd->dev, + "ASoC: Failed to create DAI %s: %ld\n", + codec_dai->name, + PTR_ERR(playback)); + goto capture; } - dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", - cpu_dai->component->name, playback_cpu->name, - codec_dai->component->name, codec->name); - - snd_soc_dapm_add_path(&card->dapm, playback, codec, - NULL, NULL); + snd_soc_dapm_add_path(&card->dapm, playback_cpu, + playback, NULL, NULL); } + + dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", + cpu_dai->component->name, playback_cpu->name, + codec_dai->component->name, codec->name); + + snd_soc_dapm_add_path(&card->dapm, playback, codec, + NULL, NULL); } - for_each_rtd_codec_dai(rtd, i, codec_dai) { - /* connect BE DAI capture if widgets are valid */ - codec = codec_dai->capture_widget; +capture: + /* connect BE DAI capture if widgets are valid */ + codec = codec_dai->capture_widget; - if (codec && capture_cpu) { - if (!capture) { - substream = streams[SNDRV_PCM_STREAM_CAPTURE].substream; - capture = snd_soc_dapm_new_dai(card, substream, - "capture"); - if (IS_ERR(capture)) { - dev_err(rtd->dev, - "ASoC: Failed to create DAI %s: %ld\n", - codec_dai->name, - PTR_ERR(capture)); - continue; - } - - snd_soc_dapm_add_path(&card->dapm, capture, - capture_cpu, NULL, NULL); + if (codec && capture_cpu) { + if (!capture) { + substream = streams[SNDRV_PCM_STREAM_CAPTURE].substream; + capture = snd_soc_dapm_new_dai(card, substream, + "capture"); + if (IS_ERR(capture)) { + dev_err(rtd->dev, + "ASoC: Failed to create DAI %s: %ld\n", + codec_dai->name, + PTR_ERR(capture)); + return; } - dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", - codec_dai->component->name, codec->name, - cpu_dai->component->name, capture_cpu->name); - - snd_soc_dapm_add_path(&card->dapm, codec, capture, - NULL, NULL); + snd_soc_dapm_add_path(&card->dapm, capture, + capture_cpu, NULL, NULL); } + + dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", + codec_dai->component->name, codec->name, + cpu_dai->component->name, capture_cpu->name); + + snd_soc_dapm_add_path(&card->dapm, codec, capture, + NULL, NULL); } } +static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, + struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai *codec_dai; + int i; + + for_each_rtd_codec_dai(rtd, i, codec_dai) + dapm_add_valid_dai_widget(card, rtd, + codec_dai, rtd->cpu_dais[0]); +} + static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream, int event) { From de6214a33633d8ce1c1490336f8e798e75ccd004 Mon Sep 17 00:00:00 2001 From: Shreyas NC Date: Tue, 25 Feb 2020 21:39:15 +0800 Subject: [PATCH 0838/4444] ASoC: Add multiple CPU DAI support in DAPM DAPM handles DAIs during soc_dapm_stream_event() and during addition and creation of DAI widgets i.e., dapm_add_valid_dai_widget() and dapm_connect_dai_link_widgets(). Extend these functions to handle multiple cpu dai. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Signed-off-by: Kuninori Morimoto Signed-off-by: Shreyas NC Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20200225133917.21314-5-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 539a1eaebeac..6ce024d52170 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -4361,9 +4361,19 @@ static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, struct snd_soc_dai *codec_dai; int i; - for_each_rtd_codec_dai(rtd, i, codec_dai) - dapm_add_valid_dai_widget(card, rtd, - codec_dai, rtd->cpu_dais[0]); + if (rtd->num_cpus == 1) { + for_each_rtd_codec_dai(rtd, i, codec_dai) + dapm_add_valid_dai_widget(card, rtd, codec_dai, + rtd->cpu_dais[0]); + } else if (rtd->num_codecs == rtd->num_cpus) { + for_each_rtd_codec_dai(rtd, i, codec_dai) + dapm_add_valid_dai_widget(card, rtd, codec_dai, + rtd->cpu_dais[i]); + } else { + dev_err(card->dev, + "N cpus to M codecs link is not supported yet\n"); + } + } static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream, @@ -4424,9 +4434,11 @@ static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, int event) { struct snd_soc_dai *codec_dai; + struct snd_soc_dai *cpu_dai; int i; - soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event); + for_each_rtd_cpu_dai(rtd, i, cpu_dai) + soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event); for_each_rtd_codec_dai(rtd, i, codec_dai) soc_dapm_dai_stream_event(codec_dai, stream, event); From 6e1276a5e613d25af71e3494b2dcb331d24f06ce Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 25 Feb 2020 21:39:16 +0800 Subject: [PATCH 0839/4444] ASoC: Return error if the function does not support multi-cpu Multi cpu is not supported by all functions yet. Add an error message and return. Suggested-by: Kuninori Morimoto Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20200225133917.21314-6-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-compress.c | 5 +++-- sound/soc/soc-generic-dmaengine-pcm.c | 18 ++++++++++++++++++ sound/soc/soc-pcm.c | 18 ++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 392a1c5b15d3..50062eb79adb 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -810,9 +810,10 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) int playback = 0, capture = 0; int i; - if (rtd->num_codecs > 1) { + if (rtd->num_cpus > 1 || + rtd->num_codecs > 1) { dev_err(rtd->card->dev, - "Compress ASoC: Multicodec not supported\n"); + "Compress ASoC: Multi CPU/Codec not supported\n"); return -EINVAL; } diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index d6b4831e8aec..facf1922a714 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -62,6 +62,12 @@ int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, struct snd_dmaengine_dai_dma_data *dma_data; int ret; + if (rtd->num_cpus > 1) { + dev_err(rtd->dev, + "%s doesn't support Multi CPU yet\n", __func__); + return -EINVAL; + } + dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config); @@ -118,6 +124,12 @@ dmaengine_pcm_set_runtime_hwparams(struct snd_soc_component *component, struct snd_dmaengine_dai_dma_data *dma_data; struct snd_pcm_hardware hw; + if (rtd->num_cpus > 1) { + dev_err(rtd->dev, + "%s doesn't support Multi CPU yet\n", __func__); + return -EINVAL; + } + if (pcm->config && pcm->config->pcm_hardware) return snd_soc_set_runtime_hwparams(substream, pcm->config->pcm_hardware); @@ -185,6 +197,12 @@ static struct dma_chan *dmaengine_pcm_compat_request_channel( struct snd_dmaengine_dai_dma_data *dma_data; dma_filter_fn fn = NULL; + if (rtd->num_cpus > 1) { + dev_err(rtd->dev, + "%s doesn't support Multi CPU yet\n", __func__); + return NULL; + } + dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) && pcm->chan[0]) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 44694e65fc4a..adbceaff07b8 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -125,6 +125,12 @@ static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf, int stream; char *buf; + if (fe->num_cpus > 1) { + dev_err(fe->dev, + "%s doesn't support Multi CPU yet\n", __func__); + return -EINVAL; + } + buf = kmalloc(out_count, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -1550,6 +1556,12 @@ int dpcm_path_get(struct snd_soc_pcm_runtime *fe, struct snd_soc_dai *cpu_dai = fe->cpu_dai; int paths; + if (fe->num_cpus > 1) { + dev_err(fe->dev, + "%s doesn't support Multi CPU yet\n", __func__); + return -EINVAL; + } + /* get number of valid DAI paths and their widgets */ paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, list, dpcm_end_walk_at_be); @@ -2834,6 +2846,12 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) int count, paths; int ret; + if (fe->num_cpus > 1) { + dev_err(fe->dev, + "%s doesn't support Multi CPU yet\n", __func__); + return -EINVAL; + } + if (!fe->dai_link->dynamic) return 0; From 0e9cf4c452ad7e2776441cbac0b9983abaf17ff0 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 25 Feb 2020 21:39:17 +0800 Subject: [PATCH 0840/4444] ASoC: pcm: check if cpu-dai supports a given stream Now multi-cpu-dais are supported, we can skip cpi-dais which don't support the current stream, following the example of multi-codec-dais. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20200225133917.21314-7-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 51 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index adbceaff07b8..90857138c823 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -607,6 +607,20 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) /* first calculate min/max only for CPUs in the DAI link */ for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + + /* + * Skip CPUs which don't support the current stream type. + * Otherwise, since the rate, channel, and format values will + * zero in that case, we would have no usable settings left, + * causing the resulting setup to fail. + * At least one CPU should match, otherwise we should have + * bailed out on a higher level, since there would be no + * CPU to support the transfer direction in that case. + */ + if (!snd_soc_dai_stream_valid(cpu_dai, + substream->stream)) + continue; + cpu_stream = snd_soc_dai_get_pcm_stream(cpu_dai, stream); cpu_chan_min = max(cpu_chan_min, cpu_stream->channels_min); @@ -1115,6 +1129,13 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, } for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + /* + * Skip CPUs which don't support the current stream + * type. See soc_pcm_init_runtime_hw() for more details + */ + if (!snd_soc_dai_stream_valid(cpu_dai, substream->stream)) + continue; + ret = snd_soc_dai_hw_params(cpu_dai, substream, params); if (ret < 0) goto interface_err; @@ -1150,6 +1171,9 @@ component_err: interface_err: for_each_rtd_cpu_dai_rollback(rtd, i, cpu_dai) { + if (!snd_soc_dai_stream_valid(cpu_dai, substream->stream)) + continue; + snd_soc_dai_hw_free(cpu_dai, substream); cpu_dai->rate = 0; } @@ -1226,8 +1250,12 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) snd_soc_dai_hw_free(codec_dai, substream); } - for_each_rtd_cpu_dai(rtd, i, cpu_dai) + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + if (!snd_soc_dai_stream_valid(cpu_dai, substream->stream)) + continue; + snd_soc_dai_hw_free(cpu_dai, substream); + } mutex_unlock(&rtd->card->pcm_mutex); return 0; @@ -1904,6 +1932,13 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream, int i; for_each_rtd_cpu_dai(be, i, dai) { + /* + * Skip CPUs which don't support the current stream + * type. See soc_pcm_init_runtime_hw() for more details + */ + if (!snd_soc_dai_stream_valid(dai, stream)) + continue; + cpu_stream = snd_soc_dai_get_pcm_stream(dai, stream); *channels_min = max(*channels_min, @@ -1952,6 +1987,13 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, int i; for_each_rtd_cpu_dai(be, i, dai) { + /* + * Skip CPUs which don't support the current stream + * type. See soc_pcm_init_runtime_hw() for more details + */ + if (!snd_soc_dai_stream_valid(dai, stream)) + continue; + cpu_stream = snd_soc_dai_get_pcm_stream(dai, stream); *rate_min = max(*rate_min, cpu_stream->rate_min); @@ -1989,6 +2031,13 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) int i; for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + /* + * Skip CPUs which don't support the current stream + * type. See soc_pcm_init_runtime_hw() for more details + */ + if (!snd_soc_dai_stream_valid(cpu_dai, substream->stream)) + continue; + cpu_dai_drv = cpu_dai->driver; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) dpcm_init_runtime_hw(runtime, &cpu_dai_drv->playback); From 36d73c4a9ed7c8a0988cfb9d1282c62d8c422a3b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 25 Feb 2020 11:00:40 -0600 Subject: [PATCH 0841/4444] ASoC: soc-dai: add get_sdw_stream() callback We only have a set() operation, provide the dual get() operation to retrieve the stream information. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200225170041.23644-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 92c382690930..7f70db149b81 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -202,6 +202,8 @@ struct snd_soc_dai_ops { int (*set_sdw_stream)(struct snd_soc_dai *dai, void *stream, int direction); + void *(*get_sdw_stream)(struct snd_soc_dai *dai, int direction); + /* * DAI digital mute - optional. * Called by soc-core to minimise any pops. @@ -423,4 +425,23 @@ static inline int snd_soc_dai_set_sdw_stream(struct snd_soc_dai *dai, return -ENOTSUPP; } +/** + * snd_soc_dai_get_sdw_stream() - Retrieves SDW stream from DAI + * @dai: DAI + * @direction: Stream direction(Playback/Capture) + * + * This routine only retrieves that was previously configured + * with snd_soc_dai_get_sdw_stream() + * + * Returns pointer to stream or NULL; + */ +static inline void *snd_soc_dai_get_sdw_stream(struct snd_soc_dai *dai, + int direction) +{ + if (dai->driver->ops->get_sdw_stream) + return dai->driver->ops->get_sdw_stream(dai, direction); + else + return NULL; +} + #endif From cef766300353613aa273791f70b3125d1f0420ae Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 26 Feb 2020 10:02:19 -0800 Subject: [PATCH 0842/4444] drm/omap: Prepare DSS for probing without legacy platform data In order to probe display subsystem (DSS) components with ti-sysc interconnect target module without legacy platform data and using devicetree, we need to update dss probing a bit. In the device tree, we will be defining the data also for the interconnect target modules as DSS really is a private interconnect. There is some information about that in 4460 TRM in "Figure 10-3. DSS Integration" for example where it mentions "32-bit interconnect (SLX)". The changes we need to make are: 1. Parse also device tree subnodes for the compatible property fixup 2. Update the component code to consider device tree subnodes Cc: dri-devel@lists.freedesktop.org Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Tomi Valkeinen Reviewed-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Reviewed-by: Tomi Valkeinen Signed-off-by: Tony Lindgren --- drivers/gpu/drm/omapdrm/dss/dss.c | 25 ++++++++++++++++--- .../gpu/drm/omapdrm/dss/omapdss-boot-init.c | 25 +++++++++++++------ 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c index 225ec808b01a..44e8faecedc7 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.c +++ b/drivers/gpu/drm/omapdrm/dss/dss.c @@ -1339,9 +1339,15 @@ static int dss_component_compare(struct device *dev, void *data) return dev == child; } +struct dss_component_match_data { + struct device *dev; + struct component_match **match; +}; + static int dss_add_child_component(struct device *dev, void *data) { - struct component_match **match = data; + struct dss_component_match_data *cmatch = data; + struct component_match **match = cmatch->match; /* * HACK @@ -1352,7 +1358,17 @@ static int dss_add_child_component(struct device *dev, void *data) if (strstr(dev_name(dev), "rfbi")) return 0; - component_match_add(dev->parent, match, dss_component_compare, dev); + /* + * Handle possible interconnect target modules defined within the DSS. + * The DSS components can be children of an interconnect target module + * after the device tree has been updated for the module data. + * See also omapdss_boot_init() for compatible fixup. + */ + if (strstr(dev_name(dev), "target-module")) + return device_for_each_child(dev, cmatch, + dss_add_child_component); + + component_match_add(cmatch->dev, match, dss_component_compare, dev); return 0; } @@ -1395,6 +1411,7 @@ static int dss_probe_hardware(struct dss_device *dss) static int dss_probe(struct platform_device *pdev) { const struct soc_device_attribute *soc; + struct dss_component_match_data cmatch; struct component_match *match = NULL; struct resource *dss_mem; struct dss_device *dss; @@ -1472,7 +1489,9 @@ static int dss_probe(struct platform_device *pdev) omapdss_gather_components(&pdev->dev); - device_for_each_child(&pdev->dev, &match, dss_add_child_component); + cmatch.dev = &pdev->dev; + cmatch.match = &match; + device_for_each_child(&pdev->dev, &cmatch, dss_add_child_component); r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match); if (r) diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c b/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c index 31502857f013..09beda9f5023 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c +++ b/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c @@ -183,9 +183,24 @@ static const struct of_device_id omapdss_of_fixups_whitelist[] __initconst = { {}, }; +static void __init omapdss_find_children(struct device_node *np) +{ + struct device_node *child; + + for_each_available_child_of_node(np, child) { + if (!of_find_property(child, "compatible", NULL)) + continue; + + omapdss_walk_device(child, true); + + if (of_device_is_compatible(child, "ti,sysc")) + omapdss_find_children(child); + } +} + static int __init omapdss_boot_init(void) { - struct device_node *dss, *child; + struct device_node *dss; INIT_LIST_HEAD(&dss_conv_list); @@ -195,13 +210,7 @@ static int __init omapdss_boot_init(void) return 0; omapdss_walk_device(dss, true); - - for_each_available_child_of_node(dss, child) { - if (!of_find_property(child, "compatible", NULL)) - continue; - - omapdss_walk_device(child, true); - } + omapdss_find_children(dss); while (!list_empty(&dss_conv_list)) { struct dss_conv_node *n; From e64c021fd92467e34b9d970a651bcaa8f326f3f2 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 24 Feb 2020 12:58:03 -0800 Subject: [PATCH 0843/4444] bus: ti-sysc: Rename clk related quirks to pre_reset and post_reset quirks The clk_disable_quirk and clk_enable_quirk should really be called pre_reset_quirk and post_reset_quirk to avoid confusion like we had with hdq1w reset. Let's also rename the related functions so the code is easier to follow. Note that we also have reset_done_quirk that is needed in some cases after checking the separate register for reset done bit. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 6113fc0a52ae..31dae22890d5 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -70,8 +70,8 @@ static const char * const clock_names[SYSC_MAX_CLOCKS] = { * @child_needs_resume: runtime resume needed for child on resume from suspend * @disable_on_idle: status flag used for disabling modules with resets * @idle_work: work structure used to perform delayed idle on a module - * @clk_enable_quirk: module specific clock enable quirk - * @clk_disable_quirk: module specific clock disable quirk + * @pre_reset_quirk: module specific pre-reset quirk + * @post_reset_quirk: module specific post-reset quirk * @reset_done_quirk: module specific reset done quirk * @module_enable_quirk: module specific enable quirk * @module_disable_quirk: module specific disable quirk @@ -97,8 +97,8 @@ struct sysc { unsigned int needs_resume:1; unsigned int child_needs_resume:1; struct delayed_work idle_work; - void (*clk_enable_quirk)(struct sysc *sysc); - void (*clk_disable_quirk)(struct sysc *sysc); + void (*pre_reset_quirk)(struct sysc *sysc); + void (*post_reset_quirk)(struct sysc *sysc); void (*reset_done_quirk)(struct sysc *sysc); void (*module_enable_quirk)(struct sysc *sysc); void (*module_disable_quirk)(struct sysc *sysc); @@ -1418,7 +1418,7 @@ static void sysc_module_enable_quirk_aess(struct sysc *ddata) sysc_write(ddata, offset, 1); } -/* I2C needs extra enable bit toggling for reset */ +/* I2C needs to be disabled for reset */ static void sysc_clk_quirk_i2c(struct sysc *ddata, bool enable) { int offset; @@ -1439,16 +1439,16 @@ static void sysc_clk_quirk_i2c(struct sysc *ddata, bool enable) sysc_write(ddata, offset, val); } -static void sysc_clk_enable_quirk_i2c(struct sysc *ddata) -{ - sysc_clk_quirk_i2c(ddata, true); -} - -static void sysc_clk_disable_quirk_i2c(struct sysc *ddata) +static void sysc_pre_reset_quirk_i2c(struct sysc *ddata) { sysc_clk_quirk_i2c(ddata, false); } +static void sysc_post_reset_quirk_i2c(struct sysc *ddata) +{ + sysc_clk_quirk_i2c(ddata, true); +} + /* 36xx SGX needs a quirk for to bypass OCP IPG interrupt logic */ static void sysc_module_enable_quirk_sgx(struct sysc *ddata) { @@ -1488,14 +1488,14 @@ static void sysc_init_module_quirks(struct sysc *ddata) return; if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_HDQ1W) { - ddata->clk_disable_quirk = sysc_pre_reset_quirk_hdq1w; + ddata->pre_reset_quirk = sysc_pre_reset_quirk_hdq1w; return; } if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_I2C) { - ddata->clk_enable_quirk = sysc_clk_enable_quirk_i2c; - ddata->clk_disable_quirk = sysc_clk_disable_quirk_i2c; + ddata->pre_reset_quirk = sysc_pre_reset_quirk_i2c; + ddata->post_reset_quirk = sysc_post_reset_quirk_i2c; return; } @@ -1583,8 +1583,8 @@ static int sysc_reset(struct sysc *ddata) else syss_done = ddata->cfg.syss_mask; - if (ddata->clk_disable_quirk) - ddata->clk_disable_quirk(ddata); + if (ddata->pre_reset_quirk) + ddata->pre_reset_quirk(ddata); sysc_val = sysc_read_sysconfig(ddata); sysc_val |= sysc_mask; @@ -1594,8 +1594,8 @@ static int sysc_reset(struct sysc *ddata) usleep_range(ddata->cfg.srst_udelay, ddata->cfg.srst_udelay * 2); - if (ddata->clk_enable_quirk) - ddata->clk_enable_quirk(ddata); + if (ddata->post_reset_quirk) + ddata->post_reset_quirk(ddata); /* Poll on reset status */ if (syss_offset >= 0) { From ab4d309d8708035bd323b2e2446eb68cda5e61e5 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 24 Feb 2020 12:58:03 -0800 Subject: [PATCH 0844/4444] bus: ti-sysc: Improve reset to work with modules with no sysconfig At least display susbsystem (DSS) has modules with no sysconfig registers and rely on custom function for module reset handling. Let's make reset work with that too. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 31dae22890d5..f32ba6ec2ba1 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1571,7 +1571,7 @@ static int sysc_reset(struct sysc *ddata) sysc_offset = ddata->offsets[SYSC_SYSCONFIG]; syss_offset = ddata->offsets[SYSC_SYSSTATUS]; - if (ddata->legacy_mode || sysc_offset < 0 || + if (ddata->legacy_mode || ddata->cap->regbits->srst_shift < 0 || ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT) return 0; @@ -1586,9 +1586,11 @@ static int sysc_reset(struct sysc *ddata) if (ddata->pre_reset_quirk) ddata->pre_reset_quirk(ddata); - sysc_val = sysc_read_sysconfig(ddata); - sysc_val |= sysc_mask; - sysc_write(ddata, sysc_offset, sysc_val); + if (sysc_offset >= 0) { + sysc_val = sysc_read_sysconfig(ddata); + sysc_val |= sysc_mask; + sysc_write(ddata, sysc_offset, sysc_val); + } if (ddata->cfg.srst_udelay) usleep_range(ddata->cfg.srst_udelay, From 590e15c76f1231329d1543570a54058dba2e4ff6 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 24 Feb 2020 12:58:03 -0800 Subject: [PATCH 0845/4444] bus: ti-sysc: Consider non-existing registers too when matching quirks We are currently setting -1 for non-existing sysconfig related registers for quirks, but setting -ENODEV elsewhere. And for matching the quirks, we're now just ignoring the non-existing registers. This will cause issues with misdetecting DSS registers as the hardware revision numbers can have duplicates. To avoid this, let's standardize on using -ENODEV also for the quirks instead of -1. That way we can always just test for a match without adding any more complicated logic. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 120 ++++++++++++++++++++---------------------- 1 file changed, 57 insertions(+), 63 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index f32ba6ec2ba1..c0298612e57c 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1216,16 +1216,16 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_OPT_CLKS_IN_RESET), SYSC_QUIRK("sham", 0, 0x100, 0x110, 0x114, 0x40000c03, 0xffffffff, SYSC_QUIRK_LEGACY_IDLE), - SYSC_QUIRK("smartreflex", 0, -1, 0x24, -1, 0x00000000, 0xffffffff, + SYSC_QUIRK("smartreflex", 0, -ENODEV, 0x24, -ENODEV, 0x00000000, 0xffffffff, SYSC_QUIRK_LEGACY_IDLE), - SYSC_QUIRK("smartreflex", 0, -1, 0x38, -1, 0x00000000, 0xffffffff, + SYSC_QUIRK("smartreflex", 0, -ENODEV, 0x38, -ENODEV, 0x00000000, 0xffffffff, SYSC_QUIRK_LEGACY_IDLE), SYSC_QUIRK("timer", 0, 0, 0x10, 0x14, 0x00000015, 0xffffffff, 0), /* Some timers on omap4 and later */ - SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x50002100, 0xffffffff, + SYSC_QUIRK("timer", 0, 0, 0x10, -ENODEV, 0x50002100, 0xffffffff, 0), - SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffff00ff, + SYSC_QUIRK("timer", 0, 0, 0x10, -ENODEV, 0x4fff1301, 0xffff00ff, 0), SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000046, 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE), @@ -1238,18 +1238,18 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE), /* Quirks that need to be set based on the module address */ - SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -1, 0x50000800, 0xffffffff, + SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -ENODEV, 0x50000800, 0xffffffff, SYSC_QUIRK_EXT_OPT_CLOCK | SYSC_QUIRK_NO_RESET_ON_INIT | SYSC_QUIRK_SWSUP_SIDLE), /* Quirks that need to be set based on detected module */ - SYSC_QUIRK("aess", 0, 0, 0x10, -1, 0x40000000, 0xffffffff, + SYSC_QUIRK("aess", 0, 0, 0x10, -ENODEV, 0x40000000, 0xffffffff, SYSC_MODULE_QUIRK_AESS), - SYSC_QUIRK("dcan", 0x48480000, 0x20, -1, -1, 0xa3170504, 0xffffffff, + SYSC_QUIRK("dcan", 0x48480000, 0x20, -ENODEV, -ENODEV, 0xa3170504, 0xffffffff, SYSC_QUIRK_CLKDM_NOAUTO), - SYSC_QUIRK("dwc3", 0x48880000, 0, 0x10, -1, 0x500a0200, 0xffffffff, + SYSC_QUIRK("dwc3", 0x48880000, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff, SYSC_QUIRK_CLKDM_NOAUTO), - SYSC_QUIRK("dwc3", 0x488c0000, 0, 0x10, -1, 0x500a0200, 0xffffffff, + SYSC_QUIRK("dwc3", 0x488c0000, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff, SYSC_QUIRK_CLKDM_NOAUTO), SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff, SYSC_MODULE_QUIRK_HDQ1W), @@ -1263,12 +1263,12 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_MODULE_QUIRK_I2C), SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffff0f0, SYSC_MODULE_QUIRK_I2C), - SYSC_QUIRK("gpu", 0x50000000, 0x14, -1, -1, 0x00010201, 0xffffffff, 0), - SYSC_QUIRK("gpu", 0x50000000, 0xfe00, 0xfe10, -1, 0x40000000 , 0xffffffff, + SYSC_QUIRK("gpu", 0x50000000, 0x14, -ENODEV, -ENODEV, 0x00010201, 0xffffffff, 0), + SYSC_QUIRK("gpu", 0x50000000, 0xfe00, 0xfe10, -ENODEV, 0x40000000 , 0xffffffff, SYSC_MODULE_QUIRK_SGX), SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050, 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY), - SYSC_QUIRK("usb_otg_hs", 0, 0, 0x10, -1, 0x4ea2080d, 0xffffffff, + SYSC_QUIRK("usb_otg_hs", 0, 0, 0x10, -ENODEV, 0x4ea2080d, 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY), SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, SYSC_MODULE_QUIRK_WDT), @@ -1277,57 +1277,57 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_MODULE_QUIRK_WDT | SYSC_QUIRK_SWSUP_SIDLE), #ifdef DEBUG - SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0), - SYSC_QUIRK("atl", 0, 0, -1, -1, 0x0a070100, 0xffffffff, 0), - SYSC_QUIRK("cm", 0, 0, -1, -1, 0x40000301, 0xffffffff, 0), - SYSC_QUIRK("control", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 0), + SYSC_QUIRK("adc", 0, 0, 0x10, -ENODEV, 0x47300001, 0xffffffff, 0), + SYSC_QUIRK("atl", 0, 0, -ENODEV, -ENODEV, 0x0a070100, 0xffffffff, 0), + SYSC_QUIRK("cm", 0, 0, -ENODEV, -ENODEV, 0x40000301, 0xffffffff, 0), + SYSC_QUIRK("control", 0, 0, 0x10, -ENODEV, 0x40000900, 0xffffffff, 0), SYSC_QUIRK("cpgmac", 0, 0x1200, 0x1208, 0x1204, 0x4edb1902, 0xffff00f0, 0), - SYSC_QUIRK("dcan", 0, 0x20, -1, -1, 0xa3170504, 0xffffffff, 0), - SYSC_QUIRK("dcan", 0, 0x20, -1, -1, 0x4edb1902, 0xffffffff, 0), - SYSC_QUIRK("dmic", 0, 0, 0x10, -1, 0x50010000, 0xffffffff, 0), - SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0), + SYSC_QUIRK("dcan", 0, 0x20, -ENODEV, -ENODEV, 0xa3170504, 0xffffffff, 0), + SYSC_QUIRK("dcan", 0, 0x20, -ENODEV, -ENODEV, 0x4edb1902, 0xffffffff, 0), + SYSC_QUIRK("dmic", 0, 0, 0x10, -ENODEV, 0x50010000, 0xffffffff, 0), + SYSC_QUIRK("dwc3", 0, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff, 0), SYSC_QUIRK("d2d", 0x4a0b6000, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0), SYSC_QUIRK("d2d", 0x4a0cd000, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0), - SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0), - SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -1, 0, 0, 0), - SYSC_QUIRK("gpu", 0, 0xfe00, 0xfe10, -1, 0x40000000 , 0xffffffff, 0), + SYSC_QUIRK("epwmss", 0, 0, 0x4, -ENODEV, 0x47400001, 0xffffffff, 0), + SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -ENODEV, 0, 0, 0), + SYSC_QUIRK("gpu", 0, 0xfe00, 0xfe10, -ENODEV, 0x40000000 , 0xffffffff, 0), SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0), - SYSC_QUIRK("iss", 0, 0, 0x10, -1, 0x40000101, 0xffffffff, 0), - SYSC_QUIRK("lcdc", 0, 0, 0x54, -1, 0x4f201000, 0xffffffff, 0), - SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44306302, 0xffffffff, 0), - SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44307b02, 0xffffffff, 0), - SYSC_QUIRK("mcbsp", 0, -1, 0x8c, -1, 0, 0, 0), - SYSC_QUIRK("mcspi", 0, 0, 0x10, -1, 0x40300a0b, 0xffff00ff, 0), + SYSC_QUIRK("iss", 0, 0, 0x10, -ENODEV, 0x40000101, 0xffffffff, 0), + SYSC_QUIRK("lcdc", 0, 0, 0x54, -ENODEV, 0x4f201000, 0xffffffff, 0), + SYSC_QUIRK("mcasp", 0, 0, 0x4, -ENODEV, 0x44306302, 0xffffffff, 0), + SYSC_QUIRK("mcasp", 0, 0, 0x4, -ENODEV, 0x44307b02, 0xffffffff, 0), + SYSC_QUIRK("mcbsp", 0, -ENODEV, 0x8c, -ENODEV, 0, 0, 0), + SYSC_QUIRK("mcspi", 0, 0, 0x10, -ENODEV, 0x40300a0b, 0xffff00ff, 0), SYSC_QUIRK("mcspi", 0, 0, 0x110, 0x114, 0x40300a0b, 0xffffffff, 0), - SYSC_QUIRK("mailbox", 0, 0, 0x10, -1, 0x00000400, 0xffffffff, 0), - SYSC_QUIRK("m3", 0, 0, -1, -1, 0x5f580105, 0x0fff0f00, 0), + SYSC_QUIRK("mailbox", 0, 0, 0x10, -ENODEV, 0x00000400, 0xffffffff, 0), + SYSC_QUIRK("m3", 0, 0, -ENODEV, -ENODEV, 0x5f580105, 0x0fff0f00, 0), SYSC_QUIRK("ocp2scp", 0, 0, 0x10, 0x14, 0x50060005, 0xfffffff0, 0), - SYSC_QUIRK("ocp2scp", 0, 0, -1, -1, 0x50060007, 0xffffffff, 0), - SYSC_QUIRK("padconf", 0, 0, 0x10, -1, 0x4fff0800, 0xffffffff, 0), - SYSC_QUIRK("padconf", 0, 0, -1, -1, 0x40001100, 0xffffffff, 0), - SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000100, 0xffffffff, 0), - SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x00004102, 0xffffffff, 0), - SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000400, 0xffffffff, 0), - SYSC_QUIRK("scm", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 0), - SYSC_QUIRK("scm", 0, 0, -1, -1, 0x4e8b0100, 0xffffffff, 0), - SYSC_QUIRK("scm", 0, 0, -1, -1, 0x4f000100, 0xffffffff, 0), - SYSC_QUIRK("scm", 0, 0, -1, -1, 0x40000900, 0xffffffff, 0), - SYSC_QUIRK("scrm", 0, 0, -1, -1, 0x00000010, 0xffffffff, 0), - SYSC_QUIRK("sdio", 0, 0, 0x10, -1, 0x40202301, 0xffff0ff0, 0), + SYSC_QUIRK("ocp2scp", 0, 0, -ENODEV, -ENODEV, 0x50060007, 0xffffffff, 0), + SYSC_QUIRK("padconf", 0, 0, 0x10, -ENODEV, 0x4fff0800, 0xffffffff, 0), + SYSC_QUIRK("padconf", 0, 0, -ENODEV, -ENODEV, 0x40001100, 0xffffffff, 0), + SYSC_QUIRK("prcm", 0, 0, -ENODEV, -ENODEV, 0x40000100, 0xffffffff, 0), + SYSC_QUIRK("prcm", 0, 0, -ENODEV, -ENODEV, 0x00004102, 0xffffffff, 0), + SYSC_QUIRK("prcm", 0, 0, -ENODEV, -ENODEV, 0x40000400, 0xffffffff, 0), + SYSC_QUIRK("scm", 0, 0, 0x10, -ENODEV, 0x40000900, 0xffffffff, 0), + SYSC_QUIRK("scm", 0, 0, -ENODEV, -ENODEV, 0x4e8b0100, 0xffffffff, 0), + SYSC_QUIRK("scm", 0, 0, -ENODEV, -ENODEV, 0x4f000100, 0xffffffff, 0), + SYSC_QUIRK("scm", 0, 0, -ENODEV, -ENODEV, 0x40000900, 0xffffffff, 0), + SYSC_QUIRK("scrm", 0, 0, -ENODEV, -ENODEV, 0x00000010, 0xffffffff, 0), + SYSC_QUIRK("sdio", 0, 0, 0x10, -ENODEV, 0x40202301, 0xffff0ff0, 0), SYSC_QUIRK("sdio", 0, 0x2fc, 0x110, 0x114, 0x31010000, 0xffffffff, 0), SYSC_QUIRK("sdma", 0, 0, 0x2c, 0x28, 0x00010900, 0xffffffff, 0), - SYSC_QUIRK("slimbus", 0, 0, 0x10, -1, 0x40000902, 0xffffffff, 0), - SYSC_QUIRK("slimbus", 0, 0, 0x10, -1, 0x40002903, 0xffffffff, 0), - SYSC_QUIRK("spinlock", 0, 0, 0x10, -1, 0x50020000, 0xffffffff, 0), - SYSC_QUIRK("rng", 0, 0x1fe0, 0x1fe4, -1, 0x00000020, 0xffffffff, 0), - SYSC_QUIRK("rtc", 0, 0x74, 0x78, -1, 0x4eb01908, 0xffff00f0, 0), - SYSC_QUIRK("timer32k", 0, 0, 0x4, -1, 0x00000060, 0xffffffff, 0), + SYSC_QUIRK("slimbus", 0, 0, 0x10, -ENODEV, 0x40000902, 0xffffffff, 0), + SYSC_QUIRK("slimbus", 0, 0, 0x10, -ENODEV, 0x40002903, 0xffffffff, 0), + SYSC_QUIRK("spinlock", 0, 0, 0x10, -ENODEV, 0x50020000, 0xffffffff, 0), + SYSC_QUIRK("rng", 0, 0x1fe0, 0x1fe4, -ENODEV, 0x00000020, 0xffffffff, 0), + SYSC_QUIRK("rtc", 0, 0x74, 0x78, -ENODEV, 0x4eb01908, 0xffff00f0, 0), + SYSC_QUIRK("timer32k", 0, 0, 0x4, -ENODEV, 0x00000060, 0xffffffff, 0), SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000004, 0xffffffff, 0), SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000008, 0xffffffff, 0), SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, 0x14, 0x50700100, 0xffffffff, 0), - SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, -1, 0x50700101, 0xffffffff, 0), - SYSC_QUIRK("vfpe", 0, 0, 0x104, -1, 0x4d001200, 0xffffffff, 0), + SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, -ENODEV, 0x50700101, 0xffffffff, 0), + SYSC_QUIRK("vfpe", 0, 0, 0x104, -ENODEV, 0x4d001200, 0xffffffff, 0), #endif }; @@ -1349,16 +1349,13 @@ static void sysc_init_early_quirks(struct sysc *ddata) if (q->base != ddata->module_pa) continue; - if (q->rev_offset >= 0 && - q->rev_offset != ddata->offsets[SYSC_REVISION]) + if (q->rev_offset != ddata->offsets[SYSC_REVISION]) continue; - if (q->sysc_offset >= 0 && - q->sysc_offset != ddata->offsets[SYSC_SYSCONFIG]) + if (q->sysc_offset != ddata->offsets[SYSC_SYSCONFIG]) continue; - if (q->syss_offset >= 0 && - q->syss_offset != ddata->offsets[SYSC_SYSSTATUS]) + if (q->syss_offset != ddata->offsets[SYSC_SYSSTATUS]) continue; ddata->name = q->name; @@ -1378,16 +1375,13 @@ static void sysc_init_revision_quirks(struct sysc *ddata) if (q->base && q->base != ddata->module_pa) continue; - if (q->rev_offset >= 0 && - q->rev_offset != ddata->offsets[SYSC_REVISION]) + if (q->rev_offset != ddata->offsets[SYSC_REVISION]) continue; - if (q->sysc_offset >= 0 && - q->sysc_offset != ddata->offsets[SYSC_SYSCONFIG]) + if (q->sysc_offset != ddata->offsets[SYSC_SYSCONFIG]) continue; - if (q->syss_offset >= 0 && - q->syss_offset != ddata->offsets[SYSC_SYSSTATUS]) + if (q->syss_offset != ddata->offsets[SYSC_SYSSTATUS]) continue; if (q->revision == ddata->revision || From 7320fd322fe9b1485372e6da294590c5bcabbe1c Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 24 Feb 2020 12:58:03 -0800 Subject: [PATCH 0846/4444] bus: ti-sysc: Don't warn about legacy property for nested ti-sysc devices In some cases we can have nested ti-sysc instances that may still use the legacy "ti,hwmods" property. Let's not warn if that's the case. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index c0298612e57c..4e87eb5e8ed7 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -624,7 +624,7 @@ static void sysc_check_one_child(struct sysc *ddata, const char *name; name = of_get_property(np, "ti,hwmods", NULL); - if (name) + if (name && !of_device_is_compatible(np, "ti,sysc")) dev_warn(ddata->dev, "really a child ti,hwmods property?"); sysc_check_quirk_stdout(ddata, np); From feaa8baee82ababa46af95b03cfc28680ad647a6 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 24 Feb 2020 12:58:03 -0800 Subject: [PATCH 0847/4444] bus: ti-sysc: Implement SoC revision handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to know SoC type and features for cases where the same SoC may be installed in various versions on the same board and would need a separate dts file otherwise for the different variants. For example, am3703 is pin compatible with omap3630, but has sgx and iva accelerators disabled. We must not try to access the sgx or iva module registers on am3703, and need to set the unavailable devices disabled early. Let's also detect omap3430 as that is needed for display subsystem (DSS) reset later on, and GP vs EMU or HS devices. Further SoC specific disabled device detection can be added as needed, such as dra71x vs dra76x rtc and usb4. Cc: Adam Ford Cc: André Hentschel Cc: H. Nikolaus Schaller Cc: Keerthy Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/pdata-quirks.c | 6 + drivers/bus/ti-sysc.c | 194 +++++++++++++++++++++++++- include/linux/platform_data/ti-sysc.h | 1 + 3 files changed, 200 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c index dbb7c2acef31..2a4fe3e68b82 100644 --- a/arch/arm/mach-omap2/pdata-quirks.c +++ b/arch/arm/mach-omap2/pdata-quirks.c @@ -397,10 +397,16 @@ static int ti_sysc_shutdown_module(struct device *dev, return omap_hwmod_shutdown(cookie->data); } +static bool ti_sysc_soc_type_gp(void) +{ + return omap_type() == OMAP2_DEVICE_TYPE_GP; +} + static struct of_dev_auxdata omap_auxdata_lookup[]; static struct ti_sysc_platform_data ti_sysc_pdata = { .auxdata = omap_auxdata_lookup, + .soc_type_gp = ti_sysc_soc_type_gp, .init_clockdomain = ti_sysc_clkdm_init, .clkdm_deny_idle = ti_sysc_clkdm_deny_idle, .clkdm_allow_idle = ti_sysc_clkdm_allow_idle, diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 4e87eb5e8ed7..4c377c576582 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -15,15 +16,47 @@ #include #include #include +#include #include #include #include +#define DIS_ISP BIT(2) +#define DIS_IVA BIT(1) +#define DIS_SGX BIT(0) + +#define SOC_FLAG(match, flag) { .machine = match, .data = (void *)(flag), } + #define MAX_MODULE_SOFTRESET_WAIT 10000 -static const char * const reg_names[] = { "rev", "sysc", "syss", }; +enum sysc_soc { + SOC_UNKNOWN, + SOC_2420, + SOC_2430, + SOC_3430, + SOC_3630, + SOC_4430, + SOC_4460, + SOC_4470, + SOC_5430, + SOC_AM3, + SOC_AM4, + SOC_DRA7, +}; + +struct sysc_address { + unsigned long base; + struct list_head node; +}; + +struct sysc_soc_info { + unsigned long general_purpose:1; + enum sysc_soc soc; + struct mutex list_lock; /* disabled modules list lock */ + struct list_head disabled_modules; +}; enum sysc_clocks { SYSC_FCK, @@ -39,6 +72,8 @@ enum sysc_clocks { SYSC_MAX_CLOCKS, }; +static struct sysc_soc_info *sysc_soc; +static const char * const reg_names[] = { "rev", "sysc", "syss", }; static const char * const clock_names[SYSC_MAX_CLOCKS] = { "fck", "ick", "opt0", "opt1", "opt2", "opt3", "opt4", "opt5", "opt6", "opt7", @@ -2382,6 +2417,154 @@ static void ti_sysc_idle(struct work_struct *work) pm_runtime_put_sync(ddata->dev); } +/* + * SoC model and features detection. Only needed for SoCs that need + * special handling for quirks, no need to list others. + */ +static const struct soc_device_attribute sysc_soc_match[] = { + SOC_FLAG("OMAP242*", SOC_2420), + SOC_FLAG("OMAP243*", SOC_2430), + SOC_FLAG("OMAP3[45]*", SOC_3430), + SOC_FLAG("OMAP3[67]*", SOC_3630), + SOC_FLAG("OMAP443*", SOC_4430), + SOC_FLAG("OMAP446*", SOC_4460), + SOC_FLAG("OMAP447*", SOC_4470), + SOC_FLAG("OMAP54*", SOC_5430), + SOC_FLAG("AM433", SOC_AM3), + SOC_FLAG("AM43*", SOC_AM4), + SOC_FLAG("DRA7*", SOC_DRA7), + + { /* sentinel */ }, +}; + +/* + * List of SoCs variants with disabled features. By default we assume all + * devices in the device tree are available so no need to list those SoCs. + */ +static const struct soc_device_attribute sysc_soc_feat_match[] = { + /* OMAP3430/3530 and AM3517 variants with some accelerators disabled */ + SOC_FLAG("AM3505", DIS_SGX), + SOC_FLAG("OMAP3525", DIS_SGX), + SOC_FLAG("OMAP3515", DIS_IVA | DIS_SGX), + SOC_FLAG("OMAP3503", DIS_ISP | DIS_IVA | DIS_SGX), + + /* OMAP3630/DM3730 variants with some accelerators disabled */ + SOC_FLAG("AM3703", DIS_IVA | DIS_SGX), + SOC_FLAG("DM3725", DIS_SGX), + SOC_FLAG("OMAP3611", DIS_ISP | DIS_IVA | DIS_SGX), + SOC_FLAG("OMAP3615/AM3715", DIS_IVA), + SOC_FLAG("OMAP3621", DIS_ISP), + + { /* sentinel */ }, +}; + +static int sysc_add_disabled(unsigned long base) +{ + struct sysc_address *disabled_module; + + disabled_module = kzalloc(sizeof(*disabled_module), GFP_KERNEL); + if (!disabled_module) + return -ENOMEM; + + disabled_module->base = base; + + mutex_lock(&sysc_soc->list_lock); + list_add(&disabled_module->node, &sysc_soc->disabled_modules); + mutex_unlock(&sysc_soc->list_lock); + + return 0; +} + +/* + * One time init to detect the booted SoC and disable unavailable features. + * Note that we initialize static data shared across all ti-sysc instances + * so ddata is only used for SoC type. This can be called from module_init + * once we no longer need to rely on platform data. + */ +static int sysc_init_soc(struct sysc *ddata) +{ + const struct soc_device_attribute *match; + struct ti_sysc_platform_data *pdata; + unsigned long features = 0; + + if (sysc_soc) + return 0; + + sysc_soc = kzalloc(sizeof(*sysc_soc), GFP_KERNEL); + if (!sysc_soc) + return -ENOMEM; + + mutex_init(&sysc_soc->list_lock); + INIT_LIST_HEAD(&sysc_soc->disabled_modules); + sysc_soc->general_purpose = true; + + pdata = dev_get_platdata(ddata->dev); + if (pdata && pdata->soc_type_gp) + sysc_soc->general_purpose = pdata->soc_type_gp(); + + match = soc_device_match(sysc_soc_match); + if (match && match->data) + sysc_soc->soc = (int)match->data; + + match = soc_device_match(sysc_soc_feat_match); + if (!match) + return 0; + + if (match->data) + features = (unsigned long)match->data; + + /* + * Add disabled devices to the list based on the module base. + * Note that this must be done before we attempt to access the + * device and have module revision checks working. + */ + if (features & DIS_ISP) + sysc_add_disabled(0x480bd400); + if (features & DIS_IVA) + sysc_add_disabled(0x5d000000); + if (features & DIS_SGX) + sysc_add_disabled(0x50000000); + + return 0; +} + +static void sysc_cleanup_soc(void) +{ + struct sysc_address *disabled_module; + struct list_head *pos, *tmp; + + if (!sysc_soc) + return; + + mutex_lock(&sysc_soc->list_lock); + list_for_each_safe(pos, tmp, &sysc_soc->disabled_modules) { + disabled_module = list_entry(pos, struct sysc_address, node); + list_del(pos); + kfree(disabled_module); + } + mutex_unlock(&sysc_soc->list_lock); +} + +static int sysc_check_disabled_devices(struct sysc *ddata) +{ + struct sysc_address *disabled_module; + struct list_head *pos; + int error = 0; + + mutex_lock(&sysc_soc->list_lock); + list_for_each(pos, &sysc_soc->disabled_modules) { + disabled_module = list_entry(pos, struct sysc_address, node); + if (ddata->module_pa == disabled_module->base) { + dev_dbg(ddata->dev, "module disabled for this SoC\n"); + error = -ENODEV; + break; + } + } + mutex_unlock(&sysc_soc->list_lock); + + return error; +} + static const struct of_device_id sysc_match_table[] = { { .compatible = "simple-bus", }, { /* sentinel */ }, @@ -2400,6 +2583,10 @@ static int sysc_probe(struct platform_device *pdev) ddata->dev = &pdev->dev; platform_set_drvdata(pdev, ddata); + error = sysc_init_soc(ddata); + if (error) + return error; + error = sysc_init_match(ddata); if (error) return error; @@ -2430,6 +2617,10 @@ static int sysc_probe(struct platform_device *pdev) sysc_init_early_quirks(ddata); + error = sysc_check_disabled_devices(ddata); + if (error) + return error; + error = sysc_get_clocks(ddata); if (error) return error; @@ -2560,6 +2751,7 @@ static void __exit sysc_exit(void) { bus_unregister_notifier(&platform_bus_type, &sysc_nb); platform_driver_unregister(&sysc_driver); + sysc_cleanup_soc(); } module_exit(sysc_exit); diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index 2cbde6542849..accab5325cf3 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -141,6 +141,7 @@ struct clk; struct ti_sysc_platform_data { struct of_dev_auxdata *auxdata; + bool (*soc_type_gp)(void); int (*init_clockdomain)(struct device *dev, struct clk *fck, struct clk *ick, struct ti_sysc_cookie *cookie); void (*clkdm_deny_idle)(struct device *dev, From e8639e1c986a8a9d0f94549170f6db579376c3ae Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 24 Feb 2020 12:58:03 -0800 Subject: [PATCH 0848/4444] bus: ti-sysc: Handle module unlock quirk needed for some RTC The RTC modules on am3 and am4 need quirk handling to unlock and lock them for reset so let's add the quirk handling based on what we already have for legacy platform data. In later patches we will simply drop the RTC related platform data and the old quirk handling. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 74 ++++++++++++++++++++++++--- include/linux/platform_data/ti-sysc.h | 1 + 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 4c377c576582..6caa2222091e 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -110,6 +110,8 @@ static const char * const clock_names[SYSC_MAX_CLOCKS] = { * @reset_done_quirk: module specific reset done quirk * @module_enable_quirk: module specific enable quirk * @module_disable_quirk: module specific disable quirk + * @module_unlock_quirk: module specific sysconfig unlock quirk + * @module_lock_quirk: module specific sysconfig lock quirk */ struct sysc { struct device *dev; @@ -137,6 +139,8 @@ struct sysc { void (*reset_done_quirk)(struct sysc *sysc); void (*module_enable_quirk)(struct sysc *sysc); void (*module_disable_quirk)(struct sysc *sysc); + void (*module_unlock_quirk)(struct sysc *sysc); + void (*module_lock_quirk)(struct sysc *sysc); }; static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np, @@ -896,6 +900,22 @@ static void sysc_show_registers(struct sysc *ddata) buf); } +/** + * sysc_write_sysconfig - handle sysconfig quirks for register write + * @ddata: device driver data + * @value: register value + */ +static void sysc_write_sysconfig(struct sysc *ddata, u32 value) +{ + if (ddata->module_unlock_quirk) + ddata->module_unlock_quirk(ddata); + + sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], value); + + if (ddata->module_lock_quirk) + ddata->module_lock_quirk(ddata); +} + #define SYSC_IDLE_MASK (SYSC_NR_IDLEMODES - 1) #define SYSC_CLOCACT_ICK 2 @@ -942,7 +962,7 @@ static int sysc_enable_module(struct device *dev) reg &= ~(SYSC_IDLE_MASK << regbits->sidle_shift); reg |= best_mode << regbits->sidle_shift; - sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg); + sysc_write_sysconfig(ddata, reg); set_midle: /* Set MIDLE mode */ @@ -961,14 +981,14 @@ set_midle: reg &= ~(SYSC_IDLE_MASK << regbits->midle_shift); reg |= best_mode << regbits->midle_shift; - sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg); + sysc_write_sysconfig(ddata, reg); set_autoidle: /* Autoidle bit must enabled separately if available */ if (regbits->autoidle_shift >= 0 && ddata->cfg.sysc_val & BIT(regbits->autoidle_shift)) { reg |= 1 << regbits->autoidle_shift; - sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg); + sysc_write_sysconfig(ddata, reg); } if (ddata->module_enable_quirk) @@ -1026,7 +1046,7 @@ static int sysc_disable_module(struct device *dev) reg &= ~(SYSC_IDLE_MASK << regbits->midle_shift); reg |= best_mode << regbits->midle_shift; - sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg); + sysc_write_sysconfig(ddata, reg); set_sidle: /* Set SIDLE mode */ @@ -1049,7 +1069,7 @@ set_sidle: if (regbits->autoidle_shift >= 0 && ddata->cfg.sysc_val & BIT(regbits->autoidle_shift)) reg |= 1 << regbits->autoidle_shift; - sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg); + sysc_write_sysconfig(ddata, reg); return 0; } @@ -1301,6 +1321,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("gpu", 0x50000000, 0x14, -ENODEV, -ENODEV, 0x00010201, 0xffffffff, 0), SYSC_QUIRK("gpu", 0x50000000, 0xfe00, 0xfe10, -ENODEV, 0x40000000 , 0xffffffff, SYSC_MODULE_QUIRK_SGX), + SYSC_QUIRK("rtc", 0, 0x74, 0x78, -ENODEV, 0x4eb01908, 0xffff00f0, + SYSC_MODULE_QUIRK_RTC_UNLOCK), SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050, 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY), SYSC_QUIRK("usb_otg_hs", 0, 0, 0x10, -ENODEV, 0x4ea2080d, 0xffffffff, @@ -1356,7 +1378,6 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("slimbus", 0, 0, 0x10, -ENODEV, 0x40002903, 0xffffffff, 0), SYSC_QUIRK("spinlock", 0, 0, 0x10, -ENODEV, 0x50020000, 0xffffffff, 0), SYSC_QUIRK("rng", 0, 0x1fe0, 0x1fe4, -ENODEV, 0x00000020, 0xffffffff, 0), - SYSC_QUIRK("rtc", 0, 0x74, 0x78, -ENODEV, 0x4eb01908, 0xffff00f0, 0), SYSC_QUIRK("timer32k", 0, 0, 0x4, -ENODEV, 0x00000060, 0xffffffff, 0), SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000004, 0xffffffff, 0), SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000008, 0xffffffff, 0), @@ -1478,6 +1499,40 @@ static void sysc_post_reset_quirk_i2c(struct sysc *ddata) sysc_clk_quirk_i2c(ddata, true); } +/* RTC on am3 and 4 needs to be unlocked and locked for sysconfig */ +static void sysc_quirk_rtc(struct sysc *ddata, bool lock) +{ + u32 val, kick0_val = 0, kick1_val = 0; + unsigned long flags; + int error; + + if (!lock) { + kick0_val = 0x83e70b13; + kick1_val = 0x95a4f1e0; + } + + local_irq_save(flags); + /* RTC_STATUS BUSY bit may stay active for 1/32768 seconds (~30 usec) */ + error = readl_poll_timeout(ddata->module_va + 0x44, val, + !(val & BIT(0)), 100, 50); + if (error) + dev_warn(ddata->dev, "rtc busy timeout\n"); + /* Now we have ~15 microseconds to read/write various registers */ + sysc_write(ddata, 0x6c, kick0_val); + sysc_write(ddata, 0x70, kick1_val); + local_irq_restore(flags); +} + +static void sysc_module_unlock_quirk_rtc(struct sysc *ddata) +{ + sysc_quirk_rtc(ddata, false); +} + +static void sysc_module_lock_quirk_rtc(struct sysc *ddata) +{ + sysc_quirk_rtc(ddata, true); +} + /* 36xx SGX needs a quirk for to bypass OCP IPG interrupt logic */ static void sysc_module_enable_quirk_sgx(struct sysc *ddata) { @@ -1532,6 +1587,13 @@ static void sysc_init_module_quirks(struct sysc *ddata) if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_AESS) ddata->module_enable_quirk = sysc_module_enable_quirk_aess; + if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_RTC_UNLOCK) { + ddata->module_unlock_quirk = sysc_module_unlock_quirk_rtc; + ddata->module_lock_quirk = sysc_module_lock_quirk_rtc; + + return; + } + if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_SGX) ddata->module_enable_quirk = sysc_module_enable_quirk_sgx; diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index accab5325cf3..0b33c3b7302f 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -49,6 +49,7 @@ struct sysc_regbits { s8 emufree_shift; }; +#define SYSC_MODULE_QUIRK_RTC_UNLOCK BIT(22) #define SYSC_QUIRK_CLKDM_NOAUTO BIT(21) #define SYSC_QUIRK_FORCE_MSTANDBY BIT(20) #define SYSC_MODULE_QUIRK_AESS BIT(19) From 77dfece2e6d8bedb6ecd4d61379ae3dc52f389bd Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 24 Feb 2020 12:58:03 -0800 Subject: [PATCH 0849/4444] bus: ti-sysc: Detect display subsystem related devices In order to prepare probing display subsystem (DSS) with ti-sysc interconnect target module driver and device tree data, let's detect DSS related modules. We need to also add reset quirk handling for DSS, but until that's done, let's just enable the optional clock quirks for DSS and omap4 HDMI. The rest is just naming of modules if CONFIG_DEBUG is set. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 6caa2222091e..b29f4e451dc1 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1302,10 +1302,18 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_MODULE_QUIRK_AESS), SYSC_QUIRK("dcan", 0x48480000, 0x20, -ENODEV, -ENODEV, 0xa3170504, 0xffffffff, SYSC_QUIRK_CLKDM_NOAUTO), + SYSC_QUIRK("dss", 0x4832a000, 0, 0x10, 0x14, 0x00000020, 0xffffffff, + SYSC_QUIRK_OPT_CLKS_IN_RESET), + SYSC_QUIRK("dss", 0x58000000, 0, -ENODEV, 0x14, 0x00000040, 0xffffffff, + SYSC_QUIRK_OPT_CLKS_IN_RESET), + SYSC_QUIRK("dss", 0x58000000, 0, -ENODEV, 0x14, 0x00000061, 0xffffffff, + SYSC_QUIRK_OPT_CLKS_IN_RESET), SYSC_QUIRK("dwc3", 0x48880000, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff, SYSC_QUIRK_CLKDM_NOAUTO), SYSC_QUIRK("dwc3", 0x488c0000, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff, SYSC_QUIRK_CLKDM_NOAUTO), + SYSC_QUIRK("hdmi", 0, 0, 0x10, -ENODEV, 0x50030200, 0xffffffff, + SYSC_QUIRK_OPT_CLKS_NEEDED), SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff, SYSC_MODULE_QUIRK_HDQ1W), SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x0000000a, 0xffffffff, @@ -1342,13 +1350,21 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { 0xffff00f0, 0), SYSC_QUIRK("dcan", 0, 0x20, -ENODEV, -ENODEV, 0xa3170504, 0xffffffff, 0), SYSC_QUIRK("dcan", 0, 0x20, -ENODEV, -ENODEV, 0x4edb1902, 0xffffffff, 0), + SYSC_QUIRK("dispc", 0x4832a400, 0, 0x10, 0x14, 0x00000030, 0xffffffff, 0), + SYSC_QUIRK("dispc", 0x58001000, 0, 0x10, 0x14, 0x00000040, 0xffffffff, 0), + SYSC_QUIRK("dispc", 0x58001000, 0, 0x10, 0x14, 0x00000051, 0xffffffff, 0), SYSC_QUIRK("dmic", 0, 0, 0x10, -ENODEV, 0x50010000, 0xffffffff, 0), + SYSC_QUIRK("dsi", 0x58004000, 0, 0x10, 0x14, 0x00000030, 0xffffffff, 0), + SYSC_QUIRK("dsi", 0x58005000, 0, 0x10, 0x14, 0x00000030, 0xffffffff, 0), + SYSC_QUIRK("dsi", 0x58005000, 0, 0x10, 0x14, 0x00000040, 0xffffffff, 0), + SYSC_QUIRK("dsi", 0x58009000, 0, 0x10, 0x14, 0x00000040, 0xffffffff, 0), SYSC_QUIRK("dwc3", 0, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff, 0), SYSC_QUIRK("d2d", 0x4a0b6000, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0), SYSC_QUIRK("d2d", 0x4a0cd000, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0), SYSC_QUIRK("epwmss", 0, 0, 0x4, -ENODEV, 0x47400001, 0xffffffff, 0), SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -ENODEV, 0, 0, 0), SYSC_QUIRK("gpu", 0, 0xfe00, 0xfe10, -ENODEV, 0x40000000 , 0xffffffff, 0), + SYSC_QUIRK("hdmi", 0, 0, 0x10, -ENODEV, 0x50031d00, 0xffffffff, 0), SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0), SYSC_QUIRK("iss", 0, 0, 0x10, -ENODEV, 0x40000101, 0xffffffff, 0), SYSC_QUIRK("lcdc", 0, 0, 0x54, -ENODEV, 0x4f201000, 0xffffffff, 0), @@ -1366,6 +1382,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("prcm", 0, 0, -ENODEV, -ENODEV, 0x40000100, 0xffffffff, 0), SYSC_QUIRK("prcm", 0, 0, -ENODEV, -ENODEV, 0x00004102, 0xffffffff, 0), SYSC_QUIRK("prcm", 0, 0, -ENODEV, -ENODEV, 0x40000400, 0xffffffff, 0), + SYSC_QUIRK("rfbi", 0x4832a800, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0), + SYSC_QUIRK("rfbi", 0x58002000, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0), SYSC_QUIRK("scm", 0, 0, 0x10, -ENODEV, 0x40000900, 0xffffffff, 0), SYSC_QUIRK("scm", 0, 0, -ENODEV, -ENODEV, 0x4e8b0100, 0xffffffff, 0), SYSC_QUIRK("scm", 0, 0, -ENODEV, -ENODEV, 0x4f000100, 0xffffffff, 0), @@ -1383,6 +1401,7 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000008, 0xffffffff, 0), SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, 0x14, 0x50700100, 0xffffffff, 0), SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, -ENODEV, 0x50700101, 0xffffffff, 0), + SYSC_QUIRK("venc", 0x58003000, 0, -ENODEV, -ENODEV, 0x00000002, 0xffffffff, 0), SYSC_QUIRK("vfpe", 0, 0, 0x104, -ENODEV, 0x4d001200, 0xffffffff, 0), #endif }; From 7324a7a0d5e232551eedad69fea3e4b91973d7c6 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 24 Feb 2020 12:58:03 -0800 Subject: [PATCH 0850/4444] bus: ti-sysc: Implement display subsystem reset quirk The display subsystem (DSS) needs the child outputs disabled for reset. In order to prepare to probe DSS without legacy platform data, let's implement sysc_pre_reset_quirk_dss() similar to what we have for the platform data with omap_dss_reset(). Note that we cannot directly use the old omap_dss_reset() without platform data callbacks and updating omap_dss_reset() to understand struct device. And we will be dropping omap_dss_reset() anyways when all the SoCs are probing with device tree, so let's not mess with the legacy code at all. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 131 +++++++++++++++++++++++++- include/linux/platform_data/ti-sysc.h | 1 + 2 files changed, 129 insertions(+), 3 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index b29f4e451dc1..e30c97ca5579 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1303,11 +1303,11 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("dcan", 0x48480000, 0x20, -ENODEV, -ENODEV, 0xa3170504, 0xffffffff, SYSC_QUIRK_CLKDM_NOAUTO), SYSC_QUIRK("dss", 0x4832a000, 0, 0x10, 0x14, 0x00000020, 0xffffffff, - SYSC_QUIRK_OPT_CLKS_IN_RESET), + SYSC_QUIRK_OPT_CLKS_IN_RESET | SYSC_MODULE_QUIRK_DSS_RESET), SYSC_QUIRK("dss", 0x58000000, 0, -ENODEV, 0x14, 0x00000040, 0xffffffff, - SYSC_QUIRK_OPT_CLKS_IN_RESET), + SYSC_QUIRK_OPT_CLKS_IN_RESET | SYSC_MODULE_QUIRK_DSS_RESET), SYSC_QUIRK("dss", 0x58000000, 0, -ENODEV, 0x14, 0x00000061, 0xffffffff, - SYSC_QUIRK_OPT_CLKS_IN_RESET), + SYSC_QUIRK_OPT_CLKS_IN_RESET | SYSC_MODULE_QUIRK_DSS_RESET), SYSC_QUIRK("dwc3", 0x48880000, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff, SYSC_QUIRK_CLKDM_NOAUTO), SYSC_QUIRK("dwc3", 0x488c0000, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff, @@ -1468,6 +1468,128 @@ static void sysc_init_revision_quirks(struct sysc *ddata) } } +/* + * DSS needs dispc outputs disabled to reset modules. Returns mask of + * enabled DSS interrupts. Eventually we may be able to do this on + * dispc init rather than top-level DSS init. + */ +static u32 sysc_quirk_dispc(struct sysc *ddata, int dispc_offset, + bool disable) +{ + bool lcd_en, digit_en, lcd2_en = false, lcd3_en = false; + const int lcd_en_mask = BIT(0), digit_en_mask = BIT(1); + int manager_count; + bool framedonetv_irq; + u32 val, irq_mask = 0; + + switch (sysc_soc->soc) { + case SOC_2420 ... SOC_3630: + manager_count = 2; + framedonetv_irq = false; + break; + case SOC_4430 ... SOC_4470: + manager_count = 3; + break; + case SOC_5430: + case SOC_DRA7: + manager_count = 4; + break; + case SOC_AM4: + manager_count = 1; + break; + case SOC_UNKNOWN: + default: + return 0; + }; + + /* Remap the whole module range to be able to reset dispc outputs */ + devm_iounmap(ddata->dev, ddata->module_va); + ddata->module_va = devm_ioremap(ddata->dev, + ddata->module_pa, + ddata->module_size); + if (!ddata->module_va) + return -EIO; + + /* DISP_CONTROL */ + val = sysc_read(ddata, dispc_offset + 0x40); + lcd_en = val & lcd_en_mask; + digit_en = val & digit_en_mask; + if (lcd_en) + irq_mask |= BIT(0); /* FRAMEDONE */ + if (digit_en) { + if (framedonetv_irq) + irq_mask |= BIT(24); /* FRAMEDONETV */ + else + irq_mask |= BIT(2) | BIT(3); /* EVSYNC bits */ + } + if (disable & (lcd_en | digit_en)) + sysc_write(ddata, dispc_offset + 0x40, + val & ~(lcd_en_mask | digit_en_mask)); + + if (manager_count <= 2) + return irq_mask; + + /* DISPC_CONTROL2 */ + val = sysc_read(ddata, dispc_offset + 0x238); + lcd2_en = val & lcd_en_mask; + if (lcd2_en) + irq_mask |= BIT(22); /* FRAMEDONE2 */ + if (disable && lcd2_en) + sysc_write(ddata, dispc_offset + 0x238, + val & ~lcd_en_mask); + + if (manager_count <= 3) + return irq_mask; + + /* DISPC_CONTROL3 */ + val = sysc_read(ddata, dispc_offset + 0x848); + lcd3_en = val & lcd_en_mask; + if (lcd3_en) + irq_mask |= BIT(30); /* FRAMEDONE3 */ + if (disable && lcd3_en) + sysc_write(ddata, dispc_offset + 0x848, + val & ~lcd_en_mask); + + return irq_mask; +} + +/* DSS needs child outputs disabled and SDI registers cleared for reset */ +static void sysc_pre_reset_quirk_dss(struct sysc *ddata) +{ + const int dispc_offset = 0x1000; + int error; + u32 irq_mask, val; + + /* Get enabled outputs */ + irq_mask = sysc_quirk_dispc(ddata, dispc_offset, false); + if (!irq_mask) + return; + + /* Clear IRQSTATUS */ + sysc_write(ddata, 0x1000 + 0x18, irq_mask); + + /* Disable outputs */ + val = sysc_quirk_dispc(ddata, dispc_offset, true); + + /* Poll IRQSTATUS */ + error = readl_poll_timeout(ddata->module_va + dispc_offset + 0x18, + val, val != irq_mask, 100, 50); + if (error) + dev_warn(ddata->dev, "%s: timed out %08x !+ %08x\n", + __func__, val, irq_mask); + + if (sysc_soc->soc == SOC_3430) { + /* Clear DSS_SDI_CONTROL */ + sysc_write(ddata, dispc_offset + 0x44, 0); + + /* Clear DSS_PLL_CONTROL */ + sysc_write(ddata, dispc_offset + 0x48, 0); + } + + /* Clear DSS_CONTROL to switch DSS clock sources to PRCM if not */ + sysc_write(ddata, dispc_offset + 0x40, 0); +} + /* 1-wire needs module's internal clocks enabled for reset */ static void sysc_pre_reset_quirk_hdq1w(struct sysc *ddata) { @@ -1606,6 +1728,9 @@ static void sysc_init_module_quirks(struct sysc *ddata) if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_AESS) ddata->module_enable_quirk = sysc_module_enable_quirk_aess; + if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_DSS_RESET) + ddata->pre_reset_quirk = sysc_pre_reset_quirk_dss; + if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_RTC_UNLOCK) { ddata->module_unlock_quirk = sysc_module_unlock_quirk_rtc; ddata->module_lock_quirk = sysc_module_lock_quirk_rtc; diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index 0b33c3b7302f..ecd3a979a14d 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -49,6 +49,7 @@ struct sysc_regbits { s8 emufree_shift; }; +#define SYSC_MODULE_QUIRK_DSS_RESET BIT(23) #define SYSC_MODULE_QUIRK_RTC_UNLOCK BIT(22) #define SYSC_QUIRK_CLKDM_NOAUTO BIT(21) #define SYSC_QUIRK_FORCE_MSTANDBY BIT(20) From 6b8e4e7db3cd236a2cbb720360fb135087a2ac1d Mon Sep 17 00:00:00 2001 From: Akshu Agrawal Date: Mon, 17 Feb 2020 10:35:01 +0530 Subject: [PATCH 0851/4444] ASoC: amd: Add machine driver for Raven based platform Add machine driver for Raven based platform using RT5682 + MAX9836 + CROS_EC codecs Signed-off-by: Akshu Agrawal Link: https://lore.kernel.org/r/20200217050515.3847-1-akshu.agrawal@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/Kconfig | 10 + sound/soc/amd/Makefile | 2 + sound/soc/amd/acp3x-rt5682-max9836.c | 334 +++++++++++++++++++++++++++ 3 files changed, 346 insertions(+) create mode 100644 sound/soc/amd/acp3x-rt5682-max9836.c diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index 5f40517717c4..b29ef1373946 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -26,3 +26,13 @@ config SND_SOC_AMD_ACP3x depends on X86 && PCI help This option enables ACP v3.x I2S support on AMD platform + +config SND_SOC_AMD_RV_RT5682_MACH + tristate "AMD RV support for RT5682" + select SND_SOC_RT5682 + select SND_SOC_MAX98357A + select SND_SOC_CROS_EC_CODEC + select I2C_CROS_EC_TUNNEL + depends on SND_SOC_AMD_ACP3x && I2C + help + This option enables machine driver for RT5682 and MAX9835. diff --git a/sound/soc/amd/Makefile b/sound/soc/amd/Makefile index c4ddc6adb6f0..e6f3d9b469f3 100644 --- a/sound/soc/amd/Makefile +++ b/sound/soc/amd/Makefile @@ -2,8 +2,10 @@ acp_audio_dma-objs := acp-pcm-dma.o snd-soc-acp-da7219mx98357-mach-objs := acp-da7219-max98357a.o snd-soc-acp-rt5645-mach-objs := acp-rt5645.o +snd-soc-acp-rt5682-mach-objs := acp3x-rt5682-max9836.o obj-$(CONFIG_SND_SOC_AMD_ACP) += acp_audio_dma.o obj-$(CONFIG_SND_SOC_AMD_CZ_DA7219MX98357_MACH) += snd-soc-acp-da7219mx98357-mach.o obj-$(CONFIG_SND_SOC_AMD_CZ_RT5645_MACH) += snd-soc-acp-rt5645-mach.o obj-$(CONFIG_SND_SOC_AMD_ACP3x) += raven/ +obj-$(CONFIG_SND_SOC_AMD_RV_RT5682_MACH) += snd-soc-acp-rt5682-mach.o diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c new file mode 100644 index 000000000000..96fbcd29e3ed --- /dev/null +++ b/sound/soc/amd/acp3x-rt5682-max9836.c @@ -0,0 +1,334 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Machine driver for AMD ACP Audio engine using DA7219 & MAX98357 codec. +// +//Copyright 2016 Advanced Micro Devices, Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "raven/acp3x.h" +#include "../codecs/rt5682.h" + +#define PCO_PLAT_CLK 48000000 +#define RT5682_PLL_FREQ (48000 * 512) +#define DUAL_CHANNEL 2 + +static struct snd_soc_jack pco_jack; +static struct clk *rt5682_dai_wclk; +static struct clk *rt5682_dai_bclk; + +static int acp3x_5682_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_component *component = codec_dai->component; + + dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); + + /* set rt5682 dai fmt */ + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S + | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) { + dev_err(rtd->card->dev, + "Failed to set rt5682 dai fmt: %d\n", ret); + return ret; + } + + /* set codec PLL */ + ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL2, RT5682_PLL2_S_MCLK, + PCO_PLAT_CLK, RT5682_PLL_FREQ); + if (ret < 0) { + dev_err(rtd->dev, "can't set rt5682 PLL: %d\n", ret); + return ret; + } + + /* Set codec sysclk */ + ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL2, + RT5682_PLL_FREQ, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(rtd->dev, + "Failed to set rt5682 SYSCLK: %d\n", ret); + return ret; + } + + /* Set tdm/i2s1 master bclk ratio */ + ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); + if (ret < 0) { + dev_err(rtd->dev, + "Failed to set rt5682 tdm bclk ratio: %d\n", ret); + return ret; + } + + rt5682_dai_wclk = clk_get(component->dev, "rt5682-dai-wclk"); + rt5682_dai_bclk = clk_get(component->dev, "rt5682-dai-bclk"); + + ret = snd_soc_card_jack_new(card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_LINEOUT | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, + &pco_jack, NULL, 0); + if (ret) { + dev_err(card->dev, "HP jack creation failed %d\n", ret); + return ret; + } + + snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP); + snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); + snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); + + ret = snd_soc_component_set_jack(component, &pco_jack, NULL); + if (ret) { + dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); + return ret; + } + + return ret; +} + +static int rt5682_clk_enable(struct snd_pcm_substream *substream) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + /* RT5682 will support only 48K output with 48M mclk */ + clk_set_rate(rt5682_dai_wclk, 48000); + clk_set_rate(rt5682_dai_bclk, 48000 * 64); + ret = clk_prepare_enable(rt5682_dai_wclk); + if (ret < 0) { + dev_err(rtd->dev, "can't enable wclk %d\n", ret); + return ret; + } + + return ret; +} + +static void rt5682_clk_disable(void) +{ + clk_disable_unprepare(rt5682_dai_wclk); +} + +static const unsigned int channels[] = { + DUAL_CHANNEL, +}; + +static const unsigned int rates[] = { + 48000, +}; + +static const struct snd_pcm_hw_constraint_list constraints_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, +}; + +static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, +}; + +static int acp3x_5682_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card); + + machine->play_i2s_instance = I2S_SP_INSTANCE; + machine->cap_i2s_instance = I2S_SP_INSTANCE; + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + return rt5682_clk_enable(substream); +} + +static int acp3x_max_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card); + + machine->play_i2s_instance = I2S_BT_INSTANCE; + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + return rt5682_clk_enable(substream); +} + +static int acp3x_ec_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card); + + machine->cap_i2s_instance = I2S_BT_INSTANCE; + snd_soc_dai_set_bclk_ratio(codec_dai, 64); + + return rt5682_clk_enable(substream); +} + +static void rt5682_shutdown(struct snd_pcm_substream *substream) +{ + rt5682_clk_disable(); +} + +static const struct snd_soc_ops acp3x_5682_ops = { + .startup = acp3x_5682_startup, + .shutdown = rt5682_shutdown, +}; + +static const struct snd_soc_ops acp3x_max_play_ops = { + .startup = acp3x_max_startup, + .shutdown = rt5682_shutdown, +}; + +static const struct snd_soc_ops acp3x_ec_cap_ops = { + .startup = acp3x_ec_startup, + .shutdown = rt5682_shutdown, +}; + +SND_SOC_DAILINK_DEF(acp3x_i2s, + DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.0"))); +SND_SOC_DAILINK_DEF(acp3x_bt, + DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.2"))); + +SND_SOC_DAILINK_DEF(rt5682, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1"))); +SND_SOC_DAILINK_DEF(max, + DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", "HiFi"))); +SND_SOC_DAILINK_DEF(cros_ec, + DAILINK_COMP_ARRAY(COMP_CODEC("GOOG0013:00", "EC Codec I2S RX"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("acp3x_rv_i2s_dma.0"))); + +static struct snd_soc_dai_link acp3x_dai_5682_98357[] = { + { + .name = "acp3x-5682-play", + .stream_name = "Playback", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .init = acp3x_5682_init, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ops = &acp3x_5682_ops, + SND_SOC_DAILINK_REG(acp3x_i2s, rt5682, platform), + }, + { + .name = "acp3x-max98357-play", + .stream_name = "HiFi Playback", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .dpcm_playback = 1, + .ops = &acp3x_max_play_ops, + SND_SOC_DAILINK_REG(acp3x_bt, max, platform), + }, + { + .name = "acp3x-ec-capture", + .stream_name = "Capture", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBS_CFS, + .dpcm_capture = 1, + .ops = &acp3x_ec_cap_ops, + SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform), + }, +}; + +static const struct snd_soc_dapm_widget acp3x_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_SPK("Spk", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), +}; + +static const struct snd_soc_dapm_route acp3x_audio_route[] = { + {"Headphone Jack", NULL, "HPOL"}, + {"Headphone Jack", NULL, "HPOR"}, + {"IN1P", NULL, "Headset Mic"}, + {"Spk", NULL, "Speaker"}, +}; + +static const struct snd_kcontrol_new acp3x_mc_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Spk"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static struct snd_soc_card acp3x_card = { + .name = "acp3xalc5682m98357", + .owner = THIS_MODULE, + .dai_link = acp3x_dai_5682_98357, + .num_links = ARRAY_SIZE(acp3x_dai_5682_98357), + .dapm_widgets = acp3x_widgets, + .num_dapm_widgets = ARRAY_SIZE(acp3x_widgets), + .dapm_routes = acp3x_audio_route, + .num_dapm_routes = ARRAY_SIZE(acp3x_audio_route), + .controls = acp3x_mc_controls, + .num_controls = ARRAY_SIZE(acp3x_mc_controls), +}; + +static int acp3x_probe(struct platform_device *pdev) +{ + int ret; + struct snd_soc_card *card; + struct acp3x_platform_info *machine; + + machine = devm_kzalloc(&pdev->dev, sizeof(*machine), GFP_KERNEL); + if (!machine) + return -ENOMEM; + + card = &acp3x_card; + acp3x_card.dev = &pdev->dev; + platform_set_drvdata(pdev, card); + snd_soc_card_set_drvdata(card, machine); + ret = devm_snd_soc_register_card(&pdev->dev, &acp3x_card); + if (ret) { + dev_err(&pdev->dev, + "devm_snd_soc_register_card(%s) failed: %d\n", + acp3x_card.name, ret); + return ret; + } + return 0; +} + +static const struct acpi_device_id acp3x_audio_acpi_match[] = { + { "AMDI5682", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, acp3x_audio_acpi_match); + +static struct platform_driver acp3x_audio = { + .driver = { + .name = "acp3x-alc5682-max98357", + .acpi_match_table = ACPI_PTR(acp3x_audio_acpi_match), + .pm = &snd_soc_pm_ops, + }, + .probe = acp3x_probe, +}; + +module_platform_driver(acp3x_audio); + +MODULE_AUTHOR("akshu.agrawal@amd.com"); +MODULE_DESCRIPTION("ALC5682 & MAX98357 audio support"); +MODULE_LICENSE("GPL v2"); From 03f6fc6de9192f4e4209ceee0e92f5947d44fc0a Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Wed, 19 Feb 2020 18:28:57 +0800 Subject: [PATCH 0852/4444] ASoC: rt5682: Add the soundwire support This patch adds the soundwire support for ALC5682. Signed-off-by: Oder Chiou Link: https://lore.kernel.org/r/20200219102858.20166-1-oder_chiou@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 7 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rt5682-sdw.c | 333 +++++++++++++++++++++ sound/soc/codecs/rt5682-sdw.h | 20 ++ sound/soc/codecs/rt5682.c | 526 +++++++++++++++++++++++++++++++--- sound/soc/codecs/rt5682.h | 49 ++++ 6 files changed, 897 insertions(+), 40 deletions(-) create mode 100644 sound/soc/codecs/rt5682-sdw.c create mode 100644 sound/soc/codecs/rt5682-sdw.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index a7e89567edbe..6aee70ed43df 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -168,6 +168,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_RT5670 imply SND_SOC_RT5677 imply SND_SOC_RT5682 + imply SND_SOC_RT5682_SDW imply SND_SOC_RT700_SDW imply SND_SOC_RT711_SDW imply SND_SOC_RT715_SDW @@ -1136,6 +1137,12 @@ config SND_SOC_RT5682 tristate depends on I2C +config SND_SOC_RT5682_SDW + tristate "Realtek RT5682 Codec - SDW" + depends on SOUNDWIRE + select SND_SOC_RT5682 + select REGMAP_SOUNDWIRE + config SND_SOC_RT700 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 943ebc93fbc1..03533157cda6 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -177,6 +177,7 @@ snd-soc-rt5670-objs := rt5670.o snd-soc-rt5677-objs := rt5677.o snd-soc-rt5677-spi-objs := rt5677-spi.o snd-soc-rt5682-objs := rt5682.o +snd-soc-rt5682-sdw-objs := rt5682-sdw.o snd-soc-rt700-objs := rt700.o rt700-sdw.o snd-soc-rt711-objs := rt711.o rt711-sdw.o snd-soc-rt715-objs := rt715.o rt715-sdw.o @@ -477,6 +478,7 @@ obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o obj-$(CONFIG_SND_SOC_RT5677_SPI) += snd-soc-rt5677-spi.o obj-$(CONFIG_SND_SOC_RT5682) += snd-soc-rt5682.o +obj-$(CONFIG_SND_SOC_RT5682_SDW) += snd-soc-rt5682-sdw.o obj-$(CONFIG_SND_SOC_RT700) += snd-soc-rt700.o obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o obj-$(CONFIG_SND_SOC_RT715) += snd-soc-rt715.o diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c new file mode 100644 index 000000000000..fc31d04b5203 --- /dev/null +++ b/sound/soc/codecs/rt5682-sdw.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// rt5682-sdw.c -- RT5682 ALSA SoC audio component driver +// +// Copyright 2019 Realtek Semiconductor Corp. +// Author: Oder Chiou +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rt5682.h" +#include "rt5682-sdw.h" + +static bool rt5682_sdw_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x00e0: + case 0x00f0: + case 0x3000: + case 0x3001: + case 0x3004: + case 0x3005: + case 0x3008: + return true; + default: + return false; + } +} + +const struct regmap_config rt5682_sdw_regmap = { + .name = "sdw", + .reg_bits = 32, + .val_bits = 8, + .max_register = RT5682_I2C_MODE, + .readable_reg = rt5682_sdw_readable_register, + .cache_type = REGCACHE_NONE, + .use_single_read = true, + .use_single_write = true, +}; + +static int rt5682_update_status(struct sdw_slave *slave, + enum sdw_slave_status status) +{ + struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev); + + /* Update the status */ + rt5682->status = status; + + if (status == SDW_SLAVE_UNATTACHED) + rt5682->hw_init = false; + + /* + * Perform initialization only if slave status is present and + * hw_init flag is false + */ + if (rt5682->hw_init || rt5682->status != SDW_SLAVE_ATTACHED) + return 0; + + /* perform I/O transfers required for Slave initialization */ + return rt5682_io_init(&slave->dev, slave); +} + +static int rt5682_read_prop(struct sdw_slave *slave) +{ + struct sdw_slave_prop *prop = &slave->prop; + int nval, i, num_of_ports = 1; + u32 bit; + unsigned long addr; + struct sdw_dpn_prop *dpn; + + prop->paging_support = false; + + /* first we need to allocate memory for set bits in port lists */ + prop->source_ports = 0x4; /* BITMAP: 00000100 */ + prop->sink_ports = 0x2; /* BITMAP: 00000010 */ + + nval = hweight32(prop->source_ports); + num_of_ports += nval; + prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->src_dpn_prop), + GFP_KERNEL); + if (!prop->src_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->src_dpn_prop; + addr = prop->source_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].type = SDW_DPN_FULL; + dpn[i].simple_ch_prep_sm = true; + dpn[i].ch_prep_timeout = 10; + i++; + } + + /* do this again for sink now */ + nval = hweight32(prop->sink_ports); + num_of_ports += nval; + prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->sink_dpn_prop), + GFP_KERNEL); + if (!prop->sink_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->sink_dpn_prop; + addr = prop->sink_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].type = SDW_DPN_FULL; + dpn[i].simple_ch_prep_sm = true; + dpn[i].ch_prep_timeout = 10; + i++; + } + + /* Allocate port_ready based on num_of_ports */ + slave->port_ready = devm_kcalloc(&slave->dev, num_of_ports, + sizeof(*slave->port_ready), + GFP_KERNEL); + if (!slave->port_ready) + return -ENOMEM; + + /* Initialize completion */ + for (i = 0; i < num_of_ports; i++) + init_completion(&slave->port_ready[i]); + + /* set the timeout values */ + prop->clk_stop_timeout = 20; + + /* wake-up event */ + prop->wake_capable = 1; + + return 0; +} + +/* Bus clock frequency */ +#define RT5682_CLK_FREQ_9600000HZ 9600000 +#define RT5682_CLK_FREQ_12000000HZ 12000000 +#define RT5682_CLK_FREQ_6000000HZ 6000000 +#define RT5682_CLK_FREQ_4800000HZ 4800000 +#define RT5682_CLK_FREQ_2400000HZ 2400000 +#define RT5682_CLK_FREQ_12288000HZ 12288000 + +int rt5682_clock_config(struct device *dev) +{ + struct rt5682_priv *rt5682 = dev_get_drvdata(dev); + unsigned int clk_freq, value; + + clk_freq = (rt5682->params.curr_dr_freq >> 1); + + switch (clk_freq) { + case RT5682_CLK_FREQ_12000000HZ: + value = 0x0; + break; + case RT5682_CLK_FREQ_6000000HZ: + value = 0x1; + break; + case RT5682_CLK_FREQ_9600000HZ: + value = 0x2; + break; + case RT5682_CLK_FREQ_4800000HZ: + value = 0x3; + break; + case RT5682_CLK_FREQ_2400000HZ: + value = 0x4; + break; + case RT5682_CLK_FREQ_12288000HZ: + value = 0x5; + break; + default: + return -EINVAL; + } + + regmap_write(rt5682->sdw_regmap, 0xe0, value); + regmap_write(rt5682->sdw_regmap, 0xf0, value); + + dev_dbg(dev, "%s complete, clk_freq=%d\n", __func__, clk_freq); + + return 0; +} + +static int rt5682_bus_config(struct sdw_slave *slave, + struct sdw_bus_params *params) +{ + struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev); + int ret; + + memcpy(&rt5682->params, params, sizeof(*params)); + + ret = rt5682_clock_config(&slave->dev); + if (ret < 0) + dev_err(&slave->dev, "Invalid clk config"); + + return ret; +} + +static int rt5682_interrupt_callback(struct sdw_slave *slave, + struct sdw_slave_intr_status *status) +{ + struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev); + + dev_dbg(&slave->dev, + "%s control_port_stat=%x", __func__, status->control_port); + + if (status->control_port & 0x4) { + mod_delayed_work(system_power_efficient_wq, + &rt5682->jack_detect_work, msecs_to_jiffies(250)); + } + + return 0; +} + +static struct sdw_slave_ops rt5682_slave_ops = { + .read_prop = rt5682_read_prop, + .interrupt_callback = rt5682_interrupt_callback, + .update_status = rt5682_update_status, + .bus_config = rt5682_bus_config, +}; + +static int rt5682_sdw_probe(struct sdw_slave *slave, + const struct sdw_device_id *id) +{ + struct regmap *regmap; + + /* Assign ops */ + slave->ops = &rt5682_slave_ops; + + /* Regmap Initialization */ + regmap = devm_regmap_init_sdw(slave, &rt5682_sdw_regmap); + if (IS_ERR(regmap)) + return -EINVAL; + + rt5682_sdw_init(&slave->dev, regmap, slave); + + return 0; +} + +static int rt5682_sdw_remove(struct sdw_slave *slave) +{ + struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev); + + if (rt5682 && rt5682->hw_init) + cancel_delayed_work(&rt5682->jack_detect_work); + + return 0; +} + +static const struct sdw_device_id rt5682_id[] = { + SDW_SLAVE_ENTRY(0x025d, 0x5682, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, rt5682_id); + +static int rt5682_dev_suspend(struct device *dev) +{ + struct rt5682_priv *rt5682 = dev_get_drvdata(dev); + + if (!rt5682->hw_init) + return 0; + + regcache_cache_only(rt5682->regmap, true); + regcache_mark_dirty(rt5682->regmap); + + return 0; +} + +static int rt5682_dev_resume(struct device *dev) +{ + struct sdw_slave *slave = dev_to_sdw_dev(dev); + struct rt5682_priv *rt5682 = dev_get_drvdata(dev); + unsigned long time; + + if (!rt5682->hw_init) + return 0; + + if (!slave->unattach_request) + goto regmap_sync; + + time = wait_for_completion_timeout(&slave->initialization_complete, + msecs_to_jiffies(RT5682_PROBE_TIMEOUT)); + if (!time) { + dev_err(&slave->dev, "Initialization not complete, timed out\n"); + return -ETIMEDOUT; + } + +regmap_sync: + slave->unattach_request = 0; + regcache_cache_only(rt5682->regmap, false); + regcache_sync(rt5682->regmap); + + return 0; +} + +static const struct dev_pm_ops rt5682_pm = { + SET_SYSTEM_SLEEP_PM_OPS(rt5682_dev_suspend, rt5682_dev_resume) + SET_RUNTIME_PM_OPS(rt5682_dev_suspend, rt5682_dev_resume, NULL) +}; + +static struct sdw_driver rt5682_sdw_driver = { + .driver = { + .name = "rt5682", + .owner = THIS_MODULE, + .pm = &rt5682_pm, + }, + .probe = rt5682_sdw_probe, + .remove = rt5682_sdw_remove, + .ops = &rt5682_slave_ops, + .id_table = rt5682_id, +}; +module_sdw_driver(rt5682_sdw_driver); + +MODULE_DESCRIPTION("ASoC RT5682 driver SDW"); +MODULE_AUTHOR("Oder Chiou "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rt5682-sdw.h b/sound/soc/codecs/rt5682-sdw.h new file mode 100644 index 000000000000..76e6f607066e --- /dev/null +++ b/sound/soc/codecs/rt5682-sdw.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * rt5682-sdw.h -- RT5682 SDW ALSA SoC audio driver + * + * Copyright 2019 Realtek Semiconductor Corp. + * Author: Oder Chiou + */ + +#ifndef __RT5682_SDW_H__ +#define __RT5682_SDW_H__ + +#define RT5682_SDW_ADDR_L 0x3000 +#define RT5682_SDW_ADDR_H 0x3001 +#define RT5682_SDW_DATA_L 0x3004 +#define RT5682_SDW_DATA_H 0x3005 +#define RT5682_SDW_CMD 0x3008 + +#define RT5682_PROBE_TIMEOUT 2000 + +#endif /* __RT5682_SDW_H__ */ diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 6774813e0eea..1795a8bbea1a 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -11,13 +11,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include #include #include @@ -27,15 +27,11 @@ #include #include #include -#include -#include -#include #include #include "rl6231.h" #include "rt5682.h" - -#define RT5682_NUM_SUPPLIES 3 +#include "rt5682-sdw.h" static const char *rt5682_supply_names[RT5682_NUM_SUPPLIES] = { "AVDD", @@ -52,37 +48,6 @@ static const struct rt5682_platform_data i2s_default_platform_data = { .dai_clk_names[RT5682_DAI_BCLK_IDX] = "rt5682-dai-bclk", }; -struct rt5682_priv { - struct snd_soc_component *component; - struct rt5682_platform_data pdata; - struct regmap *regmap; - struct snd_soc_jack *hs_jack; - struct regulator_bulk_data supplies[RT5682_NUM_SUPPLIES]; - struct delayed_work jack_detect_work; - struct delayed_work jd_check_work; - struct mutex calibrate_mutex; - bool is_sdw; - -#ifdef CONFIG_COMMON_CLK - struct clk_hw dai_clks_hw[RT5682_DAI_NUM_CLKS]; - struct clk_lookup *dai_clks_lookup[RT5682_DAI_NUM_CLKS]; - struct clk *dai_clks[RT5682_DAI_NUM_CLKS]; - struct clk *mclk; -#endif - - int sysclk; - int sysclk_src; - int lrck[RT5682_AIFS]; - int bclk[RT5682_AIFS]; - int master[RT5682_AIFS]; - - int pll_src[RT5682_PLLS]; - int pll_in[RT5682_PLLS]; - int pll_out[RT5682_PLLS]; - - int jack_type; -}; - static const struct reg_sequence patch_list[] = { {RT5682_HP_IMP_SENS_CTRL_19, 0x1000}, {RT5682_DAC_ADC_DIG_VOL1, 0xa020}, @@ -819,6 +784,22 @@ static const struct snd_kcontrol_new rt5682_if1_45_adc_swap_mux = static const struct snd_kcontrol_new rt5682_if1_67_adc_swap_mux = SOC_DAPM_ENUM("IF1 67 ADC Swap Mux", rt5682_if1_67_adc_enum); +static const char * const rt5682_dac_select[] = { + "IF1", "SOUND" +}; + +static SOC_ENUM_SINGLE_DECL(rt5682_dacl_enum, + RT5682_AD_DA_MIXER, RT5682_DAC1_L_SEL_SFT, rt5682_dac_select); + +static const struct snd_kcontrol_new rt5682_dac_l_mux = + SOC_DAPM_ENUM("DAC L Mux", rt5682_dacl_enum); + +static SOC_ENUM_SINGLE_DECL(rt5682_dacr_enum, + RT5682_AD_DA_MIXER, RT5682_DAC1_R_SEL_SFT, rt5682_dac_select); + +static const struct snd_kcontrol_new rt5682_dac_r_mux = + SOC_DAPM_ENUM("DAC R Mux", rt5682_dacr_enum); + static void rt5682_reset(struct rt5682_priv *rt5682) { regmap_write(rt5682->regmap, RT5682_RESET, 0); @@ -1271,6 +1252,9 @@ static int set_filter_clk(struct snd_soc_dapm_widget *w, static const int div_f[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48}; static const int div_o[] = {1, 2, 4, 6, 8, 12, 16, 24, 32, 48}; + if (rt5682->is_sdw) + return 0; + val = snd_soc_component_read32(component, RT5682_GPIO_CTRL_1) & RT5682_GP4_PIN_MASK; if (w->shift == RT5682_PWR_ADC_S1F_BIT && @@ -1743,6 +1727,8 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = { SND_SOC_DAPM_PGA("IF1 DAC1", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("SOUND DAC L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("SOUND DAC R", SND_SOC_NOPM, 0, 0, NULL, 0), /* Digital Interface Select */ SND_SOC_DAPM_MUX("IF1 01 ADC Swap Mux", SND_SOC_NOPM, 0, 0, @@ -1759,12 +1745,19 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = { SND_SOC_DAPM_MUX("ADCDAT Mux", SND_SOC_NOPM, 0, 0, &rt5682_adcdat_pin_ctrl), + SND_SOC_DAPM_MUX("DAC L Mux", SND_SOC_NOPM, 0, 0, + &rt5682_dac_l_mux), + SND_SOC_DAPM_MUX("DAC R Mux", SND_SOC_NOPM, 0, 0, + &rt5682_dac_r_mux), + /* Audio Interface */ SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, RT5682_I2S1_SDP, RT5682_SEL_ADCDAT_SFT, 1), SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, RT5682_I2S2_SDP, RT5682_I2S2_PIN_CFG_SFT, 1), SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("SDWRX", "SDW Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("SDWTX", "SDW Capture", 0, SND_SOC_NOPM, 0, 0), /* Output Side */ /* DAC mixer before sound effect */ @@ -1921,8 +1914,8 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = { {"IF1_ADC Mux", "Slot 2", "IF1 23 ADC Swap Mux"}, {"IF1_ADC Mux", "Slot 4", "IF1 45 ADC Swap Mux"}, {"IF1_ADC Mux", "Slot 6", "IF1 67 ADC Swap Mux"}, - {"IF1_ADC Mux", NULL, "I2S1"}, {"ADCDAT Mux", "ADCDAT1", "IF1_ADC Mux"}, + {"AIF1TX", NULL, "I2S1"}, {"AIF1TX", NULL, "ADCDAT Mux"}, {"IF2 ADC Swap Mux", "L/R", "Stereo1 ADC MIX"}, {"IF2 ADC Swap Mux", "R/L", "Stereo1 ADC MIX"}, @@ -1931,6 +1924,10 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = { {"ADCDAT Mux", "ADCDAT2", "IF2 ADC Swap Mux"}, {"AIF2TX", NULL, "ADCDAT Mux"}, + {"SDWTX", NULL, "PLL2B"}, + {"SDWTX", NULL, "PLL2F"}, + {"SDWTX", NULL, "ADCDAT Mux"}, + {"IF1 DAC1 L", NULL, "AIF1RX"}, {"IF1 DAC1 L", NULL, "I2S1"}, {"IF1 DAC1 L", NULL, "DAC Stereo1 Filter"}, @@ -1938,10 +1935,24 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = { {"IF1 DAC1 R", NULL, "I2S1"}, {"IF1 DAC1 R", NULL, "DAC Stereo1 Filter"}, + {"SOUND DAC L", NULL, "SDWRX"}, + {"SOUND DAC L", NULL, "DAC Stereo1 Filter"}, + {"SOUND DAC L", NULL, "PLL2B"}, + {"SOUND DAC L", NULL, "PLL2F"}, + {"SOUND DAC R", NULL, "SDWRX"}, + {"SOUND DAC R", NULL, "DAC Stereo1 Filter"}, + {"SOUND DAC R", NULL, "PLL2B"}, + {"SOUND DAC R", NULL, "PLL2F"}, + + {"DAC L Mux", "IF1", "IF1 DAC1 L"}, + {"DAC L Mux", "SOUND", "SOUND DAC L"}, + {"DAC R Mux", "IF1", "IF1 DAC1 R"}, + {"DAC R Mux", "SOUND", "SOUND DAC R"}, + {"DAC1 MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL"}, - {"DAC1 MIXL", "DAC1 Switch", "IF1 DAC1 L"}, + {"DAC1 MIXL", "DAC1 Switch", "DAC L Mux"}, {"DAC1 MIXR", "Stereo ADC Switch", "Stereo1 ADC MIXR"}, - {"DAC1 MIXR", "DAC1 Switch", "IF1 DAC1 R"}, + {"DAC1 MIXR", "DAC1 Switch", "DAC R Mux"}, {"Stereo1 DAC MIXL", "DAC L1 Switch", "DAC1 MIXL"}, {"Stereo1 DAC MIXL", "DAC R1 Switch", "DAC1 MIXR"}, @@ -2826,6 +2837,8 @@ err: static int rt5682_probe(struct snd_soc_component *component) { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + struct sdw_slave *slave; + unsigned long time; #ifdef CONFIG_COMMON_CLK int ret; @@ -2852,6 +2865,17 @@ static int rt5682_probe(struct snd_soc_component *component) rt5682->lrck[RT5682_AIF1] = CLK_48; #endif + if (rt5682->is_sdw) { + slave = rt5682->slave; + time = wait_for_completion_timeout( + &slave->initialization_complete, + msecs_to_jiffies(RT5682_PROBE_TIMEOUT)); + if (!time) { + dev_err(&slave->dev, "Initialization not complete, timed out\n"); + return -ETIMEDOUT; + } + } + return 0; } @@ -2914,6 +2938,194 @@ static const struct snd_soc_dai_ops rt5682_aif2_dai_ops = { .set_bclk_ratio = rt5682_set_bclk2_ratio, }; +#if IS_ENABLED(CONFIG_SND_SOC_RT5682_SDW) +struct sdw_stream_data { + struct sdw_stream_runtime *sdw_stream; +}; + +static int rt5682_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, + int direction) +{ + struct sdw_stream_data *stream; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (!stream) + return -ENOMEM; + + stream->sdw_stream = (struct sdw_stream_runtime *)sdw_stream; + + /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ + if (direction == SNDRV_PCM_STREAM_PLAYBACK) + dai->playback_dma_data = stream; + else + dai->capture_dma_data = stream; + + return 0; +} + +static void rt5682_sdw_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct sdw_stream_data *stream; + + stream = snd_soc_dai_get_dma_data(dai, substream); + snd_soc_dai_set_dma_data(dai, substream, NULL); + kfree(stream); +} + +static int rt5682_sdw_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + struct sdw_stream_config stream_config; + struct sdw_port_config port_config; + enum sdw_data_direction direction; + struct sdw_stream_data *stream; + int retval, port, num_channels; + unsigned int val_p = 0, val_c = 0, osr_p = 0, osr_c = 0; + + dev_dbg(dai->dev, "%s %s", __func__, dai->name); + stream = snd_soc_dai_get_dma_data(dai, substream); + + if (!stream) + return -ENOMEM; + + if (!rt5682->slave) + return -EINVAL; + + /* SoundWire specific configuration */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + direction = SDW_DATA_DIR_RX; + port = 1; + } else { + direction = SDW_DATA_DIR_TX; + port = 2; + } + + stream_config.frame_rate = params_rate(params); + stream_config.ch_count = params_channels(params); + stream_config.bps = snd_pcm_format_width(params_format(params)); + stream_config.direction = direction; + + num_channels = params_channels(params); + port_config.ch_mask = (1 << (num_channels)) - 1; + port_config.num = port; + + retval = sdw_stream_add_slave(rt5682->slave, &stream_config, + &port_config, 1, stream->sdw_stream); + if (retval) { + dev_err(dai->dev, "Unable to configure port\n"); + return retval; + } + + switch (params_rate(params)) { + case 48000: + val_p = RT5682_SDW_REF_1_48K; + val_c = RT5682_SDW_REF_2_48K; + break; + case 96000: + val_p = RT5682_SDW_REF_1_96K; + val_c = RT5682_SDW_REF_2_96K; + break; + case 192000: + val_p = RT5682_SDW_REF_1_192K; + val_c = RT5682_SDW_REF_2_192K; + break; + case 32000: + val_p = RT5682_SDW_REF_1_32K; + val_c = RT5682_SDW_REF_2_32K; + break; + case 24000: + val_p = RT5682_SDW_REF_1_24K; + val_c = RT5682_SDW_REF_2_24K; + break; + case 16000: + val_p = RT5682_SDW_REF_1_16K; + val_c = RT5682_SDW_REF_2_16K; + break; + case 12000: + val_p = RT5682_SDW_REF_1_12K; + val_c = RT5682_SDW_REF_2_12K; + break; + case 8000: + val_p = RT5682_SDW_REF_1_8K; + val_c = RT5682_SDW_REF_2_8K; + break; + case 44100: + val_p = RT5682_SDW_REF_1_44K; + val_c = RT5682_SDW_REF_2_44K; + break; + case 88200: + val_p = RT5682_SDW_REF_1_88K; + val_c = RT5682_SDW_REF_2_88K; + break; + case 176400: + val_p = RT5682_SDW_REF_1_176K; + val_c = RT5682_SDW_REF_2_176K; + break; + case 22050: + val_p = RT5682_SDW_REF_1_22K; + val_c = RT5682_SDW_REF_2_22K; + break; + case 11025: + val_p = RT5682_SDW_REF_1_11K; + val_c = RT5682_SDW_REF_2_11K; + break; + default: + return -EINVAL; + } + + if (params_rate(params) <= 48000) { + osr_p = RT5682_DAC_OSR_D_8; + osr_c = RT5682_ADC_OSR_D_8; + } else if (params_rate(params) <= 96000) { + osr_p = RT5682_DAC_OSR_D_4; + osr_c = RT5682_ADC_OSR_D_4; + } else { + osr_p = RT5682_DAC_OSR_D_2; + osr_c = RT5682_ADC_OSR_D_2; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK, + RT5682_SDW_REF_1_MASK, val_p); + regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1, + RT5682_DAC_OSR_MASK, osr_p); + } else { + regmap_update_bits(rt5682->regmap, RT5682_SDW_REF_CLK, + RT5682_SDW_REF_2_MASK, val_c); + regmap_update_bits(rt5682->regmap, RT5682_ADDA_CLK_1, + RT5682_ADC_OSR_MASK, osr_c); + } + + return retval; +} + +static int rt5682_sdw_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + struct sdw_stream_data *stream = + snd_soc_dai_get_dma_data(dai, substream); + + if (!rt5682->slave) + return -EINVAL; + + sdw_stream_remove_slave(rt5682->slave, stream->sdw_stream); + return 0; +} + +static struct snd_soc_dai_ops rt5682_sdw_ops = { + .hw_params = rt5682_sdw_hw_params, + .hw_free = rt5682_sdw_hw_free, + .set_sdw_stream = rt5682_set_sdw_stream, + .shutdown = rt5682_sdw_shutdown, +}; +#endif + static struct snd_soc_dai_driver rt5682_dai[] = { { .name = "rt5682-aif1", @@ -2946,6 +3158,27 @@ static struct snd_soc_dai_driver rt5682_dai[] = { }, .ops = &rt5682_aif2_dai_ops, }, +#if IS_ENABLED(CONFIG_SND_SOC_RT5682_SDW) + { + .name = "rt5682-sdw", + .id = RT5682_SDW, + .playback = { + .stream_name = "SDW Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT5682_STEREO_RATES, + .formats = RT5682_FORMATS, + }, + .capture = { + .stream_name = "SDW Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT5682_STEREO_RATES, + .formats = RT5682_FORMATS, + }, + .ops = &rt5682_sdw_ops, + }, +#endif }; static const struct snd_soc_component_driver soc_component_dev_rt5682 = { @@ -3064,6 +3297,219 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682) } +#if IS_ENABLED(CONFIG_SND_SOC_RT5682_SDW) +static int rt5682_sdw_read(void *context, unsigned int reg, unsigned int *val) +{ + struct device *dev = context; + struct rt5682_priv *rt5682 = dev_get_drvdata(dev); + unsigned int data_l, data_h; + + regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 0); + regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff); + regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff)); + regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_H, &data_h); + regmap_read(rt5682->sdw_regmap, RT5682_SDW_DATA_L, &data_l); + + *val = (data_h << 8) | data_l; + + dev_vdbg(dev, "[%s] %04x => %04x\n", __func__, reg, *val); + + return 0; +} + +static int rt5682_sdw_write(void *context, unsigned int reg, unsigned int val) +{ + struct device *dev = context; + struct rt5682_priv *rt5682 = dev_get_drvdata(dev); + + regmap_write(rt5682->sdw_regmap, RT5682_SDW_CMD, 1); + regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_H, (reg >> 8) & 0xff); + regmap_write(rt5682->sdw_regmap, RT5682_SDW_ADDR_L, (reg & 0xff)); + regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_H, (val >> 8) & 0xff); + regmap_write(rt5682->sdw_regmap, RT5682_SDW_DATA_L, (val & 0xff)); + + dev_vdbg(dev, "[%s] %04x <= %04x\n", __func__, reg, val); + + return 0; +} + +static const struct regmap_config rt5682_sdw_regmap = { + .reg_bits = 16, + .val_bits = 16, + .max_register = RT5682_I2C_MODE, + .volatile_reg = rt5682_volatile_register, + .readable_reg = rt5682_readable_register, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = rt5682_reg, + .num_reg_defaults = ARRAY_SIZE(rt5682_reg), + .use_single_read = true, + .use_single_write = true, + .reg_read = rt5682_sdw_read, + .reg_write = rt5682_sdw_write, +}; + +int rt5682_sdw_init(struct device *dev, struct regmap *regmap, + struct sdw_slave *slave) +{ + struct rt5682_priv *rt5682; + int ret; + + rt5682 = devm_kzalloc(dev, sizeof(*rt5682), GFP_KERNEL); + if (!rt5682) + return -ENOMEM; + + dev_set_drvdata(dev, rt5682); + rt5682->slave = slave; + rt5682->sdw_regmap = regmap; + rt5682->is_sdw = true; + + rt5682->regmap = devm_regmap_init(dev, NULL, dev, &rt5682_sdw_regmap); + if (IS_ERR(rt5682->regmap)) { + ret = PTR_ERR(rt5682->regmap); + dev_err(dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + /* + * Mark hw_init to false + * HW init will be performed when device reports present + */ + rt5682->hw_init = false; + rt5682->first_hw_init = false; + + mutex_init(&rt5682->calibrate_mutex); + INIT_DELAYED_WORK(&rt5682->jack_detect_work, + rt5682_jack_detect_handler); + + ret = devm_snd_soc_register_component(dev, &soc_component_dev_rt5682, + rt5682_dai, ARRAY_SIZE(rt5682_dai)); + + dev_dbg(&slave->dev, "%s\n", __func__); + + return ret; +} +EXPORT_SYMBOL_GPL(rt5682_sdw_init); + +int rt5682_io_init(struct device *dev, struct sdw_slave *slave) +{ + struct rt5682_priv *rt5682 = dev_get_drvdata(dev); + int ret = 0; + unsigned int val; + + if (rt5682->hw_init) + return 0; + + regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val); + if (val != DEVICE_ID) { + pr_err("Device with ID register %x is not rt5682\n", val); + return -ENODEV; + } + + /* + * PM runtime is only enabled when a Slave reports as Attached + */ + if (!rt5682->first_hw_init) { + /* set autosuspend parameters */ + pm_runtime_set_autosuspend_delay(&slave->dev, 3000); + pm_runtime_use_autosuspend(&slave->dev); + + /* update count of parent 'active' children */ + pm_runtime_set_active(&slave->dev); + + /* make sure the device does not suspend immediately */ + pm_runtime_mark_last_busy(&slave->dev); + + pm_runtime_enable(&slave->dev); + } + + pm_runtime_get_noresume(&slave->dev); + + rt5682_reset(rt5682); + + if (rt5682->first_hw_init) { + regcache_cache_only(rt5682->regmap, false); + regcache_cache_bypass(rt5682->regmap, true); + } + + rt5682_calibrate(rt5682); + + if (rt5682->first_hw_init) { + regcache_cache_bypass(rt5682->regmap, false); + regcache_mark_dirty(rt5682->regmap); + regcache_sync(rt5682->regmap); + + /* volatile registers */ + regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2, + RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL); + + goto reinit; + } + + ret = regmap_multi_reg_write(rt5682->regmap, patch_list, + ARRAY_SIZE(patch_list)); + if (ret != 0) + dev_warn(dev, "Failed to apply regmap patch: %d\n", ret); + + regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0000); + + regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1, + RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK, + RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X); + regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380); + regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000); + regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8, + RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA); + regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1, + RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ); + + /* Soundwire */ + regmap_write(rt5682->regmap, RT5682_PLL2_INTERNAL, 0xa266); + regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_1, 0x1700); + regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_2, 0x0006); + regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_3, 0x2600); + regmap_write(rt5682->regmap, RT5682_PLL2_CTRL_4, 0x0c8f); + regmap_write(rt5682->regmap, RT5682_PLL_TRACK_2, 0x3000); + regmap_write(rt5682->regmap, RT5682_PLL_TRACK_3, 0x4000); + regmap_update_bits(rt5682->regmap, RT5682_GLB_CLK, + RT5682_SCLK_SRC_MASK | RT5682_PLL2_SRC_MASK, + RT5682_SCLK_SRC_PLL2 | RT5682_PLL2_SRC_SDW); + + regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_2, + RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL); + regmap_write(rt5682->regmap, RT5682_CBJ_CTRL_1, 0xd042); + regmap_update_bits(rt5682->regmap, RT5682_CBJ_CTRL_3, + RT5682_CBJ_IN_BUF_EN, RT5682_CBJ_IN_BUF_EN); + regmap_update_bits(rt5682->regmap, RT5682_SAR_IL_CMD_1, + RT5682_SAR_POW_MASK, RT5682_SAR_POW_EN); + regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, + RT5682_POW_IRQ | RT5682_POW_JDH | + RT5682_POW_ANA, RT5682_POW_IRQ | + RT5682_POW_JDH | RT5682_POW_ANA); + regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_2, + RT5682_PWR_JDH, RT5682_PWR_JDH); + regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, + RT5682_JD1_EN_MASK | RT5682_JD1_IRQ_MASK, + RT5682_JD1_EN | RT5682_JD1_IRQ_PUL); + +reinit: + mod_delayed_work(system_power_efficient_wq, + &rt5682->jack_detect_work, msecs_to_jiffies(250)); + + /* Mark Slave initialization complete */ + rt5682->hw_init = true; + rt5682->first_hw_init = true; + + pm_runtime_mark_last_busy(&slave->dev); + pm_runtime_put_autosuspend(&slave->dev); + + dev_dbg(&slave->dev, "%s hw_init complete\n", __func__); + + return ret; +} +EXPORT_SYMBOL_GPL(rt5682_io_init); +#endif + static int rt5682_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h index f82126a6f211..43de6e802309 100644 --- a/sound/soc/codecs/rt5682.h +++ b/sound/soc/codecs/rt5682.h @@ -10,6 +10,12 @@ #define __RT5682_H__ #include +#include +#include +#include +#include +#include +#include #define DEVICE_ID 0x6530 @@ -1355,6 +1361,7 @@ enum { enum { RT5682_AIF1, RT5682_AIF2, + RT5682_SDW, RT5682_AIFS }; @@ -1370,7 +1377,49 @@ enum { RT5682_CLK_SEL_I2S2_ASRC, }; +#define RT5682_NUM_SUPPLIES 3 + +struct rt5682_priv { + struct snd_soc_component *component; + struct rt5682_platform_data pdata; + struct regmap *regmap; + struct regmap *sdw_regmap; + struct snd_soc_jack *hs_jack; + struct regulator_bulk_data supplies[RT5682_NUM_SUPPLIES]; + struct delayed_work jack_detect_work; + struct delayed_work jd_check_work; + struct mutex calibrate_mutex; + struct sdw_slave *slave; + enum sdw_slave_status status; + struct sdw_bus_params params; + bool hw_init; + bool first_hw_init; + bool is_sdw; + +#ifdef CONFIG_COMMON_CLK + struct clk_hw dai_clks_hw[RT5682_DAI_NUM_CLKS]; + struct clk_lookup *dai_clks_lookup[RT5682_DAI_NUM_CLKS]; + struct clk *dai_clks[RT5682_DAI_NUM_CLKS]; + struct clk *mclk; +#endif + + int sysclk; + int sysclk_src; + int lrck[RT5682_AIFS]; + int bclk[RT5682_AIFS]; + int master[RT5682_AIFS]; + + int pll_src[RT5682_PLLS]; + int pll_in[RT5682_PLLS]; + int pll_out[RT5682_PLLS]; + + int jack_type; +}; + int rt5682_sel_asrc_clk_src(struct snd_soc_component *component, unsigned int filter_mask, unsigned int clk_src); +int rt5682_sdw_init(struct device *dev, struct regmap *regmap, + struct sdw_slave *slave); +int rt5682_io_init(struct device *dev, struct sdw_slave *slave); #endif /* __RT5682_H__ */ From b2d48dde38d373487503fd36cda05f17c1183b6d Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Wed, 19 Feb 2020 18:28:58 +0800 Subject: [PATCH 0853/4444] ASoC: rt5682: Revise the function name This patch revises the function name. Signed-off-by: Oder Chiou Link: https://lore.kernel.org/r/20200219102858.20166-2-oder_chiou@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 1795a8bbea1a..e1df2d076533 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -1554,7 +1554,7 @@ static int set_dmic_power(struct snd_soc_dapm_widget *w, return 0; } -static int rt5655_set_verf(struct snd_soc_dapm_widget *w, +static int rt5682_set_verf(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = @@ -1632,7 +1632,7 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("PLL2F", RT5682_PWR_ANLG_3, RT5682_PWR_PLL2F_BIT, 0, set_filter_clk, SND_SOC_DAPM_PRE_PMU), SND_SOC_DAPM_SUPPLY("Vref1", RT5682_PWR_ANLG_1, RT5682_PWR_VREF1_BIT, 0, - rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), + rt5682_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_SUPPLY("Vref2", RT5682_PWR_ANLG_1, RT5682_PWR_VREF2_BIT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, NULL, 0), From 911abf8b050e76591479d35c928f7e72605067ac Mon Sep 17 00:00:00 2001 From: Akshu Agrawal Date: Wed, 26 Feb 2020 16:17:44 +0530 Subject: [PATCH 0854/4444] ASoC: amd: Allow I2S wake event after ACP is powerd On ACP_PME_EN allows wake interrupt to be generated when I2S wake feature is enabled. On turning ACP On, ACP_PME_EN gets cleared. Setting the bit back ensures that wake event can be received when ACP is On. Signed-off-by: Akshu Agrawal Link: https://lore.kernel.org/r/20200226104746.208656-1-akshu.agrawal@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/raven/pci-acp3x.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c index da60e2ec5535..f25ce50f1a90 100644 --- a/sound/soc/amd/raven/pci-acp3x.c +++ b/sound/soc/amd/raven/pci-acp3x.c @@ -38,8 +38,13 @@ static int acp3x_power_on(void __iomem *acp3x_base) timeout = 0; while (++timeout < 500) { val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS); - if (!val) + if (!val) { + /* Set PME_EN as after ACP power On, + * PME_EN gets cleared + */ + rv_writel(0x1, acp3x_base + mmACP_PME_EN); return 0; + } udelay(1); } return -ETIMEDOUT; From f87cdb1f9937e6f5234e3300804ac156e639bc00 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Wed, 26 Feb 2020 07:03:03 -0600 Subject: [PATCH 0855/4444] ASoC: dt-bindings: Add TAS2563 compatible to the TAS2562 binding Add the Texas Instruments TAS2563 audio amplifier to the TAS262 binding. Signed-off-by: Dan Murphy CC: Rob Herring Link: https://lore.kernel.org/r/20200226130305.12043-1-dmurphy@ti.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/tas2562.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/tas2562.txt b/Documentation/devicetree/bindings/sound/tas2562.txt index 658e1fb18a99..94796b547184 100644 --- a/Documentation/devicetree/bindings/sound/tas2562.txt +++ b/Documentation/devicetree/bindings/sound/tas2562.txt @@ -8,7 +8,7 @@ real time monitoring of loudspeaker behavior. Required properties: - #address-cells - Should be <1>. - #size-cells - Should be <0>. - - compatible: - Should contain "ti,tas2562". + - compatible: - Should contain "ti,tas2562", "ti,tas2563". - reg: - The i2c address. Should be 0x4c, 0x4d, 0x4e or 0x4f. - ti,imon-slot-no:- TDM TX current sense time slot. From 14f8c8d8fd62207f081549d45099a90dd3717696 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Wed, 26 Feb 2020 07:03:04 -0600 Subject: [PATCH 0856/4444] ASoC: tas2562: Add entries for the TAS2563 audio amplifier The TAS2563 is register compatible with the TAS2562. The main difference is the TAS2563 has a programmable DSP to manage different audio profiles. Signed-off-by: Dan Murphy Link: https://lore.kernel.org/r/20200226130305.12043-2-dmurphy@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2562.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c index d5e04030a0c1..79c3c3d79766 100644 --- a/sound/soc/codecs/tas2562.c +++ b/sound/soc/codecs/tas2562.c @@ -55,6 +55,11 @@ struct tas2562_data { int volume_lvl; }; +enum tas256x_model { + TAS2562, + TAS2563, +}; + static int tas2562_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { @@ -664,13 +669,15 @@ static int tas2562_probe(struct i2c_client *client, } static const struct i2c_device_id tas2562_id[] = { - { "tas2562", 0 }, + { "tas2562", TAS2562 }, + { "tas2563", TAS2563 }, { } }; MODULE_DEVICE_TABLE(i2c, tas2562_id); static const struct of_device_id tas2562_of_match[] = { { .compatible = "ti,tas2562", }, + { .compatible = "ti,tas2563", }, { }, }; MODULE_DEVICE_TABLE(of, tas2562_of_match); From 91bf0eee413733ac7975d1f4df64d5bc86d428a0 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 25 Feb 2020 12:40:17 +0100 Subject: [PATCH 0857/4444] ARM: dts: exynos: Fix memory on Artik5 evaluation boards The last 8MB of physical memory on Artik520 family boards is reserved for secure firmware. Adjust the total amount of the memory defined in exynos3250-artik5.dtsi to match the memory available for the Linux kernel. Signed-off-by: Marek Szyprowski Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos3250-artik5.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/exynos3250-artik5.dtsi b/arch/arm/boot/dts/exynos3250-artik5.dtsi index dee35e3a5c4b..b27a82072365 100644 --- a/arch/arm/boot/dts/exynos3250-artik5.dtsi +++ b/arch/arm/boot/dts/exynos3250-artik5.dtsi @@ -23,7 +23,7 @@ memory@40000000 { device_type = "memory"; - reg = <0x40000000 0x1ff00000>; + reg = <0x40000000 0x1f800000>; }; firmware@205f000 { From cc9c077f6afe1c0e28bb33675bc7298db3a721d7 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 22 Jan 2020 23:37:49 +0000 Subject: [PATCH 0858/4444] leds: lm3697: fix spelling mistake "To" -> "Too" There is a spelling mistake in a dev_err message. Fix it. Signed-off-by: Colin Ian King Signed-off-by: Pavel Machek --- drivers/leds/leds-lm3697.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-lm3697.c b/drivers/leds/leds-lm3697.c index b71711aff8a3..872d26f9706a 100644 --- a/drivers/leds/leds-lm3697.c +++ b/drivers/leds/leds-lm3697.c @@ -246,7 +246,7 @@ static int lm3697_probe_dt(struct lm3697 *priv) led->num_leds = fwnode_property_count_u32(child, "led-sources"); if (led->num_leds > LM3697_MAX_LED_STRINGS) { - dev_err(&priv->client->dev, "To many LED strings defined\n"); + dev_err(&priv->client->dev, "Too many LED strings defined\n"); continue; } From 64d7e23115dd91997858eb0c370d798a0d6bf118 Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Mon, 24 Feb 2020 12:17:33 +0100 Subject: [PATCH 0859/4444] leds: add SGI IP30 led support This patch implemenets a driver to support the front panel LEDs of SGI Octane (IP30) workstations. Reviewed-by: Dan Murphy Signed-off-by: Thomas Bogendoerfer Acked-by: Jacek Anaszewski Signed-off-by: Pavel Machek --- drivers/leds/Kconfig | 11 +++++ drivers/leds/Makefile | 1 + drivers/leds/leds-ip30.c | 86 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 drivers/leds/leds-ip30.c diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index d82f1dea3711..c664d84e1667 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -846,6 +846,17 @@ config LEDS_TPS6105X It is a single boost converter primarily for white LEDs and audio amplifiers. +config LEDS_IP30 + tristate "LED support for SGI Octane machines" + depends on LEDS_CLASS + depends on SGI_MFD_IOC3 + help + This option enables support for the Red and White LEDs of + SGI Octane machines. + + To compile this driver as a module, choose M here: the module + will be called leds-ip30. + comment "LED Triggers" source "drivers/leds/trigger/Kconfig" diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index d7e1107753fb..46bd611a03a9 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -86,6 +86,7 @@ obj-$(CONFIG_LEDS_TI_LMU_COMMON) += leds-ti-lmu-common.o obj-$(CONFIG_LEDS_LM3697) += leds-lm3697.o obj-$(CONFIG_LEDS_LM36274) += leds-lm36274.o obj-$(CONFIG_LEDS_TPS6105X) += leds-tps6105x.o +obj-$(CONFIG_LEDS_IP30) += leds-ip30.o # LED SPI Drivers obj-$(CONFIG_LEDS_CR0014114) += leds-cr0014114.o diff --git a/drivers/leds/leds-ip30.c b/drivers/leds/leds-ip30.c new file mode 100644 index 000000000000..e95ea786a43e --- /dev/null +++ b/drivers/leds/leds-ip30.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * LED Driver for SGI Octane machines + */ + +#include +#include +#include +#include + +#define IP30_LED_SYSTEM 0 +#define IP30_LED_FAULT 1 + +struct ip30_led { + struct led_classdev cdev; + u32 __iomem *reg; +}; + +static void ip30led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct ip30_led *led = container_of(led_cdev, struct ip30_led, cdev); + + writel(value, led->reg); +} + +static int ip30led_create(struct platform_device *pdev, int num) +{ + struct resource *res; + struct ip30_led *data; + + res = platform_get_resource(pdev, IORESOURCE_MEM, num); + if (!res) + return -EBUSY; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->reg = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(data->reg)) + return PTR_ERR(data->reg); + + + switch (num) { + case IP30_LED_SYSTEM: + data->cdev.name = "white:system"; + break; + case IP30_LED_FAULT: + data->cdev.name = "red:fault"; + break; + default: + return -EINVAL; + } + + data->cdev.brightness = readl(data->reg); + data->cdev.max_brightness = 1; + data->cdev.brightness_set = ip30led_set; + + return devm_led_classdev_register(&pdev->dev, &data->cdev); +} + +static int ip30led_probe(struct platform_device *pdev) +{ + int ret; + + ret = ip30led_create(pdev, IP30_LED_SYSTEM); + if (ret < 0) + return ret; + + return ip30led_create(pdev, IP30_LED_FAULT); +} + +static struct platform_driver ip30led_driver = { + .probe = ip30led_probe, + .driver = { + .name = "ip30-leds", + }, +}; + +module_platform_driver(ip30led_driver); + +MODULE_AUTHOR("Thomas Bogendoerfer "); +MODULE_DESCRIPTION("SGI Octane LED driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:ip30-leds"); From b43a8f01fccbfdddbc7f9b2bbad11b7db3fda4e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 24 Jan 2020 17:54:07 +0100 Subject: [PATCH 0860/4444] leds: pwm: simplify if condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .pwm_period_ns is an unsigned integer. So when led->pwm_period_ns > 0 is false, we now assign 0 to a value that is already 0, so it doesn't hurt and we can skip checking the actual value. Signed-off-by: Uwe Kleine-König Tested-by: Jeff LaBundy Signed-off-by: Pavel Machek --- drivers/leds/leds-pwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index 8b6965a563e9..b72fd89ff390 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -102,7 +102,7 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, pwm_get_args(led_data->pwm, &pargs); led_data->period = pargs.period; - if (!led_data->period && (led->pwm_period_ns > 0)) + if (!led_data->period) led_data->period = led->pwm_period_ns; ret = devm_led_classdev_register(dev, &led_data->cdev); From dd47a83453e4a5b0d6a91fe702b7fbc1984fb610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 24 Jan 2020 17:54:08 +0100 Subject: [PATCH 0861/4444] leds: pwm: convert to atomic PWM API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pwm_config(), pwm_enable() and pwm_disable() should get removed in the long run. So update the driver to use the atomic API that is here to stay. A few side effects: - led_pwm_set() now returns an error when setting the PWM fails. - During .probe() the PWM isn't disabled implicitly by pwm_apply_args() any more. Signed-off-by: Uwe Kleine-König Tested-by: Jeff LaBundy Signed-off-by: Pavel Machek --- drivers/leds/leds-pwm.c | 41 +++++++++-------------------------------- 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index b72fd89ff390..9111cdede0ee 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -22,9 +22,8 @@ struct led_pwm_data { struct led_classdev cdev; struct pwm_device *pwm; + struct pwm_state pwmstate; unsigned int active_low; - unsigned int period; - int duty; }; struct led_pwm_priv { @@ -32,44 +31,29 @@ struct led_pwm_priv { struct led_pwm_data leds[0]; }; -static void __led_pwm_set(struct led_pwm_data *led_dat) -{ - int new_duty = led_dat->duty; - - pwm_config(led_dat->pwm, new_duty, led_dat->period); - - if (new_duty == 0) - pwm_disable(led_dat->pwm); - else - pwm_enable(led_dat->pwm); -} - static int led_pwm_set(struct led_classdev *led_cdev, enum led_brightness brightness) { struct led_pwm_data *led_dat = container_of(led_cdev, struct led_pwm_data, cdev); unsigned int max = led_dat->cdev.max_brightness; - unsigned long long duty = led_dat->period; + unsigned long long duty = led_dat->pwmstate.period; duty *= brightness; do_div(duty, max); if (led_dat->active_low) - duty = led_dat->period - duty; + duty = led_dat->pwmstate.period - duty; - led_dat->duty = duty; - - __led_pwm_set(led_dat); - - return 0; + led_dat->pwmstate.duty_cycle = duty; + led_dat->pwmstate.enabled = duty > 0; + return pwm_apply_state(led_dat->pwm, &led_dat->pwmstate); } static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, struct led_pwm *led, struct fwnode_handle *fwnode) { struct led_pwm_data *led_data = &priv->leds[priv->num_leds]; - struct pwm_args pargs; int ret; led_data->active_low = led->active_low; @@ -93,17 +77,10 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, led_data->cdev.brightness_set_blocking = led_pwm_set; - /* - * FIXME: pwm_apply_args() should be removed when switching to the - * atomic PWM API. - */ - pwm_apply_args(led_data->pwm); + pwm_init_state(led_data->pwm, &led_data->pwmstate); - pwm_get_args(led_data->pwm, &pargs); - - led_data->period = pargs.period; - if (!led_data->period) - led_data->period = led->pwm_period_ns; + if (!led_data->pwmstate.period) + led_data->pwmstate.period = led->pwm_period_ns; ret = devm_led_classdev_register(dev, &led_data->cdev); if (ret == 0) { From 4dcd55fd703183fe64c570c53cd7f8c9177f879c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Feb 2020 15:04:33 +0900 Subject: [PATCH 0862/4444] dt-bindings: arm: Convert UniPhier board/SoC bindings to json-schema Convert the Socionext UniPhier board/SoC binding to DT schema format. Signed-off-by: Masahiro Yamada Signed-off-by: Rob Herring --- .../bindings/arm/socionext/uniphier.txt | 47 -------------- .../bindings/arm/socionext/uniphier.yaml | 61 +++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 62 insertions(+), 48 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/socionext/uniphier.txt create mode 100644 Documentation/devicetree/bindings/arm/socionext/uniphier.yaml diff --git a/Documentation/devicetree/bindings/arm/socionext/uniphier.txt b/Documentation/devicetree/bindings/arm/socionext/uniphier.txt deleted file mode 100644 index b3ed1033740e..000000000000 --- a/Documentation/devicetree/bindings/arm/socionext/uniphier.txt +++ /dev/null @@ -1,47 +0,0 @@ -Socionext UniPhier SoC family ------------------------------ - -Required properties in the root node: - - compatible: should contain board and SoC compatible strings - -SoC and board compatible strings: - (sorted chronologically) - - - LD4 SoC: "socionext,uniphier-ld4" - - Reference Board: "socionext,uniphier-ld4-ref" - - - Pro4 SoC: "socionext,uniphier-pro4" - - Reference Board: "socionext,uniphier-pro4-ref" - - Ace Board: "socionext,uniphier-pro4-ace" - - Sanji Board: "socionext,uniphier-pro4-sanji" - - - sLD8 SoC: "socionext,uniphier-sld8" - - Reference Board: "socionext,uniphier-sld8-ref" - - - PXs2 SoC: "socionext,uniphier-pxs2" - - Gentil Board: "socionext,uniphier-pxs2-gentil" - - Vodka Board: "socionext,uniphier-pxs2-vodka" - - - LD6b SoC: "socionext,uniphier-ld6b" - - Reference Board: "socionext,uniphier-ld6b-ref" - - - LD11 SoC: "socionext,uniphier-ld11" - - Reference Board: "socionext,uniphier-ld11-ref" - - Global Board: "socionext,uniphier-ld11-global" - - - LD20 SoC: "socionext,uniphier-ld20" - - Reference Board: "socionext,uniphier-ld20-ref" - - Global Board: "socionext,uniphier-ld20-global" - - - PXs3 SoC: "socionext,uniphier-pxs3" - - Reference Board: "socionext,uniphier-pxs3-ref" - -Example: - -/dts-v1/; - -/ { - compatible = "socionext,uniphier-ld20-ref", "socionext,uniphier-ld20"; - - ... -}; diff --git a/Documentation/devicetree/bindings/arm/socionext/uniphier.yaml b/Documentation/devicetree/bindings/arm/socionext/uniphier.yaml new file mode 100644 index 000000000000..65ad6d8a3c99 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/socionext/uniphier.yaml @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/socionext/uniphier.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Socionext UniPhier platform device tree bindings + +maintainers: + - Masahiro Yamada + +properties: + $nodename: + const: / + compatible: + oneOf: + - description: LD4 SoC boards + items: + - enum: + - socionext,uniphier-ld4-ref + - const: socionext,uniphier-ld4 + - description: Pro4 SoC boards + items: + - enum: + - socionext,uniphier-pro4-ace + - socionext,uniphier-pro4-ref + - socionext,uniphier-pro4-sanji + - const: socionext,uniphier-pro4 + - description: sLD8 SoC boards + items: + - enum: + - socionext,uniphier-sld8-ref + - const: socionext,uniphier-sld8 + - description: PXs2 SoC boards + items: + - enum: + - socionext,uniphier-pxs2-gentil + - socionext,uniphier-pxs2-vodka + - const: socionext,uniphier-pxs2 + - description: LD6b SoC boards + items: + - enum: + - socionext,uniphier-ld6b-ref + - const: socionext,uniphier-ld6b + - description: LD11 SoC boards + items: + - enum: + - socionext,uniphier-ld11-global + - socionext,uniphier-ld11-ref + - const: socionext,uniphier-ld11 + - description: LD20 SoC boards + items: + - enum: + - socionext,uniphier-ld20-global + - socionext,uniphier-ld20-ref + - const: socionext,uniphier-ld20 + - description: PXs3 SoC boards + items: + - enum: + - socionext,uniphier-pxs3-ref + - const: socionext,uniphier-pxs3 diff --git a/MAINTAINERS b/MAINTAINERS index 8044aa190bcb..67402bb4cdc4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2546,7 +2546,7 @@ M: Masahiro Yamada L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) T: git git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-uniphier.git S: Maintained -F: Documentation/devicetree/bindings/arm/socionext/uniphier.txt +F: Documentation/devicetree/bindings/arm/socionext/uniphier.yaml F: Documentation/devicetree/bindings/gpio/gpio-uniphier.txt F: Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.txt F: arch/arm/boot/dts/uniphier* From 89099d1432843a7a6bbaac6d33e37365c9fe27ad Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Feb 2020 15:04:34 +0900 Subject: [PATCH 0863/4444] dt-bindings: gpio: Convert UniPhier GPIO to json-schema Convert the UniPhier GPIO controller binding to DT schema format. I omitted the 'gpio-ranges' property because it is defined in the dt-schema project (/schemas/gpio/gpio.yaml). As of writing, the 'gpio-ranges-group-names' is not defined in that file despite it is a common property described in Documentation/devicetree/bindings/gpio/gpio.txt So, I defined it in this schema. Signed-off-by: Masahiro Yamada Signed-off-by: Rob Herring --- .../bindings/gpio/gpio-uniphier.txt | 51 ---------- .../gpio/socionext,uniphier-gpio.yaml | 92 +++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 93 insertions(+), 52 deletions(-) delete mode 100644 Documentation/devicetree/bindings/gpio/gpio-uniphier.txt create mode 100644 Documentation/devicetree/bindings/gpio/socionext,uniphier-gpio.yaml diff --git a/Documentation/devicetree/bindings/gpio/gpio-uniphier.txt b/Documentation/devicetree/bindings/gpio/gpio-uniphier.txt deleted file mode 100644 index f281f12dac18..000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-uniphier.txt +++ /dev/null @@ -1,51 +0,0 @@ -UniPhier GPIO controller - -Required properties: -- compatible: Should be "socionext,uniphier-gpio". -- reg: Specifies offset and length of the register set for the device. -- gpio-controller: Marks the device node as a GPIO controller. -- #gpio-cells: Should be 2. The first cell is the pin number and the second - cell is used to specify optional parameters. -- interrupt-controller: Marks the device node as an interrupt controller. -- #interrupt-cells: Should be 2. The first cell defines the interrupt number. - The second cell bits[3:0] is used to specify trigger type as follows: - 1 = low-to-high edge triggered - 2 = high-to-low edge triggered - 4 = active high level-sensitive - 8 = active low level-sensitive - Valid combinations are 1, 2, 3, 4, 8. -- ngpios: Specifies the number of GPIO lines. -- gpio-ranges: Mapping to pin controller pins (as described in gpio.txt) -- socionext,interrupt-ranges: Specifies an interrupt number mapping between - this GPIO controller and its interrupt parent, in the form of arbitrary - number of triplets. - -Optional properties: -- gpio-ranges-group-names: Used for named gpio ranges (as described in gpio.txt) - -Example: - gpio: gpio@55000000 { - compatible = "socionext,uniphier-gpio"; - reg = <0x55000000 0x200>; - interrupt-parent = <&aidet>; - interrupt-controller; - #interrupt-cells = <2>; - gpio-controller; - #gpio-cells = <2>; - gpio-ranges = <&pinctrl 0 0 0>; - gpio-ranges-group-names = "gpio_range"; - ngpios = <248>; - socionext,interrupt-ranges = <0 48 16>, <16 154 5>, <21 217 3>; - }; - -Consumer Example: - - sdhci0_pwrseq { - compatible = "mmc-pwrseq-emmc"; - reset-gpios = <&gpio UNIPHIER_GPIO_PORT(29, 4) GPIO_ACTIVE_LOW>; - }; - -Please note UNIPHIER_GPIO_PORT(29, 4) represents PORT294 in the SoC document. -Unfortunately, only the one's place is octal in the port numbering. (That is, -PORT 8, 9, 18, 19, 28, 29, ... are missing.) UNIPHIER_GPIO_PORT() is a helper -macro to calculate 29 * 8 + 4. diff --git a/Documentation/devicetree/bindings/gpio/socionext,uniphier-gpio.yaml b/Documentation/devicetree/bindings/gpio/socionext,uniphier-gpio.yaml new file mode 100644 index 000000000000..580a39e09d39 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/socionext,uniphier-gpio.yaml @@ -0,0 +1,92 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/socionext,uniphier-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: UniPhier GPIO controller + +maintainers: + - Masahiro Yamada + +properties: + $nodename: + pattern: "^gpio@[0-9a-f]+$" + + compatible: + const: socionext,uniphier-gpio + + reg: + maxItems: 1 + + gpio-controller: true + + "#gpio-cells": + const: 2 + + interrupt-controller: true + + "#interrupt-cells": + description: | + The first cell defines the interrupt number. + The second cell bits[3:0] is used to specify trigger type as follows: + 1 = low-to-high edge triggered + 2 = high-to-low edge triggered + 4 = active high level-sensitive + 8 = active low level-sensitive + Valid combinations are 1, 2, 3, 4, 8. + const: 2 + + ngpios: + minimum: 0 + maximum: 512 + + gpio-ranges-group-names: + $ref: /schemas/types.yaml#/definitions/string-array + + socionext,interrupt-ranges: + description: | + Specifies an interrupt number mapping between this GPIO controller and + its interrupt parent, in the form of arbitrary number of + triplets. + $ref: /schemas/types.yaml#/definitions/uint32-matrix + +required: + - compatible + - reg + - gpio-controller + - "#gpio-cells" + - interrupt-controller + - "#interrupt-cells" + - ngpios + - gpio-ranges + - socionext,interrupt-ranges + +examples: + - | + #include + #include + + gpio: gpio@55000000 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000000 0x200>; + interrupt-parent = <&aidet>; + interrupt-controller; + #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pinctrl 0 0 0>; + gpio-ranges-group-names = "gpio_range"; + ngpios = <248>; + socionext,interrupt-ranges = <0 48 16>, <16 154 5>, <21 217 3>; + }; + + // Consumer: + // Please note UNIPHIER_GPIO_PORT(29, 4) represents PORT294 in the SoC + // document. Unfortunately, only the one's place is octal in the port + // numbering. (That is, PORT 8, 9, 18, 19, 28, 29, ... do not exist.) + // UNIPHIER_GPIO_PORT() is a helper macro to calculate 29 * 8 + 4. + sdhci0_pwrseq { + compatible = "mmc-pwrseq-emmc"; + reset-gpios = <&gpio UNIPHIER_GPIO_PORT(29, 4) GPIO_ACTIVE_LOW>; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 67402bb4cdc4..56fe62c1b1f5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2547,7 +2547,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) T: git git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-uniphier.git S: Maintained F: Documentation/devicetree/bindings/arm/socionext/uniphier.yaml -F: Documentation/devicetree/bindings/gpio/gpio-uniphier.txt +F: Documentation/devicetree/bindings/gpio/socionext,uniphier-gpio.yaml F: Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.txt F: arch/arm/boot/dts/uniphier* F: arch/arm/include/asm/hardware/cache-uniphier.h From 849b10446bf939eba3d8955c89c4433f8529248e Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Feb 2020 15:04:35 +0900 Subject: [PATCH 0864/4444] dt-bindings: pinctrl: Convert UniPhier pin controller to json-schema Convert the UniPhier pin controller binding to DT schema format. Signed-off-by: Masahiro Yamada Signed-off-by: Rob Herring --- .../pinctrl/socionext,uniphier-pinctrl.txt | 27 ------------ .../pinctrl/socionext,uniphier-pinctrl.yaml | 42 +++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 43 insertions(+), 28 deletions(-) delete mode 100644 Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.txt create mode 100644 Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.txt deleted file mode 100644 index 8173b12138ad..000000000000 --- a/Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.txt +++ /dev/null @@ -1,27 +0,0 @@ -UniPhier SoCs pin controller - -Required properties: -- compatible: should be one of the following: - "socionext,uniphier-ld4-pinctrl" - for LD4 SoC - "socionext,uniphier-pro4-pinctrl" - for Pro4 SoC - "socionext,uniphier-sld8-pinctrl" - for sLD8 SoC - "socionext,uniphier-pro5-pinctrl" - for Pro5 SoC - "socionext,uniphier-pxs2-pinctrl" - for PXs2 SoC - "socionext,uniphier-ld6b-pinctrl" - for LD6b SoC - "socionext,uniphier-ld11-pinctrl" - for LD11 SoC - "socionext,uniphier-ld20-pinctrl" - for LD20 SoC - "socionext,uniphier-pxs3-pinctrl" - for PXs3 SoC - -Note: -The UniPhier pinctrl should be a subnode of a "syscon" compatible node. - -Example: - soc-glue@5f800000 { - compatible = "socionext,uniphier-pro4-soc-glue", - "simple-mfd", "syscon"; - reg = <0x5f800000 0x2000>; - - pinctrl: pinctrl { - compatible = "socionext,uniphier-pro4-pinctrl"; - }; - }; diff --git a/Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.yaml new file mode 100644 index 000000000000..f8a93d8680f9 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.yaml @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/socionext,uniphier-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: UniPhier SoCs pin controller + +maintainers: + - Masahiro Yamada + +properties: + $nodename: + pattern: "pinctrl" + + compatible: + enum: + - socionext,uniphier-ld4-pinctrl + - socionext,uniphier-pro4-pinctrl + - socionext,uniphier-sld8-pinctrl + - socionext,uniphier-pro5-pinctrl + - socionext,uniphier-pxs2-pinctrl + - socionext,uniphier-ld6b-pinctrl + - socionext,uniphier-ld11-pinctrl + - socionext,uniphier-ld20-pinctrl + - socionext,uniphier-pxs3-pinctrl + +required: + - compatible + +examples: + - | + // The UniPhier pinctrl should be a subnode of a "syscon" compatible node. + + soc-glue@5f800000 { + compatible = "socionext,uniphier-pro4-soc-glue", "simple-mfd", "syscon"; + reg = <0x5f800000 0x2000>; + + pinctrl: pinctrl { + compatible = "socionext,uniphier-pro4-pinctrl"; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 56fe62c1b1f5..c3800f3b5e6e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2548,7 +2548,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-uniphier.gi S: Maintained F: Documentation/devicetree/bindings/arm/socionext/uniphier.yaml F: Documentation/devicetree/bindings/gpio/socionext,uniphier-gpio.yaml -F: Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.txt +F: Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.yaml F: arch/arm/boot/dts/uniphier* F: arch/arm/include/asm/hardware/cache-uniphier.h F: arch/arm/mach-uniphier/ From 7f44205eb28ce1e7df947a3a2acd7da678c62940 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Feb 2020 15:11:09 +0900 Subject: [PATCH 0865/4444] dt-bindings: bus: Convert UniPhier System Bus to json-schema Convert the UniPhier System Bus controller binding to DT schema format. Signed-off-by: Masahiro Yamada Signed-off-by: Rob Herring --- .../bus/socionext,uniphier-system-bus.yaml | 96 +++++++++++++++++++ .../bindings/bus/uniphier-system-bus.txt | 66 ------------- 2 files changed, 96 insertions(+), 66 deletions(-) create mode 100644 Documentation/devicetree/bindings/bus/socionext,uniphier-system-bus.yaml delete mode 100644 Documentation/devicetree/bindings/bus/uniphier-system-bus.txt diff --git a/Documentation/devicetree/bindings/bus/socionext,uniphier-system-bus.yaml b/Documentation/devicetree/bindings/bus/socionext,uniphier-system-bus.yaml new file mode 100644 index 000000000000..ff9600d6de3b --- /dev/null +++ b/Documentation/devicetree/bindings/bus/socionext,uniphier-system-bus.yaml @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bus/socionext,uniphier-system-bus.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: UniPhier System Bus + +description: | + The UniPhier System Bus is an external bus that connects on-board devices to + the UniPhier SoC. It is a simple (semi-)parallel bus with address, data, and + some control signals. It supports up to 8 banks (chip selects). + + Before any access to the bus, the bus controller must be configured; the bus + controller registers provide the control for the translation from the offset + within each bank to the CPU-viewed address. The needed setup includes the + base address, the size of each bank. Optionally, some timing parameters can + be optimized for faster bus access. + +maintainers: + - Masahiro Yamada + +properties: + compatible: + const: socionext,uniphier-system-bus + + reg: + maxItems: 1 + + "#address-cells": + description: | + The first cell is the bank number (chip select). + The second cell is the address offset within the bank. + const: 2 + + "#size-cells": + const: 1 + + ranges: + description: | + Provide address translation from the System Bus to the parent bus. + + Note: + The address region(s) that can be assigned for the System Bus is + implementation defined. Some SoCs can use 0x00000000-0x0fffffff and + 0x40000000-0x4fffffff, while other SoCs only 0x40000000-0x4fffffff. + There might be additional limitations depending on SoCs and the boot mode. + The address translation is arbitrary as long as the banks are assigned in + the supported address space with the required alignment and they do not + overlap one another. + + For example, it is possible to map: + bank 0 to 0x42000000-0x43ffffff, bank 5 to 0x46000000-0x46ffffff + It is also possible to map: + bank 0 to 0x48000000-0x49ffffff, bank 5 to 0x44000000-0x44ffffff + There is no reason to stick to a particular translation mapping, but the + "ranges" property should provide a "reasonable" default that is known to + work. The software should initialize the bus controller according to it. + +required: + - compatible + - reg + - "#address-cells" + - "#size-cells" + - ranges + +examples: + - | + // In this example, + // - the Ethernet device is connected at the offset 0x01f00000 of CS1 and + // mapped to 0x43f00000 of the parent bus. + // - the UART device is connected at the offset 0x00200000 of CS5 and + // mapped to 0x46200000 of the parent bus. + + system-bus { + compatible = "socionext,uniphier-system-bus"; + reg = <0x58c00000 0x400>; + #address-cells = <2>; + #size-cells = <1>; + ranges = <1 0x00000000 0x42000000 0x02000000>, + <5 0x00000000 0x46000000 0x01000000>; + + ethernet@1,01f00000 { + compatible = "smsc,lan9115"; + reg = <1 0x01f00000 0x1000>; + interrupts = <0 48 4>; + phy-mode = "mii"; + }; + + uart@5,00200000 { + compatible = "ns16550a"; + reg = <5 0x00200000 0x20>; + interrupts = <0 49 4>; + clock-frequency = <12288000>; + }; + }; diff --git a/Documentation/devicetree/bindings/bus/uniphier-system-bus.txt b/Documentation/devicetree/bindings/bus/uniphier-system-bus.txt deleted file mode 100644 index 68ef80afff16..000000000000 --- a/Documentation/devicetree/bindings/bus/uniphier-system-bus.txt +++ /dev/null @@ -1,66 +0,0 @@ -UniPhier System Bus - -The UniPhier System Bus is an external bus that connects on-board devices to -the UniPhier SoC. It is a simple (semi-)parallel bus with address, data, and -some control signals. It supports up to 8 banks (chip selects). - -Before any access to the bus, the bus controller must be configured; the bus -controller registers provide the control for the translation from the offset -within each bank to the CPU-viewed address. The needed setup includes the base -address, the size of each bank. Optionally, some timing parameters can be -optimized for faster bus access. - -Required properties: -- compatible: should be "socionext,uniphier-system-bus". -- reg: offset and length of the register set for the bus controller device. -- #address-cells: should be 2. The first cell is the bank number (chip select). - The second cell is the address offset within the bank. -- #size-cells: should be 1. -- ranges: should provide a proper address translation from the System Bus to - the parent bus. - -Note: -The address region(s) that can be assigned for the System Bus is implementation -defined. Some SoCs can use 0x00000000-0x0fffffff and 0x40000000-0x4fffffff, -while other SoCs can only use 0x40000000-0x4fffffff. There might be additional -limitations depending on SoCs and the boot mode. The address translation is -arbitrary as long as the banks are assigned in the supported address space with -the required alignment and they do not overlap one another. -For example, it is possible to map: - bank 0 to 0x42000000-0x43ffffff, bank 5 to 0x46000000-0x46ffffff -It is also possible to map: - bank 0 to 0x48000000-0x49ffffff, bank 5 to 0x44000000-0x44ffffff -There is no reason to stick to a particular translation mapping, but the -"ranges" property should provide a "reasonable" default that is known to work. -The software should initialize the bus controller according to it. - -Example: - - system-bus { - compatible = "socionext,uniphier-system-bus"; - reg = <0x58c00000 0x400>; - #address-cells = <2>; - #size-cells = <1>; - ranges = <1 0x00000000 0x42000000 0x02000000 - 5 0x00000000 0x46000000 0x01000000>; - - ethernet@1,01f00000 { - compatible = "smsc,lan9115"; - reg = <1 0x01f00000 0x1000>; - interrupts = <0 48 4> - phy-mode = "mii"; - }; - - uart@5,00200000 { - compatible = "ns16550a"; - reg = <5 0x00200000 0x20>; - interrupts = <0 49 4> - clock-frequency = <12288000>; - }; - }; - -In this example, - - the Ethernet device is connected at the offset 0x01f00000 of CS1 and - mapped to 0x43f00000 of the parent bus. - - the UART device is connected at the offset 0x00200000 of CS5 and - mapped to 0x46200000 of the parent bus. From 6bb984a3cea02b76d54f2b4bcad7ef0cdca52bc6 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Feb 2020 20:04:35 +0900 Subject: [PATCH 0866/4444] dt-bindings: interrupt-controller: Convert UniPhier AIDET to json-schema Convert the UniPhier AIDET (ARM Interrupt Detector) binding to DT schema format. Signed-off-by: Masahiro Yamada Signed-off-by: Rob Herring --- .../socionext,uniphier-aidet.txt | 32 ---------- .../socionext,uniphier-aidet.yaml | 61 +++++++++++++++++++ 2 files changed, 61 insertions(+), 32 deletions(-) delete mode 100644 Documentation/devicetree/bindings/interrupt-controller/socionext,uniphier-aidet.txt create mode 100644 Documentation/devicetree/bindings/interrupt-controller/socionext,uniphier-aidet.yaml diff --git a/Documentation/devicetree/bindings/interrupt-controller/socionext,uniphier-aidet.txt b/Documentation/devicetree/bindings/interrupt-controller/socionext,uniphier-aidet.txt deleted file mode 100644 index 48e71d3ac2ad..000000000000 --- a/Documentation/devicetree/bindings/interrupt-controller/socionext,uniphier-aidet.txt +++ /dev/null @@ -1,32 +0,0 @@ -UniPhier AIDET - -UniPhier AIDET (ARM Interrupt Detector) is an add-on block for ARM GIC (Generic -Interrupt Controller). GIC itself can handle only high level and rising edge -interrupts. The AIDET provides logic inverter to support low level and falling -edge interrupts. - -Required properties: -- compatible: Should be one of the following: - "socionext,uniphier-ld4-aidet" - for LD4 SoC - "socionext,uniphier-pro4-aidet" - for Pro4 SoC - "socionext,uniphier-sld8-aidet" - for sLD8 SoC - "socionext,uniphier-pro5-aidet" - for Pro5 SoC - "socionext,uniphier-pxs2-aidet" - for PXs2/LD6b SoC - "socionext,uniphier-ld11-aidet" - for LD11 SoC - "socionext,uniphier-ld20-aidet" - for LD20 SoC - "socionext,uniphier-pxs3-aidet" - for PXs3 SoC -- reg: Specifies offset and length of the register set for the device. -- interrupt-controller: Identifies the node as an interrupt controller -- #interrupt-cells : Specifies the number of cells needed to encode an interrupt - source. The value should be 2. The first cell defines the interrupt number - (corresponds to the SPI interrupt number of GIC). The second cell specifies - the trigger type as defined in interrupts.txt in this directory. - -Example: - - aidet: aidet@5fc20000 { - compatible = "socionext,uniphier-pro4-aidet"; - reg = <0x5fc20000 0x200>; - interrupt-controller; - #interrupt-cells = <2>; - }; diff --git a/Documentation/devicetree/bindings/interrupt-controller/socionext,uniphier-aidet.yaml b/Documentation/devicetree/bindings/interrupt-controller/socionext,uniphier-aidet.yaml new file mode 100644 index 000000000000..f89ebde76dab --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/socionext,uniphier-aidet.yaml @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/socionext,uniphier-aidet.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: UniPhier AIDET + +description: | + UniPhier AIDET (ARM Interrupt Detector) is an add-on block for ARM GIC + (Generic Interrupt Controller). GIC itself can handle only high level and + rising edge interrupts. The AIDET provides logic inverter to support low + level and falling edge interrupts. + +maintainers: + - Masahiro Yamada + +allOf: + - $ref: /schemas/interrupt-controller.yaml# + +properties: + compatible: + enum: + - socionext,uniphier-ld4-aidet + - socionext,uniphier-pro4-aidet + - socionext,uniphier-sld8-aidet + - socionext,uniphier-pro5-aidet + - socionext,uniphier-pxs2-aidet + - socionext,uniphier-ld6b-aidet + - socionext,uniphier-ld11-aidet + - socionext,uniphier-ld20-aidet + - socionext,uniphier-pxs3-aidet + + reg: + maxItems: 1 + + interrupt-controller: true + + '#interrupt-cells': + description: | + The first cell defines the interrupt number (corresponds to the SPI + interrupt number of GIC). The second cell specifies the trigger type as + defined in interrupts.txt in this directory. + const: 2 + +required: + - compatible + - reg + - interrupt-controller + - '#interrupt-cells' + +additionalProperties: false + +examples: + - | + interrupt-controller@5fc20000 { + compatible = "socionext,uniphier-pro4-aidet"; + reg = <0x5fc20000 0x200>; + interrupt-controller; + #interrupt-cells = <2>; + }; From 7ebec90559ff772783208c88510632d0ced90da6 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Feb 2020 20:20:42 +0900 Subject: [PATCH 0867/4444] dt-bindings: dma: Convert UniPhier MIO DMA controller to json-schema Convert the UniPhier MIO (Media I/O) DMA controller binding to DT schema format. While I was here, I added the resets property. Signed-off-by: Masahiro Yamada Signed-off-by: Rob Herring --- .../dma/socionext,uniphier-mio-dmac.yaml | 63 +++++++++++++++++++ .../bindings/dma/uniphier-mio-dmac.txt | 25 -------- 2 files changed, 63 insertions(+), 25 deletions(-) create mode 100644 Documentation/devicetree/bindings/dma/socionext,uniphier-mio-dmac.yaml delete mode 100644 Documentation/devicetree/bindings/dma/uniphier-mio-dmac.txt diff --git a/Documentation/devicetree/bindings/dma/socionext,uniphier-mio-dmac.yaml b/Documentation/devicetree/bindings/dma/socionext,uniphier-mio-dmac.yaml new file mode 100644 index 000000000000..e7bf6dd7da29 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/socionext,uniphier-mio-dmac.yaml @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/socionext,uniphier-mio-dmac.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: UniPhier Media IO DMA controller + +description: | + This works as an external DMA engine for SD/eMMC controllers etc. + found in UniPhier LD4, Pro4, sLD8 SoCs. + +maintainers: + - Masahiro Yamada + +allOf: + - $ref: "dma-controller.yaml#" + +properties: + compatible: + const: socionext,uniphier-mio-dmac + + reg: + maxItems: 1 + + interrupts: + description: | + A list of interrupt specifiers associated with the DMA channels. + The number of interrupt lines is SoC-dependent. + + clocks: + maxItems: 1 + + resets: + maxItems: 1 + + '#dma-cells': + description: The single cell represents the channel index. + const: 1 + +required: + - compatible + - reg + - interrupts + - clocks + - '#dma-cells' + +additionalProperties: false + +examples: + - | + // In the example below, "interrupts = <0 68 4>, <0 68 4>, ..." is not a + // typo. The first two channels share a single interrupt line. + + dmac: dma-controller@5a000000 { + compatible = "socionext,uniphier-mio-dmac"; + reg = <0x5a000000 0x1000>; + interrupts = <0 68 4>, <0 68 4>, <0 69 4>, <0 70 4>, + <0 71 4>, <0 72 4>, <0 73 4>, <0 74 4>; + clocks = <&mio_clk 7>; + resets = <&mio_rst 7>; + #dma-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/dma/uniphier-mio-dmac.txt b/Documentation/devicetree/bindings/dma/uniphier-mio-dmac.txt deleted file mode 100644 index b12388dc7eac..000000000000 --- a/Documentation/devicetree/bindings/dma/uniphier-mio-dmac.txt +++ /dev/null @@ -1,25 +0,0 @@ -UniPhier Media IO DMA controller - -This works as an external DMA engine for SD/eMMC controllers etc. -found in UniPhier LD4, Pro4, sLD8 SoCs. - -Required properties: -- compatible: should be "socionext,uniphier-mio-dmac". -- reg: offset and length of the register set for the device. -- interrupts: a list of interrupt specifiers associated with the DMA channels. -- clocks: a single clock specifier. -- #dma-cells: should be <1>. The single cell represents the channel index. - -Example: - dmac: dma-controller@5a000000 { - compatible = "socionext,uniphier-mio-dmac"; - reg = <0x5a000000 0x1000>; - interrupts = <0 68 4>, <0 68 4>, <0 69 4>, <0 70 4>, - <0 71 4>, <0 72 4>, <0 73 4>, <0 74 4>; - clocks = <&mio_clk 7>; - #dma-cells = <1>; - }; - -Note: -In the example above, "interrupts = <0 68 4>, <0 68 4>, ..." is not a typo. -The first two channels share a single interrupt line. From 8dbdf23ae30af3008428dec1d199d7646e13e70d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Feb 2020 20:25:41 +0900 Subject: [PATCH 0868/4444] dt-bindings: mmc: Convert UniPhier SD controller to json-schema Convert the UniPhier SD controller binding to DT schema format. Signed-off-by: Masahiro Yamada Signed-off-by: Rob Herring --- .../bindings/mmc/socionext,uniphier-sd.yaml | 99 +++++++++++++++++++ .../devicetree/bindings/mmc/uniphier-sd.txt | 55 ----------- 2 files changed, 99 insertions(+), 55 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/socionext,uniphier-sd.yaml delete mode 100644 Documentation/devicetree/bindings/mmc/uniphier-sd.txt diff --git a/Documentation/devicetree/bindings/mmc/socionext,uniphier-sd.yaml b/Documentation/devicetree/bindings/mmc/socionext,uniphier-sd.yaml new file mode 100644 index 000000000000..cdfac9b4411b --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/socionext,uniphier-sd.yaml @@ -0,0 +1,99 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/socionext,uniphier-sd.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: UniPhier SD/SDIO/eMMC controller + +maintainers: + - Masahiro Yamada + +properties: + compatible: + description: version 2.91, 3.1, 3.1.1, respectively + enum: + - socionext,uniphier-sd-v2.91 + - socionext,uniphier-sd-v3.1 + - socionext,uniphier-sd-v3.1.1 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + reset-names: + description: | + There are three reset signals at maximum + host: mandatory for all variants + bridge: exist only for version 2.91 + hw: optional. exist if eMMC hw reset line is available + oneOf: + - const: host + - items: + - const: host + - const: bridge + - items: + - const: host + - const: hw + - items: + - const: host + - const: bridge + - const: hw + + resets: + minItems: 1 + maxItems: 3 + +allOf: + - $ref: mmc-controller.yaml + + - if: + properties: + compatible: + contains: + const: socionext,uniphier-sd-v2.91 + then: + properties: + reset-names: + contains: + const: bridge + else: + properties: + reset-names: + not: + contains: + const: bridge + +required: + - compatible + - reg + - interrupts + - clocks + - reset-names + - resets + +examples: + - | + sd: mmc@5a400000 { + compatible = "socionext,uniphier-sd-v2.91"; + reg = <0x5a400000 0x200>; + interrupts = <0 76 4>; + pinctrl-names = "default", "uhs"; + pinctrl-0 = <&pinctrl_sd>; + pinctrl-1 = <&pinctrl_sd_uhs>; + clocks = <&mio_clk 0>; + reset-names = "host", "bridge"; + resets = <&mio_rst 0>, <&mio_rst 3>; + dma-names = "rx-tx"; + dmas = <&dmac 4>; + bus-width = <4>; + cap-sd-highspeed; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + }; diff --git a/Documentation/devicetree/bindings/mmc/uniphier-sd.txt b/Documentation/devicetree/bindings/mmc/uniphier-sd.txt deleted file mode 100644 index e1d658755722..000000000000 --- a/Documentation/devicetree/bindings/mmc/uniphier-sd.txt +++ /dev/null @@ -1,55 +0,0 @@ -UniPhier SD/eMMC controller - -Required properties: -- compatible: should be one of the following: - "socionext,uniphier-sd-v2.91" - IP version 2.91 - "socionext,uniphier-sd-v3.1" - IP version 3.1 - "socionext,uniphier-sd-v3.1.1" - IP version 3.1.1 -- reg: offset and length of the register set for the device. -- interrupts: a single interrupt specifier. -- clocks: a single clock specifier of the controller clock. -- reset-names: should contain the following: - "host" - mandatory for all versions - "bridge" - should exist only for "socionext,uniphier-sd-v2.91" - "hw" - should exist if eMMC hw reset line is available -- resets: a list of reset specifiers, corresponding to the reset-names - -Optional properties: -- pinctrl-names: if present, should contain the following: - "default" - should exist for all instances - "uhs" - should exist for SD instance with UHS support -- pinctrl-0: pin control state for the default mode -- pinctrl-1: pin control state for the UHS mode -- dma-names: should be "rx-tx" if present. - This property can exist only for "socionext,uniphier-sd-v2.91". -- dmas: a single DMA channel specifier - This property can exist only for "socionext,uniphier-sd-v2.91". -- bus-width: see mmc.txt -- cap-sd-highspeed: see mmc.txt -- cap-mmc-highspeed: see mmc.txt -- sd-uhs-sdr12: see mmc.txt -- sd-uhs-sdr25: see mmc.txt -- sd-uhs-sdr50: see mmc.txt -- cap-mmc-hw-reset: should exist if reset-names contains "hw". see mmc.txt -- non-removable: see mmc.txt - -Example: - - sd: sdhc@5a400000 { - compatible = "socionext,uniphier-sd-v2.91"; - reg = <0x5a400000 0x200>; - interrupts = <0 76 4>; - pinctrl-names = "default", "uhs"; - pinctrl-0 = <&pinctrl_sd>; - pinctrl-1 = <&pinctrl_sd_uhs>; - clocks = <&mio_clk 0>; - reset-names = "host", "bridge"; - resets = <&mio_rst 0>, <&mio_rst 3>; - dma-names = "rx-tx"; - dmas = <&dmac 4>; - bus-width = <4>; - cap-sd-highspeed; - sd-uhs-sdr12; - sd-uhs-sdr25; - sd-uhs-sdr50; - }; From 2dcbfe365b130321b1b48cfa55f7bdad6baf85ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20Neusch=C3=A4fer?= Date: Sun, 23 Feb 2020 18:37:13 +0100 Subject: [PATCH 0869/4444] mtd: spi-nor: Refactor spi_nor_read_id() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Don't use `tmp` for two purposes (return value, loop counter). Instead, use `i` for the loop counter, and `ret` for the return value. - Don't use tabs between type and name in variable declarations, for consistency with other functions in spi-nor.c. - Rewrite nested `if`s as `if (a && b)`. - Remove `info` variable, and use spi_nor_ids[i] directly. Signed-off-by: Jonathan Neuschäfer [tudor.ambarus@microchip.com: change i's type from int to unsigned int, reorder local variables] Signed-off-by: Tudor Ambarus --- drivers/mtd/spi-nor/spi-nor.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 1224247b26cc..caf0c109cca0 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -2733,9 +2733,9 @@ static const struct flash_info spi_nor_ids[] = { static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) { - int tmp; - u8 *id = nor->bouncebuf; - const struct flash_info *info; + u8 *id = nor->bouncebuf; + unsigned int i; + int ret; if (nor->spimem) { struct spi_mem_op op = @@ -2744,22 +2744,20 @@ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_IN(SPI_NOR_MAX_ID_LEN, id, 1)); - tmp = spi_mem_exec_op(nor->spimem, &op); + ret = spi_mem_exec_op(nor->spimem, &op); } else { - tmp = nor->controller_ops->read_reg(nor, SPINOR_OP_RDID, id, + ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); } - if (tmp) { - dev_dbg(nor->dev, "error %d reading JEDEC ID\n", tmp); - return ERR_PTR(tmp); + if (ret) { + dev_dbg(nor->dev, "error %d reading JEDEC ID\n", ret); + return ERR_PTR(ret); } - for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { - info = &spi_nor_ids[tmp]; - if (info->id_len) { - if (!memcmp(info->id, id, info->id_len)) - return &spi_nor_ids[tmp]; - } + for (i = 0; i < ARRAY_SIZE(spi_nor_ids) - 1; i++) { + if (spi_nor_ids[i].id_len && + !memcmp(spi_nor_ids[i].id, id, spi_nor_ids[i].id_len)) + return &spi_nor_ids[i]; } dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n", SPI_NOR_MAX_ID_LEN, id); From 184bf653a7a452c18b29136e6ef59972af288c7e Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 24 Feb 2020 11:15:27 +0100 Subject: [PATCH 0870/4444] ARM: decompressor: factor out routine to obtain the inflated image size Before adding another reference to the inflated image size, factor out the slightly complicated way of loading the unaligned little-endian constant from the end of the compressed data. Tested-by: Tony Lindgren Tested-by: Linus Walleij Signed-off-by: Ard Biesheuvel --- arch/arm/boot/compressed/head.S | 43 ++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 8487221bedb0..d45952aae2b5 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -151,6 +151,25 @@ .L_\@: .endm + /* + * The kernel build system appends the size of the + * decompressed kernel at the end of the compressed data + * in little-endian form. + */ + .macro get_inflated_image_size, res:req, tmp1:req, tmp2:req + adr \res, .Linflated_image_size_offset + ldr \tmp1, [\res] + add \tmp1, \tmp1, \res @ address of inflated image size + + ldrb \res, [\tmp1] @ get_unaligned_le32 + ldrb \tmp2, [\tmp1, #1] + orr \res, \res, \tmp2, lsl #8 + ldrb \tmp2, [\tmp1, #2] + ldrb \tmp1, [\tmp1, #3] + orr \res, \res, \tmp2, lsl #16 + orr \res, \res, \tmp1, lsl #24 + .endm + .section ".start", "ax" /* * sort out different calling conventions @@ -268,15 +287,15 @@ not_angel: */ mov r0, pc cmp r0, r4 - ldrcc r0, LC0+32 + ldrcc r0, LC0+28 addcc r0, r0, pc cmpcc r4, r0 orrcc r4, r4, #1 @ remember we skipped cache_on blcs cache_on restart: adr r0, LC0 - ldmia r0, {r1, r2, r3, r6, r10, r11, r12} - ldr sp, [r0, #28] + ldmia r0, {r1, r2, r3, r6, r11, r12} + ldr sp, [r0, #24] /* * We might be running at a different address. We need @@ -284,20 +303,8 @@ restart: adr r0, LC0 */ sub r0, r0, r1 @ calculate the delta offset add r6, r6, r0 @ _edata - add r10, r10, r0 @ inflated kernel size location - /* - * The kernel build system appends the size of the - * decompressed kernel at the end of the compressed data - * in little-endian form. - */ - ldrb r9, [r10, #0] - ldrb lr, [r10, #1] - orr r9, r9, lr, lsl #8 - ldrb lr, [r10, #2] - ldrb r10, [r10, #3] - orr r9, r9, lr, lsl #16 - orr r9, r9, r10, lsl #24 + get_inflated_image_size r9, r10, lr #ifndef CONFIG_ZBOOT_ROM /* malloc space is above the relocated stack (64k max) */ @@ -652,13 +659,15 @@ LC0: .word LC0 @ r1 .word __bss_start @ r2 .word _end @ r3 .word _edata @ r6 - .word input_data_end - 4 @ r10 (inflated size location) .word _got_start @ r11 .word _got_end @ ip .word .L_user_stack_end @ sp .word _end - restart + 16384 + 1024*1024 .size LC0, . - LC0 +.Linflated_image_size_offset: + .long (input_data_end - 4) - . + #ifdef CONFIG_ARCH_RPC .globl params params: ldr r0, =0x10000100 @ params_phys for RPC From e114412f616446708b3d1e559ff4af9db7ade46e Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 18 Feb 2020 16:50:54 +0100 Subject: [PATCH 0871/4444] ARM: decompressor: prepare cache_clean_flush for doing by-VA maintenance In preparation for turning the decompressor's cache clean/flush operations into proper by-VA maintenance for v7 cores, pass the start and end addresses of the regions that need cache maintenance into cache_clean_flush in registers r0 and r1. Currently, all implementations of cache_clean_flush ignore these values, so no functional change is expected as a result of this patch. Tested-by: Tony Lindgren Tested-by: Linus Walleij Signed-off-by: Ard Biesheuvel --- arch/arm/boot/compressed/head.S | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index d45952aae2b5..f90034151aef 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -528,6 +528,8 @@ dtb_check_done: /* Preserve offset to relocated code. */ sub r6, r9, r6 + mov r0, r9 @ start of relocated zImage + add r1, sp, r6 @ end of relocated zImage #ifndef CONFIG_ZBOOT_ROM /* cache_clean_flush may use the stack, so relocate it */ add sp, sp, r6 @@ -629,6 +631,11 @@ not_relocated: mov r0, #0 add r2, sp, #0x10000 @ 64k max mov r3, r7 bl decompress_kernel + + get_inflated_image_size r1, r2, r3 + + mov r0, r4 @ start of inflated image + add r1, r1, r0 @ end of inflated image bl cache_clean_flush bl cache_off @@ -1182,6 +1189,9 @@ __armv7_mmu_cache_off: /* * Clean and flush the cache to maintain consistency. * + * On entry, + * r0 = start address + * r1 = end address (exclusive) * On exit, * r1, r2, r3, r9, r10, r11, r12 corrupted * This routine must preserve: From 401b368caaecdce1cf8f05bab448172752230cb0 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 18 Feb 2020 17:06:14 +0100 Subject: [PATCH 0872/4444] ARM: decompressor: switch to by-VA cache maintenance for v7 cores Update the v7 cache_clean_flush routine to take into account the memory range passed in r0/r1, and perform cache maintenance by virtual address on this range instead of set/way maintenance, which is inappropriate for the purpose of maintaining the cached state of memory contents. Since this removes any use of the stack in the implementation of cache_clean_flush(), we can also drop some code that manages the value of the stack pointer before calling it. Tested-by: Tony Lindgren Tested-by: Linus Walleij Signed-off-by: Ard Biesheuvel --- arch/arm/boot/compressed/head.S | 83 ++++++++++++--------------------- 1 file changed, 30 insertions(+), 53 deletions(-) diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index f90034151aef..4f7c6145e31f 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -530,11 +530,6 @@ dtb_check_done: mov r0, r9 @ start of relocated zImage add r1, sp, r6 @ end of relocated zImage -#ifndef CONFIG_ZBOOT_ROM - /* cache_clean_flush may use the stack, so relocate it */ - add sp, sp, r6 -#endif - bl cache_clean_flush badr r0, restart @@ -683,6 +678,24 @@ params: ldr r0, =0x10000100 @ params_phys for RPC .align #endif +/* + * dcache_line_size - get the minimum D-cache line size from the CTR register + * on ARMv7. + */ + .macro dcache_line_size, reg, tmp +#ifdef CONFIG_CPU_V7M + movw \tmp, #:lower16:BASEADDR_V7M_SCB + V7M_SCB_CTR + movt \tmp, #:upper16:BASEADDR_V7M_SCB + V7M_SCB_CTR + ldr \tmp, [\tmp] +#else + mrc p15, 0, \tmp, c0, c0, 1 @ read ctr +#endif + lsr \tmp, \tmp, #16 + and \tmp, \tmp, #0xf @ cache line size encoding + mov \reg, #4 @ bytes per word + mov \reg, \reg, lsl \tmp @ actual cache line size + .endm + /* * Turn on the cache. We need to setup some page tables so that we * can have both the I and D caches on. @@ -1175,8 +1188,6 @@ __armv7_mmu_cache_off: bic r0, r0, #0x000c #endif mcr p15, 0, r0, c1, c0 @ turn MMU and cache off - mov r12, lr - bl __armv7_mmu_cache_flush mov r0, #0 #ifdef CONFIG_MMU mcr p15, 0, r0, c8, c7, 0 @ invalidate whole TLB @@ -1184,7 +1195,7 @@ __armv7_mmu_cache_off: mcr p15, 0, r0, c7, c5, 6 @ invalidate BTC mcr p15, 0, r0, c7, c10, 4 @ DSB mcr p15, 0, r0, c7, c5, 4 @ ISB - mov pc, r12 + mov pc, lr /* * Clean and flush the cache to maintain consistency. @@ -1200,6 +1211,7 @@ __armv7_mmu_cache_off: .align 5 cache_clean_flush: mov r3, #16 + mov r11, r1 b call_cache_fn __armv4_mpu_cache_flush: @@ -1250,51 +1262,16 @@ __armv7_mmu_cache_flush: mcr p15, 0, r10, c7, c14, 0 @ clean+invalidate D b iflush hierarchical: - mcr p15, 0, r10, c7, c10, 5 @ DMB - stmfd sp!, {r0-r7, r9-r11} - mrc p15, 1, r0, c0, c0, 1 @ read clidr - ands r3, r0, #0x7000000 @ extract loc from clidr - mov r3, r3, lsr #23 @ left align loc bit field - beq finished @ if loc is 0, then no need to clean - mov r10, #0 @ start clean at cache level 0 -loop1: - add r2, r10, r10, lsr #1 @ work out 3x current cache level - mov r1, r0, lsr r2 @ extract cache type bits from clidr - and r1, r1, #7 @ mask of the bits for current cache only - cmp r1, #2 @ see what cache we have at this level - blt skip @ skip if no cache, or just i-cache - mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr - mcr p15, 0, r10, c7, c5, 4 @ isb to sych the new cssr&csidr - mrc p15, 1, r1, c0, c0, 0 @ read the new csidr - and r2, r1, #7 @ extract the length of the cache lines - add r2, r2, #4 @ add 4 (line length offset) - ldr r4, =0x3ff - ands r4, r4, r1, lsr #3 @ find maximum number on the way size - clz r5, r4 @ find bit position of way size increment - ldr r7, =0x7fff - ands r7, r7, r1, lsr #13 @ extract max number of the index size -loop2: - mov r9, r4 @ create working copy of max way size -loop3: - ARM( orr r11, r10, r9, lsl r5 ) @ factor way and cache number into r11 - ARM( orr r11, r11, r7, lsl r2 ) @ factor index number into r11 - THUMB( lsl r6, r9, r5 ) - THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11 - THUMB( lsl r6, r7, r2 ) - THUMB( orr r11, r11, r6 ) @ factor index number into r11 - mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way - subs r9, r9, #1 @ decrement the way - bge loop3 - subs r7, r7, #1 @ decrement the index - bge loop2 -skip: - add r10, r10, #2 @ increment cache number - cmp r3, r10 - bgt loop1 -finished: - ldmfd sp!, {r0-r7, r9-r11} - mov r10, #0 @ switch back to cache level 0 - mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + dcache_line_size r1, r2 @ r1 := dcache min line size + sub r2, r1, #1 @ r2 := line size mask + bic r0, r0, r2 @ round down start to line size + sub r11, r11, #1 @ end address is exclusive + bic r11, r11, r2 @ round down end to line size +0: cmp r0, r11 @ finished? + bgt iflush + mcr p15, 0, r0, c7, c14, 1 @ Dcache clean/invalidate by VA + add r0, r0, r1 + b 0b iflush: mcr p15, 0, r10, c7, c10, 4 @ DSB mcr p15, 0, r10, c7, c5, 0 @ invalidate I+BTB From 4098a2b45bb3fc2e928487c064974be26c7f6128 Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Wed, 26 Feb 2020 00:10:11 -0800 Subject: [PATCH 0873/4444] arm64: allwinner: a64: enable LCD-related hardware for Pinebook Pinebook has an ANX6345 bridge connected to the RGB666 LCD output and eDP panel input. The bridge is controlled via I2C that's connected to R_I2C bus. Enable all this hardware in device tree. Reviewed-by: Laurent Pinchart Signed-off-by: Icenowy Zheng Signed-off-by: Vasily Khoruzhick Signed-off-by: Maxime Ripard --- .../dts/allwinner/sun50i-a64-pinebook.dts | 61 ++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts index 12e513ba8f50..64b1c54f87c0 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts @@ -48,6 +48,18 @@ }; }; + panel_edp: panel-edp { + compatible = "neweast,wjfh116008a"; + backlight = <&backlight>; + power-supply = <®_dc1sw>; + + port { + panel_edp_in: endpoint { + remote-endpoint = <&anx6345_out_edp>; + }; + }; + }; + reg_vbklt: vbklt { compatible = "regulator-fixed"; regulator-name = "vbklt"; @@ -109,6 +121,10 @@ status = "okay"; }; +&de { + status = "okay"; +}; + &ehci0 { phys = <&usbphy 0>; phy-names = "usb"; @@ -119,6 +135,10 @@ status = "okay"; }; +&mixer0 { + status = "okay"; +}; + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins>; @@ -177,12 +197,38 @@ status = "okay"; }; -/* The ANX6345 eDP-bridge is on r_i2c */ &r_i2c { clock-frequency = <100000>; pinctrl-names = "default"; pinctrl-0 = <&r_i2c_pl89_pins>; status = "okay"; + + anx6345: anx6345@38 { + compatible = "analogix,anx6345"; + reg = <0x38>; + reset-gpios = <&pio 3 24 GPIO_ACTIVE_LOW>; /* PD24 */ + dvdd25-supply = <®_dldo2>; + dvdd12-supply = <®_fldo1>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + anx6345_in: port@0 { + reg = <0>; + anx6345_in_tcon0: endpoint { + remote-endpoint = <&tcon0_out_anx6345>; + }; + }; + + anx6345_out: port@1 { + reg = <1>; + anx6345_out_edp: endpoint { + remote-endpoint = <&panel_edp_in>; + }; + }; + }; + }; }; &r_pio { @@ -343,6 +389,19 @@ "MIC2", "Internal Microphone Right"; }; +&tcon0 { + pinctrl-names = "default"; + pinctrl-0 = <&lcd_rgb666_pins>; + + status = "okay"; +}; + +&tcon0_out { + tcon0_out_anx6345: endpoint { + remote-endpoint = <&anx6345_in_tcon0>; + }; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_pb_pins>; From 179a79fd740b6b2f66b64bae5cb6ecd483987d20 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Thu, 27 Feb 2020 11:55:26 +0000 Subject: [PATCH 0874/4444] ARM: dts: sunxi: h3/h5: add r_pwm node There is a second PWM unit available in the PL I/O block. Add a node and pinmux definition for it. Signed-off-by: Mans Rullgard Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sunxi-h3-h5.dtsi | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi index 5e9c3060aa08..ed3908849111 100644 --- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi +++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi @@ -892,6 +892,21 @@ pins = "PL0", "PL1"; function = "s_i2c"; }; + + r_pwm_pin: r-pwm-pin { + pins = "PL10"; + function = "s_pwm"; + }; + }; + + r_pwm: pwm@1f03800 { + compatible = "allwinner,sun8i-h3-pwm"; + reg = <0x01f03800 0x8>; + pinctrl-names = "default"; + pinctrl-0 = <&r_pwm_pin>; + clocks = <&osc24M>; + #pwm-cells = <3>; + status = "disabled"; }; }; }; From 29b2c68bf47a571fdae64c35060173fc4ad88dbe Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Thu, 27 Feb 2020 02:26:48 +0100 Subject: [PATCH 0875/4444] arm64: dts: sun50i-a64: Add i2c2 pins PinePhone needs I2C2 pins description. Add it, and make it default for i2c2, since it's the only possiblilty. Signed-off-by: Ondrej Jirman Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index 72b1b34879c6..990de71ca048 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -671,6 +671,11 @@ function = "i2c1"; }; + i2c2_pins: i2c2-pins { + pins = "PE14", "PE15"; + function = "i2c2"; + }; + /omit-if-no-ref/ lcd_rgb666_pins: lcd-rgb666-pins { pins = "PD0", "PD1", "PD2", "PD3", "PD4", @@ -958,12 +963,13 @@ interrupts = ; clocks = <&ccu CLK_BUS_I2C2>; resets = <&ccu RST_BUS_I2C2>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; }; - spi0: spi@1c68000 { compatible = "allwinner,sun8i-h3-spi"; reg = <0x01c68000 0x1000>; From a886ed26568646cb542866207563e2ad9afcde69 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Thu, 27 Feb 2020 02:26:49 +0100 Subject: [PATCH 0876/4444] dt-bindings: arm: sunxi: Add PinePhone 1.0 and 1.1 bindings Document board compatible names for Pine64 PinePhone: - 1.0 - Developer variant - 1.1 - Braveheart variant Signed-off-by: Ondrej Jirman Reviewed-by: Rob Herring Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/arm/sunxi.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml index 5b22b77e4bb7..abf2d97fb7ae 100644 --- a/Documentation/devicetree/bindings/arm/sunxi.yaml +++ b/Documentation/devicetree/bindings/arm/sunxi.yaml @@ -642,6 +642,16 @@ properties: - const: pine64,pinebook - const: allwinner,sun50i-a64 + - description: Pine64 PinePhone Developer Batch (1.0) + items: + - const: pine64,pinephone-1.0 + - const: allwinner,sun50i-a64 + + - description: Pine64 PinePhone Braveheart (1.1) + items: + - const: pine64,pinephone-1.1 + - const: allwinner,sun50i-a64 + - description: Pine64 PineTab items: - const: pine64,pinetab From 91f480d409429db29b402c3200e4a6f1e519ba87 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Thu, 27 Feb 2020 02:26:50 +0100 Subject: [PATCH 0877/4444] arm64: dts: allwinner: Add initial support for Pine64 PinePhone At the moment PinePhone comes in two slightly incompatible variants: - 1.0: Early Developer Batch - 1.1: Braveheart Batch There will be at least one more incompatible variant in the very near future, so let's start by sharing the dtsi among multiple variants, right away, even though the HW description doesn't yet include the different bits. The differences between 1.0 and 1.1 are: change in pins that control the flash LED, differences in modem power status signal routing, and maybe some other subtler things, that have not been determined yet. This is a basic DT that includes only features that are already supported by mainline drivers. Co-developed-by: Samuel Holland Signed-off-by: Samuel Holland Co-developed-by: Martijn Braam Signed-off-by: Martijn Braam Co-developed-by: Luca Weiss Signed-off-by: Luca Weiss Signed-off-by: Bhushan Shah Signed-off-by: Icenowy Zheng Signed-off-by: Ondrej Jirman Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/Makefile | 2 + .../allwinner/sun50i-a64-pinephone-1.0.dts | 11 + .../allwinner/sun50i-a64-pinephone-1.1.dts | 11 + .../dts/allwinner/sun50i-a64-pinephone.dtsi | 379 ++++++++++++++++++ 4 files changed, 403 insertions(+) create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile index 6dad63881cd3..e4d3cd0ac5bb 100644 --- a/arch/arm64/boot/dts/allwinner/Makefile +++ b/arch/arm64/boot/dts/allwinner/Makefile @@ -9,6 +9,8 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-orangepi-win.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-lts.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-plus.dtb sun50i-a64-pine64.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinebook.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinephone-1.0.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinephone-1.1.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinetab.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-sopine-baseboard.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-teres-i.dtb diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts new file mode 100644 index 000000000000..0c42272106af --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +// Copyright (C) 2020 Ondrej Jirman + +/dts-v1/; + +#include "sun50i-a64-pinephone.dtsi" + +/ { + model = "Pine64 PinePhone Developer Batch (1.0)"; + compatible = "pine64,pinephone-1.0", "allwinner,sun50i-a64"; +}; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts new file mode 100644 index 000000000000..06a775c41664 --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +// Copyright (C) 2020 Ondrej Jirman + +/dts-v1/; + +#include "sun50i-a64-pinephone.dtsi" + +/ { + model = "Pine64 PinePhone Braveheart (1.1)"; + compatible = "pine64,pinephone-1.1", "allwinner,sun50i-a64"; +}; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi new file mode 100644 index 000000000000..cefda145c3c9 --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi @@ -0,0 +1,379 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +// Copyright (C) 2019 Icenowy Zheng +// Copyright (C) 2020 Martijn Braam +// Copyright (C) 2020 Ondrej Jirman + +#include "sun50i-a64.dtsi" +#include "sun50i-a64-cpu-opp.dtsi" + +#include +#include +#include +#include + +/ { + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + + blue { + function = LED_FUNCTION_INDICATOR; + color = ; + gpios = <&pio 3 20 GPIO_ACTIVE_HIGH>; /* PD20 */ + }; + + green { + function = LED_FUNCTION_INDICATOR; + color = ; + gpios = <&pio 3 18 GPIO_ACTIVE_HIGH>; /* PD18 */ + }; + + red { + function = LED_FUNCTION_INDICATOR; + color = ; + gpios = <&pio 3 19 GPIO_ACTIVE_HIGH>; /* PD19 */ + }; + }; + + speaker_amp: audio-amplifier { + compatible = "simple-audio-amplifier"; + enable-gpios = <&pio 2 7 GPIO_ACTIVE_HIGH>; /* PC7 */ + sound-name-prefix = "Speaker Amp"; + }; + + vibrator { + compatible = "gpio-vibrator"; + enable-gpios = <&pio 3 2 GPIO_ACTIVE_HIGH>; /* PD2 */ + vcc-supply = <®_dcdc1>; + }; +}; + +&codec { + status = "okay"; +}; + +&codec_analog { + cpvdd-supply = <®_eldo1>; + status = "okay"; +}; + +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + +&cpu1 { + cpu-supply = <®_dcdc2>; +}; + +&cpu2 { + cpu-supply = <®_dcdc2>; +}; + +&cpu3 { + cpu-supply = <®_dcdc2>; +}; + +&dai { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + + /* Magnetometer */ + lis3mdl@1e { + compatible = "st,lis3mdl-magn"; + reg = <0x1e>; + vdd-supply = <®_dldo1>; + vddio-supply = <®_dldo1>; + }; + + /* Accelerometer/gyroscope */ + mpu6050@68 { + compatible = "invensense,mpu6050"; + reg = <0x68>; + interrupt-parent = <&pio>; + interrupts = <7 5 IRQ_TYPE_EDGE_RISING>; /* PH5 */ + vdd-supply = <®_dldo1>; + vddio-supply = <®_dldo1>; + }; +}; + +/* Connected to pogo pins (external spring based pinheader for user addons) */ +&i2c2 { + status = "okay"; +}; + +&lradc { + vref-supply = <®_aldo3>; + status = "okay"; + + button-200 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <200000>; + }; + + button-400 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <400000>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins>; + vmmc-supply = <®_dcdc1>; + vqmmc-supply = <®_dcdc1>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ + disable-wp; + bus-width = <4>; + status = "okay"; +}; + +&mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins>; + vmmc-supply = <®_dcdc1>; + vqmmc-supply = <®_dcdc1>; + bus-width = <8>; + non-removable; + cap-mmc-hw-reset; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&pio { + vcc-pb-supply = <®_dcdc1>; + vcc-pc-supply = <®_dcdc1>; + vcc-pd-supply = <®_dcdc1>; + vcc-pe-supply = <®_aldo1>; + vcc-pf-supply = <®_dcdc1>; + vcc-pg-supply = <®_dldo4>; + vcc-ph-supply = <®_dcdc1>; +}; + +&r_pio { + /* + * FIXME: We can't add that supply for now since it would + * create a circular dependency between pinctrl, the regulator + * and the RSB Bus. + * + * vcc-pl-supply = <®_aldo2>; + */ +}; + +&r_rsb { + status = "okay"; + + axp803: pmic@3a3 { + compatible = "x-powers,axp803"; + reg = <0x3a3>; + interrupt-parent = <&r_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +#include "axp803.dtsi" + +&ac_power_supply { + status = "okay"; +}; + +&battery_power_supply { + status = "okay"; +}; + +®_aldo1 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "dovdd-csi"; +}; + +®_aldo2 { + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc-pl"; +}; + +®_aldo3 { + regulator-always-on; + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-pll-avcc"; +}; + +®_dcdc1 { + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-3v3"; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1300000>; + regulator-name = "vdd-cpux"; +}; + +/* DCDC3 is polyphased with DCDC2 */ + +®_dcdc5 { + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-name = "vcc-dram"; +}; + +®_dcdc6 { + regulator-always-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-name = "vdd-sys"; +}; + +®_dldo1 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-dsi-sensor"; +}; + +®_dldo2 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc-mipi-io"; +}; + +®_dldo3 { + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-name = "avdd-csi"; +}; + +®_dldo4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-wifi-io"; +}; + +®_eldo1 { + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc-lpddr"; +}; + +®_eldo3 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "dvdd-1v8-csi"; +}; + +®_fldo1 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-name = "vcc-1v2-hsic"; +}; + +®_fldo2 { + regulator-always-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-name = "vdd-cpus"; +}; + +®_ldo_io0 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-lcd-ctp-stk"; + status = "okay"; +}; + +®_ldo_io1 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc-1v8-typec"; + status = "okay"; +}; + +®_rtc_ldo { + regulator-name = "vcc-rtc"; +}; + +&sound { + status = "okay"; + simple-audio-card,aux-devs = <&codec_analog>, <&speaker_amp>; + simple-audio-card,widgets = "Microphone", "Headset Microphone", + "Microphone", "Internal Microphone", + "Headphone", "Headphone Jack", + "Speaker", "Internal Earpiece", + "Speaker", "Internal Speaker"; + simple-audio-card,routing = + "Headphone Jack", "HP", + "Internal Earpiece", "EARPIECE", + "Internal Speaker", "Speaker Amp OUTL", + "Internal Speaker", "Speaker Amp OUTR", + "Speaker Amp INL", "LINEOUT", + "Speaker Amp INR", "LINEOUT", + "Left DAC", "AIF1 Slot 0 Left", + "Right DAC", "AIF1 Slot 0 Right", + "AIF1 Slot 0 Left ADC", "Left ADC", + "AIF1 Slot 0 Right ADC", "Right ADC", + "Internal Microphone", "MBIAS", + "MIC1", "Internal Microphone", + "Headset Microphone", "HBIAS", + "MIC2", "Headset Microphone"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pb_pins>; + status = "okay"; +}; + +/* Connected to the modem (hardware flow control can't be used) */ +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "peripheral"; + status = "okay"; +}; + +&usb_power_supply { + status = "okay"; +}; + +&usbphy { + status = "okay"; +}; From 82ba4997129a47b540d3d6714975b252f8353468 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Feb 2020 23:19:26 +0900 Subject: [PATCH 0878/4444] dt-bindings: mtd: Convert Denali NAND controller to json-schema Convert the Denali NAND controller binding to DT schema format. Signed-off-by: Masahiro Yamada Signed-off-by: Rob Herring --- .../devicetree/bindings/mtd/denali,nand.yaml | 148 ++++++++++++++++++ .../devicetree/bindings/mtd/denali-nand.txt | 61 -------- 2 files changed, 148 insertions(+), 61 deletions(-) create mode 100644 Documentation/devicetree/bindings/mtd/denali,nand.yaml delete mode 100644 Documentation/devicetree/bindings/mtd/denali-nand.txt diff --git a/Documentation/devicetree/bindings/mtd/denali,nand.yaml b/Documentation/devicetree/bindings/mtd/denali,nand.yaml new file mode 100644 index 000000000000..46e6b6726bc0 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/denali,nand.yaml @@ -0,0 +1,148 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mtd/denali,nand.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Denali NAND controller + +maintainers: + - Masahiro Yamada + +properties: + compatible: + enum: + - altr,socfpga-denali-nand + - socionext,uniphier-denali-nand-v5a + - socionext,uniphier-denali-nand-v5b + + reg-names: + description: | + There are two register regions: + nand_data: host data/command interface + denali_reg: register interface + items: + - const: nand_data + - const: denali_reg + + reg: + minItems: 2 + maxItems: 2 + + interrupts: + maxItems: 1 + + clock-names: + description: | + There are three clocks: + nand: controller core clock + nand_x: bus interface clock + ecc: ECC circuit clock + items: + - const: nand + - const: nand_x + - const: ecc + + clocks: + minItems: 3 + maxItems: 3 + + reset-names: + description: | + There are two optional resets: + nand: controller core reset + reg: register reset + oneOf: + - items: + - const: nand + - const: reg + - const: nand + - const: reg + + resets: + minItems: 1 + maxItems: 2 + +allOf: + - $ref: nand-controller.yaml + + - if: + properties: + compatible: + contains: + const: altr,socfpga-denali-nand + then: + patternProperties: + "^nand@[a-f0-9]$": + type: object + properties: + nand-ecc-strength: + enum: + - 8 + - 15 + nand-ecc-step-size: + enum: + - 512 + + - if: + properties: + compatible: + contains: + const: socionext,uniphier-denali-nand-v5a + then: + patternProperties: + "^nand@[a-f0-9]$": + type: object + properties: + nand-ecc-strength: + enum: + - 8 + - 16 + - 24 + nand-ecc-step-size: + enum: + - 1024 + + - if: + properties: + compatible: + contains: + const: socionext,uniphier-denali-nand-v5b + then: + patternProperties: + "^nand@[a-f0-9]$": + type: object + properties: + nand-ecc-strength: + enum: + - 8 + - 16 + nand-ecc-step-size: + enum: + - 1024 + +required: + - compatible + - reg + - interrupts + - clock-names + - clocks + +examples: + - | + nand-controller@ff900000 { + compatible = "altr,socfpga-denali-nand"; + reg-names = "nand_data", "denali_reg"; + reg = <0xff900000 0x20>, <0xffb80000 0x1000>; + interrupts = <0 144 4>; + clock-names = "nand", "nand_x", "ecc"; + clocks = <&nand_clk>, <&nand_x_clk>, <&nand_ecc_clk>; + reset-names = "nand", "reg"; + resets = <&nand_rst>, <&nand_reg_rst>; + #address-cells = <1>; + #size-cells = <0>; + + nand@0 { + reg = <0>; + }; + }; diff --git a/Documentation/devicetree/bindings/mtd/denali-nand.txt b/Documentation/devicetree/bindings/mtd/denali-nand.txt deleted file mode 100644 index 98916a84bbf6..000000000000 --- a/Documentation/devicetree/bindings/mtd/denali-nand.txt +++ /dev/null @@ -1,61 +0,0 @@ -* Denali NAND controller - -Required properties: - - compatible : should be one of the following: - "altr,socfpga-denali-nand" - for Altera SOCFPGA - "socionext,uniphier-denali-nand-v5a" - for Socionext UniPhier (v5a) - "socionext,uniphier-denali-nand-v5b" - for Socionext UniPhier (v5b) - - reg : should contain registers location and length for data and reg. - - reg-names: Should contain the reg names "nand_data" and "denali_reg" - - #address-cells: should be 1. The cell encodes the chip select connection. - - #size-cells : should be 0. - - interrupts : The interrupt number. - - clocks: should contain phandle of the controller core clock, the bus - interface clock, and the ECC circuit clock. - - clock-names: should contain "nand", "nand_x", "ecc" - -Optional properties: - - resets: may contain phandles to the controller core reset, the register - reset - - reset-names: may contain "nand", "reg" - -Sub-nodes: - Sub-nodes represent available NAND chips. - - Required properties: - - reg: should contain the bank ID of the controller to which each chip - select is connected. - - Optional properties: - - nand-ecc-step-size: see nand-controller.yaml for details. - If present, the value must be - 512 for "altr,socfpga-denali-nand" - 1024 for "socionext,uniphier-denali-nand-v5a" - 1024 for "socionext,uniphier-denali-nand-v5b" - - nand-ecc-strength: see nand-controller.yaml for details. Valid values are: - 8, 15 for "altr,socfpga-denali-nand" - 8, 16, 24 for "socionext,uniphier-denali-nand-v5a" - 8, 16 for "socionext,uniphier-denali-nand-v5b" - - nand-ecc-maximize: see nand-controller.yaml for details - -The chip nodes may optionally contain sub-nodes describing partitions of the -address space. See partition.txt for more detail. - -Examples: - -nand: nand@ff900000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "altr,socfpga-denali-nand"; - reg = <0xff900000 0x20>, <0xffb80000 0x1000>; - reg-names = "nand_data", "denali_reg"; - clocks = <&nand_clk>, <&nand_x_clk>, <&nand_ecc_clk>; - clock-names = "nand", "nand_x", "ecc"; - resets = <&nand_rst>, <&nand_reg_rst>; - reset-names = "nand", "reg"; - interrupts = <0 144 4>; - - nand@0 { - reg = <0>; - } -}; From 06efe6482251520d171bf33b841f35c8677727ad Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Feb 2020 23:34:44 +0900 Subject: [PATCH 0879/4444] dt-bindings: mmc: Convert Cadence SD/SDIO/eMMC controller to json-schema Convert the Cadence SD/SDIO/eMMC host controller IP (a.k.a. SD4HC) binding to DT schema format. Socionext UniPhier ARM 64-bit SoCs are integrated with this IP. Cc: Piotr Sroka Signed-off-by: Masahiro Yamada Signed-off-by: Rob Herring --- .../devicetree/bindings/mmc/cdns,sdhci.yaml | 143 ++++++++++++++++++ .../devicetree/bindings/mmc/sdhci-cadence.txt | 80 ---------- 2 files changed, 143 insertions(+), 80 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml delete mode 100644 Documentation/devicetree/bindings/mmc/sdhci-cadence.txt diff --git a/Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml b/Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml new file mode 100644 index 000000000000..2f45dd0d04db --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml @@ -0,0 +1,143 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/cdns,sdhci.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Cadence SD/SDIO/eMMC Host Controller (SD4HC) + +maintainers: + - Masahiro Yamada + - Piotr Sroka + +allOf: + - $ref: mmc-controller.yaml + +properties: + compatible: + items: + - enum: + - socionext,uniphier-sd4hc + - const: cdns,sd4hc + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + # PHY DLL input delays: + # They are used to delay the data valid window, and align the window to + # sampling clock. The delay starts from 5ns (for delay parameter equal to 0) + # and it is increased by 2.5ns in each step. + + cdns,phy-input-delay-sd-highspeed: + description: Value of the delay in the input path for SD high-speed timing + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - minimum: 0 + - maximum: 0x1f + + cdns,phy-input-delay-legacy: + description: Value of the delay in the input path for legacy timing + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - minimum: 0 + - maximum: 0x1f + + cdns,phy-input-delay-sd-uhs-sdr12: + description: Value of the delay in the input path for SD UHS SDR12 timing + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - minimum: 0 + - maximum: 0x1f + + cdns,phy-input-delay-sd-uhs-sdr25: + description: Value of the delay in the input path for SD UHS SDR25 timing + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - minimum: 0 + - maximum: 0x1f + + cdns,phy-input-delay-sd-uhs-sdr50: + description: Value of the delay in the input path for SD UHS SDR50 timing + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - minimum: 0 + - maximum: 0x1f + + cdns,phy-input-delay-sd-uhs-ddr50: + description: Value of the delay in the input path for SD UHS DDR50 timing + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - minimum: 0 + - maximum: 0x1f + + cdns,phy-input-delay-mmc-highspeed: + description: Value of the delay in the input path for MMC high-speed timing + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - minimum: 0 + - maximum: 0x1f + + cdns,phy-input-delay-mmc-ddr: + description: Value of the delay in the input path for eMMC high-speed DDR timing + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - minimum: 0 + - maximum: 0x1f + + # PHY DLL clock delays: + # Each delay property represents the fraction of the clock period. + # The approximate delay value will be + # (/128)*sdmclk_clock_period. + + cdns,phy-dll-delay-sdclk: + description: | + Value of the delay introduced on the sdclk output for all modes except + HS200, HS400 and HS400_ES. + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - minimum: 0 + - maximum: 0x7f + + cdns,phy-dll-delay-sdclk-hsmmc: + description: | + Value of the delay introduced on the sdclk output for HS200, HS400 and + HS400_ES speed modes. + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - minimum: 0 + - maximum: 0x7f + + cdns,phy-dll-delay-strobe: + description: | + Value of the delay introduced on the dat_strobe input used in + HS400 / HS400_ES speed modes. + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - minimum: 0 + - maximum: 0x7f + +required: + - compatible + - reg + - interrupts + - clocks + +examples: + - | + emmc: mmc@5a000000 { + compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc"; + reg = <0x5a000000 0x400>; + interrupts = <0 78 4>; + clocks = <&clk 4>; + bus-width = <8>; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + cdns,phy-dll-delay-sdclk = <0>; + }; diff --git a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt b/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt deleted file mode 100644 index fa423c277853..000000000000 --- a/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt +++ /dev/null @@ -1,80 +0,0 @@ -* Cadence SD/SDIO/eMMC Host Controller - -Required properties: -- compatible: should be one of the following: - "cdns,sd4hc" - default of the IP - "socionext,uniphier-sd4hc" - for Socionext UniPhier SoCs -- reg: offset and length of the register set for the device. -- interrupts: a single interrupt specifier. -- clocks: phandle to the input clock. - -Optional properties: -For eMMC configuration, supported speed modes are not indicated by the SDHCI -Capabilities Register. Instead, the following properties should be specified -if supported. See mmc.txt for details. -- mmc-ddr-1_8v -- mmc-ddr-1_2v -- mmc-hs200-1_8v -- mmc-hs200-1_2v -- mmc-hs400-1_8v -- mmc-hs400-1_2v - -Some PHY delays can be configured by following properties. -PHY DLL input delays: -They are used to delay the data valid window, and align the window -to sampling clock. The delay starts from 5ns (for delay parameter equal to 0) -and it is increased by 2.5ns in each step. -- cdns,phy-input-delay-sd-highspeed: - Value of the delay in the input path for SD high-speed timing - Valid range = [0:0x1F]. -- cdns,phy-input-delay-legacy: - Value of the delay in the input path for legacy timing - Valid range = [0:0x1F]. -- cdns,phy-input-delay-sd-uhs-sdr12: - Value of the delay in the input path for SD UHS SDR12 timing - Valid range = [0:0x1F]. -- cdns,phy-input-delay-sd-uhs-sdr25: - Value of the delay in the input path for SD UHS SDR25 timing - Valid range = [0:0x1F]. -- cdns,phy-input-delay-sd-uhs-sdr50: - Value of the delay in the input path for SD UHS SDR50 timing - Valid range = [0:0x1F]. -- cdns,phy-input-delay-sd-uhs-ddr50: - Value of the delay in the input path for SD UHS DDR50 timing - Valid range = [0:0x1F]. -- cdns,phy-input-delay-mmc-highspeed: - Value of the delay in the input path for MMC high-speed timing - Valid range = [0:0x1F]. -- cdns,phy-input-delay-mmc-ddr: - Value of the delay in the input path for eMMC high-speed DDR timing - Valid range = [0:0x1F]. - -PHY DLL clock delays: -Each delay property represents the fraction of the clock period. -The approximate delay value will be -(/128)*sdmclk_clock_period. -- cdns,phy-dll-delay-sdclk: - Value of the delay introduced on the sdclk output - for all modes except HS200, HS400 and HS400_ES. - Valid range = [0:0x7F]. -- cdns,phy-dll-delay-sdclk-hsmmc: - Value of the delay introduced on the sdclk output - for HS200, HS400 and HS400_ES speed modes. - Valid range = [0:0x7F]. -- cdns,phy-dll-delay-strobe: - Value of the delay introduced on the dat_strobe input - used in HS400 / HS400_ES speed modes. - Valid range = [0:0x7F]. - -Example: - emmc: sdhci@5a000000 { - compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc"; - reg = <0x5a000000 0x400>; - interrupts = <0 78 4>; - clocks = <&clk 4>; - bus-width = <8>; - mmc-ddr-1_8v; - mmc-hs200-1_8v; - mmc-hs400-1_8v; - cdns,phy-dll-delay-sdclk = <0>; - }; From 73c3d1da3519defab71a7aa62963d0af72cd590f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Sat, 22 Feb 2020 20:00:59 +0000 Subject: [PATCH 0880/4444] dt-bindings: rng: Convert BCM2835 to DT schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert BCM2835/6368 Random number generator bindings to DT schema. Signed-off-by: Nícolas F. R. A. Prado Signed-off-by: Rob Herring --- .../devicetree/bindings/rng/brcm,bcm2835.txt | 40 ------------- .../devicetree/bindings/rng/brcm,bcm2835.yaml | 59 +++++++++++++++++++ 2 files changed, 59 insertions(+), 40 deletions(-) delete mode 100644 Documentation/devicetree/bindings/rng/brcm,bcm2835.txt create mode 100644 Documentation/devicetree/bindings/rng/brcm,bcm2835.yaml diff --git a/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt b/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt deleted file mode 100644 index aaac7975f61c..000000000000 --- a/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt +++ /dev/null @@ -1,40 +0,0 @@ -BCM2835/6368 Random number generator - -Required properties: - -- compatible : should be one of - "brcm,bcm2835-rng" - "brcm,bcm-nsp-rng" - "brcm,bcm5301x-rng" or - "brcm,bcm6368-rng" -- reg : Specifies base physical address and size of the registers. - -Optional properties: - -- clocks : phandle to clock-controller plus clock-specifier pair -- clock-names : "ipsec" as a clock name - -Optional properties: - -- interrupts: specify the interrupt for the RNG block - -Example: - -rng { - compatible = "brcm,bcm2835-rng"; - reg = <0x7e104000 0x10>; - interrupts = <2 29>; -}; - -rng@18033000 { - compatible = "brcm,bcm-nsp-rng"; - reg = <0x18033000 0x14>; -}; - -random: rng@10004180 { - compatible = "brcm,bcm6368-rng"; - reg = <0x10004180 0x14>; - - clocks = <&periph_clk 18>; - clock-names = "ipsec"; -}; diff --git a/Documentation/devicetree/bindings/rng/brcm,bcm2835.yaml b/Documentation/devicetree/bindings/rng/brcm,bcm2835.yaml new file mode 100644 index 000000000000..42d9a38e4e1a --- /dev/null +++ b/Documentation/devicetree/bindings/rng/brcm,bcm2835.yaml @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/rng/brcm,bcm2835.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: BCM2835/6368 Random number generator + +maintainers: + - Stefan Wahren + - Florian Fainelli + - Herbert Xu + +properties: + compatible: + enum: + - brcm,bcm2835-rng + - brcm,bcm-nsp-rng + - brcm,bcm5301x-rng + - brcm,bcm6368-rng + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + const: ipsec + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + +examples: + - | + rng { + compatible = "brcm,bcm2835-rng"; + reg = <0x7e104000 0x10>; + interrupts = <2 29>; + }; + + - | + rng@18033000 { + compatible = "brcm,bcm-nsp-rng"; + reg = <0x18033000 0x14>; + }; + + - | + rng@10004180 { + compatible = "brcm,bcm6368-rng"; + reg = <0x10004180 0x14>; + + clocks = <&periph_clk 18>; + clock-names = "ipsec"; + }; From 689e16ed2b1e559eb84e16651261e5bcbf13d7e3 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Sun, 23 Feb 2020 04:16:12 +0100 Subject: [PATCH 0881/4444] dt-bindings: vendor-prefixes: Add prefix for PocketBook International SA Call it "pocketbook". Signed-off-by: Ondrej Jirman Acked-by: Maxime Ripard Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index a97601e0e537..fcdda587def5 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -767,6 +767,8 @@ patternProperties: description: Broadcom Corporation (formerly PLX Technology) "^pni,.*": description: PNI Sensor Corporation + "^pocketbook,.*": + description: PocketBook International SA "^polaroid,.*": description: Polaroid Corporation "^portwell,.*": From 6e2a7b5171ec7fd6005639479961ca28e70d4929 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Wed, 19 Feb 2020 11:19:15 +0100 Subject: [PATCH 0882/4444] s390/qdio: use QDIO_IRQ_STATE_INACTIVE instead of 0 Don't rely on the numeric value of enum constants. Signed-off-by: Julian Wiedmann Reviewed-by: Benjamin Block Signed-off-by: Vasily Gorbik --- drivers/s390/cio/qdio_setup.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index c56ff92c6e0c..d57b115867a3 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -462,7 +462,8 @@ int qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data) memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat)); irq_ptr->debugfs_dev = irq_ptr->debugfs_perf = NULL; - irq_ptr->sch_token = irq_ptr->state = irq_ptr->perf_stat_enabled = 0; + irq_ptr->sch_token = irq_ptr->perf_stat_enabled = 0; + irq_ptr->state = QDIO_IRQ_STATE_INACTIVE; /* wipes qib.ac, required by ar7063 */ memset(irq_ptr->qdr, 0, sizeof(struct qdr)); From d5d006fa0927c34fa083c8d48e33b1c30b29fd1b Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 21 Feb 2020 10:54:41 +0100 Subject: [PATCH 0883/4444] s390/qdio: simplify debugfs code There's no need for error handling, the debugfs core is smart enough to deal with IS_ERR() internally. This will also keep us from creating the debugfs files if the device directory doesn't exist. Currently (because irq_ptr->debugfs_dev gets set to NULL on error) the files would be placed into the debugfs root - without any association to their parent device. On teardown, use the debugfs_remove_recursive() helper to avoid keeping track of each created file/directory. Signed-off-by: Julian Wiedmann Reviewed-by: Benjamin Block Signed-off-by: Vasily Gorbik --- drivers/s390/cio/qdio.h | 2 -- drivers/s390/cio/qdio_debug.c | 34 ++++++++-------------------------- drivers/s390/cio/qdio_setup.c | 2 +- 3 files changed, 9 insertions(+), 29 deletions(-) diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 85d530927e4e..e24a2cde487a 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -254,7 +254,6 @@ struct qdio_q { /* upper-layer program handler */ qdio_handler_t (*handler); - struct dentry *debugfs_q; struct qdio_irq *irq_ptr; struct sl *sl; /* @@ -270,7 +269,6 @@ struct qdio_irq { struct ccw_device *cdev; struct list_head entry; /* list of thinint devices */ struct dentry *debugfs_dev; - struct dentry *debugfs_perf; unsigned long int_parm; struct subchannel_id schid; diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index 9c0370b27426..bf8d82503870 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c @@ -284,17 +284,14 @@ static const struct file_operations debugfs_perf_fops = { .release = single_release, }; -static void setup_debugfs_entry(struct qdio_q *q) +static void setup_debugfs_entry(struct dentry *parent, struct qdio_q *q) { char name[QDIO_DEBUGFS_NAME_LEN]; snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d", q->is_input_q ? "input" : "output", q->nr); - q->debugfs_q = debugfs_create_file(name, 0444, - q->irq_ptr->debugfs_dev, q, &qstat_fops); - if (IS_ERR(q->debugfs_q)) - q->debugfs_q = NULL; + debugfs_create_file(name, 0444, parent, q, &qstat_fops); } void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev) @@ -304,33 +301,18 @@ void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev) irq_ptr->debugfs_dev = debugfs_create_dir(dev_name(&cdev->dev), debugfs_root); - if (IS_ERR(irq_ptr->debugfs_dev)) - irq_ptr->debugfs_dev = NULL; - - irq_ptr->debugfs_perf = debugfs_create_file("statistics", - S_IFREG | S_IRUGO | S_IWUSR, - irq_ptr->debugfs_dev, irq_ptr, - &debugfs_perf_fops); - if (IS_ERR(irq_ptr->debugfs_perf)) - irq_ptr->debugfs_perf = NULL; + debugfs_create_file("statistics", S_IFREG | S_IRUGO | S_IWUSR, + irq_ptr->debugfs_dev, irq_ptr, &debugfs_perf_fops); for_each_input_queue(irq_ptr, q, i) - setup_debugfs_entry(q); + setup_debugfs_entry(irq_ptr->debugfs_dev, q); for_each_output_queue(irq_ptr, q, i) - setup_debugfs_entry(q); + setup_debugfs_entry(irq_ptr->debugfs_dev, q); } void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr) { - struct qdio_q *q; - int i; - - for_each_input_queue(irq_ptr, q, i) - debugfs_remove(q->debugfs_q); - for_each_output_queue(irq_ptr, q, i) - debugfs_remove(q->debugfs_q); - debugfs_remove(irq_ptr->debugfs_perf); - debugfs_remove(irq_ptr->debugfs_dev); + debugfs_remove_recursive(irq_ptr->debugfs_dev); } int __init qdio_debug_init(void) @@ -352,7 +334,7 @@ int __init qdio_debug_init(void) void qdio_debug_exit(void) { qdio_clear_dbf_list(); - debugfs_remove(debugfs_root); + debugfs_remove_recursive(debugfs_root); debug_unregister(qdio_dbf_setup); debug_unregister(qdio_dbf_error); } diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index d57b115867a3..ad04947a0032 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -461,7 +461,7 @@ int qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data) memset(&irq_ptr->ssqd_desc, 0, sizeof(irq_ptr->ssqd_desc)); memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat)); - irq_ptr->debugfs_dev = irq_ptr->debugfs_perf = NULL; + irq_ptr->debugfs_dev = NULL; irq_ptr->sch_token = irq_ptr->perf_stat_enabled = 0; irq_ptr->state = QDIO_IRQ_STATE_INACTIVE; From fa226f1d81e2d3798d30eaa14550d7f35c35e6f3 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 21 Feb 2020 09:06:12 -0600 Subject: [PATCH 0884/4444] s390: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Link: https://lkml.kernel.org/r/20200221150612.GA9717@embeddedor Signed-off-by: Gustavo A. R. Silva Signed-off-by: Vasily Gorbik --- arch/s390/appldata/appldata_os.c | 2 +- drivers/s390/block/dasd_diag.c | 2 +- drivers/s390/block/dasd_eckd.h | 2 +- drivers/s390/char/raw3270.h | 2 +- drivers/s390/char/sclp_pci.c | 2 +- drivers/s390/cio/idset.c | 2 +- drivers/s390/crypto/pkey_api.c | 2 +- drivers/s390/crypto/zcrypt_ccamisc.h | 2 +- drivers/s390/crypto/zcrypt_msgtype6.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c index 54f375627532..8bf46d705957 100644 --- a/arch/s390/appldata/appldata_os.c +++ b/arch/s390/appldata/appldata_os.c @@ -75,7 +75,7 @@ struct appldata_os_data { (waiting for I/O) */ /* per cpu data */ - struct appldata_os_per_cpu os_cpu[0]; + struct appldata_os_per_cpu os_cpu[]; } __attribute__((packed)); static struct appldata_os_data *appldata_os_data; diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 8d4971645cf1..facb588d09e4 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -58,7 +58,7 @@ struct dasd_diag_private { struct dasd_diag_req { unsigned int block_count; - struct dasd_diag_bio bio[0]; + struct dasd_diag_bio bio[]; }; static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */ diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index 6943508d0f1d..ca24a78a256e 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -220,7 +220,7 @@ struct LRE_eckd_data { __u8 imbedded_count; __u8 extended_operation; __u16 extended_parameter_length; - __u8 extended_parameter[0]; + __u8 extended_parameter[]; } __attribute__ ((packed)); /* Prefix data for format 0x00 and 0x01 */ diff --git a/drivers/s390/char/raw3270.h b/drivers/s390/char/raw3270.h index 3afaa35f7351..08f36e973b43 100644 --- a/drivers/s390/char/raw3270.h +++ b/drivers/s390/char/raw3270.h @@ -211,7 +211,7 @@ struct string struct list_head update; unsigned long size; unsigned long len; - char string[0]; + char string[]; } __attribute__ ((aligned(8))); static inline struct string * diff --git a/drivers/s390/char/sclp_pci.c b/drivers/s390/char/sclp_pci.c index 995e9196852e..a3e5a5fb0c1e 100644 --- a/drivers/s390/char/sclp_pci.c +++ b/drivers/s390/char/sclp_pci.c @@ -39,7 +39,7 @@ struct err_notify_evbuf { u8 atype; u32 fh; u32 fid; - u8 data[0]; + u8 data[]; } __packed; struct err_notify_sccb { diff --git a/drivers/s390/cio/idset.c b/drivers/s390/cio/idset.c index 835de44dbbcc..77d0ea7b381b 100644 --- a/drivers/s390/cio/idset.c +++ b/drivers/s390/cio/idset.c @@ -13,7 +13,7 @@ struct idset { int num_ssid; int num_id; - unsigned long bitmap[0]; + unsigned long bitmap[]; }; static inline unsigned long bitmap_size(int num_ssid, int num_id) diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index 2f33c5fcf676..74e63ec49068 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -80,7 +80,7 @@ struct clearaeskeytoken { u8 res1[3]; u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ u32 len; /* bytes actually stored in clearkey[] */ - u8 clearkey[0]; /* clear key value */ + u8 clearkey[]; /* clear key value */ } __packed; /* diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h index 3a9876d5ab0e..8b7a641671c9 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.h +++ b/drivers/s390/crypto/zcrypt_ccamisc.h @@ -90,7 +90,7 @@ struct cipherkeytoken { u16 kmf1; /* key management field 1 */ u16 kmf2; /* key management field 2 */ u16 kmf3; /* key management field 3 */ - u8 vdata[0]; /* variable part data follows */ + u8 vdata[]; /* variable part data follows */ } __packed; /* Some defines for the CCA AES cipherkeytoken kmf1 field */ diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c index a36251d138fb..eadd3a438a4b 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.c +++ b/drivers/s390/crypto/zcrypt_msgtype6.c @@ -590,7 +590,7 @@ struct type86x_reply { struct CPRBX cprbx; unsigned char pad[4]; /* 4 byte function code/rules block ? */ unsigned short length; - char text[0]; + char text[]; } __packed; struct type86_ep11_reply { From 4a559cd15dbc79958fa9b18ad4e8afe4a0bf4744 Mon Sep 17 00:00:00 2001 From: Torsten Duwe Date: Tue, 25 Feb 2020 15:34:30 +0100 Subject: [PATCH 0885/4444] s390/crypto: explicitly memzero stack key material in aes_s390.c aes_s390.c has several functions which allocate space for key material on the stack and leave the used keys there. It is considered good practice to clean these locations before the function returns. Link: https://lkml.kernel.org/r/20200221165511.GB6928@lst.de Signed-off-by: Torsten Duwe Signed-off-by: Harald Freudenberger Signed-off-by: Vasily Gorbik --- arch/s390/crypto/aes_s390.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index 1c23d84a9097..73044634d342 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c @@ -342,6 +342,7 @@ static int cbc_aes_crypt(struct skcipher_request *req, unsigned long modifier) memcpy(walk.iv, param.iv, AES_BLOCK_SIZE); ret = skcipher_walk_done(&walk, nbytes - n); } + memzero_explicit(¶m, sizeof(param)); return ret; } @@ -470,6 +471,8 @@ static int xts_aes_crypt(struct skcipher_request *req, unsigned long modifier) walk.dst.virt.addr, walk.src.virt.addr, n); ret = skcipher_walk_done(&walk, nbytes - n); } + memzero_explicit(&pcc_param, sizeof(pcc_param)); + memzero_explicit(&xts_param, sizeof(xts_param)); return ret; } From 701dc81e7412daaf3c5bf4bc55d35c8b1525112a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 19 Feb 2020 13:29:15 +0100 Subject: [PATCH 0886/4444] s390/mm: remove fake numa support It turned out that fake numa support is rather useless on s390, since there are no scenarios where there is any performance or other benefit when used. However it does provide maintenance cost and breaks from time to time. Therefore remove it. CONFIG_NUMA is still supported with a very small backend and only one node. This way userspace applications which require NUMA interfaces continue to work. Note that NODES_SHIFT is set to 1 (= 2 nodes) instead of 0 (= 1 node), since there is quite a bit of kernel code which assumes that more than one node is possible if CONFIG_NUMA is enabled. Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/Kconfig | 61 +--- arch/s390/include/asm/numa.h | 13 +- arch/s390/include/asm/topology.h | 9 +- arch/s390/kernel/setup.c | 1 + arch/s390/kernel/topology.c | 2 - arch/s390/numa/Makefile | 2 - arch/s390/numa/mode_emu.c | 577 ------------------------------- arch/s390/numa/numa.c | 147 +------- arch/s390/numa/numa_mode.h | 25 -- arch/s390/numa/toptree.c | 351 ------------------- arch/s390/numa/toptree.h | 61 ---- drivers/s390/char/sclp_cmd.c | 2 +- 12 files changed, 20 insertions(+), 1231 deletions(-) delete mode 100644 arch/s390/numa/mode_emu.c delete mode 100644 arch/s390/numa/numa_mode.h delete mode 100644 arch/s390/numa/toptree.c delete mode 100644 arch/s390/numa/toptree.h diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 8abe77536d9d..6b1f715dd8bb 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -450,14 +450,6 @@ config NR_CPUS config HOTPLUG_CPU def_bool y -# Some NUMA nodes have memory ranges that span -# other nodes. Even though a pfn is valid and -# between a node's start and end pfns, it may not -# reside on that node. See memmap_init_zone() -# for details. <- They meant memory holes! -config NODES_SPAN_OTHER_NODES - def_bool NUMA - config NUMA bool "NUMA support" depends on SCHED_TOPOLOGY @@ -467,58 +459,9 @@ config NUMA This option adds NUMA support to the kernel. - An operation mode can be selected by appending - numa= to the kernel command line. - - The default behaviour is identical to appending numa=plain to - the command line. This will create just one node with all - available memory and all CPUs in it. - config NODES_SHIFT - int "Maximum NUMA nodes (as a power of 2)" - range 1 10 - depends on NUMA - default "4" - help - Specify the maximum number of NUMA nodes available on the target - system. Increases memory reserved to accommodate various tables. - -menu "Select NUMA modes" - depends on NUMA - -config NUMA_EMU - bool "NUMA emulation" - default y - help - Numa emulation mode will split the available system memory into - equal chunks which then are distributed over the configured number - of nodes in a round-robin manner. - - The number of fake nodes is limited by the number of available memory - chunks (i.e. memory size / fake size) and the number of supported - nodes in the kernel. - - The CPUs are assigned to the nodes in a way that partially respects - the original machine topology (if supported by the machine). - Fair distribution of the CPUs is not guaranteed. - -config EMU_SIZE - hex "NUMA emulation memory chunk size" - default 0x10000000 - range 0x400000 0x100000000 - depends on NUMA_EMU - help - Select the default size by which the memory is chopped and then - assigned to emulated NUMA nodes. - - This can be overridden by specifying - - emu_size= - - on the kernel command line where also suffixes K, M, G, and T are - supported. - -endmenu + int + default "1" config SCHED_SMT def_bool n diff --git a/arch/s390/include/asm/numa.h b/arch/s390/include/asm/numa.h index 35f8cbe7e5bb..23cd5d1b734b 100644 --- a/arch/s390/include/asm/numa.h +++ b/arch/s390/include/asm/numa.h @@ -13,24 +13,13 @@ #ifdef CONFIG_NUMA #include -#include void numa_setup(void); -int numa_pfn_to_nid(unsigned long pfn); -int __node_distance(int a, int b); -void numa_update_cpu_topology(void); - -extern cpumask_t node_to_cpumask_map[MAX_NUMNODES]; -extern int numa_debug_enabled; #else static inline void numa_setup(void) { } -static inline void numa_update_cpu_topology(void) { } -static inline int numa_pfn_to_nid(unsigned long pfn) -{ - return 0; -} #endif /* CONFIG_NUMA */ + #endif /* _ASM_S390_NUMA_H */ diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h index cca406fdbe51..bd3417185e30 100644 --- a/arch/s390/include/asm/topology.h +++ b/arch/s390/include/asm/topology.h @@ -16,7 +16,6 @@ struct cpu_topology_s390 { unsigned short socket_id; unsigned short book_id; unsigned short drawer_id; - unsigned short node_id; unsigned short dedicated : 1; cpumask_t thread_mask; cpumask_t core_mask; @@ -71,19 +70,23 @@ static inline void topology_expect_change(void) { } #define cpu_to_node cpu_to_node static inline int cpu_to_node(int cpu) { - return cpu_topology[cpu].node_id; + return 0; } /* Returns a pointer to the cpumask of CPUs on node 'node'. */ #define cpumask_of_node cpumask_of_node static inline const struct cpumask *cpumask_of_node(int node) { - return &node_to_cpumask_map[node]; + return cpu_possible_mask; } #define pcibus_to_node(bus) __pcibus_to_node(bus) #define node_distance(a, b) __node_distance(a, b) +static inline int __node_distance(int a, int b) +{ + return 0; +} #else /* !CONFIG_NUMA */ diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index b2c2f75860e8..1158a63a8e0e 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -790,6 +790,7 @@ static void __init memblock_add_mem_detect_info(void) memblock_physmem_add(start, end - start); } memblock_set_bottom_up(false); + memblock_set_node(0, ULONG_MAX, &memblock.memory, 0); memblock_dump_all(); } diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 3627953007ed..c189f5d996ff 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c @@ -26,7 +26,6 @@ #include #include #include -#include #define PTF_HORIZONTAL (0UL) #define PTF_VERTICAL (1UL) @@ -267,7 +266,6 @@ static void update_cpu_masks(void) cpumask_set_cpu(cpu, &cpus_with_topology); } } - numa_update_cpu_topology(); } void store_topology(struct sysinfo_15_1_x *info) diff --git a/arch/s390/numa/Makefile b/arch/s390/numa/Makefile index 66c2dff74895..c89d26f4f77d 100644 --- a/arch/s390/numa/Makefile +++ b/arch/s390/numa/Makefile @@ -1,4 +1,2 @@ # SPDX-License-Identifier: GPL-2.0 obj-y += numa.o -obj-y += toptree.o -obj-$(CONFIG_NUMA_EMU) += mode_emu.o diff --git a/arch/s390/numa/mode_emu.c b/arch/s390/numa/mode_emu.c deleted file mode 100644 index 72d742bb2d17..000000000000 --- a/arch/s390/numa/mode_emu.c +++ /dev/null @@ -1,577 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * NUMA support for s390 - * - * NUMA emulation (aka fake NUMA) distributes the available memory to nodes - * without using real topology information about the physical memory of the - * machine. - * - * It distributes the available CPUs to nodes while respecting the original - * machine topology information. This is done by trying to avoid to separate - * CPUs which reside on the same book or even on the same MC. - * - * Because the current Linux scheduler code requires a stable cpu to node - * mapping, cores are pinned to nodes when the first CPU thread is set online. - * - * Copyright IBM Corp. 2015 - */ - -#define KMSG_COMPONENT "numa_emu" -#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include "numa_mode.h" -#include "toptree.h" - -/* Distances between the different system components */ -#define DIST_EMPTY 0 -#define DIST_CORE 1 -#define DIST_MC 2 -#define DIST_BOOK 3 -#define DIST_DRAWER 4 -#define DIST_MAX 5 - -/* Node distance reported to common code */ -#define EMU_NODE_DIST 10 - -/* Node ID for free (not yet pinned) cores */ -#define NODE_ID_FREE -1 - -/* Different levels of toptree */ -enum toptree_level {CORE, MC, BOOK, DRAWER, NODE, TOPOLOGY}; - -/* The two toptree IDs */ -enum {TOPTREE_ID_PHYS, TOPTREE_ID_NUMA}; - -/* Number of NUMA nodes */ -static int emu_nodes = 1; -/* NUMA stripe size */ -static unsigned long emu_size; - -/* - * Node to core pinning information updates are protected by - * "sched_domains_mutex". - */ -static struct { - s32 to_node_id[CONFIG_NR_CPUS]; /* Pinned core to node mapping */ - int total; /* Total number of pinned cores */ - int per_node_target; /* Cores per node without extra cores */ - int per_node[MAX_NUMNODES]; /* Number of cores pinned to node */ -} *emu_cores; - -/* - * Pin a core to a node - */ -static void pin_core_to_node(int core_id, int node_id) -{ - if (emu_cores->to_node_id[core_id] == NODE_ID_FREE) { - emu_cores->per_node[node_id]++; - emu_cores->to_node_id[core_id] = node_id; - emu_cores->total++; - } else { - WARN_ON(emu_cores->to_node_id[core_id] != node_id); - } -} - -/* - * Number of pinned cores of a node - */ -static int cores_pinned(struct toptree *node) -{ - return emu_cores->per_node[node->id]; -} - -/* - * ID of the node where the core is pinned (or NODE_ID_FREE) - */ -static int core_pinned_to_node_id(struct toptree *core) -{ - return emu_cores->to_node_id[core->id]; -} - -/* - * Number of cores in the tree that are not yet pinned - */ -static int cores_free(struct toptree *tree) -{ - struct toptree *core; - int count = 0; - - toptree_for_each(core, tree, CORE) { - if (core_pinned_to_node_id(core) == NODE_ID_FREE) - count++; - } - return count; -} - -/* - * Return node of core - */ -static struct toptree *core_node(struct toptree *core) -{ - return core->parent->parent->parent->parent; -} - -/* - * Return drawer of core - */ -static struct toptree *core_drawer(struct toptree *core) -{ - return core->parent->parent->parent; -} - -/* - * Return book of core - */ -static struct toptree *core_book(struct toptree *core) -{ - return core->parent->parent; -} - -/* - * Return mc of core - */ -static struct toptree *core_mc(struct toptree *core) -{ - return core->parent; -} - -/* - * Distance between two cores - */ -static int dist_core_to_core(struct toptree *core1, struct toptree *core2) -{ - if (core_drawer(core1)->id != core_drawer(core2)->id) - return DIST_DRAWER; - if (core_book(core1)->id != core_book(core2)->id) - return DIST_BOOK; - if (core_mc(core1)->id != core_mc(core2)->id) - return DIST_MC; - /* Same core or sibling on same MC */ - return DIST_CORE; -} - -/* - * Distance of a node to a core - */ -static int dist_node_to_core(struct toptree *node, struct toptree *core) -{ - struct toptree *core_node; - int dist_min = DIST_MAX; - - toptree_for_each(core_node, node, CORE) - dist_min = min(dist_min, dist_core_to_core(core_node, core)); - return dist_min == DIST_MAX ? DIST_EMPTY : dist_min; -} - -/* - * Unify will delete empty nodes, therefore recreate nodes. - */ -static void toptree_unify_tree(struct toptree *tree) -{ - int nid; - - toptree_unify(tree); - for (nid = 0; nid < emu_nodes; nid++) - toptree_get_child(tree, nid); -} - -/* - * Find the best/nearest node for a given core and ensure that no node - * gets more than "emu_cores->per_node_target + extra" cores. - */ -static struct toptree *node_for_core(struct toptree *numa, struct toptree *core, - int extra) -{ - struct toptree *node, *node_best = NULL; - int dist_cur, dist_best, cores_target; - - cores_target = emu_cores->per_node_target + extra; - dist_best = DIST_MAX; - node_best = NULL; - toptree_for_each(node, numa, NODE) { - /* Already pinned cores must use their nodes */ - if (core_pinned_to_node_id(core) == node->id) { - node_best = node; - break; - } - /* Skip nodes that already have enough cores */ - if (cores_pinned(node) >= cores_target) - continue; - dist_cur = dist_node_to_core(node, core); - if (dist_cur < dist_best) { - dist_best = dist_cur; - node_best = node; - } - } - return node_best; -} - -/* - * Find the best node for each core with respect to "extra" core count - */ -static void toptree_to_numa_single(struct toptree *numa, struct toptree *phys, - int extra) -{ - struct toptree *node, *core, *tmp; - - toptree_for_each_safe(core, tmp, phys, CORE) { - node = node_for_core(numa, core, extra); - if (!node) - return; - toptree_move(core, node); - pin_core_to_node(core->id, node->id); - } -} - -/* - * Move structures of given level to specified NUMA node - */ -static void move_level_to_numa_node(struct toptree *node, struct toptree *phys, - enum toptree_level level, bool perfect) -{ - int cores_free, cores_target = emu_cores->per_node_target; - struct toptree *cur, *tmp; - - toptree_for_each_safe(cur, tmp, phys, level) { - cores_free = cores_target - toptree_count(node, CORE); - if (perfect) { - if (cores_free == toptree_count(cur, CORE)) - toptree_move(cur, node); - } else { - if (cores_free >= toptree_count(cur, CORE)) - toptree_move(cur, node); - } - } -} - -/* - * Move structures of a given level to NUMA nodes. If "perfect" is specified - * move only perfectly fitting structures. Otherwise move also smaller - * than needed structures. - */ -static void move_level_to_numa(struct toptree *numa, struct toptree *phys, - enum toptree_level level, bool perfect) -{ - struct toptree *node; - - toptree_for_each(node, numa, NODE) - move_level_to_numa_node(node, phys, level, perfect); -} - -/* - * For the first run try to move the big structures - */ -static void toptree_to_numa_first(struct toptree *numa, struct toptree *phys) -{ - struct toptree *core; - - /* Always try to move perfectly fitting structures first */ - move_level_to_numa(numa, phys, DRAWER, true); - move_level_to_numa(numa, phys, DRAWER, false); - move_level_to_numa(numa, phys, BOOK, true); - move_level_to_numa(numa, phys, BOOK, false); - move_level_to_numa(numa, phys, MC, true); - move_level_to_numa(numa, phys, MC, false); - /* Now pin all the moved cores */ - toptree_for_each(core, numa, CORE) - pin_core_to_node(core->id, core_node(core)->id); -} - -/* - * Allocate new topology and create required nodes - */ -static struct toptree *toptree_new(int id, int nodes) -{ - struct toptree *tree; - int nid; - - tree = toptree_alloc(TOPOLOGY, id); - if (!tree) - goto fail; - for (nid = 0; nid < nodes; nid++) { - if (!toptree_get_child(tree, nid)) - goto fail; - } - return tree; -fail: - panic("NUMA emulation could not allocate topology"); -} - -/* - * Allocate and initialize core to node mapping - */ -static void __ref create_core_to_node_map(void) -{ - int i; - - emu_cores = memblock_alloc(sizeof(*emu_cores), 8); - if (!emu_cores) - panic("%s: Failed to allocate %zu bytes align=0x%x\n", - __func__, sizeof(*emu_cores), 8); - for (i = 0; i < ARRAY_SIZE(emu_cores->to_node_id); i++) - emu_cores->to_node_id[i] = NODE_ID_FREE; -} - -/* - * Move cores from physical topology into NUMA target topology - * and try to keep as much of the physical topology as possible. - */ -static struct toptree *toptree_to_numa(struct toptree *phys) -{ - static int first = 1; - struct toptree *numa; - int cores_total; - - cores_total = emu_cores->total + cores_free(phys); - emu_cores->per_node_target = cores_total / emu_nodes; - numa = toptree_new(TOPTREE_ID_NUMA, emu_nodes); - if (first) { - toptree_to_numa_first(numa, phys); - first = 0; - } - toptree_to_numa_single(numa, phys, 0); - toptree_to_numa_single(numa, phys, 1); - toptree_unify_tree(numa); - - WARN_ON(cpumask_weight(&phys->mask)); - return numa; -} - -/* - * Create a toptree out of the physical topology that we got from the hypervisor - */ -static struct toptree *toptree_from_topology(void) -{ - struct toptree *phys, *node, *drawer, *book, *mc, *core; - struct cpu_topology_s390 *top; - int cpu; - - phys = toptree_new(TOPTREE_ID_PHYS, 1); - - for_each_cpu(cpu, &cpus_with_topology) { - top = &cpu_topology[cpu]; - node = toptree_get_child(phys, 0); - drawer = toptree_get_child(node, top->drawer_id); - book = toptree_get_child(drawer, top->book_id); - mc = toptree_get_child(book, top->socket_id); - core = toptree_get_child(mc, smp_get_base_cpu(cpu)); - if (!drawer || !book || !mc || !core) - panic("NUMA emulation could not allocate memory"); - cpumask_set_cpu(cpu, &core->mask); - toptree_update_mask(mc); - } - return phys; -} - -/* - * Add toptree core to topology and create correct CPU masks - */ -static void topology_add_core(struct toptree *core) -{ - struct cpu_topology_s390 *top; - int cpu; - - for_each_cpu(cpu, &core->mask) { - top = &cpu_topology[cpu]; - cpumask_copy(&top->thread_mask, &core->mask); - cpumask_copy(&top->core_mask, &core_mc(core)->mask); - cpumask_copy(&top->book_mask, &core_book(core)->mask); - cpumask_copy(&top->drawer_mask, &core_drawer(core)->mask); - cpumask_set_cpu(cpu, &node_to_cpumask_map[core_node(core)->id]); - top->node_id = core_node(core)->id; - } -} - -/* - * Apply toptree to topology and create CPU masks - */ -static void toptree_to_topology(struct toptree *numa) -{ - struct toptree *core; - int i; - - /* Clear all node masks */ - for (i = 0; i < MAX_NUMNODES; i++) - cpumask_clear(&node_to_cpumask_map[i]); - - /* Rebuild all masks */ - toptree_for_each(core, numa, CORE) - topology_add_core(core); -} - -/* - * Show the node to core mapping - */ -static void print_node_to_core_map(void) -{ - int nid, cid; - - if (!numa_debug_enabled) - return; - printk(KERN_DEBUG "NUMA node to core mapping\n"); - for (nid = 0; nid < emu_nodes; nid++) { - printk(KERN_DEBUG " node %3d: ", nid); - for (cid = 0; cid < ARRAY_SIZE(emu_cores->to_node_id); cid++) { - if (emu_cores->to_node_id[cid] == nid) - printk(KERN_CONT "%d ", cid); - } - printk(KERN_CONT "\n"); - } -} - -static void pin_all_possible_cpus(void) -{ - int core_id, node_id, cpu; - static int initialized; - - if (initialized) - return; - print_node_to_core_map(); - node_id = 0; - for_each_possible_cpu(cpu) { - core_id = smp_get_base_cpu(cpu); - if (emu_cores->to_node_id[core_id] != NODE_ID_FREE) - continue; - pin_core_to_node(core_id, node_id); - cpu_topology[cpu].node_id = node_id; - node_id = (node_id + 1) % emu_nodes; - } - print_node_to_core_map(); - initialized = 1; -} - -/* - * Transfer physical topology into a NUMA topology and modify CPU masks - * according to the NUMA topology. - * - * Must be called with "sched_domains_mutex" lock held. - */ -static void emu_update_cpu_topology(void) -{ - struct toptree *phys, *numa; - - if (emu_cores == NULL) - create_core_to_node_map(); - phys = toptree_from_topology(); - numa = toptree_to_numa(phys); - toptree_free(phys); - toptree_to_topology(numa); - toptree_free(numa); - pin_all_possible_cpus(); -} - -/* - * If emu_size is not set, use CONFIG_EMU_SIZE. Then round to minimum - * alignment (needed for memory hotplug). - */ -static unsigned long emu_setup_size_adjust(unsigned long size) -{ - unsigned long size_new; - - size = size ? : CONFIG_EMU_SIZE; - size_new = roundup(size, memory_block_size_bytes()); - if (size_new == size) - return size; - pr_warn("Increasing memory stripe size from %ld MB to %ld MB\n", - size >> 20, size_new >> 20); - return size_new; -} - -/* - * If we have not enough memory for the specified nodes, reduce the node count. - */ -static int emu_setup_nodes_adjust(int nodes) -{ - int nodes_max; - - nodes_max = memblock.memory.total_size / emu_size; - nodes_max = max(nodes_max, 1); - if (nodes_max >= nodes) - return nodes; - pr_warn("Not enough memory for %d nodes, reducing node count\n", nodes); - return nodes_max; -} - -/* - * Early emu setup - */ -static void emu_setup(void) -{ - int nid; - - emu_size = emu_setup_size_adjust(emu_size); - emu_nodes = emu_setup_nodes_adjust(emu_nodes); - for (nid = 0; nid < emu_nodes; nid++) - node_set(nid, node_possible_map); - pr_info("Creating %d nodes with memory stripe size %ld MB\n", - emu_nodes, emu_size >> 20); -} - -/* - * Return node id for given page number - */ -static int emu_pfn_to_nid(unsigned long pfn) -{ - return (pfn / (emu_size >> PAGE_SHIFT)) % emu_nodes; -} - -/* - * Return stripe size - */ -static unsigned long emu_align(void) -{ - return emu_size; -} - -/* - * Return distance between two nodes - */ -static int emu_distance(int node1, int node2) -{ - return (node1 != node2) * EMU_NODE_DIST; -} - -/* - * Define callbacks for generic s390 NUMA infrastructure - */ -const struct numa_mode numa_mode_emu = { - .name = "emu", - .setup = emu_setup, - .update_cpu_topology = emu_update_cpu_topology, - .__pfn_to_nid = emu_pfn_to_nid, - .align = emu_align, - .distance = emu_distance, -}; - -/* - * Kernel parameter: emu_nodes= - */ -static int __init early_parse_emu_nodes(char *p) -{ - int count; - - if (!p || kstrtoint(p, 0, &count) != 0 || count <= 0) - return 0; - emu_nodes = min(count, MAX_NUMNODES); - return 0; -} -early_param("emu_nodes", early_parse_emu_nodes); - -/* - * Kernel parameter: emu_size=[[k|M|G|T]] - */ -static int __init early_parse_emu_size(char *p) -{ - if (p) - emu_size = memparse(p, NULL); - return 0; -} -early_param("emu_size", early_parse_emu_size); diff --git a/arch/s390/numa/numa.c b/arch/s390/numa/numa.c index d2910fa834c8..51c5a9f6e525 100644 --- a/arch/s390/numa/numa.c +++ b/arch/s390/numa/numa.c @@ -7,165 +7,36 @@ * Copyright IBM Corp. 2015 */ -#define KMSG_COMPONENT "numa" -#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt - #include #include #include #include -#include #include - #include -#include "numa_mode.h" -pg_data_t *node_data[MAX_NUMNODES]; +struct pglist_data *node_data[MAX_NUMNODES]; EXPORT_SYMBOL(node_data); -cpumask_t node_to_cpumask_map[MAX_NUMNODES]; -EXPORT_SYMBOL(node_to_cpumask_map); - -static void plain_setup(void) +void __init numa_setup(void) { + int nid; + + nodes_clear(node_possible_map); node_set(0, node_possible_map); -} - -const struct numa_mode numa_mode_plain = { - .name = "plain", - .setup = plain_setup, -}; - -static const struct numa_mode *mode = &numa_mode_plain; - -int numa_pfn_to_nid(unsigned long pfn) -{ - return mode->__pfn_to_nid ? mode->__pfn_to_nid(pfn) : 0; -} - -void numa_update_cpu_topology(void) -{ - if (mode->update_cpu_topology) - mode->update_cpu_topology(); -} - -int __node_distance(int a, int b) -{ - return mode->distance ? mode->distance(a, b) : 0; -} -EXPORT_SYMBOL(__node_distance); - -int numa_debug_enabled; - -/* - * numa_setup_memory() - Assign bootmem to nodes - * - * The memory is first added to memblock without any respect to nodes. - * This is fixed before remaining memblock memory is handed over to the - * buddy allocator. - * An important side effect is that large bootmem allocations might easily - * cross node boundaries, which can be needed for large allocations with - * smaller memory stripes in each node (i.e. when using NUMA emulation). - * - * Memory defines nodes: - * Therefore this routine also sets the nodes online with memory. - */ -static void __init numa_setup_memory(void) -{ - unsigned long cur_base, align, end_of_dram; - int nid = 0; - - end_of_dram = memblock_end_of_DRAM(); - align = mode->align ? mode->align() : ULONG_MAX; - - /* - * Step through all available memory and assign it to the nodes - * indicated by the mode implementation. - * All nodes which are seen here will be set online. - */ - cur_base = 0; - do { - nid = numa_pfn_to_nid(PFN_DOWN(cur_base)); - node_set_online(nid); - memblock_set_node(cur_base, align, &memblock.memory, nid); - cur_base += align; - } while (cur_base < end_of_dram); - - /* Allocate and fill out node_data */ + node_set_online(0); for (nid = 0; nid < MAX_NUMNODES; nid++) { NODE_DATA(nid) = memblock_alloc(sizeof(pg_data_t), 8); if (!NODE_DATA(nid)) panic("%s: Failed to allocate %zu bytes align=0x%x\n", __func__, sizeof(pg_data_t), 8); } - - for_each_online_node(nid) { - unsigned long start_pfn, end_pfn; - unsigned long t_start, t_end; - int i; - - start_pfn = ULONG_MAX; - end_pfn = 0; - for_each_mem_pfn_range(i, nid, &t_start, &t_end, NULL) { - if (t_start < start_pfn) - start_pfn = t_start; - if (t_end > end_pfn) - end_pfn = t_end; - } - NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn; - NODE_DATA(nid)->node_id = nid; - } + NODE_DATA(0)->node_spanned_pages = memblock_end_of_DRAM() >> PAGE_SHIFT; + NODE_DATA(0)->node_id = 0; } -/* - * numa_setup() - Earliest initialization - * - * Assign the mode and call the mode's setup routine. - */ -void __init numa_setup(void) -{ - pr_info("NUMA mode: %s\n", mode->name); - nodes_clear(node_possible_map); - /* Initially attach all possible CPUs to node 0. */ - cpumask_copy(&node_to_cpumask_map[0], cpu_possible_mask); - if (mode->setup) - mode->setup(); - numa_setup_memory(); - memblock_dump_all(); -} - -/* - * numa_init_late() - Initialization initcall - * - * Register NUMA nodes. - */ static int __init numa_init_late(void) { - int nid; - - for_each_online_node(nid) - register_one_node(nid); + register_one_node(0); return 0; } arch_initcall(numa_init_late); - -static int __init parse_debug(char *parm) -{ - numa_debug_enabled = 1; - return 0; -} -early_param("numa_debug", parse_debug); - -static int __init parse_numa(char *parm) -{ - if (!parm) - return 1; - if (strcmp(parm, numa_mode_plain.name) == 0) - mode = &numa_mode_plain; -#ifdef CONFIG_NUMA_EMU - if (strcmp(parm, numa_mode_emu.name) == 0) - mode = &numa_mode_emu; -#endif - return 0; -} -early_param("numa", parse_numa); diff --git a/arch/s390/numa/numa_mode.h b/arch/s390/numa/numa_mode.h deleted file mode 100644 index dfd3e2784081..000000000000 --- a/arch/s390/numa/numa_mode.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * NUMA support for s390 - * - * Define declarations used for communication between NUMA mode - * implementations and NUMA core functionality. - * - * Copyright IBM Corp. 2015 - */ -#ifndef __S390_NUMA_MODE_H -#define __S390_NUMA_MODE_H - -struct numa_mode { - char *name; /* Name of mode */ - void (*setup)(void); /* Initizalize mode */ - void (*update_cpu_topology)(void); /* Called by topology code */ - int (*__pfn_to_nid)(unsigned long pfn); /* PFN to node ID */ - unsigned long (*align)(void); /* Minimum node alignment */ - int (*distance)(int a, int b); /* Distance between two nodes */ -}; - -extern const struct numa_mode numa_mode_plain; -extern const struct numa_mode numa_mode_emu; - -#endif /* __S390_NUMA_MODE_H */ diff --git a/arch/s390/numa/toptree.c b/arch/s390/numa/toptree.c deleted file mode 100644 index 71a608cd4f61..000000000000 --- a/arch/s390/numa/toptree.c +++ /dev/null @@ -1,351 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * NUMA support for s390 - * - * A tree structure used for machine topology mangling - * - * Copyright IBM Corp. 2015 - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "toptree.h" - -/** - * toptree_alloc - Allocate and initialize a new tree node. - * @level: The node's vertical level; level 0 contains the leaves. - * @id: ID number, explicitly not unique beyond scope of node's siblings - * - * Allocate a new tree node and initialize it. - * - * RETURNS: - * Pointer to the new tree node or NULL on error - */ -struct toptree __ref *toptree_alloc(int level, int id) -{ - struct toptree *res; - - if (slab_is_available()) - res = kzalloc(sizeof(*res), GFP_KERNEL); - else - res = memblock_alloc(sizeof(*res), 8); - if (!res) - return res; - - INIT_LIST_HEAD(&res->children); - INIT_LIST_HEAD(&res->sibling); - cpumask_clear(&res->mask); - res->level = level; - res->id = id; - return res; -} - -/** - * toptree_remove - Remove a tree node from a tree - * @cand: Pointer to the node to remove - * - * The node is detached from its parent node. The parent node's - * masks will be updated to reflect the loss of the child. - */ -static void toptree_remove(struct toptree *cand) -{ - struct toptree *oldparent; - - list_del_init(&cand->sibling); - oldparent = cand->parent; - cand->parent = NULL; - toptree_update_mask(oldparent); -} - -/** - * toptree_free - discard a tree node - * @cand: Pointer to the tree node to discard - * - * Checks if @cand is attached to a parent node. Detaches it - * cleanly using toptree_remove. Possible children are freed - * recursively. In the end @cand itself is freed. - */ -void __ref toptree_free(struct toptree *cand) -{ - struct toptree *child, *tmp; - - if (cand->parent) - toptree_remove(cand); - toptree_for_each_child_safe(child, tmp, cand) - toptree_free(child); - if (slab_is_available()) - kfree(cand); - else - memblock_free_early((unsigned long)cand, sizeof(*cand)); -} - -/** - * toptree_update_mask - Update node bitmasks - * @cand: Pointer to a tree node - * - * The node's cpumask will be updated by combining all children's - * masks. Then toptree_update_mask is called recursively for the - * parent if applicable. - * - * NOTE: - * This must not be called on leaves. If called on a leaf, its - * CPU mask is cleared and lost. - */ -void toptree_update_mask(struct toptree *cand) -{ - struct toptree *child; - - cpumask_clear(&cand->mask); - list_for_each_entry(child, &cand->children, sibling) - cpumask_or(&cand->mask, &cand->mask, &child->mask); - if (cand->parent) - toptree_update_mask(cand->parent); -} - -/** - * toptree_insert - Insert a tree node into tree - * @cand: Pointer to the node to insert - * @target: Pointer to the node to which @cand will added as a child - * - * Insert a tree node into a tree. Masks will be updated automatically. - * - * RETURNS: - * 0 on success, -1 if NULL is passed as argument or the node levels - * don't fit. - */ -static int toptree_insert(struct toptree *cand, struct toptree *target) -{ - if (!cand || !target) - return -1; - if (target->level != (cand->level + 1)) - return -1; - list_add_tail(&cand->sibling, &target->children); - cand->parent = target; - toptree_update_mask(target); - return 0; -} - -/** - * toptree_move_children - Move all child nodes of a node to a new place - * @cand: Pointer to the node whose children are to be moved - * @target: Pointer to the node to which @cand's children will be attached - * - * Take all child nodes of @cand and move them using toptree_move. - */ -static void toptree_move_children(struct toptree *cand, struct toptree *target) -{ - struct toptree *child, *tmp; - - toptree_for_each_child_safe(child, tmp, cand) - toptree_move(child, target); -} - -/** - * toptree_unify - Merge children with same ID - * @cand: Pointer to node whose direct children should be made unique - * - * When mangling the tree it is possible that a node has two or more children - * which have the same ID. This routine merges these children into one and - * moves all children of the merged nodes into the unified node. - */ -void toptree_unify(struct toptree *cand) -{ - struct toptree *child, *tmp, *cand_copy; - - /* Threads cannot be split, cores are not split */ - if (cand->level < 2) - return; - - cand_copy = toptree_alloc(cand->level, 0); - toptree_for_each_child_safe(child, tmp, cand) { - struct toptree *tmpchild; - - if (!cpumask_empty(&child->mask)) { - tmpchild = toptree_get_child(cand_copy, child->id); - toptree_move_children(child, tmpchild); - } - toptree_free(child); - } - toptree_move_children(cand_copy, cand); - toptree_free(cand_copy); - - toptree_for_each_child(child, cand) - toptree_unify(child); -} - -/** - * toptree_move - Move a node to another context - * @cand: Pointer to the node to move - * @target: Pointer to the node where @cand should go - * - * In the easiest case @cand is exactly on the level below @target - * and will be immediately moved to the target. - * - * If @target's level is not the direct parent level of @cand, - * nodes for the missing levels are created and put between - * @cand and @target. The "stacking" nodes' IDs are taken from - * @cand's parents. - * - * After this it is likely to have redundant nodes in the tree - * which are addressed by means of toptree_unify. - */ -void toptree_move(struct toptree *cand, struct toptree *target) -{ - struct toptree *stack_target, *real_insert_point, *ptr, *tmp; - - if (cand->level + 1 == target->level) { - toptree_remove(cand); - toptree_insert(cand, target); - return; - } - - real_insert_point = NULL; - ptr = cand; - stack_target = NULL; - - do { - tmp = stack_target; - stack_target = toptree_alloc(ptr->level + 1, - ptr->parent->id); - toptree_insert(tmp, stack_target); - if (!real_insert_point) - real_insert_point = stack_target; - ptr = ptr->parent; - } while (stack_target->level < (target->level - 1)); - - toptree_remove(cand); - toptree_insert(cand, real_insert_point); - toptree_insert(stack_target, target); -} - -/** - * toptree_get_child - Access a tree node's child by its ID - * @cand: Pointer to tree node whose child is to access - * @id: The desired child's ID - * - * @cand's children are searched for a child with matching ID. - * If no match can be found, a new child with the desired ID - * is created and returned. - */ -struct toptree *toptree_get_child(struct toptree *cand, int id) -{ - struct toptree *child; - - toptree_for_each_child(child, cand) - if (child->id == id) - return child; - child = toptree_alloc(cand->level-1, id); - toptree_insert(child, cand); - return child; -} - -/** - * toptree_first - Find the first descendant on specified level - * @context: Pointer to tree node whose descendants are to be used - * @level: The level of interest - * - * RETURNS: - * @context's first descendant on the specified level, or NULL - * if there is no matching descendant - */ -struct toptree *toptree_first(struct toptree *context, int level) -{ - struct toptree *child, *tmp; - - if (context->level == level) - return context; - - if (!list_empty(&context->children)) { - list_for_each_entry(child, &context->children, sibling) { - tmp = toptree_first(child, level); - if (tmp) - return tmp; - } - } - return NULL; -} - -/** - * toptree_next_sibling - Return next sibling - * @cur: Pointer to a tree node - * - * RETURNS: - * If @cur has a parent and is not the last in the parent's children list, - * the next sibling is returned. Or NULL when there are no siblings left. - */ -static struct toptree *toptree_next_sibling(struct toptree *cur) -{ - if (cur->parent == NULL) - return NULL; - - if (cur == list_last_entry(&cur->parent->children, - struct toptree, sibling)) - return NULL; - return (struct toptree *) list_next_entry(cur, sibling); -} - -/** - * toptree_next - Tree traversal function - * @cur: Pointer to current element - * @context: Pointer to the root node of the tree or subtree to - * be traversed. - * @level: The level of interest. - * - * RETURNS: - * Pointer to the next node on level @level - * or NULL when there is no next node. - */ -struct toptree *toptree_next(struct toptree *cur, struct toptree *context, - int level) -{ - struct toptree *cur_context, *tmp; - - if (!cur) - return NULL; - - if (context->level == level) - return NULL; - - tmp = toptree_next_sibling(cur); - if (tmp != NULL) - return tmp; - - cur_context = cur; - while (cur_context->level < context->level - 1) { - /* Step up */ - cur_context = cur_context->parent; - /* Step aside */ - tmp = toptree_next_sibling(cur_context); - if (tmp != NULL) { - /* Step down */ - tmp = toptree_first(tmp, level); - if (tmp != NULL) - return tmp; - } - } - return NULL; -} - -/** - * toptree_count - Count descendants on specified level - * @context: Pointer to node whose descendants are to be considered - * @level: Only descendants on the specified level will be counted - * - * RETURNS: - * Number of descendants on the specified level - */ -int toptree_count(struct toptree *context, int level) -{ - struct toptree *cur; - int cnt = 0; - - toptree_for_each(cur, context, level) - cnt++; - return cnt; -} diff --git a/arch/s390/numa/toptree.h b/arch/s390/numa/toptree.h deleted file mode 100644 index 5246371ec713..000000000000 --- a/arch/s390/numa/toptree.h +++ /dev/null @@ -1,61 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * NUMA support for s390 - * - * A tree structure used for machine topology mangling - * - * Copyright IBM Corp. 2015 - */ -#ifndef S390_TOPTREE_H -#define S390_TOPTREE_H - -#include -#include - -struct toptree { - int level; - int id; - cpumask_t mask; - struct toptree *parent; - struct list_head sibling; - struct list_head children; -}; - -struct toptree *toptree_alloc(int level, int id); -void toptree_free(struct toptree *cand); -void toptree_update_mask(struct toptree *cand); -void toptree_unify(struct toptree *cand); -struct toptree *toptree_get_child(struct toptree *cand, int id); -void toptree_move(struct toptree *cand, struct toptree *target); -int toptree_count(struct toptree *context, int level); - -struct toptree *toptree_first(struct toptree *context, int level); -struct toptree *toptree_next(struct toptree *cur, struct toptree *context, - int level); - -#define toptree_for_each_child(child, ptree) \ - list_for_each_entry(child, &ptree->children, sibling) - -#define toptree_for_each_child_safe(child, ptmp, ptree) \ - list_for_each_entry_safe(child, ptmp, &ptree->children, sibling) - -#define toptree_is_last(ptree) \ - ((ptree->parent == NULL) || \ - (ptree->parent->children.prev == &ptree->sibling)) - -#define toptree_for_each(ptree, cont, ttype) \ - for (ptree = toptree_first(cont, ttype); \ - ptree != NULL; \ - ptree = toptree_next(ptree, cont, ttype)) - -#define toptree_for_each_safe(ptree, tmp, cont, ttype) \ - for (ptree = toptree_first(cont, ttype), \ - tmp = toptree_next(ptree, cont, ttype); \ - ptree != NULL; \ - ptree = tmp, \ - tmp = toptree_next(ptree, cont, ttype)) - -#define toptree_for_each_sibling(ptree, start) \ - toptree_for_each(ptree, start->parent, start->level) - -#endif /* S390_TOPTREE_H */ diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 37d42de06079..a864b21af602 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c @@ -406,7 +406,7 @@ static void __init add_memory_merged(u16 rn) if (!size) goto skip_add; for (addr = start; addr < start + size; addr += block_size) - add_memory(numa_pfn_to_nid(PFN_DOWN(addr)), addr, block_size); + add_memory(0, addr, block_size); skip_add: first_rn = rn; num = 1; From b749ebe77d6c251d3a049d43f7e43781409c969c Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Thu, 12 Dec 2019 21:07:51 -0600 Subject: [PATCH 0887/4444] dt-bindings: arm: cpu: Add TI AM335x and AM437x enable method Add enable-method binding for "ti,am3352" and "ti,am4372". Acked-by: Santosh Shilimkar Signed-off-by: Dave Gerlach Acked-by: Rob Herring Acked-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- Documentation/devicetree/bindings/arm/cpus.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/cpus.yaml b/Documentation/devicetree/bindings/arm/cpus.yaml index 7a9c3ce2dbef..57fd46d8dfe1 100644 --- a/Documentation/devicetree/bindings/arm/cpus.yaml +++ b/Documentation/devicetree/bindings/arm/cpus.yaml @@ -201,6 +201,8 @@ properties: - rockchip,rk3066-smp - socionext,milbeaut-m10v-smp - ste,dbx500-smp + - ti,am3352 + - ti,am4372 cpu-release-addr: $ref: '/schemas/types.yaml#/definitions/uint64' From 06ee7a950b6a342cd79590e7243bdda850141967 Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Thu, 12 Dec 2019 21:07:52 -0600 Subject: [PATCH 0888/4444] ARM: OMAP2+: pm33xx-core: Add cpuidle_ops for am335x/am437x am335x and am437x can now make use of the generic cpuidle-arm driver. This requires that we define init and suspend ops to be passed set as the cpuidle ops for the SoC. These ops are invoked directly at the last stage of the cpuidle-arm driver in order to allow low level platform code to run and bring the CPU the rest of the way into it's desired idle state. It is required that the CPUIDLE_METHOD_OF_DECLARE be called from code that is built in so define these ops in pm33xx-core where the always built-in portion of the PM code for these SoCs lives. Additionally, although an soc_suspend function is already exposed by the pm33xx platform code, it contains additional operations needed for full SoC suspend beyond what is needed for a relatively simple CPU suspend needed during cpuidle. To get around this introduce cpu_suspend ops to be used by the am335x and am437x PM driver for the last stage of cpuidle path. Acked-by: Santosh Shilimkar Signed-off-by: Dave Gerlach Acked-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/pm33xx-core.c | 117 ++++++++++++++++++++++++++- include/linux/platform_data/pm33xx.h | 3 + 2 files changed, 119 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/pm33xx-core.c b/arch/arm/mach-omap2/pm33xx-core.c index 7461b0346549..b36654186c79 100644 --- a/arch/arm/mach-omap2/pm33xx-core.c +++ b/arch/arm/mach-omap2/pm33xx-core.c @@ -6,11 +6,14 @@ * Dave Gerlach */ +#include +#include +#include #include #include #include -#include #include +#include #include #include #include @@ -35,6 +38,14 @@ static struct clockdomain *gfx_l4ls_clkdm; static void __iomem *scu_base; static struct omap_hwmod *rtc_oh; +static int (*idle_fn)(u32 wfi_flags); + +struct amx3_idle_state { + int wfi_flags; +}; + +static struct amx3_idle_state *idle_states; + static int am43xx_map_scu(void) { scu_base = ioremap(scu_a9_get_base(), SZ_256); @@ -201,6 +212,43 @@ static int am43xx_suspend(unsigned int state, int (*fn)(unsigned long), return ret; } +static int am33xx_cpu_suspend(int (*fn)(unsigned long), unsigned long args) +{ + int ret = 0; + + if (omap_irq_pending() || need_resched()) + return ret; + + ret = cpu_suspend(args, fn); + + return ret; +} + +static int am43xx_cpu_suspend(int (*fn)(unsigned long), unsigned long args) +{ + int ret = 0; + + if (!scu_base) + return 0; + + scu_power_mode(scu_base, SCU_PM_DORMANT); + ret = cpu_suspend(args, fn); + scu_power_mode(scu_base, SCU_PM_NORMAL); + + return ret; +} + +static void amx3_begin_suspend(void) +{ + cpu_idle_poll_ctrl(true); +} + +static void amx3_finish_suspend(void) +{ + cpu_idle_poll_ctrl(false); +} + + static struct am33xx_pm_sram_addr *amx3_get_sram_addrs(void) { if (soc_is_am33xx()) @@ -254,6 +302,9 @@ static void am43xx_prepare_rtc_resume(void) static struct am33xx_pm_platform_data am33xx_ops = { .init = am33xx_suspend_init, .soc_suspend = am33xx_suspend, + .cpu_suspend = am33xx_cpu_suspend, + .begin_suspend = amx3_begin_suspend, + .finish_suspend = amx3_finish_suspend, .get_sram_addrs = amx3_get_sram_addrs, .save_context = am33xx_save_context, .restore_context = am33xx_restore_context, @@ -266,6 +317,9 @@ static struct am33xx_pm_platform_data am33xx_ops = { static struct am33xx_pm_platform_data am43xx_ops = { .init = am43xx_suspend_init, .soc_suspend = am43xx_suspend, + .cpu_suspend = am43xx_cpu_suspend, + .begin_suspend = amx3_begin_suspend, + .finish_suspend = amx3_finish_suspend, .get_sram_addrs = amx3_get_sram_addrs, .save_context = am43xx_save_context, .restore_context = am43xx_restore_context, @@ -301,3 +355,64 @@ int __init amx3_common_pm_init(void) return 0; } + +static int __init amx3_idle_init(struct device_node *cpu_node, int cpu) +{ + struct device_node *state_node; + struct amx3_idle_state states[CPUIDLE_STATE_MAX]; + int i; + int state_count = 1; + + for (i = 0; ; i++) { + state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i); + if (!state_node) + break; + + if (!of_device_is_available(state_node)) + continue; + + if (i == CPUIDLE_STATE_MAX) { + pr_warn("%s: cpuidle states reached max possible\n", + __func__); + break; + } + + states[state_count].wfi_flags = 0; + + if (of_property_read_bool(state_node, "ti,idle-wkup-m3")) + states[state_count].wfi_flags |= WFI_FLAG_WAKE_M3 | + WFI_FLAG_FLUSH_CACHE; + + state_count++; + } + + idle_states = kcalloc(state_count, sizeof(*idle_states), GFP_KERNEL); + if (!idle_states) + return -ENOMEM; + + for (i = 1; i < state_count; i++) + idle_states[i].wfi_flags = states[i].wfi_flags; + + return 0; +} + +static int amx3_idle_enter(unsigned long index) +{ + struct amx3_idle_state *idle_state = &idle_states[index]; + + if (!idle_state) + return -EINVAL; + + if (idle_fn) + idle_fn(idle_state->wfi_flags); + + return 0; +} + +static struct cpuidle_ops amx3_cpuidle_ops __initdata = { + .init = amx3_idle_init, + .suspend = amx3_idle_enter, +}; + +CPUIDLE_METHOD_OF_DECLARE(pm33xx_idle, "ti,am3352", &amx3_cpuidle_ops); +CPUIDLE_METHOD_OF_DECLARE(pm43xx_idle, "ti,am4372", &amx3_cpuidle_ops); diff --git a/include/linux/platform_data/pm33xx.h b/include/linux/platform_data/pm33xx.h index dd5971937a64..8e59f2db2adc 100644 --- a/include/linux/platform_data/pm33xx.h +++ b/include/linux/platform_data/pm33xx.h @@ -49,6 +49,9 @@ struct am33xx_pm_platform_data { int (*init)(void); int (*soc_suspend)(unsigned int state, int (*fn)(unsigned long), unsigned long args); + int (*cpu_suspend)(int (*fn)(unsigned long), unsigned long args); + void (*begin_suspend)(void); + void (*finish_suspend)(void); struct am33xx_pm_sram_addr *(*get_sram_addrs)(void); void __iomem *(*get_rtc_base_addr)(void); void (*save_context)(void); From 65880ab160838e0764138894ef4450abdbed4af5 Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Thu, 12 Dec 2019 21:07:53 -0600 Subject: [PATCH 0889/4444] ARM: OMAP2+: pm33xx-core: Extend platform_data ops for cpuidle In order for am335x and am437x to properly enter deeper c-states in cpuidle they must always call into the sleep33/43xx suspend code and also sometimes invoke the wkup_m3_ipc driver. These are both controlled by the pm33xx module so we must provide a method for the platform code to call back into the module when it is available as the core cpuidle ops that are invoked by the cpuidle-arm driver must remain as built in. Extend the init platform op to take an idle function as an argument so that we can use this to call into the pm33xx module for c-states that need it. Also add a deinit op so we can unregister this idle function from the PM core when the pm33xx module gets unloaded. Acked-by: Santosh Shilimkar Signed-off-by: Dave Gerlach Acked-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/pm33xx-core.c | 20 +++++++++++++++----- drivers/soc/ti/pm33xx.c | 2 +- include/linux/platform_data/pm33xx.h | 3 ++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-omap2/pm33xx-core.c b/arch/arm/mach-omap2/pm33xx-core.c index b36654186c79..5455fc98c60e 100644 --- a/arch/arm/mach-omap2/pm33xx-core.c +++ b/arch/arm/mach-omap2/pm33xx-core.c @@ -79,7 +79,7 @@ static int am43xx_check_off_mode_enable(void) return 0; } -static int amx3_common_init(void) +static int amx3_common_init(int (*idle)(u32 wfi_flags)) { gfx_pwrdm = pwrdm_lookup("gfx_pwrdm"); per_pwrdm = pwrdm_lookup("per_pwrdm"); @@ -99,10 +99,12 @@ static int amx3_common_init(void) else omap_set_pwrdm_state(cefuse_pwrdm, PWRDM_POWER_OFF); + idle_fn = idle; + return 0; } -static int am33xx_suspend_init(void) +static int am33xx_suspend_init(int (*idle)(u32 wfi_flags)) { int ret; @@ -113,12 +115,12 @@ static int am33xx_suspend_init(void) return -ENODEV; } - ret = amx3_common_init(); + ret = amx3_common_init(idle); return ret; } -static int am43xx_suspend_init(void) +static int am43xx_suspend_init(int (*idle)(u32 wfi_flags)) { int ret = 0; @@ -128,11 +130,17 @@ static int am43xx_suspend_init(void) return ret; } - ret = amx3_common_init(); + ret = amx3_common_init(idle); return ret; } +static int amx3_suspend_deinit(void) +{ + idle_fn = NULL; + return 0; +} + static void amx3_pre_suspend_common(void) { omap_set_pwrdm_state(gfx_pwrdm, PWRDM_POWER_OFF); @@ -301,6 +309,7 @@ static void am43xx_prepare_rtc_resume(void) static struct am33xx_pm_platform_data am33xx_ops = { .init = am33xx_suspend_init, + .deinit = amx3_suspend_deinit, .soc_suspend = am33xx_suspend, .cpu_suspend = am33xx_cpu_suspend, .begin_suspend = amx3_begin_suspend, @@ -316,6 +325,7 @@ static struct am33xx_pm_platform_data am33xx_ops = { static struct am33xx_pm_platform_data am43xx_ops = { .init = am43xx_suspend_init, + .deinit = amx3_suspend_deinit, .soc_suspend = am43xx_suspend, .cpu_suspend = am43xx_cpu_suspend, .begin_suspend = amx3_begin_suspend, diff --git a/drivers/soc/ti/pm33xx.c b/drivers/soc/ti/pm33xx.c index ccc6d53fe788..19bdcaca1f21 100644 --- a/drivers/soc/ti/pm33xx.c +++ b/drivers/soc/ti/pm33xx.c @@ -503,7 +503,7 @@ static int am33xx_pm_probe(struct platform_device *pdev) suspend_wfi_flags |= WFI_FLAG_WAKE_M3; #endif /* CONFIG_SUSPEND */ - ret = pm_ops->init(); + ret = pm_ops->init(NULL); if (ret) { dev_err(dev, "Unable to call core pm init!\n"); ret = -ENODEV; diff --git a/include/linux/platform_data/pm33xx.h b/include/linux/platform_data/pm33xx.h index 8e59f2db2adc..644af1d89cfa 100644 --- a/include/linux/platform_data/pm33xx.h +++ b/include/linux/platform_data/pm33xx.h @@ -46,7 +46,8 @@ struct am33xx_pm_sram_addr { }; struct am33xx_pm_platform_data { - int (*init)(void); + int (*init)(int (*idle)(u32 wfi_flags)); + int (*deinit)(void); int (*soc_suspend)(unsigned int state, int (*fn)(unsigned long), unsigned long args); int (*cpu_suspend)(int (*fn)(unsigned long), unsigned long args); From 6afaff1c6624f8901940db13709d0dac2b39e6da Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Thu, 12 Dec 2019 21:07:54 -0600 Subject: [PATCH 0890/4444] soc: ti: pm33xx: Add base cpuidle support Some cpuidle C-states supported on am335x and am437x, like C1 on am335x, require the use of the wkup_m3_ipc driver, and all C-states beyond C0 on both platforms require the use of the SRAM sleep code. Pass am33xx_do_sram_idle as the idle function to the platform pm core to be used by the cpuidle-arm driver when entering cpuidle states. am33xx_do_sram_idle will detect when the wkup_m3 is needed and ping it if necessary before calling the final cpu_suspend op which will execute the SRAM code to put the cpu into idle. Finally, use the begin_suspend and finish_suspend platform ops to be called at the beginning and end of suspend path to allow use of cpu_idle_poll_ctrl. This prevents races between cpuidle and suspend paths trying to communicate with the wkup_m3, as during suspend we only want it configured for entry to suspend. Acked-by: Santosh Shilimkar Signed-off-by: Dave Gerlach Acked-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- drivers/soc/ti/pm33xx.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/soc/ti/pm33xx.c b/drivers/soc/ti/pm33xx.c index 19bdcaca1f21..de0123ec8ad6 100644 --- a/drivers/soc/ti/pm33xx.c +++ b/drivers/soc/ti/pm33xx.c @@ -130,6 +130,19 @@ static int am33xx_push_sram_idle(void) return 0; } +static int am33xx_do_sram_idle(u32 wfi_flags) +{ + int ret = 0; + + if (!m3_ipc || !pm_ops) + return 0; + + if (wfi_flags & WFI_FLAG_WAKE_M3) + ret = m3_ipc->ops->prepare_low_power(m3_ipc, WKUP_M3_IDLE); + + return pm_ops->cpu_suspend(am33xx_do_wfi_sram, wfi_flags); +} + static int __init am43xx_map_gic(void) { gic_dist_base = ioremap(AM43XX_GIC_DIST_BASE, SZ_4K); @@ -260,6 +273,8 @@ static int am33xx_pm_begin(suspend_state_t state) rtc_only_idle = 0; } + pm_ops->begin_suspend(); + switch (state) { case PM_SUSPEND_MEM: ret = m3_ipc->ops->prepare_low_power(m3_ipc, WKUP_M3_DEEPSLEEP); @@ -301,6 +316,8 @@ static void am33xx_pm_end(void) } rtc_only_idle = 0; + + pm_ops->finish_suspend(); } static int am33xx_pm_valid(suspend_state_t state) @@ -503,7 +520,7 @@ static int am33xx_pm_probe(struct platform_device *pdev) suspend_wfi_flags |= WFI_FLAG_WAKE_M3; #endif /* CONFIG_SUSPEND */ - ret = pm_ops->init(NULL); + ret = pm_ops->init(am33xx_do_sram_idle); if (ret) { dev_err(dev, "Unable to call core pm init!\n"); ret = -ENODEV; @@ -522,6 +539,8 @@ err_free_sram: static int am33xx_pm_remove(struct platform_device *pdev) { + if (pm_ops->deinit) + pm_ops->deinit(); suspend_set_ops(NULL); wkup_m3_ipc_put(m3_ipc); am33xx_pm_free_sram(); From 73321b5f4dafc0a0e7389174ba7eaf558291a188 Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Thu, 12 Dec 2019 21:07:55 -0600 Subject: [PATCH 0891/4444] ARM: omap2plus_defconfig: Add CONFIG_ARM_CPUIDLE Add CONFIG_ARM_CPUIDLE and supporting CONFIG_DT_IDLE_STATES as am335x and am437x will make use of these drivers. Acked-by: Santosh Shilimkar Signed-off-by: Dave Gerlach Acked-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/configs/omap2plus_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index c32c338f7704..03ecf82c9fa1 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -56,6 +56,8 @@ CONFIG_CPUFREQ_DT=m # CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set CONFIG_ARM_TI_CPUFREQ=y CONFIG_CPU_IDLE=y +CONFIG_ARM_CPUIDLE=y +CONFIG_DT_IDLE_STATES=y CONFIG_KERNEL_MODE_NEON=y CONFIG_PM_DEBUG=y CONFIG_ARM_CRYPTO=y From c3e6fccafd6ecc6f59f63aedcc6dac0f01012c3a Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Thu, 12 Dec 2019 22:17:24 -0600 Subject: [PATCH 0892/4444] ARM: dts: am33xx: Add idle_states for cpuidle Add idle_states table for CPU on am335x. Currently just add C1 state which gates the MPU clock domain. Signed-off-by: Dave Gerlach Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am33xx.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi index 41dcfb37155a..430a634357a1 100644 --- a/arch/arm/boot/dts/am33xx.dtsi +++ b/arch/arm/boot/dts/am33xx.dtsi @@ -47,6 +47,7 @@ #size-cells = <0>; cpu@0 { compatible = "arm,cortex-a8"; + enable-method = "ti,am3352"; device_type = "cpu"; reg = <0>; @@ -56,6 +57,17 @@ clock-names = "cpu"; clock-latency = <300000>; /* From omap-cpufreq driver */ + cpu-idle-states = <&mpu_gate>; + }; + + idle-states { + mpu_gate: mpu_gate { + compatible = "arm,idle-state"; + entry-latency-us = <40>; + exit-latency-us = <90>; + min-residency-us = <300>; + ti,idle-wkup-m3; + }; }; }; From 89a7b191fcd17e3f1dba963eb2cba8262b45a4d2 Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Thu, 12 Dec 2019 22:17:25 -0600 Subject: [PATCH 0893/4444] ARM: dts: am4372: Add idle_states for cpuidle Add idle_states table for CPU on am437x. Currently just add C1 state which gates the MPU clock domain. Signed-off-by: Dave Gerlach Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am4372.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index faa14dc0faff..0001d4fa4d5d 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -45,6 +45,7 @@ #size-cells = <0>; cpu: cpu@0 { compatible = "arm,cortex-a9"; + enable-method = "ti,am4372"; device_type = "cpu"; reg = <0>; @@ -54,6 +55,17 @@ operating-points-v2 = <&cpu0_opp_table>; clock-latency = <300000>; /* From omap-cpufreq driver */ + cpu-idle-states = <&mpu_gate>; + }; + + idle-states { + mpu_gate: mpu_gate { + compatible = "arm,idle-state"; + entry-latency-us = <40>; + exit-latency-us = <100>; + min-residency-us = <300>; + local-timer-stop; + }; }; }; From bce967290977fc54c619f4165b8c40b809f44ed9 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Mon, 24 Feb 2020 17:21:50 -0600 Subject: [PATCH 0894/4444] ARM: OMAP2+: Drop hwmod data for am3 and am4 PRUSS The PRUSS hwmod is currently not used in DT, and the new DTS nodes shall be added using the ti-sysc infrastructure and the omap-prm reset driver. Drop the legacy hwmod data for the PRUSS module on both the AM33xx and AM437x family of SoCs. Signed-off-by: Suman Anna Signed-off-by: Tony Lindgren --- .../omap_hwmod_33xx_43xx_common_data.h | 2 -- .../omap_hwmod_33xx_43xx_interconnect_data.c | 8 ----- .../omap_hwmod_33xx_43xx_ipblock_data.c | 33 ------------------- arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 10 ------ arch/arm/mach-omap2/omap_hwmod_43xx_data.c | 9 ----- 5 files changed, 62 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h index 5ef76fe3f33d..75aabbf5ff22 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h @@ -24,7 +24,6 @@ extern struct omap_hwmod_ocp_if am33xx_l3_s__l4_wkup; extern struct omap_hwmod_ocp_if am33xx_l3_main__l3_instr; extern struct omap_hwmod_ocp_if am33xx_mpu__prcm; extern struct omap_hwmod_ocp_if am33xx_l3_s__l3_main; -extern struct omap_hwmod_ocp_if am33xx_pruss__l3_main; extern struct omap_hwmod_ocp_if am33xx_gfx__l3_main; extern struct omap_hwmod_ocp_if am33xx_l3_main__gfx; extern struct omap_hwmod_ocp_if am33xx_l4_wkup__rtc; @@ -42,7 +41,6 @@ extern struct omap_hwmod am33xx_l3_instr_hwmod; extern struct omap_hwmod am33xx_l4_ls_hwmod; extern struct omap_hwmod am33xx_l4_wkup_hwmod; extern struct omap_hwmod am33xx_mpu_hwmod; -extern struct omap_hwmod am33xx_pruss_hwmod; extern struct omap_hwmod am33xx_gfx_hwmod; extern struct omap_hwmod am33xx_prcm_hwmod; extern struct omap_hwmod am33xx_ocmcram_hwmod; diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c index ac7d5bb1a02f..4731946ee2ab 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c @@ -74,14 +74,6 @@ struct omap_hwmod_ocp_if am33xx_l3_s__l3_main = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; -/* pru-icss -> l3 main */ -struct omap_hwmod_ocp_if am33xx_pruss__l3_main = { - .master = &am33xx_pruss_hwmod, - .slave = &am33xx_l3_main_hwmod, - .clk = "l3_gclk", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - /* gfx -> l3 main */ struct omap_hwmod_ocp_if am33xx_gfx__l3_main = { .master = &am33xx_gfx_hwmod, diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c index 78ec1bc8e3a1..dc2a684d375d 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c @@ -133,34 +133,6 @@ struct omap_hwmod_class am33xx_wkup_m3_hwmod_class = { .name = "wkup_m3", }; -/* - * 'pru-icss' class - * Programmable Real-Time Unit and Industrial Communication Subsystem - */ -static struct omap_hwmod_class am33xx_pruss_hwmod_class = { - .name = "pruss", -}; - -static struct omap_hwmod_rst_info am33xx_pruss_resets[] = { - { .name = "pruss", .rst_shift = 1 }, -}; - -/* pru-icss */ -/* Pseudo hwmod for reset control purpose only */ -struct omap_hwmod am33xx_pruss_hwmod = { - .name = "pruss", - .class = &am33xx_pruss_hwmod_class, - .clkdm_name = "pruss_ocp_clkdm", - .main_clk = "pruss_ocp_gclk", - .prcm = { - .omap4 = { - .modulemode = MODULEMODE_SWCTRL, - }, - }, - .rst_lines = am33xx_pruss_resets, - .rst_lines_cnt = ARRAY_SIZE(am33xx_pruss_resets), -}; - /* gfx */ /* Pseudo hwmod for reset control purpose only */ static struct omap_hwmod_class am33xx_gfx_hwmod_class = { @@ -486,7 +458,6 @@ static void omap_hwmod_am33xx_clkctrl(void) CLKCTRL(am33xx_tptc1_hwmod, AM33XX_CM_PER_TPTC1_CLKCTRL_OFFSET); CLKCTRL(am33xx_tptc2_hwmod, AM33XX_CM_PER_TPTC2_CLKCTRL_OFFSET); CLKCTRL(am33xx_gfx_hwmod, AM33XX_CM_GFX_GFX_CLKCTRL_OFFSET); - CLKCTRL(am33xx_pruss_hwmod, AM33XX_CM_PER_PRUSS_CLKCTRL_OFFSET); CLKCTRL(am33xx_mpu_hwmod , AM33XX_CM_MPU_MPU_CLKCTRL_OFFSET); CLKCTRL(am33xx_l3_instr_hwmod , AM33XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET); CLKCTRL(am33xx_ocmcram_hwmod , AM33XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET); @@ -494,7 +465,6 @@ static void omap_hwmod_am33xx_clkctrl(void) static void omap_hwmod_am33xx_rst(void) { - RSTCTRL(am33xx_pruss_hwmod, AM33XX_RM_PER_RSTCTRL_OFFSET); RSTCTRL(am33xx_gfx_hwmod, AM33XX_RM_GFX_RSTCTRL_OFFSET); RSTST(am33xx_gfx_hwmod, AM33XX_RM_GFX_RSTST_OFFSET); } @@ -523,7 +493,6 @@ static void omap_hwmod_am43xx_clkctrl(void) CLKCTRL(am33xx_tptc1_hwmod, AM43XX_CM_PER_TPTC1_CLKCTRL_OFFSET); CLKCTRL(am33xx_tptc2_hwmod, AM43XX_CM_PER_TPTC2_CLKCTRL_OFFSET); CLKCTRL(am33xx_gfx_hwmod, AM43XX_CM_GFX_GFX_CLKCTRL_OFFSET); - CLKCTRL(am33xx_pruss_hwmod, AM43XX_CM_PER_PRUSS_CLKCTRL_OFFSET); CLKCTRL(am33xx_mpu_hwmod , AM43XX_CM_MPU_MPU_CLKCTRL_OFFSET); CLKCTRL(am33xx_l3_instr_hwmod , AM43XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET); CLKCTRL(am33xx_ocmcram_hwmod , AM43XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET); @@ -531,9 +500,7 @@ static void omap_hwmod_am43xx_clkctrl(void) static void omap_hwmod_am43xx_rst(void) { - RSTCTRL(am33xx_pruss_hwmod, AM43XX_RM_PER_RSTCTRL_OFFSET); RSTCTRL(am33xx_gfx_hwmod, AM43XX_RM_GFX_RSTCTRL_OFFSET); - RSTST(am33xx_pruss_hwmod, AM43XX_RM_PER_RSTST_OFFSET); RSTST(am33xx_gfx_hwmod, AM43XX_RM_GFX_RSTST_OFFSET); } diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c index f1ea8c604595..1c258616b9a9 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c @@ -233,14 +233,6 @@ static struct omap_hwmod_ocp_if am33xx_l4_wkup__wkup_m3 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; -/* l4 hs -> pru-icss */ -static struct omap_hwmod_ocp_if am33xx_l4_hs__pruss = { - .master = &am33xx_l4_hs_hwmod, - .slave = &am33xx_pruss_hwmod, - .clk = "dpll_core_m4_ck", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - /* l3_main -> debugss */ static struct omap_hwmod_ocp_if am33xx_l3_main__debugss = { .master = &am33xx_l3_main_hwmod, @@ -292,7 +284,6 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = { &am33xx_l3_main__l3_instr, &am33xx_l3_main__gfx, &am33xx_l3_s__l3_main, - &am33xx_pruss__l3_main, &am33xx_wkup_m3__l4_wkup, &am33xx_gfx__l3_main, &am33xx_l3_main__debugss, @@ -302,7 +293,6 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = { &am33xx_l4_wkup__smartreflex1, &am33xx_l4_wkup__timer1, &am33xx_l4_wkup__rtc, - &am33xx_l4_hs__pruss, &am33xx_l4_ls__timer2, &am33xx_l3_main__tpcc, &am33xx_l3_s__gpmc, diff --git a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c index d0867dbd788e..e939dde4a5fe 100644 --- a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c @@ -254,13 +254,6 @@ static struct omap_hwmod_ocp_if am43xx_l4_wkup__wkup_m3 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; -static struct omap_hwmod_ocp_if am43xx_l3_main__pruss = { - .master = &am33xx_l3_main_hwmod, - .slave = &am33xx_pruss_hwmod, - .clk = "dpll_core_m4_ck", - .user = OCP_USER_MPU, -}; - static struct omap_hwmod_ocp_if am43xx_l4_wkup__smartreflex0 = { .master = &am33xx_l4_wkup_hwmod, .slave = &am33xx_smartreflex0_hwmod, @@ -340,7 +333,6 @@ static struct omap_hwmod_ocp_if am43xx_l4_ls__dss_rfbi = { static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = { &am33xx_l4_wkup__synctimer, - &am43xx_l3_main__pruss, &am33xx_mpu__l3_main, &am33xx_mpu__prcm, &am33xx_l3_s__l4_ls, @@ -351,7 +343,6 @@ static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = { &am33xx_l3_main__gfx, &am33xx_l3_s__l3_main, &am43xx_l3_main__emif, - &am33xx_pruss__l3_main, &am43xx_wkup_m3__l4_wkup, &am33xx_gfx__l3_main, &am43xx_l4_wkup__wkup_m3, From 014bb57b6d1e5c0b3539beeca92510bd6e7394b2 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Mon, 24 Feb 2020 17:21:51 -0600 Subject: [PATCH 0895/4444] ARM: OMAP2+: Drop legacy platform data for OMAP4 DSP The OMAP4 DSP hwmod is used in DT, but the DT node is not probing any real driver. The DSP device-tree node shall be updated as per the new OMAP remoteproc bindings with the underneath MMU device relying on the ti-sysc infrastructure. Drop the legacy hwmod data for the DSP device along with the custom ti,hwmods property. They have to be dropped together since the early platform data init code is based on the custom ti,hwmods property. Signed-off-by: Suman Anna Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap4.dtsi | 1 - arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 76 ---------------------- 2 files changed, 77 deletions(-) diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 9a87440d0b9d..48b97f818a68 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -108,7 +108,6 @@ dsp { compatible = "ti,omap3-c64"; - ti,hwmods = "dsp"; }; iva { diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index b7c51ea8c9a6..1d4359a43cab 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -355,37 +355,6 @@ static struct omap_hwmod omap44xx_debugss_hwmod = { }, }; -/* - * 'dsp' class - * dsp sub-system - */ - -static struct omap_hwmod_class omap44xx_dsp_hwmod_class = { - .name = "dsp", -}; - -/* dsp */ -static struct omap_hwmod_rst_info omap44xx_dsp_resets[] = { - { .name = "dsp", .rst_shift = 0 }, -}; - -static struct omap_hwmod omap44xx_dsp_hwmod = { - .name = "dsp", - .class = &omap44xx_dsp_hwmod_class, - .clkdm_name = "tesla_clkdm", - .rst_lines = omap44xx_dsp_resets, - .rst_lines_cnt = ARRAY_SIZE(omap44xx_dsp_resets), - .main_clk = "dpll_iva_m4x2_ck", - .prcm = { - .omap4 = { - .clkctrl_offs = OMAP4_CM_TESLA_TESLA_CLKCTRL_OFFSET, - .rstctrl_offs = OMAP4_RM_TESLA_RSTCTRL_OFFSET, - .context_offs = OMAP4_RM_TESLA_TESLA_CONTEXT_OFFSET, - .modulemode = MODULEMODE_HWCTRL, - }, - }, -}; - /* * 'dss' class * display sub-system @@ -1236,14 +1205,6 @@ static struct omap_hwmod_ocp_if omap44xx_ocp_wp_noc__l3_instr = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; -/* dsp -> l3_main_1 */ -static struct omap_hwmod_ocp_if omap44xx_dsp__l3_main_1 = { - .master = &omap44xx_dsp_hwmod, - .slave = &omap44xx_l3_main_1_hwmod, - .clk = "l3_div_ck", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - /* dss -> l3_main_1 */ static struct omap_hwmod_ocp_if omap44xx_dss__l3_main_1 = { .master = &omap44xx_dss_hwmod, @@ -1364,14 +1325,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_3 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; -/* dsp -> l4_abe */ -static struct omap_hwmod_ocp_if omap44xx_dsp__l4_abe = { - .master = &omap44xx_dsp_hwmod, - .slave = &omap44xx_l4_abe_hwmod, - .clk = "ocp_abe_iclk", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - /* l3_main_1 -> l4_abe */ static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_abe = { .master = &omap44xx_l3_main_1_hwmod, @@ -1476,30 +1429,6 @@ static struct omap_hwmod_ocp_if omap44xx_l3_instr__debugss = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; -/* dsp -> iva */ -static struct omap_hwmod_ocp_if omap44xx_dsp__iva = { - .master = &omap44xx_dsp_hwmod, - .slave = &omap44xx_iva_hwmod, - .clk = "dpll_iva_m5x2_ck", - .user = OCP_USER_DSP, -}; - -/* dsp -> sl2if */ -static struct omap_hwmod_ocp_if __maybe_unused omap44xx_dsp__sl2if = { - .master = &omap44xx_dsp_hwmod, - .slave = &omap44xx_sl2if_hwmod, - .clk = "dpll_iva_m5x2_ck", - .user = OCP_USER_DSP, -}; - -/* l4_cfg -> dsp */ -static struct omap_hwmod_ocp_if omap44xx_l4_cfg__dsp = { - .master = &omap44xx_l4_cfg_hwmod, - .slave = &omap44xx_dsp_hwmod, - .clk = "l4_div_ck", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - /* l3_main_2 -> dss */ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = { .master = &omap44xx_l3_main_2_hwmod, @@ -1762,7 +1691,6 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { &omap44xx_iva__l3_instr, &omap44xx_l3_main_3__l3_instr, &omap44xx_ocp_wp_noc__l3_instr, - &omap44xx_dsp__l3_main_1, &omap44xx_dss__l3_main_1, &omap44xx_l3_main_2__l3_main_1, &omap44xx_l4_cfg__l3_main_1, @@ -1778,7 +1706,6 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { &omap44xx_l3_main_1__l3_main_3, &omap44xx_l3_main_2__l3_main_3, &omap44xx_l4_cfg__l3_main_3, - &omap44xx_dsp__l4_abe, &omap44xx_l3_main_1__l4_abe, &omap44xx_mpu__l4_abe, &omap44xx_l3_main_1__l4_cfg, @@ -1792,9 +1719,6 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { &omap44xx_l4_wkup__ctrl_module_wkup, &omap44xx_l4_wkup__ctrl_module_pad_wkup, &omap44xx_l3_instr__debugss, - &omap44xx_dsp__iva, - /* &omap44xx_dsp__sl2if, */ - &omap44xx_l4_cfg__dsp, &omap44xx_l3_main_2__dss, &omap44xx_l4_per__dss, &omap44xx_l3_main_2__dss_dispc, From 84a43fddbfe654acb0e9332ed23aa8a1aea4aaa4 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Mon, 24 Feb 2020 17:21:52 -0600 Subject: [PATCH 0896/4444] ARM: OMAP4: hwmod_data: Remove OMAP4 IPU hwmod data The OMAP4 IPU hwmod is currently not used in DT, and the new DTS node shall be added as per the new OMAP remoteproc bindings with the underneath MMU device relying on the ti-sysc infrastructure. Drop the legacy hwmod data for OMAP4 IPU as this will not be used going forward. Signed-off-by: Suman Anna Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 51 ---------------------- 1 file changed, 51 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 1d4359a43cab..a616ddf8fb52 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -706,39 +706,6 @@ static struct omap_hwmod omap44xx_gpmc_hwmod = { }, }; - -/* - * 'ipu' class - * imaging processor unit - */ - -static struct omap_hwmod_class omap44xx_ipu_hwmod_class = { - .name = "ipu", -}; - -/* ipu */ -static struct omap_hwmod_rst_info omap44xx_ipu_resets[] = { - { .name = "cpu0", .rst_shift = 0 }, - { .name = "cpu1", .rst_shift = 1 }, -}; - -static struct omap_hwmod omap44xx_ipu_hwmod = { - .name = "ipu", - .class = &omap44xx_ipu_hwmod_class, - .clkdm_name = "ducati_clkdm", - .rst_lines = omap44xx_ipu_resets, - .rst_lines_cnt = ARRAY_SIZE(omap44xx_ipu_resets), - .main_clk = "ducati_clk_mux_ck", - .prcm = { - .omap4 = { - .clkctrl_offs = OMAP4_CM_DUCATI_DUCATI_CLKCTRL_OFFSET, - .rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET, - .context_offs = OMAP4_RM_DUCATI_DUCATI_CONTEXT_OFFSET, - .modulemode = MODULEMODE_HWCTRL, - }, - }, -}; - /* * 'iss' class * external images sensor pixel data processor @@ -1245,14 +1212,6 @@ static struct omap_hwmod_ocp_if omap44xx_debugss__l3_main_2 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; -/* ipu -> l3_main_2 */ -static struct omap_hwmod_ocp_if omap44xx_ipu__l3_main_2 = { - .master = &omap44xx_ipu_hwmod, - .slave = &omap44xx_l3_main_2_hwmod, - .clk = "l3_div_ck", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - /* iss -> l3_main_2 */ static struct omap_hwmod_ocp_if omap44xx_iss__l3_main_2 = { .master = &omap44xx_iss_hwmod, @@ -1549,14 +1508,6 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__gpmc = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; -/* l3_main_2 -> ipu */ -static struct omap_hwmod_ocp_if omap44xx_l3_main_2__ipu = { - .master = &omap44xx_l3_main_2_hwmod, - .slave = &omap44xx_ipu_hwmod, - .clk = "l3_div_ck", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - /* l3_main_2 -> iss */ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iss = { .master = &omap44xx_l3_main_2_hwmod, @@ -1696,7 +1647,6 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { &omap44xx_l4_cfg__l3_main_1, &omap44xx_mpu__l3_main_1, &omap44xx_debugss__l3_main_2, - &omap44xx_ipu__l3_main_2, &omap44xx_iss__l3_main_2, &omap44xx_iva__l3_main_2, &omap44xx_l3_main_1__l3_main_2, @@ -1734,7 +1684,6 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { &omap44xx_l3_main_2__dss_venc, &omap44xx_l4_per__dss_venc, &omap44xx_l3_main_2__gpmc, - &omap44xx_l3_main_2__ipu, &omap44xx_l3_main_2__iss, /* &omap44xx_iva__sl2if, */ &omap44xx_l3_main_2__iva, From dc5a941223edd803f476a153abd950cc3a83c3e1 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Fri, 14 Feb 2020 17:45:12 +0800 Subject: [PATCH 0897/4444] f2fs: fix to wait all node page writeback There is a race condition that we may miss to wait for all node pages writeback, fix it. - fsync() - shrink - f2fs_do_sync_file - __write_node_page - set_page_writeback(page#0) : remove DIRTY/TOWRITE flag - f2fs_fsync_node_pages : won't find page #0 as TOWRITE flag was removeD - f2fs_wait_on_node_pages_writeback : wont' wait page #0 writeback as it was not in fsync_node_list list. - f2fs_add_fsync_node_entry Fixes: 50fa53eccf9f ("f2fs: fix to avoid broken of dnode block list") Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/node.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 9d02cdcdbb07..e58c4c628834 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1562,15 +1562,16 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, if (atomic && !test_opt(sbi, NOBARRIER)) fio.op_flags |= REQ_PREFLUSH | REQ_FUA; - set_page_writeback(page); - ClearPageError(page); - + /* should add to global list before clearing PAGECACHE status */ if (f2fs_in_warm_node_list(sbi, page)) { seq = f2fs_add_fsync_node_entry(sbi, page); if (seq_id) *seq_id = seq; } + set_page_writeback(page); + ClearPageError(page); + fio.old_blkaddr = ni.blk_addr; f2fs_do_write_node_page(nid, &fio); set_node_addr(sbi, &ni, fio.new_blkaddr, is_fsync_dnode(page)); From bf22c3cc8ce71454dddd772284773306a68031d8 Mon Sep 17 00:00:00 2001 From: Sahitya Tummala Date: Tue, 18 Feb 2020 09:19:07 +0530 Subject: [PATCH 0898/4444] f2fs: fix the panic in do_checkpoint() There could be a scenario where f2fs_sync_meta_pages() will not ensure that all F2FS_DIRTY_META pages are submitted for IO. Thus, resulting in the below panic in do_checkpoint() - f2fs_bug_on(sbi, get_pages(sbi, F2FS_DIRTY_META) && !f2fs_cp_error(sbi)); This can happen in a low-memory condition, where shrinker could also be doing the writepage operation (stack shown below) at the same time when checkpoint is running on another core. schedule down_write f2fs_submit_page_write -> by this time, this page in page cache is tagged as PAGECACHE_TAG_WRITEBACK and PAGECACHE_TAG_DIRTY is cleared, due to which f2fs_sync_meta_pages() cannot sync this page in do_checkpoint() path. f2fs_do_write_meta_page __f2fs_write_meta_page f2fs_write_meta_page shrink_page_list shrink_inactive_list shrink_node_memcg shrink_node kswapd Signed-off-by: Sahitya Tummala Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/checkpoint.c | 16 +++++++--------- fs/f2fs/f2fs.h | 2 +- fs/f2fs/super.c | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 44e84ac5c941..9c88fb3d255a 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -1250,20 +1250,20 @@ static void unblock_operations(struct f2fs_sb_info *sbi) f2fs_unlock_all(sbi); } -void f2fs_wait_on_all_pages_writeback(struct f2fs_sb_info *sbi) +void f2fs_wait_on_all_pages(struct f2fs_sb_info *sbi, int type) { DEFINE_WAIT(wait); for (;;) { prepare_to_wait(&sbi->cp_wait, &wait, TASK_UNINTERRUPTIBLE); - if (!get_pages(sbi, F2FS_WB_CP_DATA)) + if (!get_pages(sbi, type)) break; if (unlikely(f2fs_cp_error(sbi))) break; - io_schedule_timeout(5*HZ); + io_schedule_timeout(HZ/50); } finish_wait(&sbi->cp_wait, &wait); } @@ -1384,8 +1384,6 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) /* Flush all the NAT/SIT pages */ f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO); - f2fs_bug_on(sbi, get_pages(sbi, F2FS_DIRTY_META) && - !f2fs_cp_error(sbi)); /* * modify checkpoint @@ -1493,11 +1491,11 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) /* Here, we have one bio having CP pack except cp pack 2 page */ f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO); - f2fs_bug_on(sbi, get_pages(sbi, F2FS_DIRTY_META) && - !f2fs_cp_error(sbi)); + /* Wait for all dirty meta pages to be submitted for IO */ + f2fs_wait_on_all_pages(sbi, F2FS_DIRTY_META); /* wait for previous submitted meta pages writeback */ - f2fs_wait_on_all_pages_writeback(sbi); + f2fs_wait_on_all_pages(sbi, F2FS_WB_CP_DATA); /* flush all device cache */ err = f2fs_flush_device_cache(sbi); @@ -1506,7 +1504,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) /* barrier and flush checkpoint cp pack 2 page if it can */ commit_checkpoint(sbi, ckpt, start_blk); - f2fs_wait_on_all_pages_writeback(sbi); + f2fs_wait_on_all_pages(sbi, F2FS_WB_CP_DATA); /* * invalidate intermediate page cache borrowed from meta inode which are diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 5355be6b6755..d39f5de11420 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3308,7 +3308,7 @@ int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi); void f2fs_update_dirty_page(struct inode *inode, struct page *page); void f2fs_remove_dirty_inode(struct inode *inode); int f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type); -void f2fs_wait_on_all_pages_writeback(struct f2fs_sb_info *sbi); +void f2fs_wait_on_all_pages(struct f2fs_sb_info *sbi, int type); int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc); void f2fs_init_ino_entry_info(struct f2fs_sb_info *sbi); int __init f2fs_create_checkpoint_caches(void); diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 65a7a432dfee..686f5402660e 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1172,7 +1172,7 @@ static void f2fs_put_super(struct super_block *sb) /* our cp_error case, we can wait for any writeback page */ f2fs_flush_merged_writes(sbi); - f2fs_wait_on_all_pages_writeback(sbi); + f2fs_wait_on_all_pages(sbi, F2FS_WB_CP_DATA); f2fs_bug_on(sbi, sbi->fsync_node_num); From 7fa6d59816e7d81cfd4f854468c477c12b85c789 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 20 Feb 2020 20:50:37 -0800 Subject: [PATCH 0899/4444] f2fs: fix leaking uninitialized memory in compressed clusters When the compressed data of a cluster doesn't end on a page boundary, the remainder of the last page must be zeroed in order to avoid leaking uninitialized memory to disk. Fixes: 4c8ff7095bef ("f2fs: support data compression") Signed-off-by: Eric Biggers Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/compress.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index d8a64be90a50..ef7dd04312fe 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -385,11 +385,15 @@ static int f2fs_compress_pages(struct compress_ctx *cc) for (i = 0; i < COMPRESS_DATA_RESERVED_SIZE; i++) cc->cbuf->reserved[i] = cpu_to_le32(0); + nr_cpages = DIV_ROUND_UP(cc->clen + COMPRESS_HEADER_SIZE, PAGE_SIZE); + + /* zero out any unused part of the last page */ + memset(&cc->cbuf->cdata[cc->clen], 0, + (nr_cpages * PAGE_SIZE) - (cc->clen + COMPRESS_HEADER_SIZE)); + vunmap(cc->cbuf); vunmap(cc->rbuf); - nr_cpages = DIV_ROUND_UP(cc->clen + COMPRESS_HEADER_SIZE, PAGE_SIZE); - for (i = nr_cpages; i < cc->nr_cpages; i++) { f2fs_put_compressed_page(cc->cpages[i]); cc->cpages[i] = NULL; From 61fbae2b2b1201525f8f0f35e0bdf6dfa8ec8541 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 24 Feb 2020 19:20:17 +0800 Subject: [PATCH 0900/4444] f2fs: fix to avoid NULL pointer dereference Unable to handle kernel NULL pointer dereference at virtual address 00000000 PC is at f2fs_free_dic+0x60/0x2c8 LR is at f2fs_decompress_pages+0x3c4/0x3e8 f2fs_free_dic+0x60/0x2c8 f2fs_decompress_pages+0x3c4/0x3e8 __read_end_io+0x78/0x19c f2fs_post_read_work+0x6c/0x94 process_one_work+0x210/0x48c worker_thread+0x2e8/0x44c kthread+0x110/0x120 ret_from_fork+0x10/0x18 In f2fs_free_dic(), we can not use f2fs_put_page(,1) to release dic->tpages[i], as the page's mapping is NULL. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/compress.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index ef7dd04312fe..dde8ca08e94d 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -1137,7 +1137,8 @@ void f2fs_free_dic(struct decompress_io_ctx *dic) for (i = 0; i < dic->cluster_size; i++) { if (dic->rpages[i]) continue; - f2fs_put_page(dic->tpages[i], 1); + unlock_page(dic->tpages[i]); + put_page(dic->tpages[i]); } kfree(dic->tpages); } From 0b32dc186486822b636216985802ccf05c1a2c06 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 24 Feb 2020 19:20:18 +0800 Subject: [PATCH 0901/4444] f2fs: recycle unused compress_data.chksum feild In Struct compress_data, chksum field was never used, remove it. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/compress.c | 1 - fs/f2fs/f2fs.h | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index dde8ca08e94d..5ca2ea0e1e45 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -380,7 +380,6 @@ static int f2fs_compress_pages(struct compress_ctx *cc) } cc->cbuf->clen = cpu_to_le32(cc->clen); - cc->cbuf->chksum = cpu_to_le32(0); for (i = 0; i < COMPRESS_DATA_RESERVED_SIZE; i++) cc->cbuf->reserved[i] = cpu_to_le32(0); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index d39f5de11420..16ac00f01586 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1214,10 +1214,9 @@ enum compress_algorithm_type { COMPRESS_MAX, }; -#define COMPRESS_DATA_RESERVED_SIZE 4 +#define COMPRESS_DATA_RESERVED_SIZE 5 struct compress_data { __le32 clen; /* compressed data size */ - __le32 chksum; /* checksum of compressed data */ __le32 reserved[COMPRESS_DATA_RESERVED_SIZE]; /* reserved */ u8 cdata[]; /* compressed data */ }; From 097a7686503f3a7d5c3cce66a69b1e51f51d5a4f Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 24 Feb 2020 19:20:19 +0800 Subject: [PATCH 0902/4444] f2fs: add missing function name in kernel message Otherwise, we can not distinguish the exact location of messages, when there are more than one places printing same message. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 2 +- fs/f2fs/node.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 16ac00f01586..a5656dd00bc2 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2209,7 +2209,7 @@ static inline void dec_valid_node_count(struct f2fs_sb_info *sbi, dquot_free_inode(inode); } else { if (unlikely(inode->i_blocks == 0)) { - f2fs_warn(sbi, "Inconsistent i_blocks, ino:%lu, iblocks:%llu", + f2fs_warn(sbi, "dec_valid_node_count: inconsistent i_blocks, ino:%lu, iblocks:%llu", inode->i_ino, (unsigned long long)inode->i_blocks); set_sbi_flag(sbi, SBI_NEED_FSCK); diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index e58c4c628834..d29774df0d64 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1188,8 +1188,9 @@ int f2fs_remove_inode_page(struct inode *inode) } if (unlikely(inode->i_blocks != 0 && inode->i_blocks != 8)) { - f2fs_warn(F2FS_I_SB(inode), "Inconsistent i_blocks, ino:%lu, iblocks:%llu", - inode->i_ino, (unsigned long long)inode->i_blocks); + f2fs_warn(F2FS_I_SB(inode), + "f2fs_remove_inode_page: inconsistent i_blocks, ino:%lu, iblocks:%llu", + inode->i_ino, (unsigned long long)inode->i_blocks); set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK); } From df77fbd8c5b222c680444801ffd20e8bbc90a56e Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 24 Feb 2020 19:20:16 +0800 Subject: [PATCH 0903/4444] f2fs: fix to avoid potential deadlock Using f2fs_trylock_op() in f2fs_write_compressed_pages() to avoid potential deadlock like we did in f2fs_write_single_data_page(). Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/compress.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 5ca2ea0e1e45..6da33ba2b2db 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -775,7 +775,6 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc, .encrypted_page = NULL, .compressed_page = NULL, .submitted = false, - .need_lock = LOCK_RETRY, .io_type = io_type, .io_wbc = wbc, .encrypted = f2fs_encrypted_file(cc->inode), @@ -788,9 +787,10 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc, loff_t psize; int i, err; - set_new_dnode(&dn, cc->inode, NULL, NULL, 0); + if (!f2fs_trylock_op(sbi)) + return -EAGAIN; - f2fs_lock_op(sbi); + set_new_dnode(&dn, cc->inode, NULL, NULL, 0); err = f2fs_get_dnode_of_data(&dn, start_idx, LOOKUP_NODE); if (err) From b88bf6c3b6ff77948c153cac4e564642b0b90632 Mon Sep 17 00:00:00 2001 From: Sean V Kelley Date: Thu, 20 Feb 2020 11:29:29 -0800 Subject: [PATCH 0904/4444] PCI: Add boot interrupt quirk mechanism for Xeon chipsets The following was observed by Kar Hin Ong with RT patchset: Backtrace: irq 19: nobody cared (try booting with the "irqpoll" option) CPU: 0 PID: 3329 Comm: irq/34-nipalk Tainted:4.14.87-rt49 #1 Hardware name: National Instruments NI PXIe-8880/NI PXIe-8880, BIOS 2.1.5f1 01/09/2020 Call Trace: ? dump_stack+0x46/0x5e ? __report_bad_irq+0x2e/0xb0 ? note_interrupt+0x242/0x290 ? nNIKAL100_memoryRead16+0x8/0x10 [nikal] ? handle_irq_event_percpu+0x55/0x70 ? handle_irq_event+0x4f/0x80 ? handle_fasteoi_irq+0x81/0x180 ? handle_irq+0x1c/0x30 ? do_IRQ+0x41/0xd0 ? common_interrupt+0x84/0x84 ... handlers: [] irq_default_primary_handler threaded [] usb_hcd_irq Disabling IRQ #19 The problem being that this device is triggering boot interrupts due to threaded interrupt handling and masking of the IO-APIC. These boot interrupts are then forwarded on to the legacy PCH's PIRQ lines where there is no handler present for the device. Whenever a PCI device fires interrupt (INTx) to Pin 20 of IOAPIC 2 (GSI 44), the kernel receives two interrupts: 1. Interrupt from Pin 20 of IOAPIC 2 -> Expected 2. Interrupt from Pin 19 of IOAPIC 1 -> UNEXPECTED Quirks for disabling boot interrupts (preferred) or rerouting the handler exist but do not address these Xeon chipsets' mechanism: https://lore.kernel.org/lkml/12131949181903-git-send-email-sassmann@suse.de/ Add a new mechanism via PCI CFG for those chipsets supporting CIPINTRC register's dis_intx_rout2ich bit. Link: https://lore.kernel.org/r/20200220192930.64820-2-sean.v.kelley@linux.intel.com Reported-by: Kar Hin Ong Tested-by: Kar Hin Ong Signed-off-by: Sean V Kelley Signed-off-by: Bjorn Helgaas Reviewed-by: Thomas Gleixner Cc: stable@vger.kernel.org --- drivers/pci/quirks.c | 80 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 7 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 29f473ebf20f..b7347bc6a24d 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1970,26 +1970,92 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80332_1, quirk /* * IO-APIC1 on 6300ESB generates boot interrupts, see Intel order no * 300641-004US, section 5.7.3. + * + * Core IO on Xeon E5 1600/2600/4600, see Intel order no 326509-003. + * Core IO on Xeon E5 v2, see Intel order no 329188-003. + * Core IO on Xeon E7 v2, see Intel order no 329595-002. + * Core IO on Xeon E5 v3, see Intel order no 330784-003. + * Core IO on Xeon E7 v3, see Intel order no 332315-001US. + * Core IO on Xeon E5 v4, see Intel order no 333810-002US. + * Core IO on Xeon E7 v4, see Intel order no 332315-001US. + * Core IO on Xeon D-1500, see Intel order no 332051-001. + * Core IO on Xeon Scalable, see Intel order no 610950. */ -#define INTEL_6300_IOAPIC_ABAR 0x40 +#define INTEL_6300_IOAPIC_ABAR 0x40 /* Bus 0, Dev 29, Func 5 */ #define INTEL_6300_DISABLE_BOOT_IRQ (1<<14) +#define INTEL_CIPINTRC_CFG_OFFSET 0x14C /* Bus 0, Dev 5, Func 0 */ +#define INTEL_CIPINTRC_DIS_INTX_ICH (1<<25) + static void quirk_disable_intel_boot_interrupt(struct pci_dev *dev) { u16 pci_config_word; + u32 pci_config_dword; if (noioapicquirk) return; - pci_read_config_word(dev, INTEL_6300_IOAPIC_ABAR, &pci_config_word); - pci_config_word |= INTEL_6300_DISABLE_BOOT_IRQ; - pci_write_config_word(dev, INTEL_6300_IOAPIC_ABAR, pci_config_word); - + switch (dev->device) { + case PCI_DEVICE_ID_INTEL_ESB_10: + pci_read_config_word(dev, INTEL_6300_IOAPIC_ABAR, + &pci_config_word); + pci_config_word |= INTEL_6300_DISABLE_BOOT_IRQ; + pci_write_config_word(dev, INTEL_6300_IOAPIC_ABAR, + pci_config_word); + break; + case 0x3c28: /* Xeon E5 1600/2600/4600 */ + case 0x0e28: /* Xeon E5/E7 V2 */ + case 0x2f28: /* Xeon E5/E7 V3,V4 */ + case 0x6f28: /* Xeon D-1500 */ + case 0x2034: /* Xeon Scalable Family */ + pci_read_config_dword(dev, INTEL_CIPINTRC_CFG_OFFSET, + &pci_config_dword); + pci_config_dword |= INTEL_CIPINTRC_DIS_INTX_ICH; + pci_write_config_dword(dev, INTEL_CIPINTRC_CFG_OFFSET, + pci_config_dword); + break; + default: + return; + } pci_info(dev, "disabled boot interrupts on device [%04x:%04x]\n", dev->vendor, dev->device); } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_10, quirk_disable_intel_boot_interrupt); -DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_10, quirk_disable_intel_boot_interrupt); +/* + * Device 29 Func 5 Device IDs of IO-APIC + * containing ABAR—APIC1 Alternate Base Address Register + */ +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_10, + quirk_disable_intel_boot_interrupt); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_10, + quirk_disable_intel_boot_interrupt); + +/* + * Device 5 Func 0 Device IDs of Core IO modules/hubs + * containing Coherent Interface Protocol Interrupt Control + * + * Device IDs obtained from volume 2 datasheets of commented + * families above. + */ +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x3c28, + quirk_disable_intel_boot_interrupt); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0e28, + quirk_disable_intel_boot_interrupt); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2f28, + quirk_disable_intel_boot_interrupt); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x6f28, + quirk_disable_intel_boot_interrupt); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2034, + quirk_disable_intel_boot_interrupt); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, 0x3c28, + quirk_disable_intel_boot_interrupt); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, 0x0e28, + quirk_disable_intel_boot_interrupt); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, 0x2f28, + quirk_disable_intel_boot_interrupt); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, 0x6f28, + quirk_disable_intel_boot_interrupt); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, 0x2034, + quirk_disable_intel_boot_interrupt); /* Disable boot interrupts on HT-1000 */ #define BC_HT1000_FEATURE_REG 0x64 From 5cbe0f13b51ac2fb2fd55902cff8d0077fc084c0 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Mon, 10 Feb 2020 13:00:12 +0000 Subject: [PATCH 0905/4444] random: split primary/secondary crng init paths Currently crng_initialize() is used for both the primary CRNG and secondary CRNGs. While we wish to share common logic, we need to do a number of additional things for the primary CRNG, and this would be easier to deal with were these handled in separate functions. This patch splits crng_initialize() into crng_initialize_primary() and crng_initialize_secondary(), with common logic factored out into a crng_init_try_arch() helper. There should be no functional change as a result of this patch. Signed-off-by: Mark Rutland Cc: Mark Brown Cc: Theodore Ts'o Link: https://lore.kernel.org/r/20200210130015.17664-2-mark.rutland@arm.com Signed-off-by: Theodore Ts'o --- drivers/char/random.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index c7f9584de2c8..62d32e62f2da 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -781,27 +781,37 @@ static int __init parse_trust_cpu(char *arg) } early_param("random.trust_cpu", parse_trust_cpu); -static void crng_initialize(struct crng_state *crng) +static bool crng_init_try_arch(struct crng_state *crng) { int i; - int arch_init = 1; + bool arch_init = true; unsigned long rv; - memcpy(&crng->state[0], "expand 32-byte k", 16); - if (crng == &primary_crng) - _extract_entropy(&input_pool, &crng->state[4], - sizeof(__u32) * 12, 0); - else - _get_random_bytes(&crng->state[4], sizeof(__u32) * 12); for (i = 4; i < 16; i++) { if (!arch_get_random_seed_long(&rv) && !arch_get_random_long(&rv)) { rv = random_get_entropy(); - arch_init = 0; + arch_init = false; } crng->state[i] ^= rv; } - if (trust_cpu && arch_init && crng == &primary_crng) { + + return arch_init; +} + +static void crng_initialize_secondary(struct crng_state *crng) +{ + memcpy(&crng->state[0], "expand 32-byte k", 16); + _get_random_bytes(&crng->state[4], sizeof(__u32) * 12); + crng_init_try_arch(crng); + crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1; +} + +static void __init crng_initialize_primary(struct crng_state *crng) +{ + memcpy(&crng->state[0], "expand 32-byte k", 16); + _extract_entropy(&input_pool, &crng->state[4], sizeof(__u32) * 12, 0); + if (crng_init_try_arch(crng) && trust_cpu) { invalidate_batched_entropy(); numa_crng_init(); crng_init = 2; @@ -822,7 +832,7 @@ static void do_numa_crng_init(struct work_struct *work) crng = kmalloc_node(sizeof(struct crng_state), GFP_KERNEL | __GFP_NOFAIL, i); spin_lock_init(&crng->lock); - crng_initialize(crng); + crng_initialize_secondary(crng); pool[i] = crng; } mb(); @@ -1771,7 +1781,7 @@ static void __init init_std_data(struct entropy_store *r) int __init rand_initialize(void) { init_std_data(&input_pool); - crng_initialize(&primary_crng); + crng_initialize_primary(&primary_crng); crng_global_init_time = jiffies; if (ratelimit_disable) { urandom_warning.interval = 0; From 253d3194c2b58152fe830fd27c2fd83ebc6fe5ee Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Mon, 10 Feb 2020 13:00:13 +0000 Subject: [PATCH 0906/4444] random: add arch_get_random_*long_early() Some architectures (e.g. arm64) can have heterogeneous CPUs, and the boot CPU may be able to provide entropy while secondary CPUs cannot. On such systems, arch_get_random_long() and arch_get_random_seed_long() will fail unless support for RNG instructions has been detected on all CPUs. This prevents the boot CPU from being able to provide (potentially) trusted entropy when seeding the primary CRNG. To make it possible to seed the primary CRNG from the boot CPU without adversely affecting the runtime versions of arch_get_random_long() and arch_get_random_seed_long(), this patch adds new early versions of the functions used when initializing the primary CRNG. Default implementations are provided atop of the existing arch_get_random_long() and arch_get_random_seed_long() so that only architectures with such constraints need to provide the new helpers. There should be no functional change as a result of this patch. Signed-off-by: Mark Rutland Cc: Mark Brown Cc: Theodore Ts'o Link: https://lore.kernel.org/r/20200210130015.17664-3-mark.rutland@arm.com Signed-off-by: Theodore Ts'o --- drivers/char/random.c | 20 +++++++++++++++++++- include/linux/random.h | 22 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 62d32e62f2da..02a85b87b993 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -799,6 +799,24 @@ static bool crng_init_try_arch(struct crng_state *crng) return arch_init; } +static bool __init crng_init_try_arch_early(struct crng_state *crng) +{ + int i; + bool arch_init = true; + unsigned long rv; + + for (i = 4; i < 16; i++) { + if (!arch_get_random_seed_long_early(&rv) && + !arch_get_random_long_early(&rv)) { + rv = random_get_entropy(); + arch_init = false; + } + crng->state[i] ^= rv; + } + + return arch_init; +} + static void crng_initialize_secondary(struct crng_state *crng) { memcpy(&crng->state[0], "expand 32-byte k", 16); @@ -811,7 +829,7 @@ static void __init crng_initialize_primary(struct crng_state *crng) { memcpy(&crng->state[0], "expand 32-byte k", 16); _extract_entropy(&input_pool, &crng->state[4], sizeof(__u32) * 12, 0); - if (crng_init_try_arch(crng) && trust_cpu) { + if (crng_init_try_arch_early(crng) && trust_cpu) { invalidate_batched_entropy(); numa_crng_init(); crng_init = 2; diff --git a/include/linux/random.h b/include/linux/random.h index d319f9a1e429..45e1f8fa742b 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -7,6 +7,8 @@ #ifndef _LINUX_RANDOM_H #define _LINUX_RANDOM_H +#include +#include #include #include @@ -185,6 +187,26 @@ static inline bool __must_check arch_get_random_seed_int(unsigned int *v) } #endif +/* + * Called from the boot CPU during startup; not valid to call once + * secondary CPUs are up and preemption is possible. + */ +#ifndef arch_get_random_seed_long_early +static inline bool __init arch_get_random_seed_long_early(unsigned long *v) +{ + WARN_ON(system_state != SYSTEM_BOOTING); + return arch_get_random_seed_long(v); +} +#endif + +#ifndef arch_get_random_long_early +static inline bool __init arch_get_random_long_early(unsigned long *v) +{ + WARN_ON(system_state != SYSTEM_BOOTING); + return arch_get_random_long(v); +} +#endif + /* Pseudo random number generator from numerical recipes. */ static inline u32 next_pseudo_random32(u32 seed) { From ead5084cdf5af51445d219800c2ac8b01eb85f2f Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Mon, 10 Feb 2020 13:00:14 +0000 Subject: [PATCH 0907/4444] arm64: add credited/trusted RNG support Currently arm64 doesn't initialize the primary CRNG in a (potentially) trusted manner as we only detect the presence of the RNG once secondary CPUs are up. Now that the core RNG code distinguishes the early initialization of the primary CRNG, we can implement arch_get_random_seed_long_early() to support this. This patch does so. Signed-off-by: Mark Rutland Cc: Catalin Marinas Cc: Mark Brown Cc: Theodore Ts'o Cc: Will Deacon Link: https://lore.kernel.org/r/20200210130015.17664-4-mark.rutland@arm.com Signed-off-by: Theodore Ts'o --- arch/arm64/include/asm/archrandom.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm64/include/asm/archrandom.h b/arch/arm64/include/asm/archrandom.h index 3fe02da70004..fc1594a0710e 100644 --- a/arch/arm64/include/asm/archrandom.h +++ b/arch/arm64/include/asm/archrandom.h @@ -4,6 +4,8 @@ #ifdef CONFIG_ARCH_RANDOM +#include +#include #include #include @@ -66,6 +68,18 @@ static inline bool __init __early_cpu_has_rndr(void) return (ftr >> ID_AA64ISAR0_RNDR_SHIFT) & 0xf; } +static inline bool __init __must_check +arch_get_random_seed_long_early(unsigned long *v) +{ + WARN_ON(system_state != SYSTEM_BOOTING); + + if (!__early_cpu_has_rndr()) + return false; + + return __arm64_rndr(v); +} +#define arch_get_random_seed_long_early arch_get_random_seed_long_early + #else static inline bool __arm64_rndr(unsigned long *v) { return false; } From 23ae0c17b89cfeb511aa0770735a319d35597072 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 10 Feb 2020 13:00:15 +0000 Subject: [PATCH 0908/4444] random: Make RANDOM_TRUST_CPU depend on ARCH_RANDOM Listing the set of host architectures does not scale. Depend instead on the existence of the architecture rng. This will allow RANDOM_TRUST_CPU to be selected on arm64. Today ARCH_RANDOM is only selected by x86, s390, and powerpc, so this does not adversely affect other architectures. Signed-off-by: Richard Henderson Signed-off-by: Mark Rutland Link: https://lore.kernel.org/r/20200210130015.17664-5-mark.rutland@arm.com Signed-off-by: Theodore Ts'o --- drivers/char/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 26956c006987..84207d5a9bb0 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -539,7 +539,7 @@ endmenu config RANDOM_TRUST_CPU bool "Trust the CPU manufacturer to initialize Linux's CRNG" - depends on X86 || S390 || PPC + depends on ARCH_RANDOM default n help Assume that CPU manufacturer (e.g., Intel or AMD for RDSEED or From 69efea712f5b0489e67d07565aad5c94e09a3e52 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 21 Feb 2020 21:10:37 +0100 Subject: [PATCH 0909/4444] random: always use batched entropy for get_random_u{32,64} It turns out that RDRAND is pretty slow. Comparing these two constructions: for (i = 0; i < CHACHA_BLOCK_SIZE; i += sizeof(ret)) arch_get_random_long(&ret); and long buf[CHACHA_BLOCK_SIZE / sizeof(long)]; extract_crng((u8 *)buf); it amortizes out to 352 cycles per long for the top one and 107 cycles per long for the bottom one, on Coffee Lake Refresh, Intel Core i9-9880H. And importantly, the top one has the drawback of not benefiting from the real rng, whereas the bottom one has all the nice benefits of using our own chacha rng. As get_random_u{32,64} gets used in more places (perhaps beyond what it was originally intended for when it was introduced as get_random_{int,long} back in the md5 monstrosity era), it seems like it might be a good thing to strengthen its posture a tiny bit. Doing this should only be stronger and not any weaker because that pool is already initialized with a bunch of rdrand data (when available). This way, we get the benefits of the hardware rng as well as our own rng. Another benefit of this is that we no longer hit pitfalls of the recent stream of AMD bugs in RDRAND. One often used code pattern for various things is: do { val = get_random_u32(); } while (hash_table_contains_key(val)); That recent AMD bug rendered that pattern useless, whereas we're really very certain that chacha20 output will give pretty distributed numbers, no matter what. So, this simplification seems better both from a security perspective and from a performance perspective. Signed-off-by: Jason A. Donenfeld Reviewed-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20200221201037.30231-1-Jason@zx2c4.com Signed-off-by: Theodore Ts'o --- drivers/char/random.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 02a85b87b993..c33e7a3cdb13 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -2177,11 +2177,11 @@ struct batched_entropy { /* * Get a random word for internal kernel use only. The quality of the random - * number is either as good as RDRAND or as good as /dev/urandom, with the - * goal of being quite fast and not depleting entropy. In order to ensure + * number is good as /dev/urandom, but there is no backtrack protection, with + * the goal of being quite fast and not depleting entropy. In order to ensure * that the randomness provided by this function is okay, the function - * wait_for_random_bytes() should be called and return 0 at least once - * at any point prior. + * wait_for_random_bytes() should be called and return 0 at least once at any + * point prior. */ static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64) = { .batch_lock = __SPIN_LOCK_UNLOCKED(batched_entropy_u64.lock), @@ -2194,15 +2194,6 @@ u64 get_random_u64(void) struct batched_entropy *batch; static void *previous; -#if BITS_PER_LONG == 64 - if (arch_get_random_long((unsigned long *)&ret)) - return ret; -#else - if (arch_get_random_long((unsigned long *)&ret) && - arch_get_random_long((unsigned long *)&ret + 1)) - return ret; -#endif - warn_unseeded_randomness(&previous); batch = raw_cpu_ptr(&batched_entropy_u64); @@ -2227,9 +2218,6 @@ u32 get_random_u32(void) struct batched_entropy *batch; static void *previous; - if (arch_get_random_int(&ret)) - return ret; - warn_unseeded_randomness(&previous); batch = raw_cpu_ptr(&batched_entropy_u32); From e00d996a4317aff5351c4338dd97d390225412c2 Mon Sep 17 00:00:00 2001 From: Qian Cai Date: Tue, 25 Feb 2020 11:27:04 -0500 Subject: [PATCH 0910/4444] random: fix data races at timer_rand_state Fields in "struct timer_rand_state" could be accessed concurrently. Lockless plain reads and writes result in data races. Fix them by adding pairs of READ|WRITE_ONCE(). The data races were reported by KCSAN, BUG: KCSAN: data-race in add_timer_randomness / add_timer_randomness write to 0xffff9f320a0a01d0 of 8 bytes by interrupt on cpu 22: add_timer_randomness+0x100/0x190 add_timer_randomness at drivers/char/random.c:1152 add_disk_randomness+0x85/0x280 scsi_end_request+0x43a/0x4a0 scsi_io_completion+0xb7/0x7e0 scsi_finish_command+0x1ed/0x2a0 scsi_softirq_done+0x1c9/0x1d0 blk_done_softirq+0x181/0x1d0 __do_softirq+0xd9/0x57c irq_exit+0xa2/0xc0 do_IRQ+0x8b/0x190 ret_from_intr+0x0/0x42 cpuidle_enter_state+0x15e/0x980 cpuidle_enter+0x69/0xc0 call_cpuidle+0x23/0x40 do_idle+0x248/0x280 cpu_startup_entry+0x1d/0x1f start_secondary+0x1b2/0x230 secondary_startup_64+0xb6/0xc0 no locks held by swapper/22/0. irq event stamp: 32871382 _raw_spin_unlock_irqrestore+0x53/0x60 _raw_spin_lock_irqsave+0x21/0x60 _local_bh_enable+0x21/0x30 irq_exit+0xa2/0xc0 read to 0xffff9f320a0a01d0 of 8 bytes by interrupt on cpu 2: add_timer_randomness+0xe8/0x190 add_disk_randomness+0x85/0x280 scsi_end_request+0x43a/0x4a0 scsi_io_completion+0xb7/0x7e0 scsi_finish_command+0x1ed/0x2a0 scsi_softirq_done+0x1c9/0x1d0 blk_done_softirq+0x181/0x1d0 __do_softirq+0xd9/0x57c irq_exit+0xa2/0xc0 do_IRQ+0x8b/0x190 ret_from_intr+0x0/0x42 cpuidle_enter_state+0x15e/0x980 cpuidle_enter+0x69/0xc0 call_cpuidle+0x23/0x40 do_idle+0x248/0x280 cpu_startup_entry+0x1d/0x1f start_secondary+0x1b2/0x230 secondary_startup_64+0xb6/0xc0 no locks held by swapper/2/0. irq event stamp: 37846304 _raw_spin_unlock_irqrestore+0x53/0x60 _raw_spin_lock_irqsave+0x21/0x60 _local_bh_enable+0x21/0x30 irq_exit+0xa2/0xc0 Reported by Kernel Concurrency Sanitizer on: Hardware name: HP ProLiant BL660c Gen9, BIOS I38 10/17/2018 Link: https://lore.kernel.org/r/1582648024-13111-1-git-send-email-cai@lca.pw Signed-off-by: Qian Cai Signed-off-by: Theodore Ts'o --- drivers/char/random.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index c33e7a3cdb13..f43f65c2195d 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1170,14 +1170,14 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num) * We take into account the first, second and third-order deltas * in order to make our estimate. */ - delta = sample.jiffies - state->last_time; - state->last_time = sample.jiffies; + delta = sample.jiffies - READ_ONCE(state->last_time); + WRITE_ONCE(state->last_time, sample.jiffies); - delta2 = delta - state->last_delta; - state->last_delta = delta; + delta2 = delta - READ_ONCE(state->last_delta); + WRITE_ONCE(state->last_delta, delta); - delta3 = delta2 - state->last_delta2; - state->last_delta2 = delta2; + delta3 = delta2 - READ_ONCE(state->last_delta2); + WRITE_ONCE(state->last_delta2, delta2); if (delta < 0) delta = -delta; From 1222783ecf4b02b99abc5914e971d3b0858ce255 Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Mon, 6 Jan 2020 17:49:28 +0200 Subject: [PATCH 0911/4444] arm64: dts: sdm845: follow venus-sdm845v2 DT binding Move all pmdomain and clock resources to Venus DT node. And make possible to support dynamic core assignment on v4. Signed-off-by: Stanimir Varbanov Link: https://lore.kernel.org/r/20200106154929.4331-12-stanimir.varbanov@linaro.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index 061f49faab19..ed882e086ba7 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -2787,32 +2787,33 @@ }; venus: video-codec@aa00000 { - compatible = "qcom,sdm845-venus"; + compatible = "qcom,sdm845-venus-v2"; reg = <0 0x0aa00000 0 0xff000>; interrupts = ; - power-domains = <&videocc VENUS_GDSC>; + power-domains = <&videocc VENUS_GDSC>, + <&videocc VCODEC0_GDSC>, + <&videocc VCODEC1_GDSC>; + power-domain-names = "venus", "vcodec0", "vcodec1"; clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>, <&videocc VIDEO_CC_VENUS_AHB_CLK>, - <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>; - clock-names = "core", "iface", "bus"; + <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>, + <&videocc VIDEO_CC_VCODEC0_CORE_CLK>, + <&videocc VIDEO_CC_VCODEC0_AXI_CLK>, + <&videocc VIDEO_CC_VCODEC1_CORE_CLK>, + <&videocc VIDEO_CC_VCODEC1_AXI_CLK>; + clock-names = "core", "iface", "bus", + "vcodec0_core", "vcodec0_bus", + "vcodec1_core", "vcodec1_bus"; iommus = <&apps_smmu 0x10a0 0x8>, <&apps_smmu 0x10b0 0x0>; memory-region = <&venus_mem>; video-core0 { compatible = "venus-decoder"; - clocks = <&videocc VIDEO_CC_VCODEC0_CORE_CLK>, - <&videocc VIDEO_CC_VCODEC0_AXI_CLK>; - clock-names = "core", "bus"; - power-domains = <&videocc VCODEC0_GDSC>; }; video-core1 { compatible = "venus-encoder"; - clocks = <&videocc VIDEO_CC_VCODEC1_CORE_CLK>, - <&videocc VIDEO_CC_VCODEC1_AXI_CLK>; - clock-names = "core", "bus"; - power-domains = <&videocc VCODEC1_GDSC>; }; }; From 058bd0a6895094064ba976317dba4cab0cd00e43 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Thu, 27 Feb 2020 09:26:52 -0800 Subject: [PATCH 0912/4444] arm64: dts: sc7180: Move venus node to the correct position Per convention device nodes for SC7180 should be ordered by address. This is currently not the case for the venus node, move it to the correct position. Reviewed-by: Douglas Anderson Signed-off-by: Matthias Kaehlcke Link: https://lore.kernel.org/r/20200227092649.v3.1.I15e0f7eff0c67a2b49d4992f9d80fc1d2fdadf63@changeid Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sc7180.dtsi | 52 ++++++++++++++-------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index 253274d5f04c..31bf210f2e0b 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -1376,6 +1376,32 @@ }; }; + venus: video-codec@aa00000 { + compatible = "qcom,sc7180-venus"; + reg = <0 0x0aa00000 0 0xff000>; + interrupts = ; + power-domains = <&videocc VENUS_GDSC>, + <&videocc VCODEC0_GDSC>; + power-domain-names = "venus", "vcodec0"; + clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>, + <&videocc VIDEO_CC_VENUS_AHB_CLK>, + <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>, + <&videocc VIDEO_CC_VCODEC0_CORE_CLK>, + <&videocc VIDEO_CC_VCODEC0_AXI_CLK>; + clock-names = "core", "iface", "bus", + "vcodec0_core", "vcodec0_bus"; + iommus = <&apps_smmu 0x0c00 0x60>; + memory-region = <&venus_mem>; + + video-decoder { + compatible = "venus-decoder"; + }; + + video-encoder { + compatible = "venus-encoder"; + }; + }; + videocc: clock-controller@ab00000 { compatible = "qcom,sc7180-videocc"; reg = <0 0x0ab00000 0 0x10000>; @@ -1538,32 +1564,6 @@ #power-domain-cells = <1>; }; - venus: video-codec@aa00000 { - compatible = "qcom,sc7180-venus"; - reg = <0 0x0aa00000 0 0xff000>; - interrupts = ; - power-domains = <&videocc VENUS_GDSC>, - <&videocc VCODEC0_GDSC>; - power-domain-names = "venus", "vcodec0"; - clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>, - <&videocc VIDEO_CC_VENUS_AHB_CLK>, - <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>, - <&videocc VIDEO_CC_VCODEC0_CORE_CLK>, - <&videocc VIDEO_CC_VCODEC0_AXI_CLK>; - clock-names = "core", "iface", "bus", - "vcodec0_core", "vcodec0_bus"; - iommus = <&apps_smmu 0x0c00 0x60>; - memory-region = <&venus_mem>; - - video-decoder { - compatible = "venus-decoder"; - }; - - video-encoder { - compatible = "venus-encoder"; - }; - }; - pdc: interrupt-controller@b220000 { compatible = "qcom,sc7180-pdc", "qcom,pdc"; reg = <0 0x0b220000 0 0x30000>; From 5bf635621245ad5fe2e3b69f12e95bbe2ffbf5cf Mon Sep 17 00:00:00 2001 From: Sivaprakash Murugesan Date: Thu, 20 Feb 2020 17:20:46 +0530 Subject: [PATCH 0913/4444] arm64: dts: ipq6018: Add a few device nodes add i2c, spi, crypto, rng, watchdog, peripheral nodes, also add support for wcss Q6 remoteproc driver and enable hw mutex, smem, mailbox, smp2p and rpmsg drivers Signed-off-by: Sivaprakash Murugesan Link: https://lore.kernel.org/r/1582199446-29890-1-git-send-email-sivaprak@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts | 34 +++ arch/arm64/boot/dts/qcom/ipq6018.dtsi | 226 +++++++++++++++++++ 2 files changed, 260 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts index 897b4b293a22..b31117a93995 100644 --- a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts +++ b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts @@ -28,3 +28,37 @@ pinctrl-names = "default"; status = "ok"; }; + +&i2c_1 { + pinctrl-0 = <&i2c_1_pins>; + pinctrl-names = "default"; + status = "ok"; +}; + +&spi_0 { + cs-select = <0>; + status = "ok"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + compatible = "n25q128a11"; + spi-max-frequency = <50000000>; + }; +}; + +&tlmm { + i2c_1_pins: i2c-1-pins { + pins = "gpio42", "gpio43"; + function = "blsp2_i2c"; + drive-strength = <8>; + }; + + spi_0_pins: spi-0-pins { + pins = "gpio38", "gpio39", "gpio40", "gpio41"; + function = "blsp0_spi"; + drive-strength = <8>; + bias-pull-down; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/ipq6018.dtsi b/arch/arm64/boot/dts/qcom/ipq6018.dtsi index 0fb44e56dd32..1aa8d8579463 100644 --- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi @@ -7,6 +7,7 @@ #include #include +#include / { #address-cells = <2>; @@ -69,6 +70,18 @@ }; }; + firmware { + scm { + compatible = "qcom,scm"; + }; + }; + + tcsr_mutex: hwlock { + compatible = "qcom,tcsr-mutex"; + syscon = <&tcsr_mutex_regs 0 0x80>; + #hwlock-cells = <1>; + }; + pmuv8: pmu { compatible = "arm,cortex-a53-pmu"; interrupts = ; no-map; }; + + smem_region: memory@4aa00000 { + reg = <0x0 0x4aa00000 0x0 0x00100000>; + no-map; + }; + + q6_region: memory@4ab00000 { + reg = <0x0 0x4ab00000 0x0 0x02800000>; + no-map; + }; + }; + + smem { + compatible = "qcom,smem"; + memory-region = <&smem_region>; + hwlocks = <&tcsr_mutex 0>; }; soc: soc { @@ -98,6 +127,36 @@ dma-ranges; compatible = "simple-bus"; + prng: qrng@e1000 { + compatible = "qcom,prng-ee"; + reg = <0xe3000 0x1000>; + clocks = <&gcc GCC_PRNG_AHB_CLK>; + clock-names = "core"; + }; + + cryptobam: dma@704000 { + compatible = "qcom,bam-v1.7.0"; + reg = <0x00704000 0x20000>; + interrupts = ; + clocks = <&gcc GCC_CRYPTO_AHB_CLK>; + clock-names = "bam_clk"; + #dma-cells = <1>; + qcom,ee = <1>; + qcom,controlled-remotely = <1>; + qcom,config-pipe-trust-reg = <0>; + }; + + crypto: crypto@73a000 { + compatible = "qcom,crypto-v5.1"; + reg = <0x0073a000 0x6000>; + clocks = <&gcc GCC_CRYPTO_AHB_CLK>, + <&gcc GCC_CRYPTO_AXI_CLK>, + <&gcc GCC_CRYPTO_CLK>; + clock-names = "iface", "bus", "core"; + dmas = <&cryptobam 2>, <&cryptobam 3>; + dma-names = "rx", "tx"; + }; + tlmm: pinctrl@1000000 { compatible = "qcom,ipq6018-pinctrl"; reg = <0x01000000 0x300000>; @@ -125,6 +184,26 @@ #reset-cells = <1>; }; + tcsr_mutex_regs: syscon@1905000 { + compatible = "syscon"; + reg = <0x01905000 0x8000>; + }; + + tcsr_q6: syscon@1945000 { + compatible = "syscon"; + reg = <0x01945000 0xe000>; + }; + + blsp_dma: dma@7884000 { + compatible = "qcom,bam-v1.7.0"; + reg = <0x07884000 0x2b000>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "bam_clk"; + #dma-cells = <1>; + qcom,ee = <0>; + }; + blsp1_uart3: serial@78b1000 { compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; reg = <0x078b1000 0x200>; @@ -135,6 +214,66 @@ status = "disabled"; }; + spi_0: spi@78b5000 { + compatible = "qcom,spi-qup-v2.2.1"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x078b5000 0x600>; + interrupts = ; + spi-max-frequency = <50000000>; + clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 12>, <&blsp_dma 13>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + spi_1: spi@78b6000 { + compatible = "qcom,spi-qup-v2.2.1"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x078b6000 0x600>; + interrupts = ; + spi-max-frequency = <50000000>; + clocks = <&gcc GCC_BLSP1_QUP2_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 14>, <&blsp_dma 15>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + i2c_0: i2c@78b6000 { + compatible = "qcom,i2c-qup-v2.2.1"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x078b6000 0x600>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_AHB_CLK>, + <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>; + clock-names = "iface", "core"; + clock-frequency = <400000>; + dmas = <&blsp_dma 15>, <&blsp_dma 14>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + i2c_1: i2c@78b7000 { /* BLSP1 QUP2 */ + compatible = "qcom,i2c-qup-v2.2.1"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x078b7000 0x600>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_AHB_CLK>, + <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>; + clock-names = "iface", "core"; + clock-frequency = <400000>; + dmas = <&blsp_dma 17>, <&blsp_dma 16>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + intc: interrupt-controller@b000000 { compatible = "qcom,msm-qgic2"; interrupt-controller; @@ -146,6 +285,21 @@ interrupts = ; }; + watchdog@b017000 { + compatible = "qcom,kpss-wdt"; + interrupts = ; + reg = <0x0b017000 0x40>; + clocks = <&sleep_clk>; + timeout-sec = <10>; + }; + + apcs_glb: mailbox@b111000 { + compatible = "qcom,ipq8074-apcs-apps-global"; + reg = <0x0b111000 0xc>; + + #mbox-cells = <1>; + }; + timer { compatible = "arm,armv8-timer"; interrupts = , @@ -213,5 +367,77 @@ }; }; + q6v5_wcss: remoteproc@cd00000 { + compatible = "qcom,ipq8074-wcss-pil"; + reg = <0x0cd00000 0x4040>, + <0x004ab000 0x20>; + reg-names = "qdsp6", + "rmb"; + interrupts-extended = <&intc GIC_SPI 325 IRQ_TYPE_EDGE_RISING>, + <&wcss_smp2p_in 0 0>, + <&wcss_smp2p_in 1 0>, + <&wcss_smp2p_in 2 0>, + <&wcss_smp2p_in 3 0>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack"; + + resets = <&gcc GCC_WCSSAON_RESET>, + <&gcc GCC_WCSS_BCR>, + <&gcc GCC_WCSS_Q6_BCR>; + + reset-names = "wcss_aon_reset", + "wcss_reset", + "wcss_q6_reset"; + + clocks = <&gcc GCC_PRNG_AHB_CLK>; + clock-names = "prng"; + + qcom,halt-regs = <&tcsr_q6 0xa000 0xd000 0x0>; + + qcom,smem-states = <&wcss_smp2p_out 0>, + <&wcss_smp2p_out 1>; + qcom,smem-state-names = "shutdown", + "stop"; + + memory-region = <&q6_region>; + + glink-edge { + interrupts = ; + qcom,remote-pid = <1>; + mboxes = <&apcs_glb 8>; + + qrtr_requests { + qcom,glink-channels = "IPCRTR"; + }; + }; + }; + + }; + + wcss: wcss-smp2p { + compatible = "qcom,smp2p"; + qcom,smem = <435>, <428>; + + interrupt-parent = <&intc>; + interrupts = ; + + mboxes = <&apcs_glb 9>; + + qcom,local-pid = <0>; + qcom,remote-pid = <1>; + + wcss_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + wcss_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; }; }; From 0407fad060117dee8008d93d7fc6d2eacdaaca32 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 13 May 2019 14:07:47 -0700 Subject: [PATCH 0914/4444] arm64: dts: qcom: sdm845-mtp: Add Truly display Bring in the Truly display and enable the DSI channels to make the mdss/gpu probe, even though we're lacking LABIB, preventing us from seeing anything on the screen. Tested-by: Vivek Gautam Reviewed-by: Vivek Gautam Link: https://lore.kernel.org/r/20190513210747.22429-1-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845-mtp.dts | 82 +++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts index 09ad37b0dd71..588901b1557b 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts @@ -352,6 +352,80 @@ status = "okay"; }; +&dsi0 { + status = "okay"; + vdda-supply = <&vdda_mipi_dsi0_1p2>; + + qcom,dual-dsi-mode; + qcom,master-dsi; + + #address-cells = <1>; + #size-cells = <0>; + + ports { + port@1 { + endpoint { + remote-endpoint = <&truly_in_0>; + data-lanes = <0 1 2 3>; + }; + }; + }; + + panel@0 { + compatible = "truly,nt35597-2K-display"; + reg = <0>; + vdda-supply = <&vreg_l14a_1p88>; + + reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>; + mode-gpios = <&tlmm 52 GPIO_ACTIVE_HIGH>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + truly_in_0: endpoint { + remote-endpoint = <&dsi0_out>; + }; + }; + + port@1 { + reg = <1>; + truly_in_1: endpoint { + remote-endpoint = <&dsi1_out>; + }; + }; + }; + }; +}; + +&dsi0_phy { + status = "okay"; + vdds-supply = <&vdda_mipi_dsi0_pll>; +}; + +&dsi1 { + status = "okay"; + vdda-supply = <&vdda_mipi_dsi1_1p2>; + + qcom,dual-dsi-mode; + + ports { + port@1 { + endpoint { + remote-endpoint = <&truly_in_1>; + data-lanes = <0 1 2 3>; + }; + }; + }; +}; + +&dsi1_phy { + status = "okay"; + vdds-supply = <&vdda_mipi_dsi1_pll>; +}; + &gcc { protected-clocks = , , @@ -372,6 +446,14 @@ clock-frequency = <400000>; }; +&mdss { + status = "okay"; +}; + +&mdss_mdp { + status = "okay"; +}; + &qupv3_id_1 { status = "okay"; }; From ef82b925e702646e63fe51ca260fc288867835ee Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Fri, 28 Feb 2020 12:02:41 +0530 Subject: [PATCH 0915/4444] arm64: dts: qcom: msm8916:: Add qcom,tsens-v0_1 to msm8916.dtsi compatible The qcom-tsens binding requires a SoC-specific and a TSENS family-specific binding to be specified in the compatible string. Since them family-specific binding is not listed in the .dtsi file, we see the following warnings in 'make dtbs_check'. Fix them. /home/amit/work/builds/build-aarch64/arch/arm64/boot/dts/qcom/msm8916-mtp.dt.yaml: thermal-sensor@4a9000: compatible: ['qcom,msm8916-tsens'] is not valid under any of the given schemas (Possible causes of the failure): /home/amit/work/builds/build-aarch64/arch/arm64/boot/dts/qcom/msm8916-mtp.dt.yaml: thermal-sensor@4a9000: compatible: ['qcom,msm8916-tsens'] is too short /home/amit/work/builds/build-aarch64/arch/arm64/boot/dts/qcom/msm8916-mtp.dt.yaml: thermal-sensor@4a9000: compatible:0: 'qcom,msm8916-tsens' is not one of ['qcom,msm8976-tsens', 'qcom,qcs404-tsens'] /home/amit/work/builds/build-aarch64/arch/arm64/boot/dts/qcom/msm8916-mtp.dt.yaml: thermal-sensor@4a9000: compatible:0: 'qcom,msm8916-tsens' is not one of ['qcom,msm8996-tsens', 'qcom,msm8998-tsens', 'qcom,sdm845-tsens'] Signed-off-by: Amit Kucheria Reviewed-by: Vinod Koul Link: https://lore.kernel.org/r/8cea8c0036703bcc4dd2b87a8ca3913c4a28d16e.1582871139.git.amit.kucheria@linaro.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/msm8916.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index 7c2ada02e276..be7e57fc4480 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -861,7 +861,7 @@ }; tsens: thermal-sensor@4a9000 { - compatible = "qcom,msm8916-tsens"; + compatible = "qcom,msm8916-tsens", "qcom,tsens-v0_1"; reg = <0x4a9000 0x1000>, /* TM */ <0x4a8000 0x1000>; /* SROT */ nvmem-cells = <&tsens_caldata>, <&tsens_calsel>; From 946f80074adb84e9cb729f4754c29134713afac8 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Fri, 28 Feb 2020 12:02:42 +0530 Subject: [PATCH 0916/4444] arm64: dts: qcom: msm8996:: Add qcom,tsens-v2 to msm8996.dtsi compatible The qcom-tsens binding requires a SoC-specific and a TSENS family-specific binding to be specified in the compatible string. Since them family-specific binding is not listed in the .dtsi file, we see the following warnings in 'make dtbs_check'. Fix them. /home/amit/work/builds/build-aarch64/arch/arm64/boot/dts/qcom/msm8996-mtp.dt.yaml: thermal-sensor@4a9000: compatible: ['qcom,msm8996-tsens'] is not valid under any of the given schemas (Possible causes of the failure): /home/amit/work/builds/build-aarch64/arch/arm64/boot/dts/qcom/msm8996-mtp.dt.yaml: thermal-sensor@4a9000: compatible: ['qcom,msm8996-tsens'] is too short /home/amit/work/builds/build-aarch64/arch/arm64/boot/dts/qcom/msm8996-mtp.dt.yaml: thermal-sensor@4a9000: compatible:0: 'qcom,msm8996-tsens' is not one of ['qcom,msm8916-tsens', 'qcom,msm8974-tsens'] /home/amit/work/builds/build-aarch64/arch/arm64/boot/dts/qcom/msm8996-mtp.dt.yaml: thermal-sensor@4a9000: compatible:0: 'qcom,msm8996-tsens' is not one of ['qcom,msm8976-tsens', 'qcom,qcs404-tsens'] /home/amit/work/builds/build-aarch64/arch/arm64/boot/dts/qcom/msm8996-mtp.dt.yaml: thermal-sensor@4ad000: compatible: ['qcom,msm8996-tsens'] is not valid under any of the given schemas (Possible causes of the failure): /home/amit/work/builds/build-aarch64/arch/arm64/boot/dts/qcom/msm8996-mtp.dt.yaml: thermal-sensor@4ad000: compatible: ['qcom,msm8996-tsens'] is too short /home/amit/work/builds/build-aarch64/arch/arm64/boot/dts/qcom/msm8996-mtp.dt.yaml: thermal-sensor@4ad000: compatible:0: 'qcom,msm8996-tsens' is not one of ['qcom,msm8916-tsens', 'qcom,msm8974-tsens'] /home/amit/work/builds/build-aarch64/arch/arm64/boot/dts/qcom/msm8996-mtp.dt.yaml: thermal-sensor@4ad000: compatible:0: 'qcom,msm8996-tsens' is not one of ['qcom,msm8976-tsens', 'qcom,qcs404-tsens'] Signed-off-by: Amit Kucheria Reviewed-by: Vinod Koul Link: https://lore.kernel.org/r/ebaa801adade53c567857db2f74af7d2e00f935b.1582871139.git.amit.kucheria@linaro.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/msm8996.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index eaae356a493c..4afd0d85633e 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -446,7 +446,7 @@ }; tsens0: thermal-sensor@4a9000 { - compatible = "qcom,msm8996-tsens"; + compatible = "qcom,msm8996-tsens", "qcom,tsens-v2"; reg = <0x004a9000 0x1000>, /* TM */ <0x004a8000 0x1000>; /* SROT */ #qcom,sensors = <13>; @@ -457,7 +457,7 @@ }; tsens1: thermal-sensor@4ad000 { - compatible = "qcom,msm8996-tsens"; + compatible = "qcom,msm8996-tsens", "qcom,tsens-v2"; reg = <0x004ad000 0x1000>, /* TM */ <0x004ac000 0x1000>; /* SROT */ #qcom,sensors = <8>; From a6dd255bdd7d00bbdbf78ba00bde9fc64f86c3a7 Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 17 Jan 2020 02:48:34 +0800 Subject: [PATCH 0917/4444] bus: hisi_lpc: Fixup IO ports addresses to avoid use-after-free in host removal Some released ACPI FW for Huawei boards describes incorrect the port IO address range for child devices, in that it tells us the IO port max range is 0x3fff for each child device, which is not correct. The address range should be [e4:e8) or similar. With this incorrect upper range, the child device IO port resources overlap. As such, the kernel thinks that the LPC host serial device is a child of the IPMI device: root@(none)$ more /proc/ioports [...] 00ffc0e3-00ffffff : hisi-lpc-ipmi.0.auto 00ffc0e3-00ffc0e3 : ipmi_si 00ffc0e4-00ffc0e4 : ipmi_si 00ffc0e5-00ffc0e5 : ipmi_si 00ffc2f7-00ffffff : serial8250.1.auto 00ffc2f7-00ffc2fe : serial root@(none)$ They should both be siblings. Note that these are logical PIO addresses, which have a direct mapping from the FW IO port ranges. This shows up as a real issue when we enable CONFIG_KASAN and CONFIG_DEBUG_TEST_DRIVER_REMOVE - we see use-after-free warnings in the host removal path: ================================================================== BUG: KASAN: use-after-free in release_resource+0x38/0xc8 Read of size 8 at addr ffff0026accdbc38 by task swapper/0/1 CPU: 2 PID: 1 Comm: swapper/0 Not tainted 5.5.0-rc6-00001-g68e186e77b5c-dirty #1593 Hardware name: Huawei Taishan 2180 /D03, BIOS Hisilicon D03 IT20 Nemo 2.0 RC0 03/30/2018 Call trace: dump_backtrace+0x0/0x290 show_stack+0x14/0x20 dump_stack+0xf0/0x14c print_address_description.isra.9+0x6c/0x3b8 __kasan_report+0x12c/0x23c kasan_report+0xc/0x18 __asan_load8+0x94/0xb8 release_resource+0x38/0xc8 platform_device_del.part.10+0x80/0xe0 platform_device_unregister+0x20/0x38 hisi_lpc_acpi_remove_subdev+0x10/0x20 device_for_each_child+0xc8/0x128 hisi_lpc_acpi_remove+0x4c/0xa8 hisi_lpc_remove+0xbc/0xc0 platform_drv_remove+0x3c/0x68 really_probe+0x174/0x548 driver_probe_device+0x7c/0x148 device_driver_attach+0x94/0xa0 __driver_attach+0xa4/0x110 bus_for_each_dev+0xe8/0x158 driver_attach+0x30/0x40 bus_add_driver+0x234/0x2f0 driver_register+0xbc/0x1d0 __platform_driver_register+0x7c/0x88 hisi_lpc_driver_init+0x18/0x20 do_one_initcall+0xb4/0x258 kernel_init_freeable+0x248/0x2c0 kernel_init+0x10/0x118 ret_from_fork+0x10/0x1c ... The issue here is that the kernel created an incorrect parent-child resource dependency between two devices, and references the false parent node when deleting the second child device, when it had been deleted already. Fix up the child device resources from FW to create proper IO port resource relationships for broken FW. With this, the IO port layout looks more healthy: root@(none)$ more /proc/ioports [...] 00ffc0e3-00ffc0e7 : hisi-lpc-ipmi.0.auto 00ffc0e3-00ffc0e3 : ipmi_si 00ffc0e4-00ffc0e4 : ipmi_si 00ffc0e5-00ffc0e5 : ipmi_si 00ffc2f7-00ffc2ff : serial8250.1.auto 00ffc2f7-00ffc2fe : serial Signed-off-by: John Garry Signed-off-by: Wei Xu --- drivers/bus/hisi_lpc.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c index 8101df901830..378f5d62a991 100644 --- a/drivers/bus/hisi_lpc.c +++ b/drivers/bus/hisi_lpc.c @@ -357,6 +357,26 @@ static int hisi_lpc_acpi_xlat_io_res(struct acpi_device *adev, return 0; } +/* + * Released firmware describes the IO port max address as 0x3fff, which is + * the max host bus address. Fixup to a proper range. This will probably + * never be fixed in firmware. + */ +static void hisi_lpc_acpi_fixup_child_resource(struct device *hostdev, + struct resource *r) +{ + if (r->end != 0x3fff) + return; + + if (r->start == 0xe4) + r->end = 0xe4 + 0x04 - 1; + else if (r->start == 0x2f8) + r->end = 0x2f8 + 0x08 - 1; + else + dev_warn(hostdev, "unrecognised resource %pR to fixup, ignoring\n", + r); +} + /* * hisi_lpc_acpi_set_io_res - set the resources for a child * @child: the device node to be updated the I/O resource @@ -418,8 +438,11 @@ static int hisi_lpc_acpi_set_io_res(struct device *child, return -ENOMEM; } count = 0; - list_for_each_entry(rentry, &resource_list, node) - resources[count++] = *rentry->res; + list_for_each_entry(rentry, &resource_list, node) { + resources[count] = *rentry->res; + hisi_lpc_acpi_fixup_child_resource(hostdev, &resources[count]); + count++; + } acpi_dev_free_resource_list(&resource_list); From d698e544e2107e3e161ddbb3a28324197ecd537f Mon Sep 17 00:00:00 2001 From: John Garry Date: Mon, 10 Feb 2020 18:40:40 +0800 Subject: [PATCH 0918/4444] arm64: defconfig: Enable MEGARAID_SAS Our new dev board (Huawei D06CS) has a MegaRAID SAS HBA as the storage controller, and we cannot access the HiSilicon SAS HBA, which we normally use; so enable the driver config option so we can boot a distro with the default defconfig. Signed-off-by: John Garry Signed-off-by: Wei Xu --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 0f212889c931..3c2dd127d813 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -226,6 +226,7 @@ CONFIG_BLK_DEV_SD=y CONFIG_SCSI_SAS_ATA=y CONFIG_SCSI_HISI_SAS=y CONFIG_SCSI_HISI_SAS_PCI=y +CONFIG_MEGARAID_SAS=y CONFIG_SCSI_MPT3SAS=m CONFIG_SCSI_UFSHCD=y CONFIG_SCSI_UFSHCD_PLATFORM=y From 7fd2944bdcb3f07eac29efcfdd28bc9ccfb26ce6 Mon Sep 17 00:00:00 2001 From: David Dai Date: Fri, 28 Feb 2020 12:11:40 +0200 Subject: [PATCH 0919/4444] dt-bindings: interconnect: Convert qcom,sdm845 to DT schema Convert the qcom,sdm845 interconnect provider binding to DT schema. Signed-off-by: David Dai Reviewed-by: Rob Herring Signed-off-by: Odelu Kukatla Signed-off-by: Sibi Sankar Link: https://lore.kernel.org/r/20200209183411.17195-2-sibis@codeaurora.org Signed-off-by: Georgi Djakov --- .../bindings/interconnect/qcom,sdm845.txt | 24 ----------- .../bindings/interconnect/qcom,sdm845.yaml | 43 +++++++++++++++++++ 2 files changed, 43 insertions(+), 24 deletions(-) delete mode 100644 Documentation/devicetree/bindings/interconnect/qcom,sdm845.txt create mode 100644 Documentation/devicetree/bindings/interconnect/qcom,sdm845.yaml diff --git a/Documentation/devicetree/bindings/interconnect/qcom,sdm845.txt b/Documentation/devicetree/bindings/interconnect/qcom,sdm845.txt deleted file mode 100644 index 5c4f1d911630..000000000000 --- a/Documentation/devicetree/bindings/interconnect/qcom,sdm845.txt +++ /dev/null @@ -1,24 +0,0 @@ -Qualcomm SDM845 Network-On-Chip interconnect driver binding ------------------------------------------------------------ - -SDM845 interconnect providers support system bandwidth requirements through -RPMh hardware accelerators known as Bus Clock Manager (BCM). The provider is -able to communicate with the BCM through the Resource State Coordinator (RSC) -associated with each execution environment. Provider nodes must reside within -an RPMh device node pertaining to their RSC and each provider maps to a single -RPMh resource. - -Required properties : -- compatible : shall contain only one of the following: - "qcom,sdm845-rsc-hlos" -- #interconnect-cells : should contain 1 - -Examples: - -apps_rsc: rsc { - rsc_hlos: interconnect { - compatible = "qcom,sdm845-rsc-hlos"; - #interconnect-cells = <1>; - }; -}; - diff --git a/Documentation/devicetree/bindings/interconnect/qcom,sdm845.yaml b/Documentation/devicetree/bindings/interconnect/qcom,sdm845.yaml new file mode 100644 index 000000000000..11a495dbfc52 --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/qcom,sdm845.yaml @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interconnect/qcom,sdm845.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SDM845 Network-On-Chip Interconnect + +maintainers: + - Georgi Djakov + +description: | + SDM845 interconnect providers support system bandwidth requirements through + RPMh hardware accelerators known as Bus Clock Manager (BCM). The provider is + able to communicate with the BCM through the Resource State Coordinator (RSC) + associated with each execution environment. Provider nodes must reside within + an RPMh device node pertaining to their RSC and each provider maps to a + single RPMh resource. + +properties: + compatible: + enum: + - qcom,sdm845-rsc-hlos + + '#interconnect-cells': + const: 1 + +required: + - compatible + - '#interconnect-cells' + +additionalProperties: false + +examples: + - | + #include + + apps_rsc: rsc { + rsc_hlos: interconnect { + compatible = "qcom,sdm845-rsc-hlos"; + #interconnect-cells = <1>; + }; + }; From c92cf0b40a7dc53aa3eaac3cdd0706a3892148ce Mon Sep 17 00:00:00 2001 From: David Dai Date: Fri, 28 Feb 2020 12:11:40 +0200 Subject: [PATCH 0920/4444] dt-bindings: interconnect: Add YAML schemas for QCOM bcm-voter Add YAML schemas for interconnect bcm-voters found on QCOM RPMh-based SoCs. Signed-off-by: David Dai Signed-off-by: Odelu Kukatla Signed-off-by: Sibi Sankar Acked-by: Rob Herring Link: https://lore.kernel.org/r/20200209183411.17195-3-sibis@codeaurora.org Signed-off-by: Georgi Djakov --- .../bindings/interconnect/qcom,bcm-voter.yaml | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/qcom,bcm-voter.yaml diff --git a/Documentation/devicetree/bindings/interconnect/qcom,bcm-voter.yaml b/Documentation/devicetree/bindings/interconnect/qcom,bcm-voter.yaml new file mode 100644 index 000000000000..5971fc1df08d --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/qcom,bcm-voter.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interconnect/qcom,bcm-voter.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm BCM-Voter Interconnect + +maintainers: + - Georgi Djakov + +description: | + The Bus Clock Manager (BCM) is a dedicated hardware accelerator that manages + shared system resources by aggregating requests from multiple Resource State + Coordinators (RSC). Interconnect providers are able to vote for aggregated + thresholds values from consumers by communicating through their respective + RSCs. + +properties: + compatible: + enum: + - qcom,bcm-voter + +required: + - compatible + +additionalProperties: false + +examples: + # Example 1: apps bcm_voter on SDM845 SoC should be defined inside &apps_rsc node + # as defined in Documentation/devicetree/bindings/soc/qcom/rpmh-rsc.txt + - | + + apps_bcm_voter: bcm_voter { + compatible = "qcom,bcm-voter"; + }; + + # Example 2: disp bcm_voter on SDM845 should be defined inside &disp_rsc node + # as defined in Documentation/devicetree/bindings/soc/qcom/rpmh-rsc.txt + - | + + disp_bcm_voter: bcm_voter { + compatible = "qcom,bcm-voter"; + }; +... From 6f690e16b5a08919feeced1dc4603aca01d7ed58 Mon Sep 17 00:00:00 2001 From: David Dai Date: Fri, 28 Feb 2020 12:11:40 +0200 Subject: [PATCH 0921/4444] dt-bindings: interconnect: Update Qualcomm SDM845 DT bindings Redefine the Network-on-Chip devices to more accurately describe the interconnect topology on Qualcomm's SDM845 platform. Each interconnect device can communicate with different instances of the RPMh hardware which are described as RSCs(Resource State Coordinators). Signed-off-by: David Dai Signed-off-by: Odelu Kukatla Signed-off-by: Sibi Sankar Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20200209183411.17195-4-sibis@codeaurora.org Signed-off-by: Georgi Djakov --- .../bindings/interconnect/qcom,sdm845.yaml | 49 +++++++++++++++---- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/interconnect/qcom,sdm845.yaml b/Documentation/devicetree/bindings/interconnect/qcom,sdm845.yaml index 11a495dbfc52..8b087e0b0b81 100644 --- a/Documentation/devicetree/bindings/interconnect/qcom,sdm845.yaml +++ b/Documentation/devicetree/bindings/interconnect/qcom,sdm845.yaml @@ -13,21 +13,44 @@ description: | SDM845 interconnect providers support system bandwidth requirements through RPMh hardware accelerators known as Bus Clock Manager (BCM). The provider is able to communicate with the BCM through the Resource State Coordinator (RSC) - associated with each execution environment. Provider nodes must reside within - an RPMh device node pertaining to their RSC and each provider maps to a - single RPMh resource. + associated with each execution environment. Provider nodes must point to at + least one RPMh device child node pertaining to their RSC and each provider + can map to multiple RPMh resources. properties: + reg: + maxItems: 1 + compatible: enum: - - qcom,sdm845-rsc-hlos + - qcom,sdm845-aggre1-noc + - qcom,sdm845-aggre2-noc + - qcom,sdm845-config-noc + - qcom,sdm845-dc-noc + - qcom,sdm845-gladiator-noc + - qcom,sdm845-mem-noc + - qcom,sdm845-mmss-noc + - qcom,sdm845-system-noc '#interconnect-cells': const: 1 + qcom,bcm-voters: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: | + List of phandles to qcom,bcm-voter nodes that are required by + this interconnect to send RPMh commands. + + qcom,bcm-voter-names: + $ref: /schemas/types.yaml#/definitions/string-array + description: | + Names for each of the qcom,bcm-voters specified. + required: - compatible + - reg - '#interconnect-cells' + - qcom,bcm-voters additionalProperties: false @@ -35,9 +58,17 @@ examples: - | #include - apps_rsc: rsc { - rsc_hlos: interconnect { - compatible = "qcom,sdm845-rsc-hlos"; - #interconnect-cells = <1>; - }; + mem_noc: interconnect@1380000 { + compatible = "qcom,sdm845-mem-noc"; + reg = <0 0x01380000 0 0x27200>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + mmss_noc: interconnect@1740000 { + compatible = "qcom,sdm845-mmss-noc"; + reg = <0 0x01740000 0 0x1c1000>; + #interconnect-cells = <1>; + qcom,bcm-voter-names = "apps", "disp"; + qcom,bcm-voters = <&apps_bcm_voter>, <&disp_bcm_voter>; }; From 976daac4a1c581e5d5fd64047519fd6fcde39738 Mon Sep 17 00:00:00 2001 From: David Dai Date: Fri, 28 Feb 2020 12:11:40 +0200 Subject: [PATCH 0922/4444] interconnect: qcom: Consolidate interconnect RPMh support Add bcm voter driver and add support for RPMh specific interconnect providers which implements the set and aggregate functionalities that translates bandwidth requests into RPMh messages. These modules provide a common set of functionalities for all Qualcomm RPMh based interconnect providers and should help reduce code duplication when adding new providers. Signed-off-by: David Dai Signed-off-by: Odelu Kukatla Reviewed-by: Evan Green Signed-off-by: Sibi Sankar Link: https://lore.kernel.org/r/20200228095951.15457-1-sibis@codeaurora.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/Kconfig | 8 + drivers/interconnect/qcom/Makefile | 4 + drivers/interconnect/qcom/bcm-voter.c | 366 ++++++++++++++++++++++++++ drivers/interconnect/qcom/bcm-voter.h | 27 ++ drivers/interconnect/qcom/icc-rpmh.c | 150 +++++++++++ drivers/interconnect/qcom/icc-rpmh.h | 149 +++++++++++ 6 files changed, 704 insertions(+) create mode 100644 drivers/interconnect/qcom/bcm-voter.c create mode 100644 drivers/interconnect/qcom/bcm-voter.h create mode 100644 drivers/interconnect/qcom/icc-rpmh.c create mode 100644 drivers/interconnect/qcom/icc-rpmh.h diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig index 76938ece1658..87c926897e78 100644 --- a/drivers/interconnect/qcom/Kconfig +++ b/drivers/interconnect/qcom/Kconfig @@ -5,6 +5,9 @@ config INTERCONNECT_QCOM help Support for Qualcomm's Network-on-Chip interconnect hardware. +config INTERCONNECT_QCOM_BCM_VOTER + tristate + config INTERCONNECT_QCOM_MSM8916 tristate "Qualcomm MSM8916 interconnect driver" depends on INTERCONNECT_QCOM @@ -32,10 +35,15 @@ config INTERCONNECT_QCOM_QCS404 This is a driver for the Qualcomm Network-on-Chip on qcs404-based platforms. +config INTERCONNECT_QCOM_RPMH + tristate + config INTERCONNECT_QCOM_SDM845 tristate "Qualcomm SDM845 interconnect driver" depends on INTERCONNECT_QCOM depends on (QCOM_RPMH && QCOM_COMMAND_DB && OF) || COMPILE_TEST + select INTERCONNECT_QCOM_RPMH + select INTERCONNECT_QCOM_BCM_VOTER help This is a driver for the Qualcomm Network-on-Chip on sdm845-based platforms. diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile index e8271575e3d8..d591bb56273b 100644 --- a/drivers/interconnect/qcom/Makefile +++ b/drivers/interconnect/qcom/Makefile @@ -1,13 +1,17 @@ # SPDX-License-Identifier: GPL-2.0 +icc-bcm-voter-objs := bcm-voter.o qnoc-msm8916-objs := msm8916.o qnoc-msm8974-objs := msm8974.o qnoc-qcs404-objs := qcs404.o +icc-rpmh-obj := icc-rpmh.o qnoc-sdm845-objs := sdm845.o icc-smd-rpm-objs := smd-rpm.o +obj-$(CONFIG_INTERCONNECT_QCOM_BCM_VOTER) += icc-bcm-voter.o obj-$(CONFIG_INTERCONNECT_QCOM_MSM8916) += qnoc-msm8916.o obj-$(CONFIG_INTERCONNECT_QCOM_MSM8974) += qnoc-msm8974.o obj-$(CONFIG_INTERCONNECT_QCOM_QCS404) += qnoc-qcs404.o +obj-$(CONFIG_INTERCONNECT_QCOM_RPMH) += icc-rpmh.o obj-$(CONFIG_INTERCONNECT_QCOM_SDM845) += qnoc-sdm845.o obj-$(CONFIG_INTERCONNECT_QCOM_SMD_RPM) += icc-smd-rpm.o diff --git a/drivers/interconnect/qcom/bcm-voter.c b/drivers/interconnect/qcom/bcm-voter.c new file mode 100644 index 000000000000..2adfde8cdf19 --- /dev/null +++ b/drivers/interconnect/qcom/bcm-voter.c @@ -0,0 +1,366 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bcm-voter.h" +#include "icc-rpmh.h" + +static LIST_HEAD(bcm_voters); +static DEFINE_MUTEX(bcm_voter_lock); + +/** + * struct bcm_voter - Bus Clock Manager voter + * @dev: reference to the device that communicates with the BCM + * @np: reference to the device node to match bcm voters + * @lock: mutex to protect commit and wake/sleep lists in the voter + * @commit_list: list containing bcms to be committed to hardware + * @ws_list: list containing bcms that have different wake/sleep votes + * @voter_node: list of bcm voters + */ +struct bcm_voter { + struct device *dev; + struct device_node *np; + struct mutex lock; + struct list_head commit_list; + struct list_head ws_list; + struct list_head voter_node; +}; + +static int cmp_vcd(void *priv, struct list_head *a, struct list_head *b) +{ + const struct qcom_icc_bcm *bcm_a = + list_entry(a, struct qcom_icc_bcm, list); + const struct qcom_icc_bcm *bcm_b = + list_entry(b, struct qcom_icc_bcm, list); + + if (bcm_a->aux_data.vcd < bcm_b->aux_data.vcd) + return -1; + else if (bcm_a->aux_data.vcd == bcm_b->aux_data.vcd) + return 0; + else + return 1; +} + +static void bcm_aggregate(struct qcom_icc_bcm *bcm) +{ + size_t i, bucket; + u64 agg_avg[QCOM_ICC_NUM_BUCKETS] = {0}; + u64 agg_peak[QCOM_ICC_NUM_BUCKETS] = {0}; + u64 temp; + + for (bucket = 0; bucket < QCOM_ICC_NUM_BUCKETS; bucket++) { + for (i = 0; i < bcm->num_nodes; i++) { + temp = bcm->nodes[i]->sum_avg[bucket] * bcm->aux_data.width; + do_div(temp, bcm->nodes[i]->buswidth * bcm->nodes[i]->channels); + agg_avg[bucket] = max(agg_avg[bucket], temp); + + temp = bcm->nodes[i]->max_peak[bucket] * bcm->aux_data.width; + do_div(temp, bcm->nodes[i]->buswidth); + agg_peak[bucket] = max(agg_peak[bucket], temp); + } + + temp = agg_avg[bucket] * 1000ULL; + do_div(temp, bcm->aux_data.unit); + bcm->vote_x[bucket] = temp; + + temp = agg_peak[bucket] * 1000ULL; + do_div(temp, bcm->aux_data.unit); + bcm->vote_y[bucket] = temp; + } + + if (bcm->keepalive && bcm->vote_x[QCOM_ICC_BUCKET_AMC] == 0 && + bcm->vote_y[QCOM_ICC_BUCKET_AMC] == 0) { + bcm->vote_x[QCOM_ICC_BUCKET_AMC] = 1; + bcm->vote_x[QCOM_ICC_BUCKET_WAKE] = 1; + bcm->vote_y[QCOM_ICC_BUCKET_AMC] = 1; + bcm->vote_y[QCOM_ICC_BUCKET_WAKE] = 1; + } +} + +static inline void tcs_cmd_gen(struct tcs_cmd *cmd, u64 vote_x, u64 vote_y, + u32 addr, bool commit) +{ + bool valid = true; + + if (!cmd) + return; + + if (vote_x == 0 && vote_y == 0) + valid = false; + + if (vote_x > BCM_TCS_CMD_VOTE_MASK) + vote_x = BCM_TCS_CMD_VOTE_MASK; + + if (vote_y > BCM_TCS_CMD_VOTE_MASK) + vote_y = BCM_TCS_CMD_VOTE_MASK; + + cmd->addr = addr; + cmd->data = BCM_TCS_CMD(commit, valid, vote_x, vote_y); + + /* + * Set the wait for completion flag on command that need to be completed + * before the next command. + */ + if (commit) + cmd->wait = true; +} + +static void tcs_list_gen(struct list_head *bcm_list, int bucket, + struct tcs_cmd tcs_list[MAX_BCMS], + int n[MAX_VCD + 1]) +{ + struct qcom_icc_bcm *bcm; + bool commit; + size_t idx = 0, batch = 0, cur_vcd_size = 0; + + memset(n, 0, sizeof(int) * (MAX_VCD + 1)); + + list_for_each_entry(bcm, bcm_list, list) { + commit = false; + cur_vcd_size++; + if ((list_is_last(&bcm->list, bcm_list)) || + bcm->aux_data.vcd != list_next_entry(bcm, list)->aux_data.vcd) { + commit = true; + cur_vcd_size = 0; + } + tcs_cmd_gen(&tcs_list[idx], bcm->vote_x[bucket], + bcm->vote_y[bucket], bcm->addr, commit); + idx++; + n[batch]++; + /* + * Batch the BCMs in such a way that we do not split them in + * multiple payloads when they are under the same VCD. This is + * to ensure that every BCM is committed since we only set the + * commit bit on the last BCM request of every VCD. + */ + if (n[batch] >= MAX_RPMH_PAYLOAD) { + if (!commit) { + n[batch] -= cur_vcd_size; + n[batch + 1] = cur_vcd_size; + } + batch++; + } + } +} + +/** + * of_bcm_voter_get - gets a bcm voter handle from DT node + * @dev: device pointer for the consumer device + * @name: name for the bcm voter device + * + * This function will match a device_node pointer for the phandle + * specified in the device DT and return a bcm_voter handle on success. + * + * Returns bcm_voter pointer or ERR_PTR() on error. EPROBE_DEFER is returned + * when matching bcm voter is yet to be found. + */ +struct bcm_voter *of_bcm_voter_get(struct device *dev, const char *name) +{ + struct bcm_voter *voter = ERR_PTR(-EPROBE_DEFER); + struct bcm_voter *temp; + struct device_node *np, *node; + int idx = 0; + + if (!dev || !dev->of_node) + return ERR_PTR(-ENODEV); + + np = dev->of_node; + + if (name) { + idx = of_property_match_string(np, "qcom,bcm-voter-names", name); + if (idx < 0) + return ERR_PTR(idx); + } + + node = of_parse_phandle(np, "qcom,bcm-voters", idx); + + mutex_lock(&bcm_voter_lock); + list_for_each_entry(temp, &bcm_voters, voter_node) { + if (temp->np == node) { + voter = temp; + break; + } + } + mutex_unlock(&bcm_voter_lock); + + return voter; +} +EXPORT_SYMBOL_GPL(of_bcm_voter_get); + +/** + * qcom_icc_bcm_voter_add - queues up the bcm nodes that require updates + * @voter: voter that the bcms are being added to + * @bcm: bcm to add to the commit and wake sleep list + */ +void qcom_icc_bcm_voter_add(struct bcm_voter *voter, struct qcom_icc_bcm *bcm) +{ + if (!voter) + return; + + mutex_lock(&voter->lock); + if (list_empty(&bcm->list)) + list_add_tail(&bcm->list, &voter->commit_list); + + if (list_empty(&bcm->ws_list)) + list_add_tail(&bcm->ws_list, &voter->ws_list); + + mutex_unlock(&voter->lock); +} +EXPORT_SYMBOL_GPL(qcom_icc_bcm_voter_add); + +/** + * qcom_icc_bcm_voter_commit - generates and commits tcs cmds based on bcms + * @voter: voter that needs flushing + * + * This function generates a set of AMC commands and flushes to the BCM device + * associated with the voter. It conditionally generate WAKE and SLEEP commands + * based on deltas between WAKE/SLEEP requirements. The ws_list persists + * through multiple commit requests and bcm nodes are removed only when the + * requirements for WAKE matches SLEEP. + * + * Returns 0 on success, or an appropriate error code otherwise. + */ +int qcom_icc_bcm_voter_commit(struct bcm_voter *voter) +{ + struct qcom_icc_bcm *bcm; + struct qcom_icc_bcm *bcm_tmp; + int commit_idx[MAX_VCD + 1]; + struct tcs_cmd cmds[MAX_BCMS]; + int ret = 0; + + if (!voter) + return 0; + + mutex_lock(&voter->lock); + list_for_each_entry(bcm, &voter->commit_list, list) + bcm_aggregate(bcm); + + /* + * Pre sort the BCMs based on VCD for ease of generating a command list + * that groups the BCMs with the same VCD together. VCDs are numbered + * with lowest being the most expensive time wise, ensuring that + * those commands are being sent the earliest in the queue. This needs + * to be sorted every commit since we can't guarantee the order in which + * the BCMs are added to the list. + */ + list_sort(NULL, &voter->commit_list, cmp_vcd); + + /* + * Construct the command list based on a pre ordered list of BCMs + * based on VCD. + */ + tcs_list_gen(&voter->commit_list, QCOM_ICC_BUCKET_AMC, cmds, commit_idx); + + if (!commit_idx[0]) + goto out; + + ret = rpmh_invalidate(voter->dev); + if (ret) { + pr_err("Error invalidating RPMH client (%d)\n", ret); + goto out; + } + + ret = rpmh_write_batch(voter->dev, RPMH_ACTIVE_ONLY_STATE, + cmds, commit_idx); + if (ret) { + pr_err("Error sending AMC RPMH requests (%d)\n", ret); + goto out; + } + + list_for_each_entry_safe(bcm, bcm_tmp, &voter->commit_list, list) + list_del_init(&bcm->list); + + list_for_each_entry_safe(bcm, bcm_tmp, &voter->ws_list, ws_list) { + /* + * Only generate WAKE and SLEEP commands if a resource's + * requirements change as the execution environment transitions + * between different power states. + */ + if (bcm->vote_x[QCOM_ICC_BUCKET_WAKE] != + bcm->vote_x[QCOM_ICC_BUCKET_SLEEP] || + bcm->vote_y[QCOM_ICC_BUCKET_WAKE] != + bcm->vote_y[QCOM_ICC_BUCKET_SLEEP]) + list_add_tail(&bcm->list, &voter->commit_list); + else + list_del_init(&bcm->ws_list); + } + + if (list_empty(&voter->commit_list)) + goto out; + + list_sort(NULL, &voter->commit_list, cmp_vcd); + + tcs_list_gen(&voter->commit_list, QCOM_ICC_BUCKET_WAKE, cmds, commit_idx); + + ret = rpmh_write_batch(voter->dev, RPMH_WAKE_ONLY_STATE, cmds, commit_idx); + if (ret) { + pr_err("Error sending WAKE RPMH requests (%d)\n", ret); + goto out; + } + + tcs_list_gen(&voter->commit_list, QCOM_ICC_BUCKET_SLEEP, cmds, commit_idx); + + ret = rpmh_write_batch(voter->dev, RPMH_SLEEP_STATE, cmds, commit_idx); + if (ret) { + pr_err("Error sending SLEEP RPMH requests (%d)\n", ret); + goto out; + } + +out: + list_for_each_entry_safe(bcm, bcm_tmp, &voter->commit_list, list) + list_del_init(&bcm->list); + + mutex_unlock(&voter->lock); + return ret; +} +EXPORT_SYMBOL_GPL(qcom_icc_bcm_voter_commit); + +static int qcom_icc_bcm_voter_probe(struct platform_device *pdev) +{ + struct bcm_voter *voter; + + voter = devm_kzalloc(&pdev->dev, sizeof(*voter), GFP_KERNEL); + if (!voter) + return -ENOMEM; + + voter->dev = &pdev->dev; + voter->np = pdev->dev.of_node; + mutex_init(&voter->lock); + INIT_LIST_HEAD(&voter->commit_list); + INIT_LIST_HEAD(&voter->ws_list); + + mutex_lock(&bcm_voter_lock); + list_add_tail(&voter->voter_node, &bcm_voters); + mutex_unlock(&bcm_voter_lock); + + return 0; +} + +static const struct of_device_id bcm_voter_of_match[] = { + { .compatible = "qcom,bcm-voter" }, + { } +}; + +static struct platform_driver qcom_icc_bcm_voter_driver = { + .probe = qcom_icc_bcm_voter_probe, + .driver = { + .name = "bcm_voter", + .of_match_table = bcm_voter_of_match, + }, +}; +module_platform_driver(qcom_icc_bcm_voter_driver); + +MODULE_AUTHOR("David Dai "); +MODULE_DESCRIPTION("Qualcomm BCM Voter interconnect driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/qcom/bcm-voter.h b/drivers/interconnect/qcom/bcm-voter.h new file mode 100644 index 000000000000..0f64c0bab2c0 --- /dev/null +++ b/drivers/interconnect/qcom/bcm-voter.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef __DRIVERS_INTERCONNECT_QCOM_BCM_VOTER_H__ +#define __DRIVERS_INTERCONNECT_QCOM_BCM_VOTER_H__ + +#include +#include +#include + +#include "icc-rpmh.h" + +#define DEFINE_QBCM(_name, _bcmname, _keepalive, ...) \ +static struct qcom_icc_bcm _name = { \ + .name = _bcmname, \ + .keepalive = _keepalive, \ + .num_nodes = ARRAY_SIZE(((struct qcom_icc_node *[]){ __VA_ARGS__ })), \ + .nodes = { __VA_ARGS__ }, \ +} + +struct bcm_voter *of_bcm_voter_get(struct device *dev, const char *name); +void qcom_icc_bcm_voter_add(struct bcm_voter *voter, struct qcom_icc_bcm *bcm); +int qcom_icc_bcm_voter_commit(struct bcm_voter *voter); + +#endif diff --git a/drivers/interconnect/qcom/icc-rpmh.c b/drivers/interconnect/qcom/icc-rpmh.c new file mode 100644 index 000000000000..3ac5182c9ab2 --- /dev/null +++ b/drivers/interconnect/qcom/icc-rpmh.c @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include + +#include "bcm-voter.h" +#include "icc-rpmh.h" + +/** + * qcom_icc_pre_aggregate - cleans up stale values from prior icc_set + * @node: icc node to operate on + */ +void qcom_icc_pre_aggregate(struct icc_node *node) +{ + size_t i; + struct qcom_icc_node *qn; + + qn = node->data; + + for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) { + qn->sum_avg[i] = 0; + qn->max_peak[i] = 0; + } +} +EXPORT_SYMBOL_GPL(qcom_icc_pre_aggregate); + +/** + * qcom_icc_aggregate - aggregate bw for buckets indicated by tag + * @node: node to aggregate + * @tag: tag to indicate which buckets to aggregate + * @avg_bw: new bw to sum aggregate + * @peak_bw: new bw to max aggregate + * @agg_avg: existing aggregate avg bw val + * @agg_peak: existing aggregate peak bw val + */ +int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, + u32 peak_bw, u32 *agg_avg, u32 *agg_peak) +{ + size_t i; + struct qcom_icc_node *qn; + struct qcom_icc_provider *qp; + + qn = node->data; + qp = to_qcom_provider(node->provider); + + if (!tag) + tag = QCOM_ICC_TAG_ALWAYS; + + for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) { + if (tag & BIT(i)) { + qn->sum_avg[i] += avg_bw; + qn->max_peak[i] = max_t(u32, qn->max_peak[i], peak_bw); + } + } + + *agg_avg += avg_bw; + *agg_peak = max_t(u32, *agg_peak, peak_bw); + + for (i = 0; i < qn->num_bcms; i++) + qcom_icc_bcm_voter_add(qp->voter, qn->bcms[i]); + + return 0; +} +EXPORT_SYMBOL_GPL(qcom_icc_aggregate); + +/** + * qcom_icc_set - set the constraints based on path + * @src: source node for the path to set constraints on + * @dst: destination node for the path to set constraints on + * + * Return: 0 on success, or an error code otherwise + */ +int qcom_icc_set(struct icc_node *src, struct icc_node *dst) +{ + struct qcom_icc_provider *qp; + struct icc_node *node; + + if (!src) + node = dst; + else + node = src; + + qp = to_qcom_provider(node->provider); + + qcom_icc_bcm_voter_commit(qp->voter); + + return 0; +} +EXPORT_SYMBOL_GPL(qcom_icc_set); + +/** + * qcom_icc_bcm_init - populates bcm aux data and connect qnodes + * @bcm: bcm to be initialized + * @dev: associated provider device + * + * Return: 0 on success, or an error code otherwise + */ +int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev) +{ + struct qcom_icc_node *qn; + const struct bcm_db *data; + size_t data_count; + int i; + + /* BCM is already initialised*/ + if (bcm->addr) + return 0; + + bcm->addr = cmd_db_read_addr(bcm->name); + if (!bcm->addr) { + dev_err(dev, "%s could not find RPMh address\n", + bcm->name); + return -EINVAL; + } + + data = cmd_db_read_aux_data(bcm->name, &data_count); + if (IS_ERR(data)) { + dev_err(dev, "%s command db read error (%ld)\n", + bcm->name, PTR_ERR(data)); + return PTR_ERR(data); + } + if (!data_count) { + dev_err(dev, "%s command db missing or partial aux data\n", + bcm->name); + return -EINVAL; + } + + bcm->aux_data.unit = le32_to_cpu(data->unit); + bcm->aux_data.width = le16_to_cpu(data->width); + bcm->aux_data.vcd = data->vcd; + bcm->aux_data.reserved = data->reserved; + INIT_LIST_HEAD(&bcm->list); + INIT_LIST_HEAD(&bcm->ws_list); + + /* Link Qnodes to their respective BCMs */ + for (i = 0; i < bcm->num_nodes; i++) { + qn = bcm->nodes[i]; + qn->bcms[qn->num_bcms] = bcm; + qn->num_bcms++; + } + + return 0; +} +EXPORT_SYMBOL_GPL(qcom_icc_bcm_init); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/qcom/icc-rpmh.h b/drivers/interconnect/qcom/icc-rpmh.h new file mode 100644 index 000000000000..903d25e61984 --- /dev/null +++ b/drivers/interconnect/qcom/icc-rpmh.h @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef __DRIVERS_INTERCONNECT_QCOM_ICC_RPMH_H__ +#define __DRIVERS_INTERCONNECT_QCOM_ICC_RPMH_H__ + +#define to_qcom_provider(_provider) \ + container_of(_provider, struct qcom_icc_provider, provider) + +/** + * struct qcom_icc_provider - Qualcomm specific interconnect provider + * @provider: generic interconnect provider + * @dev: reference to the NoC device + * @bcms: list of bcms that maps to the provider + * @num_bcms: number of @bcms + * @voter: bcm voter targeted by this provider + */ +struct qcom_icc_provider { + struct icc_provider provider; + struct device *dev; + struct qcom_icc_bcm **bcms; + size_t num_bcms; + struct bcm_voter *voter; +}; + +/** + * struct bcm_db - Auxiliary data pertaining to each Bus Clock Manager (BCM) + * @unit: divisor used to convert bytes/sec bw value to an RPMh msg + * @width: multiplier used to convert bytes/sec bw value to an RPMh msg + * @vcd: virtual clock domain that this bcm belongs to + * @reserved: reserved field + */ +struct bcm_db { + __le32 unit; + __le16 width; + u8 vcd; + u8 reserved; +}; + +#define MAX_LINKS 128 +#define MAX_BCMS 64 +#define MAX_BCM_PER_NODE 3 +#define MAX_VCD 10 + +/* + * The AMC bucket denotes constraints that are applied to hardware when + * icc_set_bw() completes, whereas the WAKE and SLEEP constraints are applied + * when the execution environment transitions between active and low power mode. + */ +#define QCOM_ICC_BUCKET_AMC 0 +#define QCOM_ICC_BUCKET_WAKE 1 +#define QCOM_ICC_BUCKET_SLEEP 2 +#define QCOM_ICC_NUM_BUCKETS 3 +#define QCOM_ICC_TAG_AMC BIT(QCOM_ICC_BUCKET_AMC) +#define QCOM_ICC_TAG_WAKE BIT(QCOM_ICC_BUCKET_WAKE) +#define QCOM_ICC_TAG_SLEEP BIT(QCOM_ICC_BUCKET_SLEEP) +#define QCOM_ICC_TAG_ACTIVE_ONLY (QCOM_ICC_TAG_AMC | QCOM_ICC_TAG_WAKE) +#define QCOM_ICC_TAG_ALWAYS (QCOM_ICC_TAG_AMC | QCOM_ICC_TAG_WAKE |\ + QCOM_ICC_TAG_SLEEP) + +/** + * struct qcom_icc_node - Qualcomm specific interconnect nodes + * @name: the node name used in debugfs + * @links: an array of nodes where we can go next while traversing + * @id: a unique node identifier + * @num_links: the total number of @links + * @channels: num of channels at this node + * @buswidth: width of the interconnect between a node and the bus + * @sum_avg: current sum aggregate value of all avg bw requests + * @max_peak: current max aggregate value of all peak bw requests + * @bcms: list of bcms associated with this logical node + * @num_bcms: num of @bcms + */ +struct qcom_icc_node { + const char *name; + u16 links[MAX_LINKS]; + u16 id; + u16 num_links; + u16 channels; + u16 buswidth; + u64 sum_avg[QCOM_ICC_NUM_BUCKETS]; + u64 max_peak[QCOM_ICC_NUM_BUCKETS]; + struct qcom_icc_bcm *bcms[MAX_BCM_PER_NODE]; + size_t num_bcms; +}; + +/** + * struct qcom_icc_bcm - Qualcomm specific hardware accelerator nodes + * known as Bus Clock Manager (BCM) + * @name: the bcm node name used to fetch BCM data from command db + * @type: latency or bandwidth bcm + * @addr: address offsets used when voting to RPMH + * @vote_x: aggregated threshold values, represents sum_bw when @type is bw bcm + * @vote_y: aggregated threshold values, represents peak_bw when @type is bw bcm + * @dirty: flag used to indicate whether the bcm needs to be committed + * @keepalive: flag used to indicate whether a keepalive is required + * @aux_data: auxiliary data used when calculating threshold values and + * communicating with RPMh + * @list: used to link to other bcms when compiling lists for commit + * @ws_list: used to keep track of bcms that may transition between wake/sleep + * @num_nodes: total number of @num_nodes + * @nodes: list of qcom_icc_nodes that this BCM encapsulates + */ +struct qcom_icc_bcm { + const char *name; + u32 type; + u32 addr; + u64 vote_x[QCOM_ICC_NUM_BUCKETS]; + u64 vote_y[QCOM_ICC_NUM_BUCKETS]; + bool dirty; + bool keepalive; + struct bcm_db aux_data; + struct list_head list; + struct list_head ws_list; + size_t num_nodes; + struct qcom_icc_node *nodes[]; +}; + +struct qcom_icc_fabric { + struct qcom_icc_node **nodes; + size_t num_nodes; +}; + +struct qcom_icc_desc { + struct qcom_icc_node **nodes; + size_t num_nodes; + struct qcom_icc_bcm **bcms; + size_t num_bcms; +}; + +#define DEFINE_QNODE(_name, _id, _channels, _buswidth, ...) \ + static struct qcom_icc_node _name = { \ + .id = _id, \ + .name = #_name, \ + .channels = _channels, \ + .buswidth = _buswidth, \ + .num_links = ARRAY_SIZE(((int[]){ __VA_ARGS__ })), \ + .links = { __VA_ARGS__ }, \ + } + +int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, + u32 peak_bw, u32 *agg_avg, u32 *agg_peak); +int qcom_icc_set(struct icc_node *src, struct icc_node *dst); +int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev); +void qcom_icc_pre_aggregate(struct icc_node *node); + +#endif From aae57773fbe01b573c9447d877964857cfe1d0f0 Mon Sep 17 00:00:00 2001 From: David Dai Date: Fri, 28 Feb 2020 12:11:40 +0200 Subject: [PATCH 0923/4444] interconnect: qcom: sdm845: Split qnodes into their respective NoCs In order to better represent the hardware and its different Network-On-Chip devices, split the sdm845 provider driver into NoC specific providers. Remove duplicate functionality already provided by the icc rpmh and bcm voter drivers to calculate and commit bandwidth requests to hardware. Signed-off-by: David Dai Signed-off-by: Odelu Kukatla Signed-off-by: Sibi Sankar Reviewed-by: Evan Green Link: https://lore.kernel.org/r/20200209183411.17195-6-sibis@codeaurora.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/sdm845.c | 1199 +++++++---------- .../dt-bindings/interconnect/qcom,sdm845.h | 263 ++-- 2 files changed, 639 insertions(+), 823 deletions(-) diff --git a/drivers/interconnect/qcom/sdm845.c b/drivers/interconnect/qcom/sdm845.c index f078cf0fce56..ab968afeee59 100644 --- a/drivers/interconnect/qcom/sdm845.c +++ b/drivers/interconnect/qcom/sdm845.c @@ -1,379 +1,377 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. - * + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ -#include -#include #include #include #include -#include #include #include -#include -#include -#include -#include -#include -#include +#include -#define to_qcom_provider(_provider) \ - container_of(_provider, struct qcom_icc_provider, provider) +#include "bcm-voter.h" +#include "icc-rpmh.h" -struct qcom_icc_provider { - struct icc_provider provider; - struct device *dev; - struct qcom_icc_bcm **bcms; - size_t num_bcms; +enum { + SDM845_MASTER_A1NOC_CFG = 1, + SDM845_MASTER_BLSP_1, + SDM845_MASTER_TSIF, + SDM845_MASTER_SDCC_2, + SDM845_MASTER_SDCC_4, + SDM845_MASTER_UFS_CARD, + SDM845_MASTER_UFS_MEM, + SDM845_MASTER_PCIE_0, + SDM845_MASTER_A2NOC_CFG, + SDM845_MASTER_QDSS_BAM, + SDM845_MASTER_BLSP_2, + SDM845_MASTER_CNOC_A2NOC, + SDM845_MASTER_CRYPTO, + SDM845_MASTER_IPA, + SDM845_MASTER_PCIE_1, + SDM845_MASTER_QDSS_ETR, + SDM845_MASTER_USB3_0, + SDM845_MASTER_USB3_1, + SDM845_MASTER_CAMNOC_HF0_UNCOMP, + SDM845_MASTER_CAMNOC_HF1_UNCOMP, + SDM845_MASTER_CAMNOC_SF_UNCOMP, + SDM845_MASTER_SPDM, + SDM845_MASTER_TIC, + SDM845_MASTER_SNOC_CNOC, + SDM845_MASTER_QDSS_DAP, + SDM845_MASTER_CNOC_DC_NOC, + SDM845_MASTER_APPSS_PROC, + SDM845_MASTER_GNOC_CFG, + SDM845_MASTER_LLCC, + SDM845_MASTER_TCU_0, + SDM845_MASTER_MEM_NOC_CFG, + SDM845_MASTER_GNOC_MEM_NOC, + SDM845_MASTER_MNOC_HF_MEM_NOC, + SDM845_MASTER_MNOC_SF_MEM_NOC, + SDM845_MASTER_SNOC_GC_MEM_NOC, + SDM845_MASTER_SNOC_SF_MEM_NOC, + SDM845_MASTER_GFX3D, + SDM845_MASTER_CNOC_MNOC_CFG, + SDM845_MASTER_CAMNOC_HF0, + SDM845_MASTER_CAMNOC_HF1, + SDM845_MASTER_CAMNOC_SF, + SDM845_MASTER_MDP0, + SDM845_MASTER_MDP1, + SDM845_MASTER_ROTATOR, + SDM845_MASTER_VIDEO_P0, + SDM845_MASTER_VIDEO_P1, + SDM845_MASTER_VIDEO_PROC, + SDM845_MASTER_SNOC_CFG, + SDM845_MASTER_A1NOC_SNOC, + SDM845_MASTER_A2NOC_SNOC, + SDM845_MASTER_GNOC_SNOC, + SDM845_MASTER_MEM_NOC_SNOC, + SDM845_MASTER_ANOC_PCIE_SNOC, + SDM845_MASTER_PIMEM, + SDM845_MASTER_GIC, + SDM845_SLAVE_A1NOC_SNOC, + SDM845_SLAVE_SERVICE_A1NOC, + SDM845_SLAVE_ANOC_PCIE_A1NOC_SNOC, + SDM845_SLAVE_A2NOC_SNOC, + SDM845_SLAVE_ANOC_PCIE_SNOC, + SDM845_SLAVE_SERVICE_A2NOC, + SDM845_SLAVE_CAMNOC_UNCOMP, + SDM845_SLAVE_A1NOC_CFG, + SDM845_SLAVE_A2NOC_CFG, + SDM845_SLAVE_AOP, + SDM845_SLAVE_AOSS, + SDM845_SLAVE_CAMERA_CFG, + SDM845_SLAVE_CLK_CTL, + SDM845_SLAVE_CDSP_CFG, + SDM845_SLAVE_RBCPR_CX_CFG, + SDM845_SLAVE_CRYPTO_0_CFG, + SDM845_SLAVE_DCC_CFG, + SDM845_SLAVE_CNOC_DDRSS, + SDM845_SLAVE_DISPLAY_CFG, + SDM845_SLAVE_GLM, + SDM845_SLAVE_GFX3D_CFG, + SDM845_SLAVE_IMEM_CFG, + SDM845_SLAVE_IPA_CFG, + SDM845_SLAVE_CNOC_MNOC_CFG, + SDM845_SLAVE_PCIE_0_CFG, + SDM845_SLAVE_PCIE_1_CFG, + SDM845_SLAVE_PDM, + SDM845_SLAVE_SOUTH_PHY_CFG, + SDM845_SLAVE_PIMEM_CFG, + SDM845_SLAVE_PRNG, + SDM845_SLAVE_QDSS_CFG, + SDM845_SLAVE_BLSP_2, + SDM845_SLAVE_BLSP_1, + SDM845_SLAVE_SDCC_2, + SDM845_SLAVE_SDCC_4, + SDM845_SLAVE_SNOC_CFG, + SDM845_SLAVE_SPDM_WRAPPER, + SDM845_SLAVE_SPSS_CFG, + SDM845_SLAVE_TCSR, + SDM845_SLAVE_TLMM_NORTH, + SDM845_SLAVE_TLMM_SOUTH, + SDM845_SLAVE_TSIF, + SDM845_SLAVE_UFS_CARD_CFG, + SDM845_SLAVE_UFS_MEM_CFG, + SDM845_SLAVE_USB3_0, + SDM845_SLAVE_USB3_1, + SDM845_SLAVE_VENUS_CFG, + SDM845_SLAVE_VSENSE_CTRL_CFG, + SDM845_SLAVE_CNOC_A2NOC, + SDM845_SLAVE_SERVICE_CNOC, + SDM845_SLAVE_LLCC_CFG, + SDM845_SLAVE_MEM_NOC_CFG, + SDM845_SLAVE_GNOC_SNOC, + SDM845_SLAVE_GNOC_MEM_NOC, + SDM845_SLAVE_SERVICE_GNOC, + SDM845_SLAVE_EBI1, + SDM845_SLAVE_MSS_PROC_MS_MPU_CFG, + SDM845_SLAVE_MEM_NOC_GNOC, + SDM845_SLAVE_LLCC, + SDM845_SLAVE_MEM_NOC_SNOC, + SDM845_SLAVE_SERVICE_MEM_NOC, + SDM845_SLAVE_MNOC_SF_MEM_NOC, + SDM845_SLAVE_MNOC_HF_MEM_NOC, + SDM845_SLAVE_SERVICE_MNOC, + SDM845_SLAVE_APPSS, + SDM845_SLAVE_SNOC_CNOC, + SDM845_SLAVE_SNOC_MEM_NOC_GC, + SDM845_SLAVE_SNOC_MEM_NOC_SF, + SDM845_SLAVE_IMEM, + SDM845_SLAVE_PCIE_0, + SDM845_SLAVE_PCIE_1, + SDM845_SLAVE_PIMEM, + SDM845_SLAVE_SERVICE_SNOC, + SDM845_SLAVE_QDSS_STM, + SDM845_SLAVE_TCU }; -/** - * struct bcm_db - Auxiliary data pertaining to each Bus Clock Manager (BCM) - * @unit: divisor used to convert bytes/sec bw value to an RPMh msg - * @width: multiplier used to convert bytes/sec bw value to an RPMh msg - * @vcd: virtual clock domain that this bcm belongs to - * @reserved: reserved field - */ -struct bcm_db { - __le32 unit; - __le16 width; - u8 vcd; - u8 reserved; +DEFINE_QNODE(qhm_a1noc_cfg, SDM845_MASTER_A1NOC_CFG, 1, 4, SDM845_SLAVE_SERVICE_A1NOC); +DEFINE_QNODE(qhm_qup1, SDM845_MASTER_BLSP_1, 1, 4, SDM845_SLAVE_A1NOC_SNOC); +DEFINE_QNODE(qhm_tsif, SDM845_MASTER_TSIF, 1, 4, SDM845_SLAVE_A1NOC_SNOC); +DEFINE_QNODE(xm_sdc2, SDM845_MASTER_SDCC_2, 1, 8, SDM845_SLAVE_A1NOC_SNOC); +DEFINE_QNODE(xm_sdc4, SDM845_MASTER_SDCC_4, 1, 8, SDM845_SLAVE_A1NOC_SNOC); +DEFINE_QNODE(xm_ufs_card, SDM845_MASTER_UFS_CARD, 1, 8, SDM845_SLAVE_A1NOC_SNOC); +DEFINE_QNODE(xm_ufs_mem, SDM845_MASTER_UFS_MEM, 1, 8, SDM845_SLAVE_A1NOC_SNOC); +DEFINE_QNODE(xm_pcie_0, SDM845_MASTER_PCIE_0, 1, 8, SDM845_SLAVE_ANOC_PCIE_A1NOC_SNOC); +DEFINE_QNODE(qhm_a2noc_cfg, SDM845_MASTER_A2NOC_CFG, 1, 4, SDM845_SLAVE_SERVICE_A2NOC); +DEFINE_QNODE(qhm_qdss_bam, SDM845_MASTER_QDSS_BAM, 1, 4, SDM845_SLAVE_A2NOC_SNOC); +DEFINE_QNODE(qhm_qup2, SDM845_MASTER_BLSP_2, 1, 4, SDM845_SLAVE_A2NOC_SNOC); +DEFINE_QNODE(qnm_cnoc, SDM845_MASTER_CNOC_A2NOC, 1, 8, SDM845_SLAVE_A2NOC_SNOC); +DEFINE_QNODE(qxm_crypto, SDM845_MASTER_CRYPTO, 1, 8, SDM845_SLAVE_A2NOC_SNOC); +DEFINE_QNODE(qxm_ipa, SDM845_MASTER_IPA, 1, 8, SDM845_SLAVE_A2NOC_SNOC); +DEFINE_QNODE(xm_pcie3_1, SDM845_MASTER_PCIE_1, 1, 8, SDM845_SLAVE_ANOC_PCIE_SNOC); +DEFINE_QNODE(xm_qdss_etr, SDM845_MASTER_QDSS_ETR, 1, 8, SDM845_SLAVE_A2NOC_SNOC); +DEFINE_QNODE(xm_usb3_0, SDM845_MASTER_USB3_0, 1, 8, SDM845_SLAVE_A2NOC_SNOC); +DEFINE_QNODE(xm_usb3_1, SDM845_MASTER_USB3_1, 1, 8, SDM845_SLAVE_A2NOC_SNOC); +DEFINE_QNODE(qxm_camnoc_hf0_uncomp, SDM845_MASTER_CAMNOC_HF0_UNCOMP, 1, 32, SDM845_SLAVE_CAMNOC_UNCOMP); +DEFINE_QNODE(qxm_camnoc_hf1_uncomp, SDM845_MASTER_CAMNOC_HF1_UNCOMP, 1, 32, SDM845_SLAVE_CAMNOC_UNCOMP); +DEFINE_QNODE(qxm_camnoc_sf_uncomp, SDM845_MASTER_CAMNOC_SF_UNCOMP, 1, 32, SDM845_SLAVE_CAMNOC_UNCOMP); +DEFINE_QNODE(qhm_spdm, SDM845_MASTER_SPDM, 1, 4, SDM845_SLAVE_CNOC_A2NOC); +DEFINE_QNODE(qhm_tic, SDM845_MASTER_TIC, 1, 4, SDM845_SLAVE_A1NOC_CFG, SDM845_SLAVE_A2NOC_CFG, SDM845_SLAVE_AOP, SDM845_SLAVE_AOSS, SDM845_SLAVE_CAMERA_CFG, SDM845_SLAVE_CLK_CTL, SDM845_SLAVE_CDSP_CFG, SDM845_SLAVE_RBCPR_CX_CFG, SDM845_SLAVE_CRYPTO_0_CFG, SDM845_SLAVE_DCC_CFG, SDM845_SLAVE_CNOC_DDRSS, SDM845_SLAVE_DISPLAY_CFG, SDM845_SLAVE_GLM, SDM845_SLAVE_GFX3D_CFG, SDM845_SLAVE_IMEM_CFG, SDM845_SLAVE_IPA_CFG, SDM845_SLAVE_CNOC_MNOC_CFG, SDM845_SLAVE_PCIE_0_CFG, SDM845_SLAVE_PCIE_1_CFG, SDM845_SLAVE_PDM, SDM845_SLAVE_SOUTH_PHY_CFG, SDM845_SLAVE_PIMEM_CFG, SDM845_SLAVE_PRNG, SDM845_SLAVE_QDSS_CFG, SDM845_SLAVE_BLSP_2, SDM845_SLAVE_BLSP_1, SDM845_SLAVE_SDCC_2, SDM845_SLAVE_SDCC_4, SDM845_SLAVE_SNOC_CFG, SDM845_SLAVE_SPDM_WRAPPER, SDM845_SLAVE_SPSS_CFG, SDM845_SLAVE_TCSR, SDM845_SLAVE_TLMM_NORTH, SDM845_SLAVE_TLMM_SOUTH, SDM845_SLAVE_TSIF, SDM845_SLAVE_UFS_CARD_CFG, SDM845_SLAVE_UFS_MEM_CFG, SDM845_SLAVE_USB3_0, SDM845_SLAVE_USB3_1, SDM845_SLAVE_VENUS_CFG, SDM845_SLAVE_VSENSE_CTRL_CFG, SDM845_SLAVE_CNOC_A2NOC, SDM845_SLAVE_SERVICE_CNOC); +DEFINE_QNODE(qnm_snoc, SDM845_MASTER_SNOC_CNOC, 1, 8, SDM845_SLAVE_A1NOC_CFG, SDM845_SLAVE_A2NOC_CFG, SDM845_SLAVE_AOP, SDM845_SLAVE_AOSS, SDM845_SLAVE_CAMERA_CFG, SDM845_SLAVE_CLK_CTL, SDM845_SLAVE_CDSP_CFG, SDM845_SLAVE_RBCPR_CX_CFG, SDM845_SLAVE_CRYPTO_0_CFG, SDM845_SLAVE_DCC_CFG, SDM845_SLAVE_CNOC_DDRSS, SDM845_SLAVE_DISPLAY_CFG, SDM845_SLAVE_GLM, SDM845_SLAVE_GFX3D_CFG, SDM845_SLAVE_IMEM_CFG, SDM845_SLAVE_IPA_CFG, SDM845_SLAVE_CNOC_MNOC_CFG, SDM845_SLAVE_PCIE_0_CFG, SDM845_SLAVE_PCIE_1_CFG, SDM845_SLAVE_PDM, SDM845_SLAVE_SOUTH_PHY_CFG, SDM845_SLAVE_PIMEM_CFG, SDM845_SLAVE_PRNG, SDM845_SLAVE_QDSS_CFG, SDM845_SLAVE_BLSP_2, SDM845_SLAVE_BLSP_1, SDM845_SLAVE_SDCC_2, SDM845_SLAVE_SDCC_4, SDM845_SLAVE_SNOC_CFG, SDM845_SLAVE_SPDM_WRAPPER, SDM845_SLAVE_SPSS_CFG, SDM845_SLAVE_TCSR, SDM845_SLAVE_TLMM_NORTH, SDM845_SLAVE_TLMM_SOUTH, SDM845_SLAVE_TSIF, SDM845_SLAVE_UFS_CARD_CFG, SDM845_SLAVE_UFS_MEM_CFG, SDM845_SLAVE_USB3_0, SDM845_SLAVE_USB3_1, SDM845_SLAVE_VENUS_CFG, SDM845_SLAVE_VSENSE_CTRL_CFG, SDM845_SLAVE_SERVICE_CNOC); +DEFINE_QNODE(xm_qdss_dap, SDM845_MASTER_QDSS_DAP, 1, 8, SDM845_SLAVE_A1NOC_CFG, SDM845_SLAVE_A2NOC_CFG, SDM845_SLAVE_AOP, SDM845_SLAVE_AOSS, SDM845_SLAVE_CAMERA_CFG, SDM845_SLAVE_CLK_CTL, SDM845_SLAVE_CDSP_CFG, SDM845_SLAVE_RBCPR_CX_CFG, SDM845_SLAVE_CRYPTO_0_CFG, SDM845_SLAVE_DCC_CFG, SDM845_SLAVE_CNOC_DDRSS, SDM845_SLAVE_DISPLAY_CFG, SDM845_SLAVE_GLM, SDM845_SLAVE_GFX3D_CFG, SDM845_SLAVE_IMEM_CFG, SDM845_SLAVE_IPA_CFG, SDM845_SLAVE_CNOC_MNOC_CFG, SDM845_SLAVE_PCIE_0_CFG, SDM845_SLAVE_PCIE_1_CFG, SDM845_SLAVE_PDM, SDM845_SLAVE_SOUTH_PHY_CFG, SDM845_SLAVE_PIMEM_CFG, SDM845_SLAVE_PRNG, SDM845_SLAVE_QDSS_CFG, SDM845_SLAVE_BLSP_2, SDM845_SLAVE_BLSP_1, SDM845_SLAVE_SDCC_2, SDM845_SLAVE_SDCC_4, SDM845_SLAVE_SNOC_CFG, SDM845_SLAVE_SPDM_WRAPPER, SDM845_SLAVE_SPSS_CFG, SDM845_SLAVE_TCSR, SDM845_SLAVE_TLMM_NORTH, SDM845_SLAVE_TLMM_SOUTH, SDM845_SLAVE_TSIF, SDM845_SLAVE_UFS_CARD_CFG, SDM845_SLAVE_UFS_MEM_CFG, SDM845_SLAVE_USB3_0, SDM845_SLAVE_USB3_1, SDM845_SLAVE_VENUS_CFG, SDM845_SLAVE_VSENSE_CTRL_CFG, SDM845_SLAVE_CNOC_A2NOC, SDM845_SLAVE_SERVICE_CNOC); +DEFINE_QNODE(qhm_cnoc, SDM845_MASTER_CNOC_DC_NOC, 1, 4, SDM845_SLAVE_LLCC_CFG, SDM845_SLAVE_MEM_NOC_CFG); +DEFINE_QNODE(acm_l3, SDM845_MASTER_APPSS_PROC, 1, 16, SDM845_SLAVE_GNOC_SNOC, SDM845_SLAVE_GNOC_MEM_NOC, SDM845_SLAVE_SERVICE_GNOC); +DEFINE_QNODE(pm_gnoc_cfg, SDM845_MASTER_GNOC_CFG, 1, 4, SDM845_SLAVE_SERVICE_GNOC); +DEFINE_QNODE(llcc_mc, SDM845_MASTER_LLCC, 4, 4, SDM845_SLAVE_EBI1); +DEFINE_QNODE(acm_tcu, SDM845_MASTER_TCU_0, 1, 8, SDM845_SLAVE_MEM_NOC_GNOC, SDM845_SLAVE_LLCC, SDM845_SLAVE_MEM_NOC_SNOC); +DEFINE_QNODE(qhm_memnoc_cfg, SDM845_MASTER_MEM_NOC_CFG, 1, 4, SDM845_SLAVE_MSS_PROC_MS_MPU_CFG, SDM845_SLAVE_SERVICE_MEM_NOC); +DEFINE_QNODE(qnm_apps, SDM845_MASTER_GNOC_MEM_NOC, 2, 32, SDM845_SLAVE_LLCC); +DEFINE_QNODE(qnm_mnoc_hf, SDM845_MASTER_MNOC_HF_MEM_NOC, 2, 32, SDM845_SLAVE_MEM_NOC_GNOC, SDM845_SLAVE_LLCC); +DEFINE_QNODE(qnm_mnoc_sf, SDM845_MASTER_MNOC_SF_MEM_NOC, 1, 32, SDM845_SLAVE_MEM_NOC_GNOC, SDM845_SLAVE_LLCC, SDM845_SLAVE_MEM_NOC_SNOC); +DEFINE_QNODE(qnm_snoc_gc, SDM845_MASTER_SNOC_GC_MEM_NOC, 1, 8, SDM845_SLAVE_LLCC); +DEFINE_QNODE(qnm_snoc_sf, SDM845_MASTER_SNOC_SF_MEM_NOC, 1, 16, SDM845_SLAVE_MEM_NOC_GNOC, SDM845_SLAVE_LLCC); +DEFINE_QNODE(qxm_gpu, SDM845_MASTER_GFX3D, 2, 32, SDM845_SLAVE_MEM_NOC_GNOC, SDM845_SLAVE_LLCC, SDM845_SLAVE_MEM_NOC_SNOC); +DEFINE_QNODE(qhm_mnoc_cfg, SDM845_MASTER_CNOC_MNOC_CFG, 1, 4, SDM845_SLAVE_SERVICE_MNOC); +DEFINE_QNODE(qxm_camnoc_hf0, SDM845_MASTER_CAMNOC_HF0, 1, 32, SDM845_SLAVE_MNOC_HF_MEM_NOC); +DEFINE_QNODE(qxm_camnoc_hf1, SDM845_MASTER_CAMNOC_HF1, 1, 32, SDM845_SLAVE_MNOC_HF_MEM_NOC); +DEFINE_QNODE(qxm_camnoc_sf, SDM845_MASTER_CAMNOC_SF, 1, 32, SDM845_SLAVE_MNOC_SF_MEM_NOC); +DEFINE_QNODE(qxm_mdp0, SDM845_MASTER_MDP0, 1, 32, SDM845_SLAVE_MNOC_HF_MEM_NOC); +DEFINE_QNODE(qxm_mdp1, SDM845_MASTER_MDP1, 1, 32, SDM845_SLAVE_MNOC_HF_MEM_NOC); +DEFINE_QNODE(qxm_rot, SDM845_MASTER_ROTATOR, 1, 32, SDM845_SLAVE_MNOC_SF_MEM_NOC); +DEFINE_QNODE(qxm_venus0, SDM845_MASTER_VIDEO_P0, 1, 32, SDM845_SLAVE_MNOC_SF_MEM_NOC); +DEFINE_QNODE(qxm_venus1, SDM845_MASTER_VIDEO_P1, 1, 32, SDM845_SLAVE_MNOC_SF_MEM_NOC); +DEFINE_QNODE(qxm_venus_arm9, SDM845_MASTER_VIDEO_PROC, 1, 8, SDM845_SLAVE_MNOC_SF_MEM_NOC); +DEFINE_QNODE(qhm_snoc_cfg, SDM845_MASTER_SNOC_CFG, 1, 4, SDM845_SLAVE_SERVICE_SNOC); +DEFINE_QNODE(qnm_aggre1_noc, SDM845_MASTER_A1NOC_SNOC, 1, 16, SDM845_SLAVE_APPSS, SDM845_SLAVE_SNOC_CNOC, SDM845_SLAVE_SNOC_MEM_NOC_SF, SDM845_SLAVE_IMEM, SDM845_SLAVE_PIMEM, SDM845_SLAVE_QDSS_STM); +DEFINE_QNODE(qnm_aggre2_noc, SDM845_MASTER_A2NOC_SNOC, 1, 16, SDM845_SLAVE_APPSS, SDM845_SLAVE_SNOC_CNOC, SDM845_SLAVE_SNOC_MEM_NOC_SF, SDM845_SLAVE_IMEM, SDM845_SLAVE_PCIE_0, SDM845_SLAVE_PCIE_1, SDM845_SLAVE_PIMEM, SDM845_SLAVE_QDSS_STM, SDM845_SLAVE_TCU); +DEFINE_QNODE(qnm_gladiator_sodv, SDM845_MASTER_GNOC_SNOC, 1, 8, SDM845_SLAVE_APPSS, SDM845_SLAVE_SNOC_CNOC, SDM845_SLAVE_IMEM, SDM845_SLAVE_PCIE_0, SDM845_SLAVE_PCIE_1, SDM845_SLAVE_PIMEM, SDM845_SLAVE_QDSS_STM, SDM845_SLAVE_TCU); +DEFINE_QNODE(qnm_memnoc, SDM845_MASTER_MEM_NOC_SNOC, 1, 8, SDM845_SLAVE_APPSS, SDM845_SLAVE_SNOC_CNOC, SDM845_SLAVE_IMEM, SDM845_SLAVE_PIMEM, SDM845_SLAVE_QDSS_STM); +DEFINE_QNODE(qnm_pcie_anoc, SDM845_MASTER_ANOC_PCIE_SNOC, 1, 16, SDM845_SLAVE_APPSS, SDM845_SLAVE_SNOC_CNOC, SDM845_SLAVE_SNOC_MEM_NOC_SF, SDM845_SLAVE_IMEM, SDM845_SLAVE_QDSS_STM); +DEFINE_QNODE(qxm_pimem, SDM845_MASTER_PIMEM, 1, 8, SDM845_SLAVE_SNOC_MEM_NOC_GC, SDM845_SLAVE_IMEM); +DEFINE_QNODE(xm_gic, SDM845_MASTER_GIC, 1, 8, SDM845_SLAVE_SNOC_MEM_NOC_GC, SDM845_SLAVE_IMEM); +DEFINE_QNODE(qns_a1noc_snoc, SDM845_SLAVE_A1NOC_SNOC, 1, 16, SDM845_MASTER_A1NOC_SNOC); +DEFINE_QNODE(srvc_aggre1_noc, SDM845_SLAVE_SERVICE_A1NOC, 1, 4, 0); +DEFINE_QNODE(qns_pcie_a1noc_snoc, SDM845_SLAVE_ANOC_PCIE_A1NOC_SNOC, 1, 16, SDM845_MASTER_ANOC_PCIE_SNOC); +DEFINE_QNODE(qns_a2noc_snoc, SDM845_SLAVE_A2NOC_SNOC, 1, 16, SDM845_MASTER_A2NOC_SNOC); +DEFINE_QNODE(qns_pcie_snoc, SDM845_SLAVE_ANOC_PCIE_SNOC, 1, 16, SDM845_MASTER_ANOC_PCIE_SNOC); +DEFINE_QNODE(srvc_aggre2_noc, SDM845_SLAVE_SERVICE_A2NOC, 1, 4); +DEFINE_QNODE(qns_camnoc_uncomp, SDM845_SLAVE_CAMNOC_UNCOMP, 1, 32); +DEFINE_QNODE(qhs_a1_noc_cfg, SDM845_SLAVE_A1NOC_CFG, 1, 4, SDM845_MASTER_A1NOC_CFG); +DEFINE_QNODE(qhs_a2_noc_cfg, SDM845_SLAVE_A2NOC_CFG, 1, 4, SDM845_MASTER_A2NOC_CFG); +DEFINE_QNODE(qhs_aop, SDM845_SLAVE_AOP, 1, 4); +DEFINE_QNODE(qhs_aoss, SDM845_SLAVE_AOSS, 1, 4); +DEFINE_QNODE(qhs_camera_cfg, SDM845_SLAVE_CAMERA_CFG, 1, 4); +DEFINE_QNODE(qhs_clk_ctl, SDM845_SLAVE_CLK_CTL, 1, 4); +DEFINE_QNODE(qhs_compute_dsp_cfg, SDM845_SLAVE_CDSP_CFG, 1, 4); +DEFINE_QNODE(qhs_cpr_cx, SDM845_SLAVE_RBCPR_CX_CFG, 1, 4); +DEFINE_QNODE(qhs_crypto0_cfg, SDM845_SLAVE_CRYPTO_0_CFG, 1, 4); +DEFINE_QNODE(qhs_dcc_cfg, SDM845_SLAVE_DCC_CFG, 1, 4, SDM845_MASTER_CNOC_DC_NOC); +DEFINE_QNODE(qhs_ddrss_cfg, SDM845_SLAVE_CNOC_DDRSS, 1, 4); +DEFINE_QNODE(qhs_display_cfg, SDM845_SLAVE_DISPLAY_CFG, 1, 4); +DEFINE_QNODE(qhs_glm, SDM845_SLAVE_GLM, 1, 4); +DEFINE_QNODE(qhs_gpuss_cfg, SDM845_SLAVE_GFX3D_CFG, 1, 8); +DEFINE_QNODE(qhs_imem_cfg, SDM845_SLAVE_IMEM_CFG, 1, 4); +DEFINE_QNODE(qhs_ipa, SDM845_SLAVE_IPA_CFG, 1, 4); +DEFINE_QNODE(qhs_mnoc_cfg, SDM845_SLAVE_CNOC_MNOC_CFG, 1, 4, SDM845_MASTER_CNOC_MNOC_CFG); +DEFINE_QNODE(qhs_pcie0_cfg, SDM845_SLAVE_PCIE_0_CFG, 1, 4); +DEFINE_QNODE(qhs_pcie_gen3_cfg, SDM845_SLAVE_PCIE_1_CFG, 1, 4); +DEFINE_QNODE(qhs_pdm, SDM845_SLAVE_PDM, 1, 4); +DEFINE_QNODE(qhs_phy_refgen_south, SDM845_SLAVE_SOUTH_PHY_CFG, 1, 4); +DEFINE_QNODE(qhs_pimem_cfg, SDM845_SLAVE_PIMEM_CFG, 1, 4); +DEFINE_QNODE(qhs_prng, SDM845_SLAVE_PRNG, 1, 4); +DEFINE_QNODE(qhs_qdss_cfg, SDM845_SLAVE_QDSS_CFG, 1, 4); +DEFINE_QNODE(qhs_qupv3_north, SDM845_SLAVE_BLSP_2, 1, 4); +DEFINE_QNODE(qhs_qupv3_south, SDM845_SLAVE_BLSP_1, 1, 4); +DEFINE_QNODE(qhs_sdc2, SDM845_SLAVE_SDCC_2, 1, 4); +DEFINE_QNODE(qhs_sdc4, SDM845_SLAVE_SDCC_4, 1, 4); +DEFINE_QNODE(qhs_snoc_cfg, SDM845_SLAVE_SNOC_CFG, 1, 4, SDM845_MASTER_SNOC_CFG); +DEFINE_QNODE(qhs_spdm, SDM845_SLAVE_SPDM_WRAPPER, 1, 4); +DEFINE_QNODE(qhs_spss_cfg, SDM845_SLAVE_SPSS_CFG, 1, 4); +DEFINE_QNODE(qhs_tcsr, SDM845_SLAVE_TCSR, 1, 4); +DEFINE_QNODE(qhs_tlmm_north, SDM845_SLAVE_TLMM_NORTH, 1, 4); +DEFINE_QNODE(qhs_tlmm_south, SDM845_SLAVE_TLMM_SOUTH, 1, 4); +DEFINE_QNODE(qhs_tsif, SDM845_SLAVE_TSIF, 1, 4); +DEFINE_QNODE(qhs_ufs_card_cfg, SDM845_SLAVE_UFS_CARD_CFG, 1, 4); +DEFINE_QNODE(qhs_ufs_mem_cfg, SDM845_SLAVE_UFS_MEM_CFG, 1, 4); +DEFINE_QNODE(qhs_usb3_0, SDM845_SLAVE_USB3_0, 1, 4); +DEFINE_QNODE(qhs_usb3_1, SDM845_SLAVE_USB3_1, 1, 4); +DEFINE_QNODE(qhs_venus_cfg, SDM845_SLAVE_VENUS_CFG, 1, 4); +DEFINE_QNODE(qhs_vsense_ctrl_cfg, SDM845_SLAVE_VSENSE_CTRL_CFG, 1, 4); +DEFINE_QNODE(qns_cnoc_a2noc, SDM845_SLAVE_CNOC_A2NOC, 1, 8, SDM845_MASTER_CNOC_A2NOC); +DEFINE_QNODE(srvc_cnoc, SDM845_SLAVE_SERVICE_CNOC, 1, 4); +DEFINE_QNODE(qhs_llcc, SDM845_SLAVE_LLCC_CFG, 1, 4); +DEFINE_QNODE(qhs_memnoc, SDM845_SLAVE_MEM_NOC_CFG, 1, 4, SDM845_MASTER_MEM_NOC_CFG); +DEFINE_QNODE(qns_gladiator_sodv, SDM845_SLAVE_GNOC_SNOC, 1, 8, SDM845_MASTER_GNOC_SNOC); +DEFINE_QNODE(qns_gnoc_memnoc, SDM845_SLAVE_GNOC_MEM_NOC, 2, 32, SDM845_MASTER_GNOC_MEM_NOC); +DEFINE_QNODE(srvc_gnoc, SDM845_SLAVE_SERVICE_GNOC, 1, 4); +DEFINE_QNODE(ebi, SDM845_SLAVE_EBI1, 4, 4); +DEFINE_QNODE(qhs_mdsp_ms_mpu_cfg, SDM845_SLAVE_MSS_PROC_MS_MPU_CFG, 1, 4); +DEFINE_QNODE(qns_apps_io, SDM845_SLAVE_MEM_NOC_GNOC, 1, 32); +DEFINE_QNODE(qns_llcc, SDM845_SLAVE_LLCC, 4, 16, SDM845_MASTER_LLCC); +DEFINE_QNODE(qns_memnoc_snoc, SDM845_SLAVE_MEM_NOC_SNOC, 1, 8, SDM845_MASTER_MEM_NOC_SNOC); +DEFINE_QNODE(srvc_memnoc, SDM845_SLAVE_SERVICE_MEM_NOC, 1, 4); +DEFINE_QNODE(qns2_mem_noc, SDM845_SLAVE_MNOC_SF_MEM_NOC, 1, 32, SDM845_MASTER_MNOC_SF_MEM_NOC); +DEFINE_QNODE(qns_mem_noc_hf, SDM845_SLAVE_MNOC_HF_MEM_NOC, 2, 32, SDM845_MASTER_MNOC_HF_MEM_NOC); +DEFINE_QNODE(srvc_mnoc, SDM845_SLAVE_SERVICE_MNOC, 1, 4); +DEFINE_QNODE(qhs_apss, SDM845_SLAVE_APPSS, 1, 8); +DEFINE_QNODE(qns_cnoc, SDM845_SLAVE_SNOC_CNOC, 1, 8, SDM845_MASTER_SNOC_CNOC); +DEFINE_QNODE(qns_memnoc_gc, SDM845_SLAVE_SNOC_MEM_NOC_GC, 1, 8, SDM845_MASTER_SNOC_GC_MEM_NOC); +DEFINE_QNODE(qns_memnoc_sf, SDM845_SLAVE_SNOC_MEM_NOC_SF, 1, 16, SDM845_MASTER_SNOC_SF_MEM_NOC); +DEFINE_QNODE(qxs_imem, SDM845_SLAVE_IMEM, 1, 8); +DEFINE_QNODE(qxs_pcie, SDM845_SLAVE_PCIE_0, 1, 8); +DEFINE_QNODE(qxs_pcie_gen3, SDM845_SLAVE_PCIE_1, 1, 8); +DEFINE_QNODE(qxs_pimem, SDM845_SLAVE_PIMEM, 1, 8); +DEFINE_QNODE(srvc_snoc, SDM845_SLAVE_SERVICE_SNOC, 1, 4); +DEFINE_QNODE(xs_qdss_stm, SDM845_SLAVE_QDSS_STM, 1, 4); +DEFINE_QNODE(xs_sys_tcu_cfg, SDM845_SLAVE_TCU, 1, 8); + +DEFINE_QBCM(bcm_acv, "ACV", false, &ebi); +DEFINE_QBCM(bcm_mc0, "MC0", true, &ebi); +DEFINE_QBCM(bcm_sh0, "SH0", true, &qns_llcc); +DEFINE_QBCM(bcm_mm0, "MM0", false, &qns_mem_noc_hf); +DEFINE_QBCM(bcm_sh1, "SH1", false, &qns_apps_io); +DEFINE_QBCM(bcm_mm1, "MM1", false, &qxm_camnoc_hf0_uncomp, &qxm_camnoc_hf1_uncomp, &qxm_camnoc_sf_uncomp, &qxm_camnoc_hf0, &qxm_camnoc_hf1, &qxm_mdp0, &qxm_mdp1); +DEFINE_QBCM(bcm_sh2, "SH2", false, &qns_memnoc_snoc); +DEFINE_QBCM(bcm_mm2, "MM2", false, &qns2_mem_noc); +DEFINE_QBCM(bcm_sh3, "SH3", false, &acm_tcu); +DEFINE_QBCM(bcm_mm3, "MM3", false, &qxm_camnoc_sf, &qxm_rot, &qxm_venus0, &qxm_venus1, &qxm_venus_arm9); +DEFINE_QBCM(bcm_sh5, "SH5", false, &qnm_apps); +DEFINE_QBCM(bcm_sn0, "SN0", true, &qns_memnoc_sf); +DEFINE_QBCM(bcm_ce0, "CE0", false, &qxm_crypto); +DEFINE_QBCM(bcm_cn0, "CN0", false, &qhm_spdm, &qhm_tic, &qnm_snoc, &xm_qdss_dap, &qhs_a1_noc_cfg, &qhs_a2_noc_cfg, &qhs_aop, &qhs_aoss, &qhs_camera_cfg, &qhs_clk_ctl, &qhs_compute_dsp_cfg, &qhs_cpr_cx, &qhs_crypto0_cfg, &qhs_dcc_cfg, &qhs_ddrss_cfg, &qhs_display_cfg, &qhs_glm, &qhs_gpuss_cfg, &qhs_imem_cfg, &qhs_ipa, &qhs_mnoc_cfg, &qhs_pcie0_cfg, &qhs_pcie_gen3_cfg, &qhs_pdm, &qhs_phy_refgen_south, &qhs_pimem_cfg, &qhs_prng, &qhs_qdss_cfg, &qhs_qupv3_north, &qhs_qupv3_south, &qhs_sdc2, &qhs_sdc4, &qhs_snoc_cfg, &qhs_spdm, &qhs_spss_cfg, &qhs_tcsr, &qhs_tlmm_north, &qhs_tlmm_south, &qhs_tsif, &qhs_ufs_card_cfg, &qhs_ufs_mem_cfg, &qhs_usb3_0, &qhs_usb3_1, &qhs_venus_cfg, &qhs_vsense_ctrl_cfg, &qns_cnoc_a2noc, &srvc_cnoc); +DEFINE_QBCM(bcm_qup0, "QUP0", false, &qhm_qup1, &qhm_qup2); +DEFINE_QBCM(bcm_sn1, "SN1", false, &qxs_imem); +DEFINE_QBCM(bcm_sn2, "SN2", false, &qns_memnoc_gc); +DEFINE_QBCM(bcm_sn3, "SN3", false, &qns_cnoc); +DEFINE_QBCM(bcm_sn4, "SN4", false, &qxm_pimem); +DEFINE_QBCM(bcm_sn5, "SN5", false, &xs_qdss_stm); +DEFINE_QBCM(bcm_sn6, "SN6", false, &qhs_apss, &srvc_snoc, &xs_sys_tcu_cfg); +DEFINE_QBCM(bcm_sn7, "SN7", false, &qxs_pcie); +DEFINE_QBCM(bcm_sn8, "SN8", false, &qxs_pcie_gen3); +DEFINE_QBCM(bcm_sn9, "SN9", false, &srvc_aggre1_noc, &qnm_aggre1_noc); +DEFINE_QBCM(bcm_sn11, "SN11", false, &srvc_aggre2_noc, &qnm_aggre2_noc); +DEFINE_QBCM(bcm_sn12, "SN12", false, &qnm_gladiator_sodv, &xm_gic); +DEFINE_QBCM(bcm_sn14, "SN14", false, &qnm_pcie_anoc); +DEFINE_QBCM(bcm_sn15, "SN15", false, &qnm_memnoc); + +static struct qcom_icc_bcm *aggre1_noc_bcms[] = { + &bcm_sn9, }; -#define SDM845_MAX_LINKS 43 -#define SDM845_MAX_BCMS 30 -#define SDM845_MAX_BCM_PER_NODE 2 -#define SDM845_MAX_VCD 10 - -/* - * The AMC bucket denotes constraints that are applied to hardware when - * icc_set_bw() completes, whereas the WAKE and SLEEP constraints are applied - * when the execution environment transitions between active and low power mode. - */ -#define QCOM_ICC_BUCKET_AMC 0 -#define QCOM_ICC_BUCKET_WAKE 1 -#define QCOM_ICC_BUCKET_SLEEP 2 -#define QCOM_ICC_NUM_BUCKETS 3 -#define QCOM_ICC_TAG_AMC BIT(QCOM_ICC_BUCKET_AMC) -#define QCOM_ICC_TAG_WAKE BIT(QCOM_ICC_BUCKET_WAKE) -#define QCOM_ICC_TAG_SLEEP BIT(QCOM_ICC_BUCKET_SLEEP) -#define QCOM_ICC_TAG_ACTIVE_ONLY (QCOM_ICC_TAG_AMC | QCOM_ICC_TAG_WAKE) -#define QCOM_ICC_TAG_ALWAYS (QCOM_ICC_TAG_AMC | QCOM_ICC_TAG_WAKE |\ - QCOM_ICC_TAG_SLEEP) - -/** - * struct qcom_icc_node - Qualcomm specific interconnect nodes - * @name: the node name used in debugfs - * @links: an array of nodes where we can go next while traversing - * @id: a unique node identifier - * @num_links: the total number of @links - * @channels: num of channels at this node - * @buswidth: width of the interconnect between a node and the bus - * @sum_avg: current sum aggregate value of all avg bw requests - * @max_peak: current max aggregate value of all peak bw requests - * @bcms: list of bcms associated with this logical node - * @num_bcms: num of @bcms - */ -struct qcom_icc_node { - const char *name; - u16 links[SDM845_MAX_LINKS]; - u16 id; - u16 num_links; - u16 channels; - u16 buswidth; - u64 sum_avg[QCOM_ICC_NUM_BUCKETS]; - u64 max_peak[QCOM_ICC_NUM_BUCKETS]; - struct qcom_icc_bcm *bcms[SDM845_MAX_BCM_PER_NODE]; - size_t num_bcms; -}; - -/** - * struct qcom_icc_bcm - Qualcomm specific hardware accelerator nodes - * known as Bus Clock Manager (BCM) - * @name: the bcm node name used to fetch BCM data from command db - * @type: latency or bandwidth bcm - * @addr: address offsets used when voting to RPMH - * @vote_x: aggregated threshold values, represents sum_bw when @type is bw bcm - * @vote_y: aggregated threshold values, represents peak_bw when @type is bw bcm - * @dirty: flag used to indicate whether the bcm needs to be committed - * @keepalive: flag used to indicate whether a keepalive is required - * @aux_data: auxiliary data used when calculating threshold values and - * communicating with RPMh - * @list: used to link to other bcms when compiling lists for commit - * @num_nodes: total number of @num_nodes - * @nodes: list of qcom_icc_nodes that this BCM encapsulates - */ -struct qcom_icc_bcm { - const char *name; - u32 type; - u32 addr; - u64 vote_x[QCOM_ICC_NUM_BUCKETS]; - u64 vote_y[QCOM_ICC_NUM_BUCKETS]; - bool dirty; - bool keepalive; - struct bcm_db aux_data; - struct list_head list; - size_t num_nodes; - struct qcom_icc_node *nodes[]; -}; - -struct qcom_icc_fabric { - struct qcom_icc_node **nodes; - size_t num_nodes; -}; - -struct qcom_icc_desc { - struct qcom_icc_node **nodes; - size_t num_nodes; - struct qcom_icc_bcm **bcms; - size_t num_bcms; -}; - -#define DEFINE_QNODE(_name, _id, _channels, _buswidth, \ - _numlinks, ...) \ - static struct qcom_icc_node _name = { \ - .id = _id, \ - .name = #_name, \ - .channels = _channels, \ - .buswidth = _buswidth, \ - .num_links = _numlinks, \ - .links = { __VA_ARGS__ }, \ - } - -DEFINE_QNODE(qhm_a1noc_cfg, MASTER_A1NOC_CFG, 1, 4, 1, SLAVE_SERVICE_A1NOC); -DEFINE_QNODE(qhm_qup1, MASTER_BLSP_1, 1, 4, 1, SLAVE_A1NOC_SNOC); -DEFINE_QNODE(qhm_tsif, MASTER_TSIF, 1, 4, 1, SLAVE_A1NOC_SNOC); -DEFINE_QNODE(xm_sdc2, MASTER_SDCC_2, 1, 8, 1, SLAVE_A1NOC_SNOC); -DEFINE_QNODE(xm_sdc4, MASTER_SDCC_4, 1, 8, 1, SLAVE_A1NOC_SNOC); -DEFINE_QNODE(xm_ufs_card, MASTER_UFS_CARD, 1, 8, 1, SLAVE_A1NOC_SNOC); -DEFINE_QNODE(xm_ufs_mem, MASTER_UFS_MEM, 1, 8, 1, SLAVE_A1NOC_SNOC); -DEFINE_QNODE(xm_pcie_0, MASTER_PCIE_0, 1, 8, 1, SLAVE_ANOC_PCIE_A1NOC_SNOC); -DEFINE_QNODE(qhm_a2noc_cfg, MASTER_A2NOC_CFG, 1, 4, 1, SLAVE_SERVICE_A2NOC); -DEFINE_QNODE(qhm_qdss_bam, MASTER_QDSS_BAM, 1, 4, 1, SLAVE_A2NOC_SNOC); -DEFINE_QNODE(qhm_qup2, MASTER_BLSP_2, 1, 4, 1, SLAVE_A2NOC_SNOC); -DEFINE_QNODE(qnm_cnoc, MASTER_CNOC_A2NOC, 1, 8, 1, SLAVE_A2NOC_SNOC); -DEFINE_QNODE(qxm_crypto, MASTER_CRYPTO, 1, 8, 1, SLAVE_A2NOC_SNOC); -DEFINE_QNODE(qxm_ipa, MASTER_IPA, 1, 8, 1, SLAVE_A2NOC_SNOC); -DEFINE_QNODE(xm_pcie3_1, MASTER_PCIE_1, 1, 8, 1, SLAVE_ANOC_PCIE_SNOC); -DEFINE_QNODE(xm_qdss_etr, MASTER_QDSS_ETR, 1, 8, 1, SLAVE_A2NOC_SNOC); -DEFINE_QNODE(xm_usb3_0, MASTER_USB3_0, 1, 8, 1, SLAVE_A2NOC_SNOC); -DEFINE_QNODE(xm_usb3_1, MASTER_USB3_1, 1, 8, 1, SLAVE_A2NOC_SNOC); -DEFINE_QNODE(qxm_camnoc_hf0_uncomp, MASTER_CAMNOC_HF0_UNCOMP, 1, 32, 1, SLAVE_CAMNOC_UNCOMP); -DEFINE_QNODE(qxm_camnoc_hf1_uncomp, MASTER_CAMNOC_HF1_UNCOMP, 1, 32, 1, SLAVE_CAMNOC_UNCOMP); -DEFINE_QNODE(qxm_camnoc_sf_uncomp, MASTER_CAMNOC_SF_UNCOMP, 1, 32, 1, SLAVE_CAMNOC_UNCOMP); -DEFINE_QNODE(qhm_spdm, MASTER_SPDM, 1, 4, 1, SLAVE_CNOC_A2NOC); -DEFINE_QNODE(qhm_tic, MASTER_TIC, 1, 4, 43, SLAVE_A1NOC_CFG, SLAVE_A2NOC_CFG, SLAVE_AOP, SLAVE_AOSS, SLAVE_CAMERA_CFG, SLAVE_CLK_CTL, SLAVE_CDSP_CFG, SLAVE_RBCPR_CX_CFG, SLAVE_CRYPTO_0_CFG, SLAVE_DCC_CFG, SLAVE_CNOC_DDRSS, SLAVE_DISPLAY_CFG, SLAVE_GLM, SLAVE_GFX3D_CFG, SLAVE_IMEM_CFG, SLAVE_IPA_CFG, SLAVE_CNOC_MNOC_CFG, SLAVE_PCIE_0_CFG, SLAVE_PCIE_1_CFG, SLAVE_PDM, SLAVE_SOUTH_PHY_CFG, SLAVE_PIMEM_CFG, SLAVE_PRNG, SLAVE_QDSS_CFG, SLAVE_BLSP_2, SLAVE_BLSP_1, SLAVE_SDCC_2, SLAVE_SDCC_4, SLAVE_SNOC_CFG, SLAVE_SPDM_WRAPPER, SLAVE_SPSS_CFG, SLAVE_TCSR, SLAVE_TLMM_NORTH, SLAVE_TLMM_SOUTH, SLAVE_TSIF, SLAVE_UFS_CARD_CFG, SLAVE_UFS_MEM_CFG, SLAVE_USB3_0, SLAVE_USB3_1, SLAVE_VENUS_CFG, SLAVE_VSENSE_CTRL_CFG, SLAVE_CNOC_A2NOC, SLAVE_SERVICE_CNOC); -DEFINE_QNODE(qnm_snoc, MASTER_SNOC_CNOC, 1, 8, 42, SLAVE_A1NOC_CFG, SLAVE_A2NOC_CFG, SLAVE_AOP, SLAVE_AOSS, SLAVE_CAMERA_CFG, SLAVE_CLK_CTL, SLAVE_CDSP_CFG, SLAVE_RBCPR_CX_CFG, SLAVE_CRYPTO_0_CFG, SLAVE_DCC_CFG, SLAVE_CNOC_DDRSS, SLAVE_DISPLAY_CFG, SLAVE_GLM, SLAVE_GFX3D_CFG, SLAVE_IMEM_CFG, SLAVE_IPA_CFG, SLAVE_CNOC_MNOC_CFG, SLAVE_PCIE_0_CFG, SLAVE_PCIE_1_CFG, SLAVE_PDM, SLAVE_SOUTH_PHY_CFG, SLAVE_PIMEM_CFG, SLAVE_PRNG, SLAVE_QDSS_CFG, SLAVE_BLSP_2, SLAVE_BLSP_1, SLAVE_SDCC_2, SLAVE_SDCC_4, SLAVE_SNOC_CFG, SLAVE_SPDM_WRAPPER, SLAVE_SPSS_CFG, SLAVE_TCSR, SLAVE_TLMM_NORTH, SLAVE_TLMM_SOUTH, SLAVE_TSIF, SLAVE_UFS_CARD_CFG, SLAVE_UFS_MEM_CFG, SLAVE_USB3_0, SLAVE_USB3_1, SLAVE_VENUS_CFG, SLAVE_VSENSE_CTRL_CFG, SLAVE_SERVICE_CNOC); -DEFINE_QNODE(xm_qdss_dap, MASTER_QDSS_DAP, 1, 8, 43, SLAVE_A1NOC_CFG, SLAVE_A2NOC_CFG, SLAVE_AOP, SLAVE_AOSS, SLAVE_CAMERA_CFG, SLAVE_CLK_CTL, SLAVE_CDSP_CFG, SLAVE_RBCPR_CX_CFG, SLAVE_CRYPTO_0_CFG, SLAVE_DCC_CFG, SLAVE_CNOC_DDRSS, SLAVE_DISPLAY_CFG, SLAVE_GLM, SLAVE_GFX3D_CFG, SLAVE_IMEM_CFG, SLAVE_IPA_CFG, SLAVE_CNOC_MNOC_CFG, SLAVE_PCIE_0_CFG, SLAVE_PCIE_1_CFG, SLAVE_PDM, SLAVE_SOUTH_PHY_CFG, SLAVE_PIMEM_CFG, SLAVE_PRNG, SLAVE_QDSS_CFG, SLAVE_BLSP_2, SLAVE_BLSP_1, SLAVE_SDCC_2, SLAVE_SDCC_4, SLAVE_SNOC_CFG, SLAVE_SPDM_WRAPPER, SLAVE_SPSS_CFG, SLAVE_TCSR, SLAVE_TLMM_NORTH, SLAVE_TLMM_SOUTH, SLAVE_TSIF, SLAVE_UFS_CARD_CFG, SLAVE_UFS_MEM_CFG, SLAVE_USB3_0, SLAVE_USB3_1, SLAVE_VENUS_CFG, SLAVE_VSENSE_CTRL_CFG, SLAVE_CNOC_A2NOC, SLAVE_SERVICE_CNOC); -DEFINE_QNODE(qhm_cnoc, MASTER_CNOC_DC_NOC, 1, 4, 2, SLAVE_LLCC_CFG, SLAVE_MEM_NOC_CFG); -DEFINE_QNODE(acm_l3, MASTER_APPSS_PROC, 1, 16, 3, SLAVE_GNOC_SNOC, SLAVE_GNOC_MEM_NOC, SLAVE_SERVICE_GNOC); -DEFINE_QNODE(pm_gnoc_cfg, MASTER_GNOC_CFG, 1, 4, 1, SLAVE_SERVICE_GNOC); -DEFINE_QNODE(llcc_mc, MASTER_LLCC, 4, 4, 1, SLAVE_EBI1); -DEFINE_QNODE(acm_tcu, MASTER_TCU_0, 1, 8, 3, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC, SLAVE_MEM_NOC_SNOC); -DEFINE_QNODE(qhm_memnoc_cfg, MASTER_MEM_NOC_CFG, 1, 4, 2, SLAVE_MSS_PROC_MS_MPU_CFG, SLAVE_SERVICE_MEM_NOC); -DEFINE_QNODE(qnm_apps, MASTER_GNOC_MEM_NOC, 2, 32, 1, SLAVE_LLCC); -DEFINE_QNODE(qnm_mnoc_hf, MASTER_MNOC_HF_MEM_NOC, 2, 32, 2, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC); -DEFINE_QNODE(qnm_mnoc_sf, MASTER_MNOC_SF_MEM_NOC, 1, 32, 3, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC, SLAVE_MEM_NOC_SNOC); -DEFINE_QNODE(qnm_snoc_gc, MASTER_SNOC_GC_MEM_NOC, 1, 8, 1, SLAVE_LLCC); -DEFINE_QNODE(qnm_snoc_sf, MASTER_SNOC_SF_MEM_NOC, 1, 16, 2, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC); -DEFINE_QNODE(qxm_gpu, MASTER_GFX3D, 2, 32, 3, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC, SLAVE_MEM_NOC_SNOC); -DEFINE_QNODE(qhm_mnoc_cfg, MASTER_CNOC_MNOC_CFG, 1, 4, 1, SLAVE_SERVICE_MNOC); -DEFINE_QNODE(qxm_camnoc_hf0, MASTER_CAMNOC_HF0, 1, 32, 1, SLAVE_MNOC_HF_MEM_NOC); -DEFINE_QNODE(qxm_camnoc_hf1, MASTER_CAMNOC_HF1, 1, 32, 1, SLAVE_MNOC_HF_MEM_NOC); -DEFINE_QNODE(qxm_camnoc_sf, MASTER_CAMNOC_SF, 1, 32, 1, SLAVE_MNOC_SF_MEM_NOC); -DEFINE_QNODE(qxm_mdp0, MASTER_MDP0, 1, 32, 1, SLAVE_MNOC_HF_MEM_NOC); -DEFINE_QNODE(qxm_mdp1, MASTER_MDP1, 1, 32, 1, SLAVE_MNOC_HF_MEM_NOC); -DEFINE_QNODE(qxm_rot, MASTER_ROTATOR, 1, 32, 1, SLAVE_MNOC_SF_MEM_NOC); -DEFINE_QNODE(qxm_venus0, MASTER_VIDEO_P0, 1, 32, 1, SLAVE_MNOC_SF_MEM_NOC); -DEFINE_QNODE(qxm_venus1, MASTER_VIDEO_P1, 1, 32, 1, SLAVE_MNOC_SF_MEM_NOC); -DEFINE_QNODE(qxm_venus_arm9, MASTER_VIDEO_PROC, 1, 8, 1, SLAVE_MNOC_SF_MEM_NOC); -DEFINE_QNODE(qhm_snoc_cfg, MASTER_SNOC_CFG, 1, 4, 1, SLAVE_SERVICE_SNOC); -DEFINE_QNODE(qnm_aggre1_noc, MASTER_A1NOC_SNOC, 1, 16, 6, SLAVE_APPSS, SLAVE_SNOC_CNOC, SLAVE_SNOC_MEM_NOC_SF, SLAVE_IMEM, SLAVE_PIMEM, SLAVE_QDSS_STM); -DEFINE_QNODE(qnm_aggre2_noc, MASTER_A2NOC_SNOC, 1, 16, 9, SLAVE_APPSS, SLAVE_SNOC_CNOC, SLAVE_SNOC_MEM_NOC_SF, SLAVE_IMEM, SLAVE_PCIE_0, SLAVE_PCIE_1, SLAVE_PIMEM, SLAVE_QDSS_STM, SLAVE_TCU); -DEFINE_QNODE(qnm_gladiator_sodv, MASTER_GNOC_SNOC, 1, 8, 8, SLAVE_APPSS, SLAVE_SNOC_CNOC, SLAVE_IMEM, SLAVE_PCIE_0, SLAVE_PCIE_1, SLAVE_PIMEM, SLAVE_QDSS_STM, SLAVE_TCU); -DEFINE_QNODE(qnm_memnoc, MASTER_MEM_NOC_SNOC, 1, 8, 5, SLAVE_APPSS, SLAVE_SNOC_CNOC, SLAVE_IMEM, SLAVE_PIMEM, SLAVE_QDSS_STM); -DEFINE_QNODE(qnm_pcie_anoc, MASTER_ANOC_PCIE_SNOC, 1, 16, 5, SLAVE_APPSS, SLAVE_SNOC_CNOC, SLAVE_SNOC_MEM_NOC_SF, SLAVE_IMEM, SLAVE_QDSS_STM); -DEFINE_QNODE(qxm_pimem, MASTER_PIMEM, 1, 8, 2, SLAVE_SNOC_MEM_NOC_GC, SLAVE_IMEM); -DEFINE_QNODE(xm_gic, MASTER_GIC, 1, 8, 2, SLAVE_SNOC_MEM_NOC_GC, SLAVE_IMEM); -DEFINE_QNODE(qns_a1noc_snoc, SLAVE_A1NOC_SNOC, 1, 16, 1, MASTER_A1NOC_SNOC); -DEFINE_QNODE(srvc_aggre1_noc, SLAVE_SERVICE_A1NOC, 1, 4, 0); -DEFINE_QNODE(qns_pcie_a1noc_snoc, SLAVE_ANOC_PCIE_A1NOC_SNOC, 1, 16, 1, MASTER_ANOC_PCIE_SNOC); -DEFINE_QNODE(qns_a2noc_snoc, SLAVE_A2NOC_SNOC, 1, 16, 1, MASTER_A2NOC_SNOC); -DEFINE_QNODE(qns_pcie_snoc, SLAVE_ANOC_PCIE_SNOC, 1, 16, 1, MASTER_ANOC_PCIE_SNOC); -DEFINE_QNODE(srvc_aggre2_noc, SLAVE_SERVICE_A2NOC, 1, 4, 0); -DEFINE_QNODE(qns_camnoc_uncomp, SLAVE_CAMNOC_UNCOMP, 1, 32, 0); -DEFINE_QNODE(qhs_a1_noc_cfg, SLAVE_A1NOC_CFG, 1, 4, 1, MASTER_A1NOC_CFG); -DEFINE_QNODE(qhs_a2_noc_cfg, SLAVE_A2NOC_CFG, 1, 4, 1, MASTER_A2NOC_CFG); -DEFINE_QNODE(qhs_aop, SLAVE_AOP, 1, 4, 0); -DEFINE_QNODE(qhs_aoss, SLAVE_AOSS, 1, 4, 0); -DEFINE_QNODE(qhs_camera_cfg, SLAVE_CAMERA_CFG, 1, 4, 0); -DEFINE_QNODE(qhs_clk_ctl, SLAVE_CLK_CTL, 1, 4, 0); -DEFINE_QNODE(qhs_compute_dsp_cfg, SLAVE_CDSP_CFG, 1, 4, 0); -DEFINE_QNODE(qhs_cpr_cx, SLAVE_RBCPR_CX_CFG, 1, 4, 0); -DEFINE_QNODE(qhs_crypto0_cfg, SLAVE_CRYPTO_0_CFG, 1, 4, 0); -DEFINE_QNODE(qhs_dcc_cfg, SLAVE_DCC_CFG, 1, 4, 1, MASTER_CNOC_DC_NOC); -DEFINE_QNODE(qhs_ddrss_cfg, SLAVE_CNOC_DDRSS, 1, 4, 0); -DEFINE_QNODE(qhs_display_cfg, SLAVE_DISPLAY_CFG, 1, 4, 0); -DEFINE_QNODE(qhs_glm, SLAVE_GLM, 1, 4, 0); -DEFINE_QNODE(qhs_gpuss_cfg, SLAVE_GFX3D_CFG, 1, 8, 0); -DEFINE_QNODE(qhs_imem_cfg, SLAVE_IMEM_CFG, 1, 4, 0); -DEFINE_QNODE(qhs_ipa, SLAVE_IPA_CFG, 1, 4, 0); -DEFINE_QNODE(qhs_mnoc_cfg, SLAVE_CNOC_MNOC_CFG, 1, 4, 1, MASTER_CNOC_MNOC_CFG); -DEFINE_QNODE(qhs_pcie0_cfg, SLAVE_PCIE_0_CFG, 1, 4, 0); -DEFINE_QNODE(qhs_pcie_gen3_cfg, SLAVE_PCIE_1_CFG, 1, 4, 0); -DEFINE_QNODE(qhs_pdm, SLAVE_PDM, 1, 4, 0); -DEFINE_QNODE(qhs_phy_refgen_south, SLAVE_SOUTH_PHY_CFG, 1, 4, 0); -DEFINE_QNODE(qhs_pimem_cfg, SLAVE_PIMEM_CFG, 1, 4, 0); -DEFINE_QNODE(qhs_prng, SLAVE_PRNG, 1, 4, 0); -DEFINE_QNODE(qhs_qdss_cfg, SLAVE_QDSS_CFG, 1, 4, 0); -DEFINE_QNODE(qhs_qupv3_north, SLAVE_BLSP_2, 1, 4, 0); -DEFINE_QNODE(qhs_qupv3_south, SLAVE_BLSP_1, 1, 4, 0); -DEFINE_QNODE(qhs_sdc2, SLAVE_SDCC_2, 1, 4, 0); -DEFINE_QNODE(qhs_sdc4, SLAVE_SDCC_4, 1, 4, 0); -DEFINE_QNODE(qhs_snoc_cfg, SLAVE_SNOC_CFG, 1, 4, 1, MASTER_SNOC_CFG); -DEFINE_QNODE(qhs_spdm, SLAVE_SPDM_WRAPPER, 1, 4, 0); -DEFINE_QNODE(qhs_spss_cfg, SLAVE_SPSS_CFG, 1, 4, 0); -DEFINE_QNODE(qhs_tcsr, SLAVE_TCSR, 1, 4, 0); -DEFINE_QNODE(qhs_tlmm_north, SLAVE_TLMM_NORTH, 1, 4, 0); -DEFINE_QNODE(qhs_tlmm_south, SLAVE_TLMM_SOUTH, 1, 4, 0); -DEFINE_QNODE(qhs_tsif, SLAVE_TSIF, 1, 4, 0); -DEFINE_QNODE(qhs_ufs_card_cfg, SLAVE_UFS_CARD_CFG, 1, 4, 0); -DEFINE_QNODE(qhs_ufs_mem_cfg, SLAVE_UFS_MEM_CFG, 1, 4, 0); -DEFINE_QNODE(qhs_usb3_0, SLAVE_USB3_0, 1, 4, 0); -DEFINE_QNODE(qhs_usb3_1, SLAVE_USB3_1, 1, 4, 0); -DEFINE_QNODE(qhs_venus_cfg, SLAVE_VENUS_CFG, 1, 4, 0); -DEFINE_QNODE(qhs_vsense_ctrl_cfg, SLAVE_VSENSE_CTRL_CFG, 1, 4, 0); -DEFINE_QNODE(qns_cnoc_a2noc, SLAVE_CNOC_A2NOC, 1, 8, 1, MASTER_CNOC_A2NOC); -DEFINE_QNODE(srvc_cnoc, SLAVE_SERVICE_CNOC, 1, 4, 0); -DEFINE_QNODE(qhs_llcc, SLAVE_LLCC_CFG, 1, 4, 0); -DEFINE_QNODE(qhs_memnoc, SLAVE_MEM_NOC_CFG, 1, 4, 1, MASTER_MEM_NOC_CFG); -DEFINE_QNODE(qns_gladiator_sodv, SLAVE_GNOC_SNOC, 1, 8, 1, MASTER_GNOC_SNOC); -DEFINE_QNODE(qns_gnoc_memnoc, SLAVE_GNOC_MEM_NOC, 2, 32, 1, MASTER_GNOC_MEM_NOC); -DEFINE_QNODE(srvc_gnoc, SLAVE_SERVICE_GNOC, 1, 4, 0); -DEFINE_QNODE(ebi, SLAVE_EBI1, 4, 4, 0); -DEFINE_QNODE(qhs_mdsp_ms_mpu_cfg, SLAVE_MSS_PROC_MS_MPU_CFG, 1, 4, 0); -DEFINE_QNODE(qns_apps_io, SLAVE_MEM_NOC_GNOC, 1, 32, 0); -DEFINE_QNODE(qns_llcc, SLAVE_LLCC, 4, 16, 1, MASTER_LLCC); -DEFINE_QNODE(qns_memnoc_snoc, SLAVE_MEM_NOC_SNOC, 1, 8, 1, MASTER_MEM_NOC_SNOC); -DEFINE_QNODE(srvc_memnoc, SLAVE_SERVICE_MEM_NOC, 1, 4, 0); -DEFINE_QNODE(qns2_mem_noc, SLAVE_MNOC_SF_MEM_NOC, 1, 32, 1, MASTER_MNOC_SF_MEM_NOC); -DEFINE_QNODE(qns_mem_noc_hf, SLAVE_MNOC_HF_MEM_NOC, 2, 32, 1, MASTER_MNOC_HF_MEM_NOC); -DEFINE_QNODE(srvc_mnoc, SLAVE_SERVICE_MNOC, 1, 4, 0); -DEFINE_QNODE(qhs_apss, SLAVE_APPSS, 1, 8, 0); -DEFINE_QNODE(qns_cnoc, SLAVE_SNOC_CNOC, 1, 8, 1, MASTER_SNOC_CNOC); -DEFINE_QNODE(qns_memnoc_gc, SLAVE_SNOC_MEM_NOC_GC, 1, 8, 1, MASTER_SNOC_GC_MEM_NOC); -DEFINE_QNODE(qns_memnoc_sf, SLAVE_SNOC_MEM_NOC_SF, 1, 16, 1, MASTER_SNOC_SF_MEM_NOC); -DEFINE_QNODE(qxs_imem, SLAVE_IMEM, 1, 8, 0); -DEFINE_QNODE(qxs_pcie, SLAVE_PCIE_0, 1, 8, 0); -DEFINE_QNODE(qxs_pcie_gen3, SLAVE_PCIE_1, 1, 8, 0); -DEFINE_QNODE(qxs_pimem, SLAVE_PIMEM, 1, 8, 0); -DEFINE_QNODE(srvc_snoc, SLAVE_SERVICE_SNOC, 1, 4, 0); -DEFINE_QNODE(xs_qdss_stm, SLAVE_QDSS_STM, 1, 4, 0); -DEFINE_QNODE(xs_sys_tcu_cfg, SLAVE_TCU, 1, 8, 0); - -#define DEFINE_QBCM(_name, _bcmname, _keepalive, _numnodes, ...) \ - static struct qcom_icc_bcm _name = { \ - .name = _bcmname, \ - .keepalive = _keepalive, \ - .num_nodes = _numnodes, \ - .nodes = { __VA_ARGS__ }, \ - } - -DEFINE_QBCM(bcm_acv, "ACV", false, 1, &ebi); -DEFINE_QBCM(bcm_mc0, "MC0", true, 1, &ebi); -DEFINE_QBCM(bcm_sh0, "SH0", true, 1, &qns_llcc); -DEFINE_QBCM(bcm_mm0, "MM0", false, 1, &qns_mem_noc_hf); -DEFINE_QBCM(bcm_sh1, "SH1", false, 1, &qns_apps_io); -DEFINE_QBCM(bcm_mm1, "MM1", false, 7, &qxm_camnoc_hf0_uncomp, &qxm_camnoc_hf1_uncomp, &qxm_camnoc_sf_uncomp, &qxm_camnoc_hf0, &qxm_camnoc_hf1, &qxm_mdp0, &qxm_mdp1); -DEFINE_QBCM(bcm_sh2, "SH2", false, 1, &qns_memnoc_snoc); -DEFINE_QBCM(bcm_mm2, "MM2", false, 1, &qns2_mem_noc); -DEFINE_QBCM(bcm_sh3, "SH3", false, 1, &acm_tcu); -DEFINE_QBCM(bcm_mm3, "MM3", false, 5, &qxm_camnoc_sf, &qxm_rot, &qxm_venus0, &qxm_venus1, &qxm_venus_arm9); -DEFINE_QBCM(bcm_sh5, "SH5", false, 1, &qnm_apps); -DEFINE_QBCM(bcm_sn0, "SN0", true, 1, &qns_memnoc_sf); -DEFINE_QBCM(bcm_ce0, "CE0", false, 1, &qxm_crypto); -DEFINE_QBCM(bcm_cn0, "CN0", false, 47, &qhm_spdm, &qhm_tic, &qnm_snoc, &xm_qdss_dap, &qhs_a1_noc_cfg, &qhs_a2_noc_cfg, &qhs_aop, &qhs_aoss, &qhs_camera_cfg, &qhs_clk_ctl, &qhs_compute_dsp_cfg, &qhs_cpr_cx, &qhs_crypto0_cfg, &qhs_dcc_cfg, &qhs_ddrss_cfg, &qhs_display_cfg, &qhs_glm, &qhs_gpuss_cfg, &qhs_imem_cfg, &qhs_ipa, &qhs_mnoc_cfg, &qhs_pcie0_cfg, &qhs_pcie_gen3_cfg, &qhs_pdm, &qhs_phy_refgen_south, &qhs_pimem_cfg, &qhs_prng, &qhs_qdss_cfg, &qhs_qupv3_north, &qhs_qupv3_south, &qhs_sdc2, &qhs_sdc4, &qhs_snoc_cfg, &qhs_spdm, &qhs_spss_cfg, &qhs_tcsr, &qhs_tlmm_north, &qhs_tlmm_south, &qhs_tsif, &qhs_ufs_card_cfg, &qhs_ufs_mem_cfg, &qhs_usb3_0, &qhs_usb3_1, &qhs_venus_cfg, &qhs_vsense_ctrl_cfg, &qns_cnoc_a2noc, &srvc_cnoc); -DEFINE_QBCM(bcm_qup0, "QUP0", false, 2, &qhm_qup1, &qhm_qup2); -DEFINE_QBCM(bcm_sn1, "SN1", false, 1, &qxs_imem); -DEFINE_QBCM(bcm_sn2, "SN2", false, 1, &qns_memnoc_gc); -DEFINE_QBCM(bcm_sn3, "SN3", false, 1, &qns_cnoc); -DEFINE_QBCM(bcm_sn4, "SN4", false, 1, &qxm_pimem); -DEFINE_QBCM(bcm_sn5, "SN5", false, 1, &xs_qdss_stm); -DEFINE_QBCM(bcm_sn6, "SN6", false, 3, &qhs_apss, &srvc_snoc, &xs_sys_tcu_cfg); -DEFINE_QBCM(bcm_sn7, "SN7", false, 1, &qxs_pcie); -DEFINE_QBCM(bcm_sn8, "SN8", false, 1, &qxs_pcie_gen3); -DEFINE_QBCM(bcm_sn9, "SN9", false, 2, &srvc_aggre1_noc, &qnm_aggre1_noc); -DEFINE_QBCM(bcm_sn11, "SN11", false, 2, &srvc_aggre2_noc, &qnm_aggre2_noc); -DEFINE_QBCM(bcm_sn12, "SN12", false, 2, &qnm_gladiator_sodv, &xm_gic); -DEFINE_QBCM(bcm_sn14, "SN14", false, 1, &qnm_pcie_anoc); -DEFINE_QBCM(bcm_sn15, "SN15", false, 1, &qnm_memnoc); - -static struct qcom_icc_node *rsc_hlos_nodes[] = { - [MASTER_APPSS_PROC] = &acm_l3, - [MASTER_TCU_0] = &acm_tcu, - [MASTER_LLCC] = &llcc_mc, - [MASTER_GNOC_CFG] = &pm_gnoc_cfg, +static struct qcom_icc_node *aggre1_noc_nodes[] = { [MASTER_A1NOC_CFG] = &qhm_a1noc_cfg, - [MASTER_A2NOC_CFG] = &qhm_a2noc_cfg, - [MASTER_CNOC_DC_NOC] = &qhm_cnoc, - [MASTER_MEM_NOC_CFG] = &qhm_memnoc_cfg, - [MASTER_CNOC_MNOC_CFG] = &qhm_mnoc_cfg, - [MASTER_QDSS_BAM] = &qhm_qdss_bam, - [MASTER_BLSP_1] = &qhm_qup1, - [MASTER_BLSP_2] = &qhm_qup2, - [MASTER_SNOC_CFG] = &qhm_snoc_cfg, - [MASTER_SPDM] = &qhm_spdm, - [MASTER_TIC] = &qhm_tic, [MASTER_TSIF] = &qhm_tsif, - [MASTER_A1NOC_SNOC] = &qnm_aggre1_noc, - [MASTER_A2NOC_SNOC] = &qnm_aggre2_noc, - [MASTER_GNOC_MEM_NOC] = &qnm_apps, - [MASTER_CNOC_A2NOC] = &qnm_cnoc, - [MASTER_GNOC_SNOC] = &qnm_gladiator_sodv, - [MASTER_MEM_NOC_SNOC] = &qnm_memnoc, - [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf, - [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf, - [MASTER_ANOC_PCIE_SNOC] = &qnm_pcie_anoc, - [MASTER_SNOC_CNOC] = &qnm_snoc, - [MASTER_SNOC_GC_MEM_NOC] = &qnm_snoc_gc, - [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf, - [MASTER_CAMNOC_HF0] = &qxm_camnoc_hf0, - [MASTER_CAMNOC_HF0_UNCOMP] = &qxm_camnoc_hf0_uncomp, - [MASTER_CAMNOC_HF1] = &qxm_camnoc_hf1, - [MASTER_CAMNOC_HF1_UNCOMP] = &qxm_camnoc_hf1_uncomp, - [MASTER_CAMNOC_SF] = &qxm_camnoc_sf, - [MASTER_CAMNOC_SF_UNCOMP] = &qxm_camnoc_sf_uncomp, - [MASTER_CRYPTO] = &qxm_crypto, - [MASTER_GFX3D] = &qxm_gpu, - [MASTER_IPA] = &qxm_ipa, - [MASTER_MDP0] = &qxm_mdp0, - [MASTER_MDP1] = &qxm_mdp1, - [MASTER_PIMEM] = &qxm_pimem, - [MASTER_ROTATOR] = &qxm_rot, - [MASTER_VIDEO_P0] = &qxm_venus0, - [MASTER_VIDEO_P1] = &qxm_venus1, - [MASTER_VIDEO_PROC] = &qxm_venus_arm9, - [MASTER_GIC] = &xm_gic, - [MASTER_PCIE_1] = &xm_pcie3_1, - [MASTER_PCIE_0] = &xm_pcie_0, - [MASTER_QDSS_DAP] = &xm_qdss_dap, - [MASTER_QDSS_ETR] = &xm_qdss_etr, [MASTER_SDCC_2] = &xm_sdc2, [MASTER_SDCC_4] = &xm_sdc4, [MASTER_UFS_CARD] = &xm_ufs_card, [MASTER_UFS_MEM] = &xm_ufs_mem, + [MASTER_PCIE_0] = &xm_pcie_0, + [SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc, + [SLAVE_SERVICE_A1NOC] = &srvc_aggre1_noc, + [SLAVE_ANOC_PCIE_A1NOC_SNOC] = &qns_pcie_a1noc_snoc, +}; + +const static struct qcom_icc_desc sdm845_aggre1_noc = { + .nodes = aggre1_noc_nodes, + .num_nodes = ARRAY_SIZE(aggre1_noc_nodes), + .bcms = aggre1_noc_bcms, + .num_bcms = ARRAY_SIZE(aggre1_noc_bcms), +}; + +static struct qcom_icc_bcm *aggre2_noc_bcms[] = { + &bcm_ce0, + &bcm_sn11, + &bcm_qup0, +}; + +static struct qcom_icc_node *aggre2_noc_nodes[] = { + [MASTER_A2NOC_CFG] = &qhm_a2noc_cfg, + [MASTER_QDSS_BAM] = &qhm_qdss_bam, + [MASTER_CNOC_A2NOC] = &qnm_cnoc, + [MASTER_CRYPTO] = &qxm_crypto, + [MASTER_IPA] = &qxm_ipa, + [MASTER_PCIE_1] = &xm_pcie3_1, + [MASTER_QDSS_ETR] = &xm_qdss_etr, [MASTER_USB3_0] = &xm_usb3_0, [MASTER_USB3_1] = &xm_usb3_1, - [SLAVE_EBI1] = &ebi, + [SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc, + [SLAVE_ANOC_PCIE_SNOC] = &qns_pcie_snoc, + [SLAVE_SERVICE_A2NOC] = &srvc_aggre2_noc, +}; + +const static struct qcom_icc_desc sdm845_aggre2_noc = { + .nodes = aggre2_noc_nodes, + .num_nodes = ARRAY_SIZE(aggre2_noc_nodes), + .bcms = aggre2_noc_bcms, + .num_bcms = ARRAY_SIZE(aggre2_noc_bcms), +}; + +static struct qcom_icc_bcm *config_noc_bcms[] = { + &bcm_cn0, +}; + +static struct qcom_icc_node *config_noc_nodes[] = { + [MASTER_SPDM] = &qhm_spdm, + [MASTER_TIC] = &qhm_tic, + [MASTER_SNOC_CNOC] = &qnm_snoc, + [MASTER_QDSS_DAP] = &xm_qdss_dap, [SLAVE_A1NOC_CFG] = &qhs_a1_noc_cfg, [SLAVE_A2NOC_CFG] = &qhs_a2_noc_cfg, [SLAVE_AOP] = &qhs_aop, [SLAVE_AOSS] = &qhs_aoss, - [SLAVE_APPSS] = &qhs_apss, [SLAVE_CAMERA_CFG] = &qhs_camera_cfg, [SLAVE_CLK_CTL] = &qhs_clk_ctl, [SLAVE_CDSP_CFG] = &qhs_compute_dsp_cfg, @@ -386,9 +384,6 @@ static struct qcom_icc_node *rsc_hlos_nodes[] = { [SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg, [SLAVE_IMEM_CFG] = &qhs_imem_cfg, [SLAVE_IPA_CFG] = &qhs_ipa, - [SLAVE_LLCC_CFG] = &qhs_llcc, - [SLAVE_MSS_PROC_MS_MPU_CFG] = &qhs_mdsp_ms_mpu_cfg, - [SLAVE_MEM_NOC_CFG] = &qhs_memnoc, [SLAVE_CNOC_MNOC_CFG] = &qhs_mnoc_cfg, [SLAVE_PCIE_0_CFG] = &qhs_pcie0_cfg, [SLAVE_PCIE_1_CFG] = &qhs_pcie_gen3_cfg, @@ -414,53 +409,122 @@ static struct qcom_icc_node *rsc_hlos_nodes[] = { [SLAVE_USB3_1] = &qhs_usb3_1, [SLAVE_VENUS_CFG] = &qhs_venus_cfg, [SLAVE_VSENSE_CTRL_CFG] = &qhs_vsense_ctrl_cfg, - [SLAVE_MNOC_SF_MEM_NOC] = &qns2_mem_noc, - [SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc, - [SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc, - [SLAVE_MEM_NOC_GNOC] = &qns_apps_io, - [SLAVE_CAMNOC_UNCOMP] = &qns_camnoc_uncomp, - [SLAVE_SNOC_CNOC] = &qns_cnoc, [SLAVE_CNOC_A2NOC] = &qns_cnoc_a2noc, - [SLAVE_GNOC_SNOC] = &qns_gladiator_sodv, - [SLAVE_GNOC_MEM_NOC] = &qns_gnoc_memnoc, - [SLAVE_LLCC] = &qns_llcc, - [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf, - [SLAVE_SNOC_MEM_NOC_GC] = &qns_memnoc_gc, - [SLAVE_SNOC_MEM_NOC_SF] = &qns_memnoc_sf, - [SLAVE_MEM_NOC_SNOC] = &qns_memnoc_snoc, - [SLAVE_ANOC_PCIE_A1NOC_SNOC] = &qns_pcie_a1noc_snoc, - [SLAVE_ANOC_PCIE_SNOC] = &qns_pcie_snoc, - [SLAVE_IMEM] = &qxs_imem, - [SLAVE_PCIE_0] = &qxs_pcie, - [SLAVE_PCIE_1] = &qxs_pcie_gen3, - [SLAVE_PIMEM] = &qxs_pimem, - [SLAVE_SERVICE_A1NOC] = &srvc_aggre1_noc, - [SLAVE_SERVICE_A2NOC] = &srvc_aggre2_noc, [SLAVE_SERVICE_CNOC] = &srvc_cnoc, - [SLAVE_SERVICE_GNOC] = &srvc_gnoc, - [SLAVE_SERVICE_MEM_NOC] = &srvc_memnoc, - [SLAVE_SERVICE_MNOC] = &srvc_mnoc, - [SLAVE_SERVICE_SNOC] = &srvc_snoc, - [SLAVE_QDSS_STM] = &xs_qdss_stm, - [SLAVE_TCU] = &xs_sys_tcu_cfg, }; -static struct qcom_icc_bcm *rsc_hlos_bcms[] = { - &bcm_acv, +const static struct qcom_icc_desc sdm845_config_noc = { + .nodes = config_noc_nodes, + .num_nodes = ARRAY_SIZE(config_noc_nodes), + .bcms = config_noc_bcms, + .num_bcms = ARRAY_SIZE(config_noc_bcms), +}; + +static struct qcom_icc_bcm *dc_noc_bcms[] = { +}; + +static struct qcom_icc_node *dc_noc_nodes[] = { + [MASTER_CNOC_DC_NOC] = &qhm_cnoc, + [SLAVE_LLCC_CFG] = &qhs_llcc, + [SLAVE_MEM_NOC_CFG] = &qhs_memnoc, +}; + +const static struct qcom_icc_desc sdm845_dc_noc = { + .nodes = dc_noc_nodes, + .num_nodes = ARRAY_SIZE(dc_noc_nodes), + .bcms = dc_noc_bcms, + .num_bcms = ARRAY_SIZE(dc_noc_bcms), +}; + +static struct qcom_icc_bcm *gladiator_noc_bcms[] = { +}; + +static struct qcom_icc_node *gladiator_noc_nodes[] = { + [MASTER_APPSS_PROC] = &acm_l3, + [MASTER_GNOC_CFG] = &pm_gnoc_cfg, + [SLAVE_GNOC_SNOC] = &qns_gladiator_sodv, + [SLAVE_GNOC_MEM_NOC] = &qns_gnoc_memnoc, + [SLAVE_SERVICE_GNOC] = &srvc_gnoc, +}; + +const static struct qcom_icc_desc sdm845_gladiator_noc = { + .nodes = gladiator_noc_nodes, + .num_nodes = ARRAY_SIZE(gladiator_noc_nodes), + .bcms = gladiator_noc_bcms, + .num_bcms = ARRAY_SIZE(gladiator_noc_bcms), +}; + +static struct qcom_icc_bcm *mem_noc_bcms[] = { &bcm_mc0, + &bcm_acv, &bcm_sh0, - &bcm_mm0, &bcm_sh1, - &bcm_mm1, &bcm_sh2, - &bcm_mm2, &bcm_sh3, - &bcm_mm3, &bcm_sh5, +}; + +static struct qcom_icc_node *mem_noc_nodes[] = { + [MASTER_TCU_0] = &acm_tcu, + [MASTER_MEM_NOC_CFG] = &qhm_memnoc_cfg, + [MASTER_GNOC_MEM_NOC] = &qnm_apps, + [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf, + [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf, + [MASTER_SNOC_GC_MEM_NOC] = &qnm_snoc_gc, + [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf, + [MASTER_GFX3D] = &qxm_gpu, + [SLAVE_MSS_PROC_MS_MPU_CFG] = &qhs_mdsp_ms_mpu_cfg, + [SLAVE_MEM_NOC_GNOC] = &qns_apps_io, + [SLAVE_LLCC] = &qns_llcc, + [SLAVE_MEM_NOC_SNOC] = &qns_memnoc_snoc, + [SLAVE_SERVICE_MEM_NOC] = &srvc_memnoc, + [MASTER_LLCC] = &llcc_mc, + [SLAVE_EBI1] = &ebi, +}; + +const static struct qcom_icc_desc sdm845_mem_noc = { + .nodes = mem_noc_nodes, + .num_nodes = ARRAY_SIZE(mem_noc_nodes), + .bcms = mem_noc_bcms, + .num_bcms = ARRAY_SIZE(mem_noc_bcms), +}; + +static struct qcom_icc_bcm *mmss_noc_bcms[] = { + &bcm_mm0, + &bcm_mm1, + &bcm_mm2, + &bcm_mm3, +}; + +static struct qcom_icc_node *mmss_noc_nodes[] = { + [MASTER_CNOC_MNOC_CFG] = &qhm_mnoc_cfg, + [MASTER_CAMNOC_HF0] = &qxm_camnoc_hf0, + [MASTER_CAMNOC_HF1] = &qxm_camnoc_hf1, + [MASTER_CAMNOC_SF] = &qxm_camnoc_sf, + [MASTER_MDP0] = &qxm_mdp0, + [MASTER_MDP1] = &qxm_mdp1, + [MASTER_ROTATOR] = &qxm_rot, + [MASTER_VIDEO_P0] = &qxm_venus0, + [MASTER_VIDEO_P1] = &qxm_venus1, + [MASTER_VIDEO_PROC] = &qxm_venus_arm9, + [SLAVE_MNOC_SF_MEM_NOC] = &qns2_mem_noc, + [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf, + [SLAVE_SERVICE_MNOC] = &srvc_mnoc, + [MASTER_CAMNOC_HF0_UNCOMP] = &qxm_camnoc_hf0_uncomp, + [MASTER_CAMNOC_HF1_UNCOMP] = &qxm_camnoc_hf1_uncomp, + [MASTER_CAMNOC_SF_UNCOMP] = &qxm_camnoc_sf_uncomp, + [SLAVE_CAMNOC_UNCOMP] = &qns_camnoc_uncomp, +}; + +const static struct qcom_icc_desc sdm845_mmss_noc = { + .nodes = mmss_noc_nodes, + .num_nodes = ARRAY_SIZE(mmss_noc_nodes), + .bcms = mmss_noc_bcms, + .num_bcms = ARRAY_SIZE(mmss_noc_bcms), +}; + +static struct qcom_icc_bcm *system_noc_bcms[] = { &bcm_sn0, - &bcm_ce0, - &bcm_cn0, - &bcm_qup0, &bcm_sn1, &bcm_sn2, &bcm_sn3, @@ -476,297 +540,34 @@ static struct qcom_icc_bcm *rsc_hlos_bcms[] = { &bcm_sn15, }; -static struct qcom_icc_desc sdm845_rsc_hlos = { - .nodes = rsc_hlos_nodes, - .num_nodes = ARRAY_SIZE(rsc_hlos_nodes), - .bcms = rsc_hlos_bcms, - .num_bcms = ARRAY_SIZE(rsc_hlos_bcms), +static struct qcom_icc_node *system_noc_nodes[] = { + [MASTER_SNOC_CFG] = &qhm_snoc_cfg, + [MASTER_A1NOC_SNOC] = &qnm_aggre1_noc, + [MASTER_A2NOC_SNOC] = &qnm_aggre2_noc, + [MASTER_GNOC_SNOC] = &qnm_gladiator_sodv, + [MASTER_MEM_NOC_SNOC] = &qnm_memnoc, + [MASTER_ANOC_PCIE_SNOC] = &qnm_pcie_anoc, + [MASTER_PIMEM] = &qxm_pimem, + [MASTER_GIC] = &xm_gic, + [SLAVE_APPSS] = &qhs_apss, + [SLAVE_SNOC_CNOC] = &qns_cnoc, + [SLAVE_SNOC_MEM_NOC_GC] = &qns_memnoc_gc, + [SLAVE_SNOC_MEM_NOC_SF] = &qns_memnoc_sf, + [SLAVE_IMEM] = &qxs_imem, + [SLAVE_PCIE_0] = &qxs_pcie, + [SLAVE_PCIE_1] = &qxs_pcie_gen3, + [SLAVE_PIMEM] = &qxs_pimem, + [SLAVE_SERVICE_SNOC] = &srvc_snoc, + [SLAVE_QDSS_STM] = &xs_qdss_stm, + [SLAVE_TCU] = &xs_sys_tcu_cfg, }; -static int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev) -{ - struct qcom_icc_node *qn; - const struct bcm_db *data; - size_t data_count; - int i; - - bcm->addr = cmd_db_read_addr(bcm->name); - if (!bcm->addr) { - dev_err(dev, "%s could not find RPMh address\n", - bcm->name); - return -EINVAL; - } - - data = cmd_db_read_aux_data(bcm->name, &data_count); - if (IS_ERR(data)) { - dev_err(dev, "%s command db read error (%ld)\n", - bcm->name, PTR_ERR(data)); - return PTR_ERR(data); - } - if (!data_count) { - dev_err(dev, "%s command db missing or partial aux data\n", - bcm->name); - return -EINVAL; - } - - bcm->aux_data.unit = le32_to_cpu(data->unit); - bcm->aux_data.width = le16_to_cpu(data->width); - bcm->aux_data.vcd = data->vcd; - bcm->aux_data.reserved = data->reserved; - - /* - * Link Qnodes to their respective BCMs - */ - for (i = 0; i < bcm->num_nodes; i++) { - qn = bcm->nodes[i]; - qn->bcms[qn->num_bcms] = bcm; - qn->num_bcms++; - } - - return 0; -} - -inline void tcs_cmd_gen(struct tcs_cmd *cmd, u64 vote_x, u64 vote_y, - u32 addr, bool commit) -{ - bool valid = true; - - if (!cmd) - return; - - if (vote_x == 0 && vote_y == 0) - valid = false; - - if (vote_x > BCM_TCS_CMD_VOTE_MASK) - vote_x = BCM_TCS_CMD_VOTE_MASK; - - if (vote_y > BCM_TCS_CMD_VOTE_MASK) - vote_y = BCM_TCS_CMD_VOTE_MASK; - - cmd->addr = addr; - cmd->data = BCM_TCS_CMD(commit, valid, vote_x, vote_y); - - /* - * Set the wait for completion flag on command that need to be completed - * before the next command. - */ - if (commit) - cmd->wait = true; -} - -static void tcs_list_gen(struct list_head *bcm_list, int bucket, - struct tcs_cmd tcs_list[SDM845_MAX_VCD], - int n[SDM845_MAX_VCD]) -{ - struct qcom_icc_bcm *bcm; - bool commit; - size_t idx = 0, batch = 0, cur_vcd_size = 0; - - memset(n, 0, sizeof(int) * SDM845_MAX_VCD); - - list_for_each_entry(bcm, bcm_list, list) { - commit = false; - cur_vcd_size++; - if ((list_is_last(&bcm->list, bcm_list)) || - bcm->aux_data.vcd != list_next_entry(bcm, list)->aux_data.vcd) { - commit = true; - cur_vcd_size = 0; - } - tcs_cmd_gen(&tcs_list[idx], bcm->vote_x[bucket], - bcm->vote_y[bucket], bcm->addr, commit); - idx++; - n[batch]++; - /* - * Batch the BCMs in such a way that we do not split them in - * multiple payloads when they are under the same VCD. This is - * to ensure that every BCM is committed since we only set the - * commit bit on the last BCM request of every VCD. - */ - if (n[batch] >= MAX_RPMH_PAYLOAD) { - if (!commit) { - n[batch] -= cur_vcd_size; - n[batch + 1] = cur_vcd_size; - } - batch++; - } - } -} - -static void bcm_aggregate(struct qcom_icc_bcm *bcm) -{ - size_t i, bucket; - u64 agg_avg[QCOM_ICC_NUM_BUCKETS] = {0}; - u64 agg_peak[QCOM_ICC_NUM_BUCKETS] = {0}; - u64 temp; - - for (bucket = 0; bucket < QCOM_ICC_NUM_BUCKETS; bucket++) { - for (i = 0; i < bcm->num_nodes; i++) { - temp = bcm->nodes[i]->sum_avg[bucket] * bcm->aux_data.width; - do_div(temp, bcm->nodes[i]->buswidth * bcm->nodes[i]->channels); - agg_avg[bucket] = max(agg_avg[bucket], temp); - - temp = bcm->nodes[i]->max_peak[bucket] * bcm->aux_data.width; - do_div(temp, bcm->nodes[i]->buswidth); - agg_peak[bucket] = max(agg_peak[bucket], temp); - } - - temp = agg_avg[bucket] * 1000ULL; - do_div(temp, bcm->aux_data.unit); - bcm->vote_x[bucket] = temp; - - temp = agg_peak[bucket] * 1000ULL; - do_div(temp, bcm->aux_data.unit); - bcm->vote_y[bucket] = temp; - } - - if (bcm->keepalive && bcm->vote_x[QCOM_ICC_BUCKET_AMC] == 0 && - bcm->vote_y[QCOM_ICC_BUCKET_AMC] == 0) { - bcm->vote_x[QCOM_ICC_BUCKET_AMC] = 1; - bcm->vote_x[QCOM_ICC_BUCKET_WAKE] = 1; - bcm->vote_y[QCOM_ICC_BUCKET_AMC] = 1; - bcm->vote_y[QCOM_ICC_BUCKET_WAKE] = 1; - } - - bcm->dirty = false; -} - -static void qcom_icc_pre_aggregate(struct icc_node *node) -{ - size_t i; - struct qcom_icc_node *qn; - - qn = node->data; - - for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) { - qn->sum_avg[i] = 0; - qn->max_peak[i] = 0; - } -} - -static int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, - u32 peak_bw, u32 *agg_avg, u32 *agg_peak) -{ - size_t i; - struct qcom_icc_node *qn; - - qn = node->data; - - if (!tag) - tag = QCOM_ICC_TAG_ALWAYS; - - for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) { - if (tag & BIT(i)) { - qn->sum_avg[i] += avg_bw; - qn->max_peak[i] = max_t(u32, qn->max_peak[i], peak_bw); - } - } - - *agg_avg += avg_bw; - *agg_peak = max_t(u32, *agg_peak, peak_bw); - - for (i = 0; i < qn->num_bcms; i++) - qn->bcms[i]->dirty = true; - - return 0; -} - -static int qcom_icc_set(struct icc_node *src, struct icc_node *dst) -{ - struct qcom_icc_provider *qp; - struct icc_node *node; - struct tcs_cmd cmds[SDM845_MAX_BCMS]; - struct list_head commit_list; - int commit_idx[SDM845_MAX_VCD]; - int ret = 0, i; - - if (!src) - node = dst; - else - node = src; - - qp = to_qcom_provider(node->provider); - - INIT_LIST_HEAD(&commit_list); - - for (i = 0; i < qp->num_bcms; i++) { - if (qp->bcms[i]->dirty) { - bcm_aggregate(qp->bcms[i]); - list_add_tail(&qp->bcms[i]->list, &commit_list); - } - } - - /* - * Construct the command list based on a pre ordered list of BCMs - * based on VCD. - */ - tcs_list_gen(&commit_list, QCOM_ICC_BUCKET_AMC, cmds, commit_idx); - - if (!commit_idx[0]) - return ret; - - ret = rpmh_invalidate(qp->dev); - if (ret) { - pr_err("Error invalidating RPMH client (%d)\n", ret); - return ret; - } - - ret = rpmh_write_batch(qp->dev, RPMH_ACTIVE_ONLY_STATE, - cmds, commit_idx); - if (ret) { - pr_err("Error sending AMC RPMH requests (%d)\n", ret); - return ret; - } - - INIT_LIST_HEAD(&commit_list); - - for (i = 0; i < qp->num_bcms; i++) { - /* - * Only generate WAKE and SLEEP commands if a resource's - * requirements change as the execution environment transitions - * between different power states. - */ - if (qp->bcms[i]->vote_x[QCOM_ICC_BUCKET_WAKE] != - qp->bcms[i]->vote_x[QCOM_ICC_BUCKET_SLEEP] || - qp->bcms[i]->vote_y[QCOM_ICC_BUCKET_WAKE] != - qp->bcms[i]->vote_y[QCOM_ICC_BUCKET_SLEEP]) { - list_add_tail(&qp->bcms[i]->list, &commit_list); - } - } - - if (list_empty(&commit_list)) - return ret; - - tcs_list_gen(&commit_list, QCOM_ICC_BUCKET_WAKE, cmds, commit_idx); - - ret = rpmh_write_batch(qp->dev, RPMH_WAKE_ONLY_STATE, cmds, commit_idx); - if (ret) { - pr_err("Error sending WAKE RPMH requests (%d)\n", ret); - return ret; - } - - tcs_list_gen(&commit_list, QCOM_ICC_BUCKET_SLEEP, cmds, commit_idx); - - ret = rpmh_write_batch(qp->dev, RPMH_SLEEP_STATE, cmds, commit_idx); - if (ret) { - pr_err("Error sending SLEEP RPMH requests (%d)\n", ret); - return ret; - } - - return ret; -} - -static int cmp_vcd(const void *_l, const void *_r) -{ - const struct qcom_icc_bcm **l = (const struct qcom_icc_bcm **)_l; - const struct qcom_icc_bcm **r = (const struct qcom_icc_bcm **)_r; - - if (l[0]->aux_data.vcd < r[0]->aux_data.vcd) - return -1; - else if (l[0]->aux_data.vcd == r[0]->aux_data.vcd) - return 0; - else - return 1; -} +const static struct qcom_icc_desc sdm845_system_noc = { + .nodes = system_noc_nodes, + .num_nodes = ARRAY_SIZE(system_noc_nodes), + .bcms = system_noc_bcms, + .num_bcms = ARRAY_SIZE(system_noc_bcms), +}; static int qnoc_probe(struct platform_device *pdev) { @@ -779,7 +580,7 @@ static int qnoc_probe(struct platform_device *pdev) size_t num_nodes, i; int ret; - desc = of_device_get_match_data(&pdev->dev); + desc = device_get_match_data(&pdev->dev); if (!desc) return -EINVAL; @@ -808,6 +609,12 @@ static int qnoc_probe(struct platform_device *pdev) qp->bcms = desc->bcms; qp->num_bcms = desc->num_bcms; + qp->voter = of_bcm_voter_get(qp->dev, NULL); + if (IS_ERR(qp->voter)) { + dev_err(&pdev->dev, "bcm_voter err:%ld\n", PTR_ERR(qp->voter)); + return PTR_ERR(qp->voter); + } + ret = icc_provider_add(provider); if (ret) { dev_err(&pdev->dev, "error adding interconnect provider\n"); @@ -817,6 +624,9 @@ static int qnoc_probe(struct platform_device *pdev) for (i = 0; i < num_nodes; i++) { size_t j; + if (!qnodes[i]) + continue; + node = icc_node_create(qnodes[i]->id); if (IS_ERR(node)) { ret = PTR_ERR(node); @@ -827,10 +637,6 @@ static int qnoc_probe(struct platform_device *pdev) node->data = qnodes[i]; icc_node_add(node, provider); - dev_dbg(&pdev->dev, "registered node %p %s %d\n", node, - qnodes[i]->name, node->id); - - /* populate links */ for (j = 0; j < qnodes[i]->num_links; j++) icc_link_create(node, qnodes[i]->links[j]); @@ -841,19 +647,9 @@ static int qnoc_probe(struct platform_device *pdev) for (i = 0; i < qp->num_bcms; i++) qcom_icc_bcm_init(qp->bcms[i], &pdev->dev); - /* - * Pre sort the BCMs based on VCD for ease of generating a command list - * that groups the BCMs with the same VCD together. VCDs are numbered - * with lowest being the most expensive time wise, ensuring that - * those commands are being sent the earliest in the queue. - */ - sort(qp->bcms, qp->num_bcms, sizeof(*qp->bcms), cmp_vcd, NULL); - platform_set_drvdata(pdev, qp); - dev_dbg(&pdev->dev, "Registered SDM845 ICC\n"); - - return ret; + return 0; err: icc_nodes_remove(provider); icc_provider_del(provider); @@ -869,8 +665,23 @@ static int qnoc_remove(struct platform_device *pdev) } static const struct of_device_id qnoc_of_match[] = { - { .compatible = "qcom,sdm845-rsc-hlos", .data = &sdm845_rsc_hlos }, - { }, + { .compatible = "qcom,sdm845-aggre1-noc", + .data = &sdm845_aggre1_noc}, + { .compatible = "qcom,sdm845-aggre2-noc", + .data = &sdm845_aggre2_noc}, + { .compatible = "qcom,sdm845-config-noc", + .data = &sdm845_config_noc}, + { .compatible = "qcom,sdm845-dc-noc", + .data = &sdm845_dc_noc}, + { .compatible = "qcom,sdm845-gladiator-noc", + .data = &sdm845_gladiator_noc}, + { .compatible = "qcom,sdm845-mem-noc", + .data = &sdm845_mem_noc}, + { .compatible = "qcom,sdm845-mmss-noc", + .data = &sdm845_mmss_noc}, + { .compatible = "qcom,sdm845-system-noc", + .data = &sdm845_system_noc}, + { } }; MODULE_DEVICE_TABLE(of, qnoc_of_match); diff --git a/include/dt-bindings/interconnect/qcom,sdm845.h b/include/dt-bindings/interconnect/qcom,sdm845.h index 7b2393be7361..290be38f40e6 100644 --- a/include/dt-bindings/interconnect/qcom,sdm845.h +++ b/include/dt-bindings/interconnect/qcom,sdm845.h @@ -10,134 +10,139 @@ #define __DT_BINDINGS_INTERCONNECT_QCOM_SDM845_H #define MASTER_A1NOC_CFG 0 -#define MASTER_BLSP_1 1 -#define MASTER_TSIF 2 -#define MASTER_SDCC_2 3 -#define MASTER_SDCC_4 4 -#define MASTER_UFS_CARD 5 -#define MASTER_UFS_MEM 6 -#define MASTER_PCIE_0 7 -#define MASTER_A2NOC_CFG 8 -#define MASTER_QDSS_BAM 9 -#define MASTER_BLSP_2 10 -#define MASTER_CNOC_A2NOC 11 -#define MASTER_CRYPTO 12 -#define MASTER_IPA 13 -#define MASTER_PCIE_1 14 -#define MASTER_QDSS_ETR 15 -#define MASTER_USB3_0 16 -#define MASTER_USB3_1 17 -#define MASTER_CAMNOC_HF0_UNCOMP 18 -#define MASTER_CAMNOC_HF1_UNCOMP 19 -#define MASTER_CAMNOC_SF_UNCOMP 20 -#define MASTER_SPDM 21 -#define MASTER_TIC 22 -#define MASTER_SNOC_CNOC 23 -#define MASTER_QDSS_DAP 24 -#define MASTER_CNOC_DC_NOC 25 -#define MASTER_APPSS_PROC 26 -#define MASTER_GNOC_CFG 27 -#define MASTER_LLCC 28 -#define MASTER_TCU_0 29 -#define MASTER_MEM_NOC_CFG 30 -#define MASTER_GNOC_MEM_NOC 31 -#define MASTER_MNOC_HF_MEM_NOC 32 -#define MASTER_MNOC_SF_MEM_NOC 33 -#define MASTER_SNOC_GC_MEM_NOC 34 -#define MASTER_SNOC_SF_MEM_NOC 35 -#define MASTER_GFX3D 36 -#define MASTER_CNOC_MNOC_CFG 37 -#define MASTER_CAMNOC_HF0 38 -#define MASTER_CAMNOC_HF1 39 -#define MASTER_CAMNOC_SF 40 -#define MASTER_MDP0 41 -#define MASTER_MDP1 42 -#define MASTER_ROTATOR 43 -#define MASTER_VIDEO_P0 44 -#define MASTER_VIDEO_P1 45 -#define MASTER_VIDEO_PROC 46 -#define MASTER_SNOC_CFG 47 -#define MASTER_A1NOC_SNOC 48 -#define MASTER_A2NOC_SNOC 49 -#define MASTER_GNOC_SNOC 50 -#define MASTER_MEM_NOC_SNOC 51 -#define MASTER_ANOC_PCIE_SNOC 52 -#define MASTER_PIMEM 53 -#define MASTER_GIC 54 -#define SLAVE_A1NOC_SNOC 55 -#define SLAVE_SERVICE_A1NOC 56 -#define SLAVE_ANOC_PCIE_A1NOC_SNOC 57 -#define SLAVE_A2NOC_SNOC 58 -#define SLAVE_ANOC_PCIE_SNOC 59 -#define SLAVE_SERVICE_A2NOC 60 -#define SLAVE_CAMNOC_UNCOMP 61 -#define SLAVE_A1NOC_CFG 62 -#define SLAVE_A2NOC_CFG 63 -#define SLAVE_AOP 64 -#define SLAVE_AOSS 65 -#define SLAVE_CAMERA_CFG 66 -#define SLAVE_CLK_CTL 67 -#define SLAVE_CDSP_CFG 68 -#define SLAVE_RBCPR_CX_CFG 69 -#define SLAVE_CRYPTO_0_CFG 70 -#define SLAVE_DCC_CFG 71 -#define SLAVE_CNOC_DDRSS 72 -#define SLAVE_DISPLAY_CFG 73 -#define SLAVE_GLM 74 -#define SLAVE_GFX3D_CFG 75 -#define SLAVE_IMEM_CFG 76 -#define SLAVE_IPA_CFG 77 -#define SLAVE_CNOC_MNOC_CFG 78 -#define SLAVE_PCIE_0_CFG 79 -#define SLAVE_PCIE_1_CFG 80 -#define SLAVE_PDM 81 -#define SLAVE_SOUTH_PHY_CFG 82 -#define SLAVE_PIMEM_CFG 83 -#define SLAVE_PRNG 84 -#define SLAVE_QDSS_CFG 85 -#define SLAVE_BLSP_2 86 -#define SLAVE_BLSP_1 87 -#define SLAVE_SDCC_2 88 -#define SLAVE_SDCC_4 89 -#define SLAVE_SNOC_CFG 90 -#define SLAVE_SPDM_WRAPPER 91 -#define SLAVE_SPSS_CFG 92 -#define SLAVE_TCSR 93 -#define SLAVE_TLMM_NORTH 94 -#define SLAVE_TLMM_SOUTH 95 -#define SLAVE_TSIF 96 -#define SLAVE_UFS_CARD_CFG 97 -#define SLAVE_UFS_MEM_CFG 98 -#define SLAVE_USB3_0 99 -#define SLAVE_USB3_1 100 -#define SLAVE_VENUS_CFG 101 -#define SLAVE_VSENSE_CTRL_CFG 102 -#define SLAVE_CNOC_A2NOC 103 -#define SLAVE_SERVICE_CNOC 104 -#define SLAVE_LLCC_CFG 105 -#define SLAVE_MEM_NOC_CFG 106 -#define SLAVE_GNOC_SNOC 107 -#define SLAVE_GNOC_MEM_NOC 108 -#define SLAVE_SERVICE_GNOC 109 -#define SLAVE_EBI1 110 -#define SLAVE_MSS_PROC_MS_MPU_CFG 111 -#define SLAVE_MEM_NOC_GNOC 112 -#define SLAVE_LLCC 113 -#define SLAVE_MEM_NOC_SNOC 114 -#define SLAVE_SERVICE_MEM_NOC 115 -#define SLAVE_MNOC_SF_MEM_NOC 116 -#define SLAVE_MNOC_HF_MEM_NOC 117 -#define SLAVE_SERVICE_MNOC 118 -#define SLAVE_APPSS 119 -#define SLAVE_SNOC_CNOC 120 -#define SLAVE_SNOC_MEM_NOC_GC 121 -#define SLAVE_SNOC_MEM_NOC_SF 122 -#define SLAVE_IMEM 123 -#define SLAVE_PCIE_0 124 -#define SLAVE_PCIE_1 125 -#define SLAVE_PIMEM 126 -#define SLAVE_SERVICE_SNOC 127 -#define SLAVE_QDSS_STM 128 -#define SLAVE_TCU 129 +#define MASTER_TSIF 1 +#define MASTER_SDCC_2 2 +#define MASTER_SDCC_4 3 +#define MASTER_UFS_CARD 4 +#define MASTER_UFS_MEM 5 +#define MASTER_PCIE_0 6 +#define SLAVE_A1NOC_SNOC 7 +#define SLAVE_SERVICE_A1NOC 8 +#define SLAVE_ANOC_PCIE_A1NOC_SNOC 9 + +#define MASTER_A2NOC_CFG 0 +#define MASTER_QDSS_BAM 1 +#define MASTER_CNOC_A2NOC 2 +#define MASTER_CRYPTO 3 +#define MASTER_IPA 4 +#define MASTER_PCIE_1 5 +#define MASTER_QDSS_ETR 6 +#define MASTER_USB3_0 7 +#define MASTER_USB3_1 8 +#define SLAVE_A2NOC_SNOC 9 +#define SLAVE_ANOC_PCIE_SNOC 10 +#define SLAVE_SERVICE_A2NOC 11 + +#define MASTER_SPDM 0 +#define MASTER_TIC 1 +#define MASTER_SNOC_CNOC 2 +#define MASTER_QDSS_DAP 3 +#define SLAVE_A1NOC_CFG 4 +#define SLAVE_A2NOC_CFG 5 +#define SLAVE_AOP 6 +#define SLAVE_AOSS 7 +#define SLAVE_CAMERA_CFG 8 +#define SLAVE_CLK_CTL 9 +#define SLAVE_CDSP_CFG 10 +#define SLAVE_RBCPR_CX_CFG 11 +#define SLAVE_CRYPTO_0_CFG 12 +#define SLAVE_DCC_CFG 13 +#define SLAVE_CNOC_DDRSS 14 +#define SLAVE_DISPLAY_CFG 15 +#define SLAVE_GLM 16 +#define SLAVE_GFX3D_CFG 17 +#define SLAVE_IMEM_CFG 18 +#define SLAVE_IPA_CFG 19 +#define SLAVE_CNOC_MNOC_CFG 20 +#define SLAVE_PCIE_0_CFG 21 +#define SLAVE_PCIE_1_CFG 22 +#define SLAVE_PDM 23 +#define SLAVE_SOUTH_PHY_CFG 24 +#define SLAVE_PIMEM_CFG 25 +#define SLAVE_PRNG 26 +#define SLAVE_QDSS_CFG 27 +#define SLAVE_BLSP_2 28 +#define SLAVE_BLSP_1 29 +#define SLAVE_SDCC_2 30 +#define SLAVE_SDCC_4 31 +#define SLAVE_SNOC_CFG 32 +#define SLAVE_SPDM_WRAPPER 33 +#define SLAVE_SPSS_CFG 34 +#define SLAVE_TCSR 35 +#define SLAVE_TLMM_NORTH 36 +#define SLAVE_TLMM_SOUTH 37 +#define SLAVE_TSIF 38 +#define SLAVE_UFS_CARD_CFG 39 +#define SLAVE_UFS_MEM_CFG 40 +#define SLAVE_USB3_0 41 +#define SLAVE_USB3_1 42 +#define SLAVE_VENUS_CFG 43 +#define SLAVE_VSENSE_CTRL_CFG 44 +#define SLAVE_CNOC_A2NOC 45 +#define SLAVE_SERVICE_CNOC 46 + +#define MASTER_CNOC_DC_NOC 0 +#define SLAVE_LLCC_CFG 1 +#define SLAVE_MEM_NOC_CFG 2 + +#define MASTER_APPSS_PROC 0 +#define MASTER_GNOC_CFG 1 +#define SLAVE_GNOC_SNOC 2 +#define SLAVE_GNOC_MEM_NOC 3 +#define SLAVE_SERVICE_GNOC 4 + +#define MASTER_TCU_0 0 +#define MASTER_MEM_NOC_CFG 1 +#define MASTER_GNOC_MEM_NOC 2 +#define MASTER_MNOC_HF_MEM_NOC 3 +#define MASTER_MNOC_SF_MEM_NOC 4 +#define MASTER_SNOC_GC_MEM_NOC 5 +#define MASTER_SNOC_SF_MEM_NOC 6 +#define MASTER_GFX3D 7 +#define SLAVE_MSS_PROC_MS_MPU_CFG 8 +#define SLAVE_MEM_NOC_GNOC 9 +#define SLAVE_LLCC 10 +#define SLAVE_MEM_NOC_SNOC 11 +#define SLAVE_SERVICE_MEM_NOC 12 +#define MASTER_LLCC 13 +#define SLAVE_EBI1 14 + +#define MASTER_CNOC_MNOC_CFG 0 +#define MASTER_CAMNOC_HF0 1 +#define MASTER_CAMNOC_HF1 2 +#define MASTER_CAMNOC_SF 3 +#define MASTER_MDP0 4 +#define MASTER_MDP1 5 +#define MASTER_ROTATOR 6 +#define MASTER_VIDEO_P0 7 +#define MASTER_VIDEO_P1 8 +#define MASTER_VIDEO_PROC 9 +#define SLAVE_MNOC_SF_MEM_NOC 10 +#define SLAVE_MNOC_HF_MEM_NOC 11 +#define SLAVE_SERVICE_MNOC 12 +#define MASTER_CAMNOC_HF0_UNCOMP 13 +#define MASTER_CAMNOC_HF1_UNCOMP 14 +#define MASTER_CAMNOC_SF_UNCOMP 15 +#define SLAVE_CAMNOC_UNCOMP 16 + +#define MASTER_SNOC_CFG 0 +#define MASTER_A1NOC_SNOC 1 +#define MASTER_A2NOC_SNOC 2 +#define MASTER_GNOC_SNOC 3 +#define MASTER_MEM_NOC_SNOC 4 +#define MASTER_ANOC_PCIE_SNOC 5 +#define MASTER_PIMEM 6 +#define MASTER_GIC 7 +#define SLAVE_APPSS 8 +#define SLAVE_SNOC_CNOC 9 +#define SLAVE_SNOC_MEM_NOC_GC 10 +#define SLAVE_SNOC_MEM_NOC_SF 11 +#define SLAVE_IMEM 12 +#define SLAVE_PCIE_0 13 +#define SLAVE_PCIE_1 14 +#define SLAVE_PIMEM 15 +#define SLAVE_SERVICE_SNOC 16 +#define SLAVE_QDSS_STM 17 +#define SLAVE_TCU 18 #endif From 59a135f6fb669f4f79f43160c7b8c8d6bfb37f75 Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Thu, 7 Nov 2019 11:42:49 +0100 Subject: [PATCH 0924/4444] tee: remove linked list of struct tee_shm Removes list_shm from struct tee_context since the linked list isn't used any longer. Signed-off-by: Jens Wiklander --- drivers/tee/tee_core.c | 1 - drivers/tee/tee_shm.c | 12 +----------- include/linux/tee_drv.h | 3 --- 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 37d22e39fd8d..6aec502c495c 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -44,7 +44,6 @@ static struct tee_context *teedev_open(struct tee_device *teedev) kref_init(&ctx->refcount); ctx->teedev = teedev; - INIT_LIST_HEAD(&ctx->list_shm); rc = teedev->desc->ops->open(ctx); if (rc) goto err; diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index 937ac5aaa6d8..99f1c890ca3d 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -17,8 +17,6 @@ static void tee_shm_release(struct tee_shm *shm) mutex_lock(&teedev->mutex); idr_remove(&teedev->idr, shm->id); - if (shm->ctx) - list_del(&shm->link); mutex_unlock(&teedev->mutex); if (shm->flags & TEE_SHM_POOL) { @@ -168,12 +166,8 @@ static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx, } } - if (ctx) { + if (ctx) teedev_ctx_get(ctx); - mutex_lock(&teedev->mutex); - list_add_tail(&shm->link, &ctx->list_shm); - mutex_unlock(&teedev->mutex); - } return shm; err_rem: @@ -301,10 +295,6 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, } } - mutex_lock(&teedev->mutex); - list_add_tail(&shm->link, &ctx->list_shm); - mutex_unlock(&teedev->mutex); - return shm; err: if (shm) { diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index 7a03f68fb982..cbddb883a7f8 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -49,7 +49,6 @@ struct tee_shm_pool; */ struct tee_context { struct tee_device *teedev; - struct list_head list_shm; void *data; struct kref refcount; bool releasing; @@ -170,7 +169,6 @@ void tee_device_unregister(struct tee_device *teedev); * struct tee_shm - shared memory object * @teedev: device used to allocate the object * @ctx: context using the object, if NULL the context is gone - * @link link element * @paddr: physical address of the shared memory * @kaddr: virtual address of the shared memory * @size: size of shared memory @@ -187,7 +185,6 @@ void tee_device_unregister(struct tee_device *teedev); struct tee_shm { struct tee_device *teedev; struct tee_context *ctx; - struct list_head link; phys_addr_t paddr; void *kaddr; size_t size; From c180f9bbe29a403459dd76422f435382aec6adaa Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Thu, 7 Nov 2019 11:42:52 +0100 Subject: [PATCH 0925/4444] tee: remove unused tee_shm_priv_alloc() tee_shm_priv_alloc() isn't useful in the current state and it's also not not used so remove it. Signed-off-by: Jens Wiklander --- drivers/tee/tee_shm.c | 33 ++------------------------------- include/linux/tee_drv.h | 12 ------------ 2 files changed, 2 insertions(+), 43 deletions(-) diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index 99f1c890ca3d..b666854c2491 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -89,20 +89,14 @@ static const struct dma_buf_ops tee_shm_dma_buf_ops = { .mmap = tee_shm_op_mmap, }; -static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx, - struct tee_device *teedev, - size_t size, u32 flags) +struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags) { + struct tee_device *teedev = ctx->teedev; struct tee_shm_pool_mgr *poolm = NULL; struct tee_shm *shm; void *ret; int rc; - if (ctx && ctx->teedev != teedev) { - dev_err(teedev->dev.parent, "ctx and teedev mismatch\n"); - return ERR_PTR(-EINVAL); - } - if (!(flags & TEE_SHM_MAPPED)) { dev_err(teedev->dev.parent, "only mapped allocations supported\n"); @@ -182,31 +176,8 @@ err_dev_put: tee_device_put(teedev); return ret; } - -/** - * tee_shm_alloc() - Allocate shared memory - * @ctx: Context that allocates the shared memory - * @size: Requested size of shared memory - * @flags: Flags setting properties for the requested shared memory. - * - * Memory allocated as global shared memory is automatically freed when the - * TEE file pointer is closed. The @flags field uses the bits defined by - * TEE_SHM_* in . TEE_SHM_MAPPED must currently always be - * set. If TEE_SHM_DMA_BUF global shared memory will be allocated and - * associated with a dma-buf handle, else driver private memory. - */ -struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags) -{ - return __tee_shm_alloc(ctx, ctx->teedev, size, flags); -} EXPORT_SYMBOL_GPL(tee_shm_alloc); -struct tee_shm *tee_shm_priv_alloc(struct tee_device *teedev, size_t size) -{ - return __tee_shm_alloc(NULL, teedev, size, TEE_SHM_MAPPED); -} -EXPORT_SYMBOL_GPL(tee_shm_priv_alloc); - struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, size_t length, u32 flags) { diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index cbddb883a7f8..42687f6c546d 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -315,18 +315,6 @@ void *tee_get_drvdata(struct tee_device *teedev); */ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags); -/** - * tee_shm_priv_alloc() - Allocate shared memory privately - * @dev: Device that allocates the shared memory - * @size: Requested size of shared memory - * - * Allocates shared memory buffer that is not associated with any client - * context. Such buffers are owned by TEE driver and used for internal calls. - * - * @returns a pointer to 'struct tee_shm' - */ -struct tee_shm *tee_shm_priv_alloc(struct tee_device *teedev, size_t size); - /** * tee_shm_register() - Register shared memory buffer * @ctx: Context that registers the shared memory From f1bbacedb0af640a93e47799203e556be2825da3 Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Thu, 7 Nov 2019 11:42:56 +0100 Subject: [PATCH 0926/4444] tee: don't assign shm id for private shms Private shared memory object must not be referenced from user space. To guarantee that, don't assign an id to shared memory objects which are driver private. Signed-off-by: Jens Wiklander --- drivers/tee/tee_private.h | 3 ++- drivers/tee/tee_shm.c | 31 ++++++++++++++++++------------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/tee/tee_private.h b/drivers/tee/tee_private.h index f797171f0434..e55204df31ce 100644 --- a/drivers/tee/tee_private.h +++ b/drivers/tee/tee_private.h @@ -37,7 +37,8 @@ struct tee_shm_pool { * @num_users: number of active users of this device * @c_no_user: completion used when unregistering the device * @mutex: mutex protecting @num_users and @idr - * @idr: register of shared memory object allocated on this device + * @idr: register of user space shared memory objects allocated or + * registered on this device * @pool: shared memory pool */ struct tee_device { diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index b666854c2491..02210f179ae3 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -15,9 +15,11 @@ static void tee_shm_release(struct tee_shm *shm) { struct tee_device *teedev = shm->teedev; - mutex_lock(&teedev->mutex); - idr_remove(&teedev->idr, shm->id); - mutex_unlock(&teedev->mutex); + if (shm->flags & TEE_SHM_DMA_BUF) { + mutex_lock(&teedev->mutex); + idr_remove(&teedev->idr, shm->id); + mutex_unlock(&teedev->mutex); + } if (shm->flags & TEE_SHM_POOL) { struct tee_shm_pool_mgr *poolm; @@ -137,17 +139,18 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags) goto err_kfree; } - mutex_lock(&teedev->mutex); - shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL); - mutex_unlock(&teedev->mutex); - if (shm->id < 0) { - ret = ERR_PTR(shm->id); - goto err_pool_free; - } if (flags & TEE_SHM_DMA_BUF) { DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + mutex_lock(&teedev->mutex); + shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL); + mutex_unlock(&teedev->mutex); + if (shm->id < 0) { + ret = ERR_PTR(shm->id); + goto err_pool_free; + } + exp_info.ops = &tee_shm_dma_buf_ops; exp_info.size = shm->size; exp_info.flags = O_RDWR; @@ -165,9 +168,11 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags) return shm; err_rem: - mutex_lock(&teedev->mutex); - idr_remove(&teedev->idr, shm->id); - mutex_unlock(&teedev->mutex); + if (flags & TEE_SHM_DMA_BUF) { + mutex_lock(&teedev->mutex); + idr_remove(&teedev->idr, shm->id); + mutex_unlock(&teedev->mutex); + } err_pool_free: poolm->ops->free(poolm, shm); err_kfree: From 5271b2011e448f1be7433554e4684e91951476fa Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Thu, 7 Nov 2019 11:42:59 +0100 Subject: [PATCH 0927/4444] tee: remove redundant teedev in struct tee_shm The ctx element in struct tee_shm is always valid. So remove the now redundant teedev element. Signed-off-by: Jens Wiklander --- drivers/tee/tee_shm.c | 7 ++----- include/linux/tee_drv.h | 4 +--- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index 02210f179ae3..b01d2b7eea71 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -13,7 +13,7 @@ static void tee_shm_release(struct tee_shm *shm) { - struct tee_device *teedev = shm->teedev; + struct tee_device *teedev = shm->ctx->teedev; if (shm->flags & TEE_SHM_DMA_BUF) { mutex_lock(&teedev->mutex); @@ -44,8 +44,7 @@ static void tee_shm_release(struct tee_shm *shm) kfree(shm->pages); } - if (shm->ctx) - teedev_ctx_put(shm->ctx); + teedev_ctx_put(shm->ctx); kfree(shm); @@ -126,7 +125,6 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags) } shm->flags = flags | TEE_SHM_POOL; - shm->teedev = teedev; shm->ctx = ctx; if (flags & TEE_SHM_DMA_BUF) poolm = teedev->pool->dma_buf_mgr; @@ -215,7 +213,6 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, } shm->flags = flags | TEE_SHM_REGISTER; - shm->teedev = teedev; shm->ctx = ctx; shm->id = -1; addr = untagged_addr(addr); diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index 42687f6c546d..1412e9cc79ce 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -167,8 +167,7 @@ void tee_device_unregister(struct tee_device *teedev); /** * struct tee_shm - shared memory object - * @teedev: device used to allocate the object - * @ctx: context using the object, if NULL the context is gone + * @ctx: context using the object * @paddr: physical address of the shared memory * @kaddr: virtual address of the shared memory * @size: size of shared memory @@ -183,7 +182,6 @@ void tee_device_unregister(struct tee_device *teedev); * subsystem and from drivers that implements their own shm pool manager. */ struct tee_shm { - struct tee_device *teedev; struct tee_context *ctx; phys_addr_t paddr; void *kaddr; From 758ecf13a41a9dc4f019c1381566132ef46c08ee Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Thu, 7 Nov 2019 11:43:02 +0100 Subject: [PATCH 0928/4444] tee: tee_shm_op_mmap(): use TEE_SHM_USER_MAPPED tee_shm_op_mmap() uses the TEE_SHM_USER_MAPPED flag instead of the TEE_SHM_REGISTER flag to tell if a shared memory object is originating from registered user space memory. Signed-off-by: Jens Wiklander --- drivers/tee/tee_shm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index b01d2b7eea71..bd679b72bd05 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -76,7 +76,7 @@ static int tee_shm_op_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) size_t size = vma->vm_end - vma->vm_start; /* Refuse sharing shared memory provided by application */ - if (shm->flags & TEE_SHM_REGISTER) + if (shm->flags & TEE_SHM_USER_MAPPED) return -EINVAL; return remap_pfn_range(vma, vma->vm_start, shm->paddr >> PAGE_SHIFT, From 2353810dac9ab72d3f835e3fb015c6819a0ef6c2 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 28 Feb 2020 14:34:29 +0800 Subject: [PATCH 0929/4444] pinctrl: da9062: Fix error gpiolib.h path gcc 7.4.0 build fails: drivers/pinctrl/pinctrl-da9062.c:28:10: fatal error: ../gpio/gpiolib.h: No such file or directory #include <../gpio/gpiolib.h> ^~~~~~~~~~~~~~~~~~~ Fix this wrong include path. Fixes: 56cc3af4e8c8 ("pinctrl: da9062: add driver support") Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20200228063429.47528-1-yuehaibing@huawei.com Reviewed-by: Marco Felsch Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-da9062.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-da9062.c b/drivers/pinctrl/pinctrl-da9062.c index f704ee0b2fd9..1c08579f0198 100644 --- a/drivers/pinctrl/pinctrl-da9062.c +++ b/drivers/pinctrl/pinctrl-da9062.c @@ -25,7 +25,7 @@ * We need this get the gpio_desc from a tuple to decide if * the gpio is active low without a vendor specific dt-binding. */ -#include <../gpio/gpiolib.h> +#include "../gpio/gpiolib.h" #define DA9062_TYPE(offset) (4 * (offset % 2)) #define DA9062_PIN_SHIFT(offset) (4 * (offset % 2)) From e26060e1d47a535e0bc41a00708b79bc52dc9fb3 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 12 Feb 2020 18:14:01 -0600 Subject: [PATCH 0930/4444] iommu/qcom: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Joerg Roedel --- drivers/iommu/qcom_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index 4328da0b0a9f..f6117726da99 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -48,7 +48,7 @@ struct qcom_iommu_dev { void __iomem *local_base; u32 sec_id; u8 num_ctxs; - struct qcom_iommu_ctx *ctxs[0]; /* indexed by asid-1 */ + struct qcom_iommu_ctx *ctxs[]; /* indexed by asid-1 */ }; struct qcom_iommu_ctx { From c20f36534666e37858a14e591114d93cc1be0d34 Mon Sep 17 00:00:00 2001 From: Adrian Huang Date: Fri, 14 Feb 2020 18:44:51 +0800 Subject: [PATCH 0931/4444] iommu/amd: Fix the configuration of GCR3 table root pointer The SPA of the GCR3 table root pointer[51:31] masks 20 bits. However, this requires 21 bits (Please see the AMD IOMMU specification). This leads to the potential failure when the bit 51 of SPA of the GCR3 table root pointer is 1'. Signed-off-by: Adrian Huang Fixes: 52815b75682e2 ("iommu/amd: Add support for IOMMUv2 domain mode") Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index f8d01d6b00da..ca8c4522045b 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h @@ -348,7 +348,7 @@ #define DTE_GCR3_VAL_A(x) (((x) >> 12) & 0x00007ULL) #define DTE_GCR3_VAL_B(x) (((x) >> 15) & 0x0ffffULL) -#define DTE_GCR3_VAL_C(x) (((x) >> 31) & 0xfffffULL) +#define DTE_GCR3_VAL_C(x) (((x) >> 31) & 0x1fffffULL) #define DTE_GCR3_INDEX_A 0 #define DTE_GCR3_INDEX_B 1 From fa4afd78ea12cf31113f8b146b696c500d6a9dc3 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Brucker Date: Fri, 14 Feb 2020 17:38:27 +0100 Subject: [PATCH 0932/4444] iommu/virtio: Build virtio-iommu as module Now that the infrastructure changes are in place, enable virtio-iommu to be built as a module. Remove the redundant pci_request_acs() call, since it's not exported but is already invoked during DMA setup. Signed-off-by: Jean-Philippe Brucker Signed-off-by: Joerg Roedel --- drivers/iommu/Kconfig | 4 ++-- drivers/iommu/virtio-iommu.c | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index d2fade984999..c5df570ef84a 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -506,8 +506,8 @@ config HYPERV_IOMMU guests to run with x2APIC mode enabled. config VIRTIO_IOMMU - bool "Virtio IOMMU driver" - depends on VIRTIO=y + tristate "Virtio IOMMU driver" + depends on VIRTIO depends on ARM64 select IOMMU_API select INTERVAL_TREE diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c index cce329d71fba..93ff58632452 100644 --- a/drivers/iommu/virtio-iommu.c +++ b/drivers/iommu/virtio-iommu.c @@ -1082,7 +1082,6 @@ static int viommu_probe(struct virtio_device *vdev) #ifdef CONFIG_PCI if (pci_bus_type.iommu_ops != &viommu_ops) { - pci_request_acs(); ret = bus_set_iommu(&pci_bus_type, &viommu_ops); if (ret) goto err_unregister; From 098accf2da940189f4d62d3514d17f8bb05dc6e1 Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Thu, 13 Feb 2020 14:00:21 +0000 Subject: [PATCH 0933/4444] iommu: Use C99 flexible array in fwspec Although the 1-element array was a typical pre-C99 way to implement variable-length structures, and indeed is a fundamental construct in the APIs of certain other popular platforms, there's no good reason for it here (and in particular the sizeof() trick is far too "clever" for its own good). We can just as easily implement iommu_fwspec's preallocation behaviour using a standard flexible array member, so let's make it look the way most readers would expect. Signed-off-by: Robin Murphy Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 15 ++++++++------- include/linux/iommu.h | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 3e3528436e0b..660eea8d1d2f 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -2405,7 +2405,8 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode, if (fwspec) return ops == fwspec->ops ? 0 : -EINVAL; - fwspec = kzalloc(sizeof(*fwspec), GFP_KERNEL); + /* Preallocate for the overwhelmingly common case of 1 ID */ + fwspec = kzalloc(struct_size(fwspec, ids, 1), GFP_KERNEL); if (!fwspec) return -ENOMEM; @@ -2432,15 +2433,15 @@ EXPORT_SYMBOL_GPL(iommu_fwspec_free); int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids) { struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); - size_t size; - int i; + int i, new_num; if (!fwspec) return -EINVAL; - size = offsetof(struct iommu_fwspec, ids[fwspec->num_ids + num_ids]); - if (size > sizeof(*fwspec)) { - fwspec = krealloc(fwspec, size, GFP_KERNEL); + new_num = fwspec->num_ids + num_ids; + if (new_num > 1) { + fwspec = krealloc(fwspec, struct_size(fwspec, ids, new_num), + GFP_KERNEL); if (!fwspec) return -ENOMEM; @@ -2450,7 +2451,7 @@ int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids) for (i = 0; i < num_ids; i++) fwspec->ids[fwspec->num_ids + i] = ids[i]; - fwspec->num_ids += num_ids; + fwspec->num_ids = new_num; return 0; } EXPORT_SYMBOL_GPL(iommu_fwspec_add_ids); diff --git a/include/linux/iommu.h b/include/linux/iommu.h index d1b5f4d98569..4d1ba76c9a64 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -592,7 +592,7 @@ struct iommu_fwspec { u32 flags; u32 num_pasid_bits; unsigned int num_ids; - u32 ids[1]; + u32 ids[]; }; /* ATS is supported */ From 4a88b7dec331cf1ac661e38d610cd0ff0c073607 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Thu, 27 Feb 2020 10:06:37 +0800 Subject: [PATCH 0934/4444] ASoC: rt1015: modify some structure to be static. Modify rt1015_aif_dai_ops and rt1015_dai[] to be static. Signed-off-by: Jack Yu Link: https://lore.kernel.org/r/20200227020637.15135-1-jack.yu@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index d300b417dd50..c118d030bd2d 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -841,12 +841,12 @@ static void rt1015_remove(struct snd_soc_component *component) #define RT1015_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) -struct snd_soc_dai_ops rt1015_aif_dai_ops = { +static struct snd_soc_dai_ops rt1015_aif_dai_ops = { .hw_params = rt1015_hw_params, .set_fmt = rt1015_set_dai_fmt, }; -struct snd_soc_dai_driver rt1015_dai[] = { +static struct snd_soc_dai_driver rt1015_dai[] = { { .name = "rt1015-aif", .id = 0, From a3c2e894cdafbfa376a28a89a60df415b6ab6ee6 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 28 Feb 2020 15:56:09 +0800 Subject: [PATCH 0935/4444] ASoC: rt5682: Make rt5682_clock_config static Fix sparse warning: sound/soc/codecs/rt5682-sdw.c:163:5: warning: symbol 'rt5682_clock_config' was not declared. Should it be static? Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20200228075609.38236-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682-sdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index fc31d04b5203..1d6963dd6403 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -160,7 +160,7 @@ static int rt5682_read_prop(struct sdw_slave *slave) #define RT5682_CLK_FREQ_2400000HZ 2400000 #define RT5682_CLK_FREQ_12288000HZ 12288000 -int rt5682_clock_config(struct device *dev) +static int rt5682_clock_config(struct device *dev) { struct rt5682_priv *rt5682 = dev_get_drvdata(dev); unsigned int clk_freq, value; From 1a1b3743487317514f7d5d66dd9d6c9233321eba Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 28 Feb 2020 11:11:20 +0100 Subject: [PATCH 0936/4444] ASoC: samsung: Silence warnings during deferred probe Don't confuse user with meaningless warning about the failure in getting resources and registering card in case of deferred probe. Signed-off-by: Marek Szyprowski Reviewed-by: Sylwester Nawrocki Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200228101120.28819-1-m.szyprowski@samsung.com Signed-off-by: Mark Brown --- sound/soc/samsung/arndale.c | 4 +++- sound/soc/samsung/littlemill.c | 2 +- sound/soc/samsung/lowland.c | 2 +- sound/soc/samsung/odroid.c | 4 +++- sound/soc/samsung/smdk_wm8994.c | 2 +- sound/soc/samsung/smdk_wm8994pcm.c | 2 +- sound/soc/samsung/snow.c | 4 +++- sound/soc/samsung/speyside.c | 2 +- sound/soc/samsung/tm2_wm5110.c | 3 ++- sound/soc/samsung/tobermory.c | 2 +- 10 files changed, 17 insertions(+), 10 deletions(-) diff --git a/sound/soc/samsung/arndale.c b/sound/soc/samsung/arndale.c index d64602950cbd..6e6d67d6e0ab 100644 --- a/sound/soc/samsung/arndale.c +++ b/sound/soc/samsung/arndale.c @@ -174,7 +174,9 @@ static int arndale_audio_probe(struct platform_device *pdev) ret = devm_snd_soc_register_card(card->dev, card); if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "snd_soc_register_card() failed: %d\n", ret); goto err_put_of_nodes; } return 0; diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c index 59904f44118b..2f2f83a8c23a 100644 --- a/sound/soc/samsung/littlemill.c +++ b/sound/soc/samsung/littlemill.c @@ -325,7 +325,7 @@ static int littlemill_probe(struct platform_device *pdev) card->dev = &pdev->dev; ret = devm_snd_soc_register_card(&pdev->dev, card); - if (ret) + if (ret && ret != -EPROBE_DEFER) dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c index 098eefc764db..fcc7897ee7d0 100644 --- a/sound/soc/samsung/lowland.c +++ b/sound/soc/samsung/lowland.c @@ -183,7 +183,7 @@ static int lowland_probe(struct platform_device *pdev) card->dev = &pdev->dev; ret = devm_snd_soc_register_card(&pdev->dev, card); - if (ret) + if (ret && ret != -EPROBE_DEFER) dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index f0f5fa9c27d3..30c7e1bc2a30 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -311,7 +311,9 @@ static int odroid_audio_probe(struct platform_device *pdev) ret = devm_snd_soc_register_card(dev, card); if (ret < 0) { - dev_err(dev, "snd_soc_register_card() failed: %d\n", ret); + if (ret != -EPROBE_DEFER) + dev_err(dev, "snd_soc_register_card() failed: %d\n", + ret); goto err_put_clk_i2s; } diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index 28f8be000aa1..8fa5f6b387ad 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c @@ -178,7 +178,7 @@ static int smdk_audio_probe(struct platform_device *pdev) ret = devm_snd_soc_register_card(&pdev->dev, card); - if (ret) + if (ret && ret != -EPROBE_DEFER) dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret); return ret; diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c index 2e3dc7320c62..6e44f7927852 100644 --- a/sound/soc/samsung/smdk_wm8994pcm.c +++ b/sound/soc/samsung/smdk_wm8994pcm.c @@ -118,7 +118,7 @@ static int snd_smdk_probe(struct platform_device *pdev) smdk_pcm.dev = &pdev->dev; ret = devm_snd_soc_register_card(&pdev->dev, &smdk_pcm); - if (ret) + if (ret && ret != -EPROBE_DEFER) dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret); return ret; diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index f075aae9561a..bebcf0a4d608 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c @@ -216,7 +216,9 @@ static int snow_probe(struct platform_device *pdev) ret = devm_snd_soc_register_card(dev, card); if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "snd_soc_register_card failed (%d)\n", ret); return ret; } diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index ea0d1ec67f01..8f175f204eb7 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c @@ -330,7 +330,7 @@ static int speyside_probe(struct platform_device *pdev) card->dev = &pdev->dev; ret = devm_snd_soc_register_card(&pdev->dev, card); - if (ret) + if (ret && ret != -EPROBE_DEFER) dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c index 10ff14b856f2..043a287728b3 100644 --- a/sound/soc/samsung/tm2_wm5110.c +++ b/sound/soc/samsung/tm2_wm5110.c @@ -611,7 +611,8 @@ static int tm2_probe(struct platform_device *pdev) ret = devm_snd_soc_register_card(dev, card); if (ret < 0) { - dev_err(dev, "Failed to register card: %d\n", ret); + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to register card: %d\n", ret); goto dai_node_put; } diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c index fdce28cc26c4..1aa3fdb4b152 100644 --- a/sound/soc/samsung/tobermory.c +++ b/sound/soc/samsung/tobermory.c @@ -229,7 +229,7 @@ static int tobermory_probe(struct platform_device *pdev) card->dev = &pdev->dev; ret = devm_snd_soc_register_card(&pdev->dev, card); - if (ret) + if (ret && ret != -EPROBE_DEFER) dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); From ac5bf39e39683c6f06c2e5b4baf27c7208f0c86d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 27 Feb 2020 10:47:02 +0900 Subject: [PATCH 0937/4444] ASoC: soc-dapm: don't use rtd->cpu_dai on for_each_rtd_cpu_dai() soc_dapm_stream_event() is using for_each_rtd_cpu_dais(). It should use "cpu_dai", instead of "rtd->cpu_dai". This patch fixup it. Fixes: commit de6214a33633d ("ASoC: Add multiple CPU DAI support in DAPM") Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87pne07qeh.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 6ce024d52170..9a809f2caa10 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -4438,7 +4438,7 @@ static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, int i; for_each_rtd_cpu_dai(rtd, i, cpu_dai) - soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event); + soc_dapm_dai_stream_event(cpu_dai, stream, event); for_each_rtd_codec_dai(rtd, i, codec_dai) soc_dapm_dai_stream_event(codec_dai, stream, event); From a57ec83a7104eab6f08215702067fbcbef90c0a0 Mon Sep 17 00:00:00 2001 From: tangbin Date: Thu, 27 Feb 2020 23:07:01 +0800 Subject: [PATCH 0938/4444] ASoC: zte: zx-spdif: remove redundant dev_err message devm_ioremap_resource has already contains error message, so remove the redundant dev_err message Signed-off-by: tangbin Link: https://lore.kernel.org/r/20200227150701.15652-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/zte/zx-spdif.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/zte/zx-spdif.c b/sound/soc/zte/zx-spdif.c index 60382ec23832..a3a07c0730e6 100644 --- a/sound/soc/zte/zx-spdif.c +++ b/sound/soc/zte/zx-spdif.c @@ -322,7 +322,6 @@ static int zx_spdif_probe(struct platform_device *pdev) zx_spdif->mapbase = res->start; zx_spdif->reg_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(zx_spdif->reg_base)) { - dev_err(&pdev->dev, "ioremap failed!\n"); return PTR_ERR(zx_spdif->reg_base); } From c3944ec8c6df256ab480b56cb776f36df44b2ba5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Feb 2020 14:42:48 +0100 Subject: [PATCH 0939/4444] clk: Fix phase init check Commit 2760878662a2 ("clk: Bail out when calculating phase fails during clk registration") introduced a check on error values at the time the clock is registered to bail out when such an error occurs. However, it doesn't check whether the returned value is positive which will happen if the driver returns a non-zero phase. Since a phase is usually a non-zero positive number this ends up returning something that isn't 0 to the caller of __clk_core_init(), making most clks fail to register if they implement a phase clk op and return anything besides 0 for the phase. Fix this by returning the error if phase is less than zero or just return zero if the phase is a positive number. Fixes: 2760878662a2 ("clk: Bail out when calculating phase fails during clk registration") Signed-off-by: Maxime Ripard Link: https://lkml.kernel.org/r/20200225134248.919889-1-maxime@cerno.tech Reported-by: "kernelci.org bot" [sboyd@kernel.org: Reword commit text to provide clarity] Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index ed1797857bae..4d6fd7de05ae 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3344,6 +3344,7 @@ static int __clk_core_init(struct clk_core *core) int ret; struct clk_core *parent; unsigned long rate; + int phase; if (!core) return -EINVAL; @@ -3457,8 +3458,9 @@ static int __clk_core_init(struct clk_core *core) * Since a phase is by definition relative to its parent, just * query the current clock phase, or just assume it's in phase. */ - ret = clk_core_get_phase(core); - if (ret < 0) { + phase = clk_core_get_phase(core); + if (phase < 0) { + ret = phase; pr_warn("%s: Failed to get phase for clk '%s'\n", __func__, core->name); goto out; From 776ab6a3c2460404530345c270b90c51480c9473 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 24 Feb 2020 14:51:29 +0100 Subject: [PATCH 0940/4444] dt-bindings: reset: rcar-rst: Convert to json-schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert the Renesas R-Car Reset Controller Device Tree binding documentation to json-schema. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Signed-off-by: Rob Herring --- .../devicetree/bindings/reset/renesas,rst.txt | 48 -------------- .../bindings/reset/renesas,rst.yaml | 63 +++++++++++++++++++ 2 files changed, 63 insertions(+), 48 deletions(-) delete mode 100644 Documentation/devicetree/bindings/reset/renesas,rst.txt create mode 100644 Documentation/devicetree/bindings/reset/renesas,rst.yaml diff --git a/Documentation/devicetree/bindings/reset/renesas,rst.txt b/Documentation/devicetree/bindings/reset/renesas,rst.txt deleted file mode 100644 index de7f06ccd003..000000000000 --- a/Documentation/devicetree/bindings/reset/renesas,rst.txt +++ /dev/null @@ -1,48 +0,0 @@ -DT bindings for the Renesas R-Car and RZ/G Reset Controllers - -The R-Car and RZ/G Reset Controllers provide reset control, and implement the -following functions: - - Latching of the levels on mode pins when PRESET# is negated, - - Mode monitoring register, - - Reset control of peripheral devices (on R-Car Gen1), - - Watchdog timer (on R-Car Gen1), - - Register-based reset control and boot address registers for the various CPU - cores (on R-Car Gen2 and Gen3, and on RZ/G). - - -Required properties: - - compatible: Should be - - "renesas,-reset-wdt" for R-Car Gen1, - - "renesas,-rst" for R-Car Gen2 and Gen3, and RZ/G - Examples with soctypes are: - - "renesas,r8a7743-rst" (RZ/G1M) - - "renesas,r8a7744-rst" (RZ/G1N) - - "renesas,r8a7745-rst" (RZ/G1E) - - "renesas,r8a77470-rst" (RZ/G1C) - - "renesas,r8a774a1-rst" (RZ/G2M) - - "renesas,r8a774b1-rst" (RZ/G2N) - - "renesas,r8a774c0-rst" (RZ/G2E) - - "renesas,r8a7778-reset-wdt" (R-Car M1A) - - "renesas,r8a7779-reset-wdt" (R-Car H1) - - "renesas,r8a7790-rst" (R-Car H2) - - "renesas,r8a7791-rst" (R-Car M2-W) - - "renesas,r8a7792-rst" (R-Car V2H - - "renesas,r8a7793-rst" (R-Car M2-N) - - "renesas,r8a7794-rst" (R-Car E2) - - "renesas,r8a7795-rst" (R-Car H3) - - "renesas,r8a7796-rst" (R-Car M3-W) - - "renesas,r8a77961-rst" (R-Car M3-W+) - - "renesas,r8a77965-rst" (R-Car M3-N) - - "renesas,r8a77970-rst" (R-Car V3M) - - "renesas,r8a77980-rst" (R-Car V3H) - - "renesas,r8a77990-rst" (R-Car E3) - - "renesas,r8a77995-rst" (R-Car D3) - - reg: Address start and address range for the device. - - -Example: - - rst: reset-controller@e6160000 { - compatible = "renesas,r8a7795-rst"; - reg = <0 0xe6160000 0 0x0200>; - }; diff --git a/Documentation/devicetree/bindings/reset/renesas,rst.yaml b/Documentation/devicetree/bindings/reset/renesas,rst.yaml new file mode 100644 index 000000000000..b5de1d196a13 --- /dev/null +++ b/Documentation/devicetree/bindings/reset/renesas,rst.yaml @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/reset/renesas,rst.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Renesas R-Car and RZ/G Reset Controller + +maintainers: + - Geert Uytterhoeven + - Magnus Damm + +description: | + The R-Car and RZ/G Reset Controllers provide reset control, and implement the + following functions: + - Latching of the levels on mode pins when PRESET# is negated, + - Mode monitoring register, + - Reset control of peripheral devices (on R-Car Gen1), + - Watchdog timer (on R-Car Gen1), + - Register-based reset control and boot address registers for the various + CPU cores (on R-Car Gen2 and Gen3, and on RZ/G). + +properties: + compatible: + enum: + - renesas,r8a7743-rst # RZ/G1M + - renesas,r8a7744-rst # RZ/G1N + - renesas,r8a7745-rst # RZ/G1E + - renesas,r8a77470-rst # RZ/G1C + - renesas,r8a774a1-rst # RZ/G2M + - renesas,r8a774b1-rst # RZ/G2N + - renesas,r8a774c0-rst # RZ/G2E + - renesas,r8a7778-reset-wdt # R-Car M1A + - renesas,r8a7779-reset-wdt # R-Car H1 + - renesas,r8a7790-rst # R-Car H2 + - renesas,r8a7791-rst # R-Car M2-W + - renesas,r8a7792-rst # R-Car V2H + - renesas,r8a7793-rst # R-Car M2-N + - renesas,r8a7794-rst # R-Car E2 + - renesas,r8a7795-rst # R-Car H3 + - renesas,r8a7796-rst # R-Car M3-W + - renesas,r8a77961-rst # R-Car M3-W+ + - renesas,r8a77965-rst # R-Car M3-N + - renesas,r8a77970-rst # R-Car V3M + - renesas,r8a77980-rst # R-Car V3H + - renesas,r8a77990-rst # R-Car E3 + - renesas,r8a77995-rst # R-Car D3 + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + rst: reset-controller@e6160000 { + compatible = "renesas,r8a7795-rst"; + reg = <0xe6160000 0x0200>; + }; From 8db9684beb500a4a1ec50aeadfe30f2e7e44fa24 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 24 Feb 2020 14:52:34 +0100 Subject: [PATCH 0941/4444] dt-bindings: power: rcar-sysc: Convert to json-schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert the Renesas R-Car System Controller Device Tree binding documentation to json-schema. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Signed-off-by: Rob Herring --- .../bindings/power/renesas,rcar-sysc.txt | 62 ---------------- .../bindings/power/renesas,rcar-sysc.yaml | 73 +++++++++++++++++++ 2 files changed, 73 insertions(+), 62 deletions(-) delete mode 100644 Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt create mode 100644 Documentation/devicetree/bindings/power/renesas,rcar-sysc.yaml diff --git a/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt b/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt deleted file mode 100644 index acb41fade926..000000000000 --- a/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt +++ /dev/null @@ -1,62 +0,0 @@ -DT bindings for the Renesas R-Car (RZ/G) System Controller - -== System Controller Node == - -The R-Car (RZ/G) System Controller provides power management for the CPU cores -and various coprocessors. - -Required properties: - - compatible: Must contain exactly one of the following: - - "renesas,r8a7743-sysc" (RZ/G1M) - - "renesas,r8a7744-sysc" (RZ/G1N) - - "renesas,r8a7745-sysc" (RZ/G1E) - - "renesas,r8a77470-sysc" (RZ/G1C) - - "renesas,r8a774a1-sysc" (RZ/G2M) - - "renesas,r8a774b1-sysc" (RZ/G2N) - - "renesas,r8a774c0-sysc" (RZ/G2E) - - "renesas,r8a7779-sysc" (R-Car H1) - - "renesas,r8a7790-sysc" (R-Car H2) - - "renesas,r8a7791-sysc" (R-Car M2-W) - - "renesas,r8a7792-sysc" (R-Car V2H) - - "renesas,r8a7793-sysc" (R-Car M2-N) - - "renesas,r8a7794-sysc" (R-Car E2) - - "renesas,r8a7795-sysc" (R-Car H3) - - "renesas,r8a7796-sysc" (R-Car M3-W) - - "renesas,r8a77961-sysc" (R-Car M3-W+) - - "renesas,r8a77965-sysc" (R-Car M3-N) - - "renesas,r8a77970-sysc" (R-Car V3M) - - "renesas,r8a77980-sysc" (R-Car V3H) - - "renesas,r8a77990-sysc" (R-Car E3) - - "renesas,r8a77995-sysc" (R-Car D3) - - reg: Address start and address range for the device. - - #power-domain-cells: Must be 1. - - -Example: - - sysc: system-controller@e6180000 { - compatible = "renesas,r8a7791-sysc"; - reg = <0 0xe6180000 0 0x0200>; - #power-domain-cells = <1>; - }; - - -== PM Domain Consumers == - -Devices residing in a power area must refer to that power area, as documented -by the generic PM domain bindings in -Documentation/devicetree/bindings/power/power_domain.txt. - -Required properties: - - power-domains: A phandle and symbolic PM domain specifier, as defined in - . - - -Example: - - L2_CA15: cache-controller@0 { - compatible = "cache"; - power-domains = <&sysc R8A7791_PD_CA15_SCU>; - cache-unified; - cache-level = <2>; - }; diff --git a/Documentation/devicetree/bindings/power/renesas,rcar-sysc.yaml b/Documentation/devicetree/bindings/power/renesas,rcar-sysc.yaml new file mode 100644 index 000000000000..e59331e1d944 --- /dev/null +++ b/Documentation/devicetree/bindings/power/renesas,rcar-sysc.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/power/renesas,rcar-sysc.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Renesas R-Car and RZ/G System Controller + +maintainers: + - Geert Uytterhoeven + - Magnus Damm + +description: + The R-Car (RZ/G) System Controller provides power management for the CPU + cores and various coprocessors. + +properties: + compatible: + enum: + - renesas,r8a7743-sysc # RZ/G1M + - renesas,r8a7744-sysc # RZ/G1N + - renesas,r8a7745-sysc # RZ/G1E + - renesas,r8a77470-sysc # RZ/G1C + - renesas,r8a774a1-sysc # RZ/G2M + - renesas,r8a774b1-sysc # RZ/G2N + - renesas,r8a774c0-sysc # RZ/G2E + - renesas,r8a7779-sysc # R-Car H1 + - renesas,r8a7790-sysc # R-Car H2 + - renesas,r8a7791-sysc # R-Car M2-W + - renesas,r8a7792-sysc # R-Car V2H + - renesas,r8a7793-sysc # R-Car M2-N + - renesas,r8a7794-sysc # R-Car E2 + - renesas,r8a7795-sysc # R-Car H3 + - renesas,r8a77961-sysc # R-Car M3-W+ + - renesas,r8a77965-sysc # R-Car M3-N + - renesas,r8a7796-sysc # R-Car M3-W + - renesas,r8a77970-sysc # R-Car V3M + - renesas,r8a77980-sysc # R-Car V3H + - renesas,r8a77990-sysc # R-Car E3 + - renesas,r8a77995-sysc # R-Car D3 + + reg: + maxItems: 1 + + '#power-domain-cells': + const: 1 + +required: + - compatible + - reg + - '#power-domain-cells' + +additionalProperties: false + +examples: + - | + // System Controller node + sysc: system-controller@e6180000 { + compatible = "renesas,r8a7791-sysc"; + reg = <0xe6180000 0x0200>; + #power-domain-cells = <1>; + }; + + - | + // Power Domain consumers + #include + + cache-controller-0 { + compatible = "cache"; + power-domains = <&sysc R8A7791_PD_CA15_SCU>; + cache-unified; + cache-level = <2>; + }; From c1507cf227824827135bc7df5522ce0b3c50be73 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 24 Feb 2020 14:52:51 +0100 Subject: [PATCH 0942/4444] dt-bindings: power: apmu: Convert to json-schema Convert the Renesas Advanced Power Management Unit Device Tree binding documentation to json-schema. Signed-off-by: Geert Uytterhoeven Signed-off-by: Rob Herring --- .../bindings/power/renesas,apmu.txt | 35 ------------ .../bindings/power/renesas,apmu.yaml | 55 +++++++++++++++++++ 2 files changed, 55 insertions(+), 35 deletions(-) delete mode 100644 Documentation/devicetree/bindings/power/renesas,apmu.txt create mode 100644 Documentation/devicetree/bindings/power/renesas,apmu.yaml diff --git a/Documentation/devicetree/bindings/power/renesas,apmu.txt b/Documentation/devicetree/bindings/power/renesas,apmu.txt deleted file mode 100644 index 5f24586c8cf3..000000000000 --- a/Documentation/devicetree/bindings/power/renesas,apmu.txt +++ /dev/null @@ -1,35 +0,0 @@ -DT bindings for the Renesas Advanced Power Management Unit - -Renesas R-Car and RZ/G1 SoCs utilize one or more APMU hardware units -for CPU core power domain control including SMP boot and CPU Hotplug. - -Required properties: - -- compatible: Should be "renesas,-apmu", "renesas,apmu" as fallback. - Examples with soctypes are: - - "renesas,r8a7743-apmu" (RZ/G1M) - - "renesas,r8a7744-apmu" (RZ/G1N) - - "renesas,r8a7745-apmu" (RZ/G1E) - - "renesas,r8a77470-apmu" (RZ/G1C) - - "renesas,r8a7790-apmu" (R-Car H2) - - "renesas,r8a7791-apmu" (R-Car M2-W) - - "renesas,r8a7792-apmu" (R-Car V2H) - - "renesas,r8a7793-apmu" (R-Car M2-N) - - "renesas,r8a7794-apmu" (R-Car E2) - -- reg: Base address and length of the I/O registers used by the APMU. - -- cpus: This node contains a list of CPU cores, which should match the order - of CPU cores used by the WUPCR and PSTR registers in the Advanced Power - Management Unit section of the device's datasheet. - - -Example: - -This shows the r8a7791 APMU that can control CPU0 and CPU1. - - apmu@e6152000 { - compatible = "renesas,r8a7791-apmu", "renesas,apmu"; - reg = <0 0xe6152000 0 0x188>; - cpus = <&cpu0 &cpu1>; - }; diff --git a/Documentation/devicetree/bindings/power/renesas,apmu.yaml b/Documentation/devicetree/bindings/power/renesas,apmu.yaml new file mode 100644 index 000000000000..078b2cb40fe3 --- /dev/null +++ b/Documentation/devicetree/bindings/power/renesas,apmu.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/power/renesas,apmu.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Renesas Advanced Power Management Unit + +maintainers: + - Geert Uytterhoeven + - Magnus Damm + +description: + Renesas R-Car Gen2 and RZ/G1 SoCs utilize one or more APMU hardware units for + CPU core power domain control including SMP boot and CPU Hotplug. + +properties: + compatible: + items: + - enum: + - renesas,r8a7743-apmu # RZ/G1M + - renesas,r8a7744-apmu # RZ/G1N + - renesas,r8a7745-apmu # RZ/G1E + - renesas,r8a77470-apmu # RZ/G1C + - renesas,r8a7790-apmu # R-Car H2 + - renesas,r8a7791-apmu # R-Car M2-W + - renesas,r8a7792-apmu # R-Car V2H + - renesas,r8a7793-apmu # R-Car M2-N + - renesas,r8a7794-apmu # R-Car E2 + - const: renesas,apmu + + reg: + maxItems: 1 + + cpus: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: | + Array of phandles pointing to CPU cores, which should match the order of + CPU cores used by the WUPCR and PSTR registers in the Advanced Power + Management Unit section of the device's datasheet. + +required: + - compatible + - reg + - cpus + +additionalProperties: false + +examples: + - | + apmu@e6152000 { + compatible = "renesas,r8a7791-apmu", "renesas,apmu"; + reg = <0xe6152000 0x188>; + cpus = <&cpu0 &cpu1>; + }; From 869233f81337bfb33c79f1e7539147d52c0ba383 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 25 Feb 2020 13:47:25 +0200 Subject: [PATCH 0943/4444] gpiolib: Optimize gpiochip_remove() when check for requested line Here are the following optimizations have been done: - break the loop after first found requested line - due to above, drop redundant boolean variable - replace open coded variant of gpiochip_is_requested() - due to above, drop redundant pointer to struct gpio_desc - use 'unsigned int' instead of 'unsigned' for loop counter Note, pointer to struct gpio_chip followed by pointer to struct gpio_device is still valid, back link is not. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200225114725.839-1-andriy.shevchenko@linux.intel.com Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 9ad86477af9c..2253ab495349 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1797,10 +1797,8 @@ EXPORT_SYMBOL_GPL(gpiochip_get_data); void gpiochip_remove(struct gpio_chip *chip) { struct gpio_device *gdev = chip->gpiodev; - struct gpio_desc *desc; unsigned long flags; - unsigned i; - bool requested = false; + unsigned int i; /* FIXME: should the legacy sysfs handling be moved to gpio_device? */ gpiochip_sysfs_unregister(gdev); @@ -1820,13 +1818,12 @@ void gpiochip_remove(struct gpio_chip *chip) spin_lock_irqsave(&gpio_lock, flags); for (i = 0; i < gdev->ngpio; i++) { - desc = &gdev->descs[i]; - if (test_bit(FLAG_REQUESTED, &desc->flags)) - requested = true; + if (gpiochip_is_requested(chip, i)) + break; } spin_unlock_irqrestore(&gpio_lock, flags); - if (requested) + if (i == gdev->ngpio) dev_crit(&gdev->dev, "REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED\n"); From b88d145191ad02b865c601ff87c2c685ca11a20a Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 27 Feb 2020 12:13:46 +0800 Subject: [PATCH 0944/4444] pinctrl: Export some needed symbols at module load time Export the pin_get_name()/pinconf_generic_parse_dt_config() symbols needed by the Spreadtrum pinctrl driver when building it as a module. Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/f4e7e20afacb23e6fa7a6b33ea4319b2b3492840.1582776447.git.baolin.wang7@gmail.com Signed-off-by: Linus Walleij --- drivers/pinctrl/core.c | 1 + drivers/pinctrl/pinconf-generic.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 446d84fe0e31..893b1acb3e6e 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -176,6 +176,7 @@ const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin) return desc->name; } +EXPORT_SYMBOL_GPL(pin_get_name); /* Deletes a range of pin descriptors */ static void pinctrl_free_pindescs(struct pinctrl_dev *pctldev, diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c index 9eb86309c70b..dfef471201f6 100644 --- a/drivers/pinctrl/pinconf-generic.c +++ b/drivers/pinctrl/pinconf-generic.c @@ -286,6 +286,7 @@ out: kfree(cfg); return ret; } +EXPORT_SYMBOL_GPL(pinconf_generic_parse_dt_config); int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev, struct device_node *np, struct pinctrl_map **map, From 1df49cc80da167f3fa91e3a47c3c1aabd4a3953c Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 27 Feb 2020 12:13:47 +0800 Subject: [PATCH 0945/4444] pinctrl: sprd: Allow the SPRD pinctrl driver building into a module Change the config to 'tristate' and export some symbols needed by modules to allow the Spreadtrum pinctrl driver building into a module. Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/d7239f3c7379e402f665fc8927f635ac56691380.1582776447.git.baolin.wang7@gmail.com Signed-off-by: Linus Walleij --- drivers/pinctrl/sprd/Kconfig | 6 +++--- drivers/pinctrl/sprd/pinctrl-sprd.c | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/pinctrl/sprd/Kconfig b/drivers/pinctrl/sprd/Kconfig index b6c5479b58fb..c9e7f0bb1145 100644 --- a/drivers/pinctrl/sprd/Kconfig +++ b/drivers/pinctrl/sprd/Kconfig @@ -4,7 +4,7 @@ # config PINCTRL_SPRD - bool "Spreadtrum pinctrl driver" + tristate "Spreadtrum pinctrl driver" depends on OF depends on ARCH_SPRD || COMPILE_TEST select PINMUX @@ -15,7 +15,7 @@ config PINCTRL_SPRD Say Y here to enable Spreadtrum pinctrl driver config PINCTRL_SPRD_SC9860 - bool "Spreadtrum SC9860 pinctrl driver" - depends on PINCTRL_SPRD + tristate "Spreadtrum SC9860 pinctrl driver" + select PINCTRL_SPRD help Say Y here to enable Spreadtrum SC9860 pinctrl driver diff --git a/drivers/pinctrl/sprd/pinctrl-sprd.c b/drivers/pinctrl/sprd/pinctrl-sprd.c index 157712ab05a8..ea04bac3b453 100644 --- a/drivers/pinctrl/sprd/pinctrl-sprd.c +++ b/drivers/pinctrl/sprd/pinctrl-sprd.c @@ -1090,6 +1090,7 @@ int sprd_pinctrl_core_probe(struct platform_device *pdev, return 0; } +EXPORT_SYMBOL_GPL(sprd_pinctrl_core_probe); int sprd_pinctrl_remove(struct platform_device *pdev) { @@ -1098,6 +1099,7 @@ int sprd_pinctrl_remove(struct platform_device *pdev) pinctrl_unregister(sprd_pctl->pctl); return 0; } +EXPORT_SYMBOL_GPL(sprd_pinctrl_remove); void sprd_pinctrl_shutdown(struct platform_device *pdev) { @@ -1112,6 +1114,7 @@ void sprd_pinctrl_shutdown(struct platform_device *pdev) return; pinctrl_select_state(pinctl, state); } +EXPORT_SYMBOL_GPL(sprd_pinctrl_shutdown); MODULE_DESCRIPTION("SPREADTRUM Pin Controller Driver"); MODULE_AUTHOR("Baolin Wang "); From b87e4249c2b4f15932f80a97e00dff794fc1f11e Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 27 Feb 2020 12:58:37 -0600 Subject: [PATCH 0946/4444] pinctrl: sirf/atlas7: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200227185837.GA4469@embeddedor Signed-off-by: Linus Walleij --- drivers/pinctrl/sirf/pinctrl-atlas7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/sirf/pinctrl-atlas7.c b/drivers/pinctrl/sirf/pinctrl-atlas7.c index b1a9611f46b3..50df9e084414 100644 --- a/drivers/pinctrl/sirf/pinctrl-atlas7.c +++ b/drivers/pinctrl/sirf/pinctrl-atlas7.c @@ -352,7 +352,7 @@ struct atlas7_gpio_chip { int nbank; raw_spinlock_t lock; struct gpio_chip chip; - struct atlas7_gpio_bank banks[0]; + struct atlas7_gpio_bank banks[]; }; /** From 9cb3985af63555810bb07de50acdf4170771451d Mon Sep 17 00:00:00 2001 From: Yicong Yang Date: Mon, 17 Feb 2020 19:12:55 +0800 Subject: [PATCH 0947/4444] PCI: Add 32 GT/s decoding in some macros Link speed 32.0 GT/s is supported in PCIe r5.0. Add this speed to PCIE_SPEED2STR() and PCIE_SPEED2MBS_ENC() to correctly decode it. This is complementary to de76cda215d5 ("PCI: Decode PCIe 32 GT/s link speed"). Link: https://lore.kernel.org/r/1581937984-40353-2-git-send-email-yangyicong@hisilicon.com Signed-off-by: Yicong Yang Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 6394e7746fb5..f65912e0f30d 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -294,7 +294,8 @@ void pci_bus_put(struct pci_bus *bus); /* PCIe link information */ #define PCIE_SPEED2STR(speed) \ - ((speed) == PCIE_SPEED_16_0GT ? "16 GT/s" : \ + ((speed) == PCIE_SPEED_32_0GT ? "32 GT/s" : \ + (speed) == PCIE_SPEED_16_0GT ? "16 GT/s" : \ (speed) == PCIE_SPEED_8_0GT ? "8 GT/s" : \ (speed) == PCIE_SPEED_5_0GT ? "5 GT/s" : \ (speed) == PCIE_SPEED_2_5GT ? "2.5 GT/s" : \ @@ -302,7 +303,8 @@ void pci_bus_put(struct pci_bus *bus); /* PCIe speed to Mb/s reduced by encoding overhead */ #define PCIE_SPEED2MBS_ENC(speed) \ - ((speed) == PCIE_SPEED_16_0GT ? 16000*128/130 : \ + ((speed) == PCIE_SPEED_32_0GT ? 32000*128/130 : \ + (speed) == PCIE_SPEED_16_0GT ? 16000*128/130 : \ (speed) == PCIE_SPEED_8_0GT ? 8000*128/130 : \ (speed) == PCIE_SPEED_5_0GT ? 5000*8/10 : \ (speed) == PCIE_SPEED_2_5GT ? 2500*8/10 : \ From 0a36fd6cef5e3a11a273300e777a26cb26274547 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Thu, 27 Feb 2020 12:11:48 -0800 Subject: [PATCH 0948/4444] scsi: qla2xxx: Fix sparse warning reported by kbuild bot this patch fixes following sparse warnings >> drivers/scsi/qla2xxx/qla_tmpl.c:873:32: sparse: sparse: incorrect type in assignment (different base types) >> drivers/scsi/qla2xxx/qla_tmpl.c:873:32: sparse: expected unsigned int [usertype] capture_timestamp >> drivers/scsi/qla2xxx/qla_tmpl.c:873:32: sparse: got restricted __le32 [usertype] drivers/scsi/qla2xxx/qla_tmpl.c:885:29: sparse: sparse: incorrect type in assignment (different base types) >> drivers/scsi/qla2xxx/qla_tmpl.c:885:29: sparse: expected unsigned int vim +873 drivers/scsi/qla2xxx/qla_tmpl.c 869 870 static void 871 qla27xx_time_stamp(struct qla27xx_fwdt_template *tmp) 872 { > 873 tmp->capture_timestamp = cpu_to_le32(jiffies); 874 } 875 876 static void 877 qla27xx_driver_info(struct qla27xx_fwdt_template *tmp) 878 { 879 uint8_t v[] = { 0, 0, 0, 0, 0, 0 }; 880 881 WARN_ON_ONCE(sscanf(qla2x00_version_str, 882 "%hhu.%hhu.%hhu.%hhu.%hhu.%hhu", 883 v+0, v+1, v+2, v+3, v+4, v+5) != 6); 884 > 885 tmp->driver_info[0] = cpu_to_le32( 886 v[3] << 24 | v[2] << 16 | v[1] << 8 | v[0]); 887 tmp->driver_info[1] = cpu_to_le32(v[5] << 8 | v[4]); 888 tmp->driver_info[2] = __constant_cpu_to_le32(0x12345678); 889 } 890 Link: https://lore.kernel.org/r/20200227201148.13973-1-hmadhani@marvell.com Fixes: a31056ddc665 ("scsi: qla2xxx: Use endian macros to assign static fields in fwdump header") Reported-by: kbuild test robot Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_tmpl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_tmpl.h b/drivers/scsi/qla2xxx/qla_tmpl.h index d2a0014e8b21..bba8dc90acfb 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.h +++ b/drivers/scsi/qla2xxx/qla_tmpl.h @@ -18,11 +18,11 @@ struct __packed qla27xx_fwdt_template { __le32 entry_count; uint32_t template_version; - uint32_t capture_timestamp; + __le32 capture_timestamp; uint32_t template_checksum; uint32_t reserved_2; - uint32_t driver_info[3]; + __le32 driver_info[3]; uint32_t saved_state[16]; From c81ef0ed4477c637d1f1dd96ecd8e8fbe18b7283 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 19 Feb 2020 20:34:37 -0800 Subject: [PATCH 0949/4444] scsi: qla2xxx: Simplify the code for aborting SCSI commands Since the SCSI core does not reuse the tag of the SCSI command that is being aborted by .eh_abort() before .eh_abort() has finished it is not necessary to check from inside that callback whether or not the SCSI command has already completed. Instead, rely on the firmware to return an error code when attempting to abort a command that has already completed. Additionally, rely on the firmware to return an error code when attempting to abort an already aborted command. In qla2x00_abort_srb(), use blk_mq_request_started() instead of sp->completed and sp->aborted. Link: https://lore.kernel.org/r/20200220043441.20504-2-bvanassche@acm.org Cc: Martin Wilck Cc: Quinn Tran Reviewed-by: Daniel Wagner Reviewed-by: Roman Bolshakov Acked-by: Himanshu Madhani Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 3 --- drivers/scsi/qla2xxx/qla_isr.c | 5 ----- drivers/scsi/qla2xxx/qla_os.c | 27 ++++++++++++++------------- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 17367639953c..138152c26733 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -597,9 +597,6 @@ typedef struct srb { struct fc_port *fcport; struct scsi_qla_host *vha; unsigned int start_timer:1; - unsigned int abort:1; - unsigned int aborted:1; - unsigned int completed:1; uint32_t handle; uint16_t flags; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 7c0c32d5d6ec..7eb3df423162 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -2657,11 +2657,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) return; } - if (sp->abort) - sp->aborted = 1; - else - sp->completed = 1; - if (sp->cmd_type != TYPE_SRB) { req->outstanding_cmds[handle] = NULL; ql_dbg(ql_dbg_io, vha, 0x3015, diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index f5a264f0afd6..78ce264d9168 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1270,17 +1270,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) return SUCCESS; spin_lock_irqsave(qpair->qp_lock_ptr, flags); - if (sp->completed) { - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - return SUCCESS; - } - - if (sp->abort || sp->aborted) { - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - return FAILED; - } - - sp->abort = 1; sp->comp = ∁ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); @@ -1705,6 +1694,10 @@ qla2x00_loop_reset(scsi_qla_host_t *vha) return QLA_SUCCESS; } +/* + * The caller must ensure that no completion interrupts will happen + * while this function is in progress. + */ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, unsigned long *flags) __releases(qp->qp_lock_ptr) @@ -1713,6 +1706,7 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, DECLARE_COMPLETION_ONSTACK(comp); scsi_qla_host_t *vha = qp->vha; struct qla_hw_data *ha = vha->hw; + struct scsi_cmnd *cmd = GET_CMD_SP(sp); int rval; bool ret_cmd; uint32_t ratov_j; @@ -1734,7 +1728,6 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, } sp->comp = ∁ - sp->abort = 1; spin_unlock_irqrestore(qp->qp_lock_ptr, *flags); rval = ha->isp_ops->abort_command(sp); @@ -1758,13 +1751,17 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, } spin_lock_irqsave(qp->qp_lock_ptr, *flags); - if (ret_cmd && (!sp->completed || !sp->aborted)) + if (ret_cmd && blk_mq_request_started(cmd->request)) sp->done(sp, res); } else { sp->done(sp, res); } } +/* + * The caller must ensure that no completion interrupts will happen + * while this function is in progress. + */ static void __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) { @@ -1811,6 +1808,10 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) spin_unlock_irqrestore(qp->qp_lock_ptr, flags); } +/* + * The caller must ensure that no completion interrupts will happen + * while this function is in progress. + */ void qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) { From 1ee5ac365c2a554b59b0e7445455d93a0577662b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 19 Feb 2020 20:34:38 -0800 Subject: [PATCH 0950/4444] scsi: qla2xxx: Suppress endianness complaints in qla2x00_configure_local_loop() Instead of changing endianness in-place, write the data in CPU endian format in another buffer and copy that buffer back. This patch does not change any functionality but silences some sparse endianness warnings. Link: https://lore.kernel.org/r/20200220043441.20504-3-bvanassche@acm.org Cc: Roman Bolshakov Cc: Martin Wilck Cc: Quinn Tran Reviewed-by: Daniel Wagner Reviewed-by: Roman Bolshakov Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 2 +- drivers/scsi/qla2xxx/qla_init.c | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 138152c26733..163e140490c7 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -414,7 +414,7 @@ struct els_logo_payload { struct els_plogi_payload { uint8_t opcode; uint8_t rsvd[3]; - uint8_t data[112]; + __be32 data[112 / 4]; }; struct ct_arg { diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 1ec93e28560e..12fcf5b5932a 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -5076,7 +5076,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) if (N2N_TOPO(ha)) { if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) { /* borrowing */ - u32 *bp, i, sz; + u32 *bp, sz; memset(ha->init_cb, 0, ha->init_cb_size); sz = min_t(int, sizeof(struct els_plogi_payload), @@ -5084,13 +5084,12 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) rval = qla24xx_get_port_login_templ(vha, ha->init_cb_dma, (void *)ha->init_cb, sz); if (rval == QLA_SUCCESS) { - bp = (uint32_t *)ha->init_cb; - for (i = 0; i < sz/4 ; i++, bp++) - *bp = cpu_to_be32(*bp); + __be32 *q = &ha->plogi_els_payld.data[0]; - memcpy(&ha->plogi_els_payld.data, - (void *)ha->init_cb, - sizeof(ha->plogi_els_payld.data)); + bp = (uint32_t *)ha->init_cb; + cpu_to_be32_array(q, bp, sz / 4); + + memcpy(bp, q, sizeof(ha->plogi_els_payld.data)); } else { ql_dbg(ql_dbg_init, vha, 0x00d1, "PLOGI ELS param read fail.\n"); From 471298cab82d255e358901ea5baff24abe1a53b8 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 19 Feb 2020 20:34:39 -0800 Subject: [PATCH 0951/4444] scsi: qla2xxx: Fix sparse warnings triggered by the PCI state checking code This patch fixes the following sparse warnings: drivers/scsi/qla2xxx/qla_mbx.c:120:21: warning: restricted pci_channel_state_t degrades to integer drivers/scsi/qla2xxx/qla_mbx.c:120:37: warning: restricted pci_channel_state_t degrades to integer >From include/linux/pci.h: enum pci_channel_state { /* I/O channel is in normal state */ pci_channel_io_normal = (__force pci_channel_state_t) 1, /* I/O to channel is blocked */ pci_channel_io_frozen = (__force pci_channel_state_t) 2, /* PCI card is dead */ pci_channel_io_perm_failure = (__force pci_channel_state_t) 3, }; Link: https://lore.kernel.org/r/20200220043441.20504-4-bvanassche@acm.org Cc: Roman Bolshakov Cc: Martin Wilck Cc: Quinn Tran Reviewed-by: Daniel Wagner Reviewed-by: Roman Bolshakov Acked-by: Himanshu Madhani Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_mbx.c | 5 ++--- drivers/scsi/qla2xxx/qla_mr.c | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 3bb6ab6f254a..85e5a1b6a611 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -117,10 +117,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) ql_dbg(ql_dbg_mbx, vha, 0x1000, "Entered %s.\n", __func__); - if (ha->pdev->error_state > pci_channel_io_frozen) { + if (ha->pdev->error_state == pci_channel_io_perm_failure) { ql_log(ql_log_warn, vha, 0x1001, - "error_state is greater than pci_channel_io_frozen, " - "exiting.\n"); + "PCI channel failed permanently, exiting.\n"); return QLA_FUNCTION_TIMEOUT; } diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index cad1fc2a1b28..6d120457478e 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -53,10 +53,9 @@ qlafx00_mailbox_command(scsi_qla_host_t *vha, struct mbx_cmd_32 *mcp) struct qla_hw_data *ha = vha->hw; scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); - if (ha->pdev->error_state > pci_channel_io_frozen) { + if (ha->pdev->error_state == pci_channel_io_perm_failure) { ql_log(ql_log_warn, vha, 0x115c, - "error_state is greater than pci_channel_io_frozen, " - "exiting.\n"); + "PCI channel failed permanently, exiting.\n"); return QLA_FUNCTION_TIMEOUT; } From c25eb70a10243c1ad24e74375aceb65ab8951e93 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 19 Feb 2020 20:34:40 -0800 Subject: [PATCH 0952/4444] scsi: qla2xxx: Convert MAKE_HANDLE() from a define into an inline function This patch allows sparse to verify the endianness of the arguments passed to make_handle(). Link: https://lore.kernel.org/r/20200220043441.20504-5-bvanassche@acm.org Cc: Roman Bolshakov Cc: Daniel Wagner Cc: Martin Wilck Cc: Quinn Tran Reviewed-by: Daniel Wagner Reviewed-by: Roman Bolshakov Acked-by: Himanshu Madhani Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 5 ++++- drivers/scsi/qla2xxx/qla_iocb.c | 22 +++++++++++----------- drivers/scsi/qla2xxx/qla_mbx.c | 10 +++++----- drivers/scsi/qla2xxx/qla_mr.c | 8 ++++---- drivers/scsi/qla2xxx/qla_nvme.c | 2 +- drivers/scsi/qla2xxx/qla_target.c | 6 +++--- 6 files changed, 28 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 163e140490c7..4d07c6e902fe 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -119,7 +119,10 @@ typedef struct { #define LSD(x) ((uint32_t)((uint64_t)(x))) #define MSD(x) ((uint32_t)((((uint64_t)(x)) >> 16) >> 16)) -#define MAKE_HANDLE(x, y) ((uint32_t)((((uint32_t)(x)) << 16) | (uint32_t)(y))) +static inline uint32_t make_handle(uint16_t x, uint16_t y) +{ + return ((uint32_t)x << 16) | y; +} /* * I/O register diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 4f022955eb94..182bd68c79ac 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -530,7 +530,7 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct qla_qpair *qpair, int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun); host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun)); mrk24->vp_index = vha->vp_idx; - mrk24->handle = MAKE_HANDLE(req->id, mrk24->handle); + mrk24->handle = make_handle(req->id, mrk24->handle); } else { SET_TARGET_ID(ha, mrk->target, loop_id); mrk->lun = cpu_to_le16((uint16_t)lun); @@ -1655,7 +1655,7 @@ qla24xx_start_scsi(srb_t *sp) req->cnt -= req_cnt; cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ @@ -1843,7 +1843,7 @@ qla24xx_dif_start_scsi(srb_t *sp) /* Fill-in common area */ cmd_pkt = (struct cmd_type_crc_2 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); clr_ptr = (uint32_t *)cmd_pkt + 2; memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); @@ -1975,7 +1975,7 @@ qla2xxx_start_scsi_mq(srb_t *sp) req->cnt -= req_cnt; cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ @@ -2178,7 +2178,7 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp) /* Fill-in common area */ cmd_pkt = (struct cmd_type_crc_2 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); clr_ptr = (uint32_t *)cmd_pkt + 2; memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); @@ -2491,7 +2491,7 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) tsk->entry_type = TSK_MGMT_IOCB_TYPE; tsk->entry_count = 1; - tsk->handle = MAKE_HANDLE(req->id, tsk->handle); + tsk->handle = make_handle(req->id, tsk->handle); tsk->nport_handle = cpu_to_le16(fcport->loop_id); tsk->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); tsk->control_flags = cpu_to_le32(flags); @@ -3360,7 +3360,7 @@ sufficient_dsds: } cmd_pkt = (struct cmd_type_6 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ @@ -3431,7 +3431,7 @@ sufficient_dsds: goto queuing_error; cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0).*/ @@ -3536,7 +3536,7 @@ qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb) memset(abt_iocb, 0, sizeof(struct abort_entry_24xx)); abt_iocb->entry_type = ABORT_IOCB_TYPE; abt_iocb->entry_count = 1; - abt_iocb->handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle)); + abt_iocb->handle = cpu_to_le32(make_handle(req->id, sp->handle)); if (sp->fcport) { abt_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); abt_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; @@ -3544,7 +3544,7 @@ qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb) abt_iocb->port_id[2] = sp->fcport->d_id.b.domain; } abt_iocb->handle_to_abort = - cpu_to_le32(MAKE_HANDLE(aio->u.abt.req_que_no, + cpu_to_le32(make_handle(aio->u.abt.req_que_no, aio->u.abt.cmd_hndl)); abt_iocb->vp_index = vha->vp_idx; abt_iocb->req_que_no = cpu_to_le16(aio->u.abt.req_que_no); @@ -3907,7 +3907,7 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds) } cmd_pkt = (struct cmd_bidir *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0).*/ diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 85e5a1b6a611..0f0af3c2cf81 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -2437,7 +2437,7 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, lg->entry_type = LOGINOUT_PORT_IOCB_TYPE; lg->entry_count = 1; - lg->handle = MAKE_HANDLE(req->id, lg->handle); + lg->handle = make_handle(req->id, lg->handle); lg->nport_handle = cpu_to_le16(loop_id); lg->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); if (opt & BIT_0) @@ -2707,7 +2707,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, req = vha->req; lg->entry_type = LOGINOUT_PORT_IOCB_TYPE; lg->entry_count = 1; - lg->handle = MAKE_HANDLE(req->id, lg->handle); + lg->handle = make_handle(req->id, lg->handle); lg->nport_handle = cpu_to_le16(loop_id); lg->control_flags = cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO| @@ -3197,9 +3197,9 @@ qla24xx_abort_command(srb_t *sp) abt->entry_type = ABORT_IOCB_TYPE; abt->entry_count = 1; - abt->handle = MAKE_HANDLE(req->id, abt->handle); + abt->handle = make_handle(req->id, abt->handle); abt->nport_handle = cpu_to_le16(fcport->loop_id); - abt->handle_to_abort = MAKE_HANDLE(req->id, handle); + abt->handle_to_abort = make_handle(req->id, handle); abt->port_id[0] = fcport->d_id.b.al_pa; abt->port_id[1] = fcport->d_id.b.area; abt->port_id[2] = fcport->d_id.b.domain; @@ -3276,7 +3276,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, tsk->p.tsk.entry_type = TSK_MGMT_IOCB_TYPE; tsk->p.tsk.entry_count = 1; - tsk->p.tsk.handle = MAKE_HANDLE(req->id, tsk->p.tsk.handle); + tsk->p.tsk.handle = make_handle(req->id, tsk->p.tsk.handle); tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id); tsk->p.tsk.timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); tsk->p.tsk.control_flags = cpu_to_le32(type); diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 6d120457478e..df99911b8bb9 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -3135,7 +3135,7 @@ qlafx00_start_scsi(srb_t *sp) memset(&lcmd_pkt, 0, REQUEST_ENTRY_SIZE); - lcmd_pkt.handle = MAKE_HANDLE(req->id, sp->handle); + lcmd_pkt.handle = make_handle(req->id, sp->handle); lcmd_pkt.reserved_0 = 0; lcmd_pkt.port_path_ctrl = 0; lcmd_pkt.reserved_1 = 0; @@ -3205,7 +3205,7 @@ qlafx00_tm_iocb(srb_t *sp, struct tsk_mgmt_entry_fx00 *ptm_iocb) memset(&tm_iocb, 0, sizeof(struct tsk_mgmt_entry_fx00)); tm_iocb.entry_type = TSK_MGMT_IOCB_TYPE_FX00; tm_iocb.entry_count = 1; - tm_iocb.handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle)); + tm_iocb.handle = cpu_to_le32(make_handle(req->id, sp->handle)); tm_iocb.reserved_0 = 0; tm_iocb.tgt_id = cpu_to_le16(sp->fcport->tgt_id); tm_iocb.control_flags = cpu_to_le32(fxio->u.tmf.flags); @@ -3231,9 +3231,9 @@ qlafx00_abort_iocb(srb_t *sp, struct abort_iocb_entry_fx00 *pabt_iocb) memset(&abt_iocb, 0, sizeof(struct abort_iocb_entry_fx00)); abt_iocb.entry_type = ABORT_IOCB_TYPE_FX00; abt_iocb.entry_count = 1; - abt_iocb.handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle)); + abt_iocb.handle = cpu_to_le32(make_handle(req->id, sp->handle)); abt_iocb.abort_handle = - cpu_to_le32(MAKE_HANDLE(req->id, fxio->u.abt.cmd_hndl)); + cpu_to_le32(make_handle(req->id, fxio->u.abt.cmd_hndl)); abt_iocb.tgt_id_sts = cpu_to_le16(sp->fcport->tgt_id); abt_iocb.req_que_no = cpu_to_le16(req->id); diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index bfcd02fdf2b8..84e2a980dea0 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -413,7 +413,7 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp) req->cnt -= req_cnt; cmd_pkt = (struct cmd_nvme *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ clr_ptr = (uint32_t *)cmd_pkt + 2; diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 243f87df3d2b..d0dbddcef70f 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -1758,7 +1758,7 @@ static int qlt_build_abts_resp_iocb(struct qla_tgt_mgmt_cmd *mcmd) qpair->req->outstanding_cmds[h] = (srb_t *)mcmd; } - resp->handle = MAKE_HANDLE(qpair->req->id, h); + resp->handle = make_handle(qpair->req->id, h); resp->entry_type = ABTS_RESP_24XX; resp->entry_count = 1; resp->nport_handle = abts->nport_handle; @@ -2580,7 +2580,7 @@ static int qlt_24xx_build_ctio_pkt(struct qla_qpair *qpair, } else qpair->req->outstanding_cmds[h] = (srb_t *)prm->cmd; - pkt->handle = MAKE_HANDLE(qpair->req->id, h); + pkt->handle = make_handle(qpair->req->id, h); pkt->handle |= CTIO_COMPLETION_HANDLE_MARK; pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id); pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); @@ -3093,7 +3093,7 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm) } else qpair->req->outstanding_cmds[h] = (srb_t *)prm->cmd; - pkt->handle = MAKE_HANDLE(qpair->req->id, h); + pkt->handle = make_handle(qpair->req->id, h); pkt->handle |= CTIO_COMPLETION_HANDLE_MARK; pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id); pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); From efd39a2ad6ff6d1187caac8491d710f41b6a93ab Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Wed, 26 Feb 2020 14:40:05 -0800 Subject: [PATCH 0953/4444] scsi: qla2xxx: Add 16.0GT for PCI String This patch adds 16.0GT for readable display string. Link: https://lore.kernel.org/r/20200226224022.24518-2-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 78ce264d9168..e42862d265e9 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -600,6 +600,9 @@ qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len) case 3: speed_str = "8.0GT/s"; break; + case 4: + speed_str = "16.0GT/s"; + break; default: speed_str = ""; break; From 9ef4847a80d317e4033c2ecf0e73e54c5fd4771d Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Wed, 26 Feb 2020 14:40:06 -0800 Subject: [PATCH 0954/4444] scsi: qla2xxx: Avoid setting firmware options twice in 24xx_update_fw_options. This patch moves ql2xrdpenable check earlier to avoids setting fw_option once again before exiting qla24xx_update_fw_options. Link: https://lore.kernel.org/r/20200226224022.24518-3-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Giridhar Malavali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 12fcf5b5932a..1a3c723f4450 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3929,6 +3929,9 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) ha->fw_options[2] &= ~BIT_8; } + if (ql2xrdpenable) + ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; + ql_dbg(ql_dbg_init, vha, 0x00e8, "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n", __func__, ha->fw_options[1], ha->fw_options[2], @@ -3939,7 +3942,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) /* Update Serial Link options. */ if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0) - goto enable_purex; + return; rval = qla2x00_set_serdes_params(vha, le16_to_cpu(ha->fw_seriallink_options24[1]), @@ -3949,12 +3952,6 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) ql_log(ql_log_warn, vha, 0x0104, "Unable to update Serial Link options (%x).\n", rval); } - -enable_purex: - if (ql2xrdpenable) - ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; - - qla2x00_set_fw_options(vha, ha->fw_options); } void From 37efd51f75f30b48c2d19ee94eeccfd4325c3cb4 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Wed, 26 Feb 2020 14:40:07 -0800 Subject: [PATCH 0955/4444] scsi: qla2xxx: Use FC generic update firmware options routine for ISP27xx This patch uses generic firmware update options for FCoE based adapters as well to reduce code duplication. Link: https://lore.kernel.org/r/20200226224022.24518-4-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Giridhar Malavali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_gbl.h | 2 - drivers/scsi/qla2xxx/qla_init.c | 66 --------------------------------- drivers/scsi/qla2xxx/qla_os.c | 4 +- 3 files changed, 2 insertions(+), 70 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index bb3dfef9afb8..73b663defee1 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -31,8 +31,6 @@ extern int qla24xx_nvram_config(struct scsi_qla_host *); extern int qla81xx_nvram_config(struct scsi_qla_host *); extern void qla2x00_update_fw_options(struct scsi_qla_host *); extern void qla24xx_update_fw_options(scsi_qla_host_t *); -extern void qla81xx_update_fw_options(scsi_qla_host_t *); -extern void qla83xx_update_fw_options(scsi_qla_host_t *); extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *); extern int qla24xx_load_risc(scsi_qla_host_t *, uint32_t *); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 1a3c723f4450..b7d65c099deb 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -8679,72 +8679,6 @@ qla82xx_restart_isp(scsi_qla_host_t *vha) return status; } -void -qla83xx_update_fw_options(scsi_qla_host_t *vha) -{ - struct qla_hw_data *ha = vha->hw; - - if (ql2xrdpenable) - ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; - - qla2x00_set_fw_options(vha, ha->fw_options); -} - -void -qla81xx_update_fw_options(scsi_qla_host_t *vha) -{ - struct qla_hw_data *ha = vha->hw; - - /* Hold status IOCBs until ABTS response received. */ - if (ql2xfwholdabts) - ha->fw_options[3] |= BIT_12; - - /* Set Retry FLOGI in case of P2P connection */ - if (ha->operating_mode == P2P) { - ha->fw_options[2] |= BIT_3; - ql_dbg(ql_dbg_disc, vha, 0x2103, - "(%s): Setting FLOGI retry BIT in fw_options[2]: 0x%x\n", - __func__, ha->fw_options[2]); - } - - /* Move PUREX, ABTS RX & RIDA to ATIOQ */ - if (ql2xmvasynctoatio) { - if (qla_tgt_mode_enabled(vha) || - qla_dual_mode_enabled(vha)) - ha->fw_options[2] |= BIT_11; - else - ha->fw_options[2] &= ~BIT_11; - } - - if (qla_tgt_mode_enabled(vha) || - qla_dual_mode_enabled(vha)) { - /* FW auto send SCSI status during */ - ha->fw_options[1] |= BIT_8; - ha->fw_options[10] |= (u16)SAM_STAT_BUSY << 8; - - /* FW perform Exchange validation */ - ha->fw_options[2] |= BIT_4; - } else { - ha->fw_options[1] &= ~BIT_8; - ha->fw_options[10] &= 0x00ff; - - ha->fw_options[2] &= ~BIT_4; - } - - if (ql2xetsenable) { - /* Enable ETS Burst. */ - memset(ha->fw_options, 0, sizeof(ha->fw_options)); - ha->fw_options[2] |= BIT_9; - } - - ql_dbg(ql_dbg_init, vha, 0x00e9, - "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n", - __func__, ha->fw_options[1], ha->fw_options[2], - ha->fw_options[3], vha->host->active_mode); - - qla2x00_set_fw_options(vha, ha->fw_options); -} - /* * qla24xx_get_fcp_prio * Gets the fcp cmd priority value for the logged in port. diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index e42862d265e9..dddb86dc4b81 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2308,7 +2308,7 @@ static struct isp_operations qla81xx_isp_ops = { .config_rings = qla24xx_config_rings, .reset_adapter = qla24xx_reset_adapter, .nvram_config = qla81xx_nvram_config, - .update_fw_options = qla83xx_update_fw_options, + .update_fw_options = qla24xx_update_fw_options, .load_risc = qla81xx_load_risc, .pci_info_str = qla24xx_pci_info_str, .fw_version_str = qla24xx_fw_version_str, @@ -2425,7 +2425,7 @@ static struct isp_operations qla83xx_isp_ops = { .config_rings = qla24xx_config_rings, .reset_adapter = qla24xx_reset_adapter, .nvram_config = qla81xx_nvram_config, - .update_fw_options = qla83xx_update_fw_options, + .update_fw_options = qla24xx_update_fw_options, .load_risc = qla81xx_load_risc, .pci_info_str = qla24xx_pci_info_str, .fw_version_str = qla24xx_fw_version_str, From 8e0e063af0d1be30245a08fab0515a3cccfcd513 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Wed, 26 Feb 2020 14:40:08 -0800 Subject: [PATCH 0956/4444] scsi: qla2xxx: Fix FCP-SCSI FC4 flag passing error This patch fixes issue where incorrect flag was used for sending switch commands. Link: https://lore.kernel.org/r/20200226224022.24518-5-hmadhani@marvell.com Fixes: e8c72ba51a15 ("[SCSI] qla2xxx: Use GFF_ID to check FCP-SCSI FC4 type before logging into Nx_Ports") Fixes: a4239945b8ad ("scsi: qla2xxx: Add switch command to simplify fabric discovery") Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_gs.c | 4 ++-- drivers/scsi/qla2xxx/qla_init.c | 4 ++-- drivers/scsi/qla2xxx/qla_target.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 5af49a7ddb22..42c3ad27f1cb 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -2733,7 +2733,7 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list) for (i = 0; i < ha->max_fibre_devices; i++) { /* Set default FC4 Type as UNKNOWN so the default is to * Process this port */ - list[i].fc4_type = FC4_TYPE_UNKNOWN; + list[i].fc4_type = 0; /* Do not attempt GFF_ID if we are not FWI_2 capable */ if (!IS_FWI2_CAPABLE(ha)) @@ -3083,7 +3083,7 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea) "%s %d %8phC post new sess\n", __func__, __LINE__, ea->port_name); qla24xx_post_newsess_work(vha, &ea->id, - ea->port_name, NULL, NULL, FC4_TYPE_UNKNOWN); + ea->port_name, NULL, NULL, 0); } } } diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index b7d65c099deb..23a9617fe035 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1043,7 +1043,7 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res) __func__, __LINE__, (u8 *)&wwn, id.b24); wwnn = wwn_to_u64(e->node_name); qla24xx_post_newsess_work(vha, &id, (u8 *)&wwn, - (u8 *)&wwnn, NULL, FC4_TYPE_UNKNOWN); + (u8 *)&wwnn, NULL, 0); } } @@ -5828,7 +5828,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha) /* Bypass ports whose FCP-4 type is not FCP_SCSI */ if (ql2xgffidenable && (!(new_fcport->fc4_type & FS_FC4TYPE_FCP) && - new_fcport->fc4_type != FC4_TYPE_UNKNOWN)) + new_fcport->fc4_type != 0)) continue; spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index d0dbddcef70f..622e7337affc 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -4739,11 +4739,11 @@ static int qlt_handle_login(struct scsi_qla_host *vha, qla24xx_post_newsess_work(vha, &port_id, iocb->u.isp24.port_name, iocb->u.isp24.u.plogi.node_name, - pla, FC4_TYPE_UNKNOWN); + pla, 0); else qla24xx_post_newsess_work(vha, &port_id, iocb->u.isp24.port_name, NULL, - pla, FC4_TYPE_UNKNOWN); + pla, 0); goto out; } From 4ba836f686284ef1eab0cf7a8f3402e24e6dc4cd Mon Sep 17 00:00:00 2001 From: Michael Hernandez Date: Wed, 26 Feb 2020 14:40:09 -0800 Subject: [PATCH 0957/4444] scsi: qla2xxx: Improved secure flash support messages This patch improved message for Secure Flash support. No functionality has been changed. Link: https://lore.kernel.org/r/20200226224022.24518-6-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Michael Hernandez Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 6 +++--- drivers/scsi/qla2xxx/qla_mbx.c | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 23a9617fe035..87b2d62b91f9 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2219,10 +2219,10 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) /* Check for secure flash support */ if (IS_QLA28XX(ha)) { - if (RD_REG_DWORD(®->mailbox12) & BIT_0) { - ql_log(ql_log_info, vha, 0xffff, "Adapter is Secure\n"); + if (RD_REG_DWORD(®->mailbox12) & BIT_0) ha->flags.secure_adapter = 1; - } + ql_log(ql_log_info, vha, 0xffff, "Secure Adapter: %s\n", + (ha->flags.secure_adapter) ? "Yes" : "No"); } diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 0f0af3c2cf81..938b4e4190c9 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1135,11 +1135,13 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) ha->fw_ddr_ram_start = (mcp->mb[23] << 16) | mcp->mb[22]; ha->fw_ddr_ram_end = (mcp->mb[25] << 16) | mcp->mb[24]; if (IS_QLA28XX(ha)) { - if (mcp->mb[16] & BIT_10) { - ql_log(ql_log_info, vha, 0xffff, - "FW support secure flash updates\n"); + if (mcp->mb[16] & BIT_10) ha->flags.secure_fw = 1; - } + + ql_log(ql_log_info, vha, 0xffff, + "Secure Flash Update in FW: %s\n", + (ha->flags.secure_fw) ? "Supported" : + "Not Supported"); } } From 1b81e7f3019d632a707e07927e946ffbbc102910 Mon Sep 17 00:00:00 2001 From: Michael Hernandez Date: Wed, 26 Feb 2020 14:40:10 -0800 Subject: [PATCH 0958/4444] scsi: qla2xxx: Return appropriate failure through BSG Interface This patch ensures flash updates API calls return possible failure status through BSG interface to the application. Link: https://lore.kernel.org/r/20200226224022.24518-7-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Michael Hernandez Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_bsg.c | 9 +++++++-- drivers/scsi/qla2xxx/qla_sup.c | 13 ++++++++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 714bcf5e6e53..97b51c477972 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -1517,10 +1517,15 @@ qla2x00_update_optrom(struct bsg_job *bsg_job) bsg_job->request_payload.sg_cnt, ha->optrom_buffer, ha->optrom_region_size); - ha->isp_ops->write_optrom(vha, ha->optrom_buffer, + rval = ha->isp_ops->write_optrom(vha, ha->optrom_buffer, ha->optrom_region_start, ha->optrom_region_size); - bsg_reply->result = DID_OK; + if (rval) { + bsg_reply->result = -EINVAL; + rval = -EINVAL; + } else { + bsg_reply->result = DID_OK; + } vfree(ha->optrom_buffer); ha->optrom_buffer = NULL; ha->optrom_state = QLA_SWAITING; diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 76a38bf86cbc..3da79ee1d88e 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -2683,7 +2683,7 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, uint32_t sec_mask, rest_addr, fdata; void *optrom = NULL; dma_addr_t optrom_dma; - int rval; + int rval, ret; struct secure_flash_update_block *sfub; dma_addr_t sfub_dma; uint32_t offset = faddr << 2; @@ -2939,11 +2939,12 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, write_protect: ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, "Protect flash...\n"); - rval = qla24xx_protect_flash(vha); - if (rval) { + ret = qla24xx_protect_flash(vha); + if (ret) { qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_UNLOCK); ql_log(ql_log_warn, vha, 0x7099, "Failed protect flash\n"); + rval = QLA_COMMAND_ERROR; } if (reset_to_rom == true) { @@ -2951,10 +2952,12 @@ write_protect: set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); qla2xxx_wake_dpc(vha); - rval = qla2x00_wait_for_hba_online(vha); - if (rval != QLA_SUCCESS) + ret = qla2x00_wait_for_hba_online(vha); + if (ret != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0xffff, "Adapter did not come out of reset\n"); + rval = QLA_COMMAND_ERROR; + } } done: From 7b2a73963c91cf6bad6b8f58636560cd1f3cf319 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 26 Feb 2020 14:40:11 -0800 Subject: [PATCH 0959/4444] scsi: qla2xxx: Use a dedicated interrupt handler for 'handshake-required' ISPs There's no point checking flags.disable_msix_handshake in the interrupt handler hot-path. Instead perform the check during queue-pair instantiation and use the proper interrupt handler. Link: https://lore.kernel.org/r/20200226224022.24518-8-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Andrew Vasquez Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_gbl.h | 2 ++ drivers/scsi/qla2xxx/qla_isr.c | 31 ++++++++++++++++++++++++------- drivers/scsi/qla2xxx/qla_mid.c | 3 ++- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 4d07c6e902fe..51827492cddd 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -3250,6 +3250,7 @@ struct isp_operations { #define QLA_MSIX_RSP_Q 0x01 #define QLA_ATIO_VECTOR 0x02 #define QLA_MSIX_QPAIR_MULTIQ_RSP_Q 0x03 +#define QLA_MSIX_QPAIR_MULTIQ_RSP_Q_HS 0x04 #define QLA_MIDX_DEFAULT 0 #define QLA_MIDX_RSP_Q 1 diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 73b663defee1..33ea79181dd7 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -565,6 +565,8 @@ qla2x00_process_completed_request(struct scsi_qla_host *, struct req_que *, uint32_t); extern irqreturn_t qla2xxx_msix_rsp_q(int irq, void *dev_id); +extern irqreturn_t +qla2xxx_msix_rsp_q_hs(int irq, void *dev_id); fc_port_t *qla2x00_find_fcport_by_loopid(scsi_qla_host_t *, uint16_t); fc_port_t *qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *, u8 *, u8); fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8); diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 7eb3df423162..2918bb018196 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -3593,6 +3593,25 @@ qla24xx_msix_default(int irq, void *dev_id) irqreturn_t qla2xxx_msix_rsp_q(int irq, void *dev_id) +{ + struct qla_hw_data *ha; + struct qla_qpair *qpair; + + qpair = dev_id; + if (!qpair) { + ql_log(ql_log_info, NULL, 0x505b, + "%s: NULL response queue pointer.\n", __func__); + return IRQ_NONE; + } + ha = qpair->hw; + + queue_work(ha->wq, &qpair->q_work); + + return IRQ_HANDLED; +} + +irqreturn_t +qla2xxx_msix_rsp_q_hs(int irq, void *dev_id) { struct qla_hw_data *ha; struct qla_qpair *qpair; @@ -3607,13 +3626,10 @@ qla2xxx_msix_rsp_q(int irq, void *dev_id) } ha = qpair->hw; - /* Clear the interrupt, if enabled, for this response queue */ - if (unlikely(!ha->flags.disable_msix_handshake)) { - reg = &ha->iobase->isp24; - spin_lock_irqsave(&ha->hardware_lock, flags); - WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - } + reg = &ha->iobase->isp24; + spin_lock_irqsave(&ha->hardware_lock, flags); + WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); + spin_unlock_irqrestore(&ha->hardware_lock, flags); queue_work(ha->wq, &qpair->q_work); @@ -3632,6 +3648,7 @@ static const struct qla_init_msix_entry msix_entries[] = { { "rsp_q", qla24xx_msix_rsp_q }, { "atio_q", qla83xx_msix_atio_q }, { "qpair_multiq", qla2xxx_msix_rsp_q }, + { "qpair_multiq_hs", qla2xxx_msix_rsp_q_hs }, }; static const struct qla_init_msix_entry qla82xx_msix_entries[] = { diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index e86c94f78196..d82e92da529a 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -896,7 +896,8 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options, rsp->rsp_q_out); ret = qla25xx_request_irq(ha, qpair, qpair->msix, - QLA_MSIX_QPAIR_MULTIQ_RSP_Q); + ha->flags.disable_msix_handshake ? + QLA_MSIX_QPAIR_MULTIQ_RSP_Q : QLA_MSIX_QPAIR_MULTIQ_RSP_Q_HS); if (ret) goto que_failed; From ce1ee122e0f048fc67c1259489f0802a28049bfd Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Wed, 26 Feb 2020 14:40:12 -0800 Subject: [PATCH 0960/4444] scsi: qla2xxx: fix FW resource count values This patch fixes issue where current and original exchanges count were swapped for intiator and targets. Also fix IOCB count for current and original which were swapped. Link: https://lore.kernel.org/r/20200226224022.24518-9-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_dfs.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c index 0a6fb359f4d5..e62b2115235e 100644 --- a/drivers/scsi/qla2xxx/qla_dfs.c +++ b/drivers/scsi/qla2xxx/qla_dfs.c @@ -134,11 +134,11 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused) } else { seq_puts(s, "FW Resource count\n\n"); seq_printf(s, "Original TGT exchg count[%d]\n", mb[1]); - seq_printf(s, "current TGT exchg count[%d]\n", mb[2]); - seq_printf(s, "original Initiator Exchange count[%d]\n", mb[3]); - seq_printf(s, "Current Initiator Exchange count[%d]\n", mb[6]); - seq_printf(s, "Original IOCB count[%d]\n", mb[7]); - seq_printf(s, "Current IOCB count[%d]\n", mb[10]); + seq_printf(s, "Current TGT exchg count[%d]\n", mb[2]); + seq_printf(s, "Current Initiator Exchange count[%d]\n", mb[3]); + seq_printf(s, "Original Initiator Exchange count[%d]\n", mb[6]); + seq_printf(s, "Current IOCB count[%d]\n", mb[7]); + seq_printf(s, "Original IOCB count[%d]\n", mb[10]); seq_printf(s, "MAX VP count[%d]\n", mb[11]); seq_printf(s, "MAX FCF count[%d]\n", mb[12]); seq_printf(s, "Current free pageable XCB buffer cnt[%d]\n", @@ -149,7 +149,6 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused) mb[22]); seq_printf(s, "Original Target fast XCB buffer cnt[%d]\n", mb[23]); - } return 0; From b0f18eee6fc1ee21c07abb55e9ccabc9ed9c09f0 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 26 Feb 2020 14:40:13 -0800 Subject: [PATCH 0961/4444] scsi: qla2xxx: Update BPM enablement semantics. commit e4e3a2ce9556 ("scsi: qla2xxx: Add ability to autodetect SFP type") takes a heavy handed approach to BPM (Buffer Plus Management) enablement: 1) During hardware initialization, if an LR-capable transceiver is recognized, the driver schedules a disruptive post-initialization chip-reset (ISP-ABORT) to allow the BPM settings to be sent to the firmware. This chip-reset will result in (short-term) path-loss to all fc-rports and their attached SCSI devices. 2) LR-detection is triggered during any link-up event, resulting in a refresh and potential chip-reset Based on firmware-team guidance, upon LR-capable transceiver recognition, the driver's hardware initialization code will now re-execute firmware with the new BPM settings, then continue on with driver initialization. To address the second issue, the driver performs LR-capable detection upon the driver receiving a transceiver-insertion asynchronous event from firmware. No short-term path loss is needed with this new semantic. Link: https://lore.kernel.org/r/20200226224022.24518-10-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Andrew Vasquez Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 20 +++++--- drivers/scsi/qla2xxx/qla_fw.h | 3 +- drivers/scsi/qla2xxx/qla_gbl.h | 2 +- drivers/scsi/qla2xxx/qla_init.c | 88 +++++++++++++++++++++++---------- drivers/scsi/qla2xxx/qla_isr.c | 9 ++-- drivers/scsi/qla2xxx/qla_mbx.c | 48 +++--------------- drivers/scsi/qla2xxx/qla_os.c | 22 +++------ 7 files changed, 97 insertions(+), 95 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 51827492cddd..47c7a56438b5 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1049,6 +1049,7 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs) #define MBA_TEMPERATURE_ALERT 0x8070 /* Temperature Alert */ #define MBA_DPORT_DIAGNOSTICS 0x8080 /* D-port Diagnostics */ #define MBA_TRANS_INSERT 0x8130 /* Transceiver Insertion */ +#define MBA_TRANS_REMOVE 0x8131 /* Transceiver Removal */ #define MBA_FW_INIT_FAILURE 0x8401 /* Firmware initialization failure */ #define MBA_MIRROR_LUN_CHANGE 0x8402 /* Mirror LUN State Change Notification */ @@ -3802,8 +3803,8 @@ struct qla_hw_data { uint32_t fw_started:1; uint32_t fw_init_done:1; - uint32_t detected_lr_sfp:1; - uint32_t using_lr_setting:1; + uint32_t lr_detected:1; + uint32_t rida_fmt2:1; uint32_t purge_mbox:1; uint32_t n2n_bigger:1; @@ -3812,7 +3813,7 @@ struct qla_hw_data { } flags; uint16_t max_exchg; - uint16_t long_range_distance; /* 32G & above */ + uint16_t lr_distance; /* 32G & above */ #define LR_DISTANCE_5K 1 #define LR_DISTANCE_10K 0 @@ -4971,11 +4972,14 @@ struct sff_8247_a0 { u8 resv2[128]; }; -#define AUTO_DETECT_SFP_SUPPORT(_vha)\ - (ql2xautodetectsfp && !_vha->vp_idx && \ - (IS_QLA25XX(_vha->hw) || IS_QLA81XX(_vha->hw) ||\ - IS_QLA83XX(_vha->hw) || IS_QLA27XX(_vha->hw) || \ - IS_QLA28XX(_vha->hw))) +/* BPM -- Buffer Plus Management support. */ +#define IS_BPM_CAPABLE(ha) \ + (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || \ + IS_QLA27XX(ha) || IS_QLA28XX(ha)) +#define IS_BPM_RANGE_CAPABLE(ha) \ + (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) +#define IS_BPM_ENABLED(vha) \ + (ql2xautodetectsfp && !vha->vp_idx && IS_BPM_CAPABLE(vha->hw)) #define FLASH_SEMAPHORE_REGISTER_ADDR 0x00101016 diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 8af5bc4e2cc6..f9bad5bd7198 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -1867,9 +1867,8 @@ struct access_chip_rsp_84xx { /* LR Distance bit positions */ #define LR_DIST_NV_POS 2 +#define LR_DIST_NV_MASK 0xf #define LR_DIST_FW_POS 12 -#define LR_DIST_FW_SHIFT (LR_DIST_FW_POS - LR_DIST_NV_POS) -#define LR_DIST_FW_FIELD(x) ((x) << LR_DIST_FW_SHIFT & 0xf000) /* FAC semaphore defines */ #define FAC_SEMAPHORE_UNLOCK 0 diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 33ea79181dd7..1b93f5b4d77d 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -109,7 +109,7 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *, int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *, u8*, void *, u8); int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *); -int qla24xx_detect_sfp(scsi_qla_host_t *vha); +int qla24xx_detect_sfp(scsi_qla_host_t *); int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8); extern void qla28xx_get_aux_images(struct scsi_qla_host *, diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 87b2d62b91f9..3d615cc959cc 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3550,53 +3550,77 @@ static void qla2xxx_print_sfp_info(struct scsi_qla_host *vha) } -/* - * Return Code: - * QLA_SUCCESS: no action - * QLA_INTERFACE_ERROR: SFP is not there. - * QLA_FUNCTION_FAILED: detected New SFP +/** + * qla24xx_detect_sfp() + * + * @vha: adapter state pointer. + * + * @return + * 0 -- Configure firmware to use short-range settings -- normal + * buffer-to-buffer credits. + * + * 1 -- Configure firmware to use long-range settings -- extra + * buffer-to-buffer credits should be allocated with + * ha->lr_distance containing distance settings from NVRAM or SFP + * (if supported). */ int qla24xx_detect_sfp(scsi_qla_host_t *vha) { - int rc = QLA_SUCCESS; + int rc, used_nvram; struct sff_8247_a0 *a; struct qla_hw_data *ha = vha->hw; + struct nvram_81xx *nv = ha->nvram; +#define LR_DISTANCE_UNKNOWN 2 + static const char * const types[] = { "Short", "Long" }; + static const char * const lengths[] = { "(10km)", "(5km)", "" }; + u8 ll = 0; - if (!AUTO_DETECT_SFP_SUPPORT(vha)) + /* Seed with NVRAM settings. */ + used_nvram = 0; + ha->flags.lr_detected = 0; + if (IS_BPM_RANGE_CAPABLE(ha) && + (nv->enhanced_features & NEF_LR_DIST_ENABLE)) { + used_nvram = 1; + ha->flags.lr_detected = 1; + ha->lr_distance = + (nv->enhanced_features >> LR_DIST_NV_POS) + & LR_DIST_NV_MASK; + } + + if (!IS_BPM_ENABLED(vha)) goto out; - + /* Determine SR/LR capabilities of SFP/Transceiver. */ rc = qla2x00_read_sfp_dev(vha, NULL, 0); if (rc) goto out; + used_nvram = 0; a = (struct sff_8247_a0 *)vha->hw->sfp_data; qla2xxx_print_sfp_info(vha); - if (a->fc_ll_cc7 & FC_LL_VL || a->fc_ll_cc7 & FC_LL_L) { - /* long range */ - ha->flags.detected_lr_sfp = 1; + ha->flags.lr_detected = 0; + ll = a->fc_ll_cc7; + if (ll & FC_LL_VL || ll & FC_LL_L) { + /* Long range, track length. */ + ha->flags.lr_detected = 1; if (a->length_km > 5 || a->length_100m > 50) - ha->long_range_distance = LR_DISTANCE_10K; + ha->lr_distance = LR_DISTANCE_10K; else - ha->long_range_distance = LR_DISTANCE_5K; - - if (ha->flags.detected_lr_sfp != ha->flags.using_lr_setting) - ql_dbg(ql_dbg_async, vha, 0x507b, - "Detected Long Range SFP.\n"); - } else { - /* short range */ - ha->flags.detected_lr_sfp = 0; - if (ha->flags.using_lr_setting) - ql_dbg(ql_dbg_async, vha, 0x5084, - "Detected Short Range SFP.\n"); + ha->lr_distance = LR_DISTANCE_5K; } if (!vha->flags.init_done) rc = QLA_SUCCESS; out: - return rc; + ql_dbg(ql_dbg_async, vha, 0x507b, + "SFP detect: %s-Range SFP %s (nvr=%x ll=%x lr=%x lrd=%x).\n", + types[ha->flags.lr_detected], + ha->flags.lr_detected ? lengths[ha->lr_distance] : + lengths[LR_DISTANCE_UNKNOWN], + used_nvram, ll, ha->flags.lr_detected, ha->lr_distance); + return ha->flags.lr_detected; } /** @@ -3614,6 +3638,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; unsigned long flags; uint16_t fw_major_version; + int done_once = 0; if (IS_P3P_TYPE(ha)) { rval = ha->isp_ops->load_risc(vha, &srisc_address); @@ -3634,6 +3659,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) qla81xx_mpi_sync(vha); +execute_fw_with_lr: /* Load firmware sequences */ rval = ha->isp_ops->load_risc(vha, &srisc_address); if (rval == QLA_SUCCESS) { @@ -3655,7 +3681,15 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) rval = qla2x00_execute_fw(vha, srisc_address); /* Retrieve firmware information. */ if (rval == QLA_SUCCESS) { - qla24xx_detect_sfp(vha); + /* Enable BPM support? */ + if (!done_once++ && qla24xx_detect_sfp(vha)) { + ql_dbg(ql_dbg_init, vha, 0x00ca, + "Re-starting firmware -- BPM.\n"); + /* Best-effort - re-init. */ + ha->isp_ops->reset_chip(vha); + ha->isp_ops->chip_diag(vha); + goto execute_fw_with_lr; + } if ((IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) && @@ -3932,6 +3966,10 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) if (ql2xrdpenable) ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; + /* Enable Async 8130/8131 events -- transceiver insertion/removal */ + if (IS_BPM_RANGE_CAPABLE(ha)) + ha->fw_options[3] |= BIT_10; + ql_dbg(ql_dbg_init, vha, 0x00e8, "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n", __func__, ha->fw_options[1], ha->fw_options[2], diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 2918bb018196..9a14349e8376 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -960,10 +960,6 @@ skip_rio: vha->flags.management_server_logged_in = 0; qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate); - if (AUTO_DETECT_SFP_SUPPORT(vha)) { - set_bit(DETECT_SFP_CHANGE, &vha->dpc_flags); - qla2xxx_wake_dpc(vha); - } break; case MBA_LOOP_DOWN: /* Loop Down Event */ @@ -1436,6 +1432,11 @@ global_port_update: case MBA_TRANS_INSERT: ql_dbg(ql_dbg_async, vha, 0x5091, "Transceiver Insertion: %04x\n", mb[1]); + set_bit(DETECT_SFP_CHANGE, &vha->dpc_flags); + break; + + case MBA_TRANS_REMOVE: + ql_dbg(ql_dbg_async, vha, 0x5091, "Transceiver Removal\n"); break; default: diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 938b4e4190c9..11a60fb1b9a1 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -643,28 +643,6 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr, } #define NVME_ENABLE_FLAG BIT_3 -static inline uint16_t qla25xx_set_sfp_lr_dist(struct qla_hw_data *ha) -{ - uint16_t mb4 = BIT_0; - - if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) - mb4 |= ha->long_range_distance << LR_DIST_FW_POS; - - return mb4; -} - -static inline uint16_t qla25xx_set_nvr_lr_dist(struct qla_hw_data *ha) -{ - uint16_t mb4 = BIT_0; - - if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { - struct nvram_81xx *nv = ha->nvram; - - mb4 |= LR_DIST_FW_FIELD(nv->enhanced_features); - } - - return mb4; -} /* * qla2x00_execute_fw @@ -701,25 +679,13 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) mcp->mb[3] = 0; mcp->mb[4] = 0; mcp->mb[11] = 0; - ha->flags.using_lr_setting = 0; - if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || - IS_QLA27XX(ha) || IS_QLA28XX(ha)) { - if (ql2xautodetectsfp) { - if (ha->flags.detected_lr_sfp) { - mcp->mb[4] |= - qla25xx_set_sfp_lr_dist(ha); - ha->flags.using_lr_setting = 1; - } - } else { - struct nvram_81xx *nv = ha->nvram; - /* set LR distance if specified in nvram */ - if (nv->enhanced_features & - NEF_LR_DIST_ENABLE) { - mcp->mb[4] |= - qla25xx_set_nvr_lr_dist(ha); - ha->flags.using_lr_setting = 1; - } - } + + /* Enable BPM? */ + if (ha->flags.lr_detected) { + mcp->mb[4] = BIT_0; + if (IS_BPM_RANGE_CAPABLE(ha)) + mcp->mb[4] |= + ha->lr_distance << LR_DIST_FW_POS; } if (ql2xnvmeenable && (IS_QLA27XX(ha) || IS_QLA28XX(ha))) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index dddb86dc4b81..7db32f983a93 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -3462,13 +3462,6 @@ skip_dpc: if (test_bit(UNLOADING, &base_vha->dpc_flags)) return -ENODEV; - if (ha->flags.detected_lr_sfp) { - ql_log(ql_log_info, base_vha, 0xffff, - "Reset chip to pick up LR SFP setting\n"); - set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); - qla2xxx_wake_dpc(base_vha); - } - return 0; probe_failed: @@ -6881,13 +6874,14 @@ qla2x00_do_dpc(void *data) } if (test_and_clear_bit(DETECT_SFP_CHANGE, - &base_vha->dpc_flags) && - !test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) { - qla24xx_detect_sfp(base_vha); - - if (ha->flags.detected_lr_sfp != - ha->flags.using_lr_setting) - set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); + &base_vha->dpc_flags)) { + /* Semantic: + * - NO-OP -- await next ISP-ABORT. Preferred method + * to minimize disruptions that will occur + * when a forced chip-reset occurs. + * - Force -- ISP-ABORT scheduled. + */ + /* set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); */ } if (test_and_clear_bit From a82c307e69c465e4d80cc15fde3c00f5b95832d6 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Wed, 26 Feb 2020 14:40:14 -0800 Subject: [PATCH 0962/4444] scsi: qla2xxx: add more FW debug information Per FW request, MB 1-7 should be logged for 8002 error. Link: https://lore.kernel.org/r/20200226224022.24518-11-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_isr.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 9a14349e8376..117bb2998f19 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -854,12 +854,24 @@ skip_rio: break; case MBA_SYSTEM_ERR: /* System Error */ - mbx = (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || - IS_QLA28XX(ha)) ? - RD_REG_WORD(®24->mailbox7) : 0; - ql_log(ql_log_warn, vha, 0x5003, - "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh " - "mbx7=%xh.\n", mb[1], mb[2], mb[3], mbx); + mbx = 0; + if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || + IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + u16 m[4]; + + m[0] = RD_REG_WORD(®24->mailbox4); + m[1] = RD_REG_WORD(®24->mailbox5); + m[2] = RD_REG_WORD(®24->mailbox6); + mbx = m[3] = RD_REG_WORD(®24->mailbox7); + + ql_log(ql_log_warn, vha, 0x5003, + "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh mbx4=%xh mbx5=%xh mbx6=%xh mbx7=%xh.\n", + mb[1], mb[2], mb[3], m[0], m[1], m[2], m[3]); + } else + ql_log(ql_log_warn, vha, 0x5003, + "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n ", + mb[1], mb[2], mb[3]); + ha->fw_dump_mpi = (IS_QLA27XX(ha) || IS_QLA28XX(ha)) && RD_REG_WORD(®24->mailbox7) & BIT_8; From cad9c2d28ec69f1d0370b2ba5abe309b0b709be4 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Wed, 26 Feb 2020 14:40:15 -0800 Subject: [PATCH 0963/4444] scsi: qla2xxx: Force semaphore on flash validation failure For single port 28XX adapter, the second core can still run in the background. The flash semaphore can be held by the non-active core. This patch tell MPI FW to check for this case and clear the semaphore from the non-active core. Link: https://lore.kernel.org/r/20200226224022.24518-12-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_mbx.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 11a60fb1b9a1..2c01deb5c80d 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -666,10 +666,14 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) struct qla_hw_data *ha = vha->hw; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; + u8 semaphore = 0; +#define EXE_FW_FORCE_SEMAPHORE BIT_7 + u8 retry = 3; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1025, "Entered %s.\n", __func__); +again: mcp->mb[0] = MBC_EXECUTE_FIRMWARE; mcp->out_mb = MBX_0; mcp->in_mb = MBX_0; @@ -711,6 +715,9 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) if (ha->flags.exchoffld_enabled) mcp->mb[4] |= ENABLE_EXCHANGE_OFFLD; + if (semaphore) + mcp->mb[11] |= EXE_FW_FORCE_SEMAPHORE; + mcp->out_mb |= MBX_4 | MBX_3 | MBX_2 | MBX_1 | MBX_11; mcp->in_mb |= MBX_3 | MBX_2 | MBX_1; } else { @@ -727,6 +734,15 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) rval = qla2x00_mailbox_command(vha, mcp); if (rval != QLA_SUCCESS) { + if (IS_QLA28XX(ha) && rval == QLA_COMMAND_ERROR && + mcp->mb[1] == 0x27 && retry) { + semaphore = 1; + retry--; + ql_dbg(ql_dbg_async, vha, 0x1026, + "Exe FW: force semaphore.\n"); + goto again; + } + ql_dbg(ql_dbg_mbx, vha, 0x1026, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); return rval; From 770538c3012ac8ff92d5e4ae18850588c188c5fa Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Wed, 26 Feb 2020 14:40:16 -0800 Subject: [PATCH 0964/4444] scsi: qla2xxx: Fix RDP respond data format RPD information failed to display by switch cli command. This is caused by driver failure to properly format RDP response data with data descriptor to allow switch to parse it correctly. Link: https://lore.kernel.org/r/20200226224022.24518-13-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 102 ++++++++++++++++------------------ 1 file changed, 47 insertions(+), 55 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 7db32f983a93..faf63c2195f2 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -5973,7 +5973,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) &bbc_dma, GFP_KERNEL); /* Prepare Response IOCB */ - memset(rsp_els, 0, sizeof(*rsp_els)); rsp_els->entry_type = ELS_IOCB_TYPE; rsp_els->entry_count = 1; rsp_els->sys_define = 0; @@ -6020,6 +6019,11 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) rsp_payload->ls_req_info_desc2.req_payload_word_0 = cpu_to_be32p((uint32_t *)purex->els_frame_payload); + + rsp_payload->sfp_diag_desc.desc_tag = cpu_to_be32(0x10000); + rsp_payload->sfp_diag_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->sfp_diag_desc)); + if (sfp) { /* SFP Flags */ memset(sfp, 0, SFP_RTDI_LEN); @@ -6043,23 +6047,18 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) sfp_flags |= BIT_6; /* sfp+ */ } + rsp_payload->sfp_diag_desc.sfp_flags = cpu_to_be16(sfp_flags); + /* SFP Diagnostics */ memset(sfp, 0, SFP_RTDI_LEN); rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0x60, 10, 0); - if (!rval && sfp_flags) { + if (!rval) { uint16_t *trx = (void *)sfp; /* already be16 */ - - rsp_payload->sfp_diag_desc.desc_tag = - cpu_to_be32(0x10000); - rsp_payload->sfp_diag_desc.desc_len = - cpu_to_be32(RDP_DESC_LEN(rsp_payload->sfp_diag_desc)); rsp_payload->sfp_diag_desc.temperature = trx[0]; rsp_payload->sfp_diag_desc.vcc = trx[1]; rsp_payload->sfp_diag_desc.tx_bias = trx[2]; rsp_payload->sfp_diag_desc.tx_power = trx[3]; rsp_payload->sfp_diag_desc.rx_power = trx[4]; - rsp_payload->sfp_diag_desc.sfp_flags = - cpu_to_be16(sfp_flags); } } @@ -6072,14 +6071,14 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) rsp_payload->port_speed_desc.operating_speed = cpu_to_be16( qla25xx_rdp_port_speed_currently(ha)); + /* Link Error Status Descriptor */ + rsp_payload->ls_err_desc.desc_tag = cpu_to_be32(0x10002); + rsp_payload->ls_err_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_err_desc)); + if (stat) { rval = qla24xx_get_isp_stats(vha, stat, stat_dma, 0); if (!rval) { - /* Link Error Status Descriptor */ - rsp_payload->ls_err_desc.desc_tag = - cpu_to_be32(0x10002); - rsp_payload->ls_err_desc.desc_len = - cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_err_desc)); rsp_payload->ls_err_desc.link_fail_cnt = cpu_to_be32(stat->link_fail_cnt); rsp_payload->ls_err_desc.loss_sync_cnt = @@ -6118,28 +6117,47 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) vha->fabric_port_name, sizeof(rsp_payload->port_name_direct_desc.WWPN)); + /* Bufer Credit Descriptor */ + rsp_payload->buffer_credit_desc.desc_tag = cpu_to_be32(0x10006); + rsp_payload->buffer_credit_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->buffer_credit_desc)); + rsp_payload->buffer_credit_desc.fcport_b2b = 0; + rsp_payload->buffer_credit_desc.attached_fcport_b2b = cpu_to_be32(0); + rsp_payload->buffer_credit_desc.fcport_rtt = cpu_to_be32(0); + if (bbc) { memset(bbc, 0, sizeof(*bbc)); rval = qla24xx_get_buffer_credits(vha, bbc, bbc_dma); if (!rval) { - /* Bufer Credit Descriptor */ - rsp_payload->buffer_credit_desc.desc_tag = - cpu_to_be32(0x10006); - rsp_payload->buffer_credit_desc.desc_len = - cpu_to_be32(RDP_DESC_LEN( - rsp_payload->buffer_credit_desc)); rsp_payload->buffer_credit_desc.fcport_b2b = cpu_to_be32(LSW(bbc->parameter[0])); - rsp_payload->buffer_credit_desc.attached_fcport_b2b = - cpu_to_be32(0); - rsp_payload->buffer_credit_desc.fcport_rtt = - cpu_to_be32(0); } } if (rsp_payload_length < sizeof(*rsp_payload)) goto send; + /* Optical Element Descriptor, Temperature */ + rsp_payload->optical_elmt_desc[0].desc_tag = cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[0].desc_len = + cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); + /* Optical Element Descriptor, Voltage */ + rsp_payload->optical_elmt_desc[1].desc_tag = cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[1].desc_len = + cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); + /* Optical Element Descriptor, Tx Bias Current */ + rsp_payload->optical_elmt_desc[2].desc_tag = cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[2].desc_len = + cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); + /* Optical Element Descriptor, Tx Power */ + rsp_payload->optical_elmt_desc[3].desc_tag = cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[3].desc_len = + cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); + /* Optical Element Descriptor, Rx Power */ + rsp_payload->optical_elmt_desc[4].desc_tag = cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[4].desc_len = + cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); + if (sfp) { memset(sfp, 0, SFP_RTDI_LEN); rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0, 64, 0); @@ -6147,11 +6165,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) uint16_t *trx = (void *)sfp; /* already be16 */ /* Optical Element Descriptor, Temperature */ - rsp_payload->optical_elmt_desc[0].desc_tag = - cpu_to_be32(0x10007); - rsp_payload->optical_elmt_desc[0].desc_len = - cpu_to_be32(RDP_DESC_LEN( - *rsp_payload->optical_elmt_desc)); rsp_payload->optical_elmt_desc[0].high_alarm = trx[0]; rsp_payload->optical_elmt_desc[0].low_alarm = trx[1]; rsp_payload->optical_elmt_desc[0].high_warn = trx[2]; @@ -6160,11 +6173,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) cpu_to_be32(1 << 28); /* Optical Element Descriptor, Voltage */ - rsp_payload->optical_elmt_desc[1].desc_tag = - cpu_to_be32(0x10007); - rsp_payload->optical_elmt_desc[1].desc_len = - cpu_to_be32(RDP_DESC_LEN( - *rsp_payload->optical_elmt_desc)); rsp_payload->optical_elmt_desc[1].high_alarm = trx[4]; rsp_payload->optical_elmt_desc[1].low_alarm = trx[5]; rsp_payload->optical_elmt_desc[1].high_warn = trx[6]; @@ -6173,11 +6181,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) cpu_to_be32(2 << 28); /* Optical Element Descriptor, Tx Bias Current */ - rsp_payload->optical_elmt_desc[2].desc_tag = - cpu_to_be32(0x10007); - rsp_payload->optical_elmt_desc[2].desc_len = - cpu_to_be32(RDP_DESC_LEN( - *rsp_payload->optical_elmt_desc)); rsp_payload->optical_elmt_desc[2].high_alarm = trx[8]; rsp_payload->optical_elmt_desc[2].low_alarm = trx[9]; rsp_payload->optical_elmt_desc[2].high_warn = trx[10]; @@ -6186,11 +6189,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) cpu_to_be32(3 << 28); /* Optical Element Descriptor, Tx Power */ - rsp_payload->optical_elmt_desc[3].desc_tag = - cpu_to_be32(0x10007); - rsp_payload->optical_elmt_desc[3].desc_len = - cpu_to_be32(RDP_DESC_LEN( - *rsp_payload->optical_elmt_desc)); rsp_payload->optical_elmt_desc[3].high_alarm = trx[12]; rsp_payload->optical_elmt_desc[3].low_alarm = trx[13]; rsp_payload->optical_elmt_desc[3].high_warn = trx[14]; @@ -6199,11 +6197,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) cpu_to_be32(4 << 28); /* Optical Element Descriptor, Rx Power */ - rsp_payload->optical_elmt_desc[4].desc_tag = - cpu_to_be32(0x10007); - rsp_payload->optical_elmt_desc[4].desc_len = - cpu_to_be32(RDP_DESC_LEN( - *rsp_payload->optical_elmt_desc)); rsp_payload->optical_elmt_desc[4].high_alarm = trx[16]; rsp_payload->optical_elmt_desc[4].low_alarm = trx[17]; rsp_payload->optical_elmt_desc[4].high_warn = trx[18]; @@ -6257,16 +6250,15 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) } } + /* Optical Product Data Descriptor */ + rsp_payload->optical_prod_desc.desc_tag = cpu_to_be32(0x10008); + rsp_payload->optical_prod_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->optical_prod_desc)); + if (sfp) { memset(sfp, 0, SFP_RTDI_LEN); rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 20, 64, 0); if (!rval) { - /* Optical Product Data Descriptor */ - rsp_payload->optical_prod_desc.desc_tag = - cpu_to_be32(0x10008); - rsp_payload->optical_prod_desc.desc_len = - cpu_to_be32(RDP_DESC_LEN( - rsp_payload->optical_prod_desc)); memcpy(rsp_payload->optical_prod_desc.vendor_name, sfp + 0, sizeof(rsp_payload->optical_prod_desc.vendor_name)); From ab391abdc191c2a2874098df86d1fe4b9762ef60 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Wed, 26 Feb 2020 14:40:17 -0800 Subject: [PATCH 0965/4444] scsi: qla2xxx: Fix NPIV instantiation after FW dump NPIV re-enable code was blocked after FW had been initialized. The blocking check was too broad. Reduce the check to make sure if FW is initialized or not. Link: https://lore.kernel.org/r/20200226224022.24518-14-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_mbx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 2c01deb5c80d..dee7edc1a3f2 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1387,7 +1387,7 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (qla2x00_chip_is_down(vha)) + if (!vha->hw->flags.fw_started) return QLA_INVALID_COMMAND; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1038, From 11efe8755d73efd153d6459240866b6d52448f19 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Wed, 26 Feb 2020 14:40:18 -0800 Subject: [PATCH 0966/4444] scsi: qla2xxx: Serialize fc_port alloc in N2N For N2N, fc_port struct is created during report id acquisition. At later time, the loop resync (fabric, n2n, loop) would trigger the rest of the login using the created fc_port struct. The loop resync logic can trigger another fc_port allocation if the 1st allocation was not able to execute. This patch prevents the 2nd allocation trigger. Link: https://lore.kernel.org/r/20200226224022.24518-15-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 1 + drivers/scsi/qla2xxx/qla_os.c | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 3d615cc959cc..5b2deaa730bf 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -5147,6 +5147,7 @@ skip_login: set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); } + return QLA_FUNCTION_FAILED; } found_devs = 0; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index faf63c2195f2..96b654c63aa4 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -5203,9 +5203,8 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) fcport->n2n_flag = 1; } fcport->fw_login_state = 0; - /* - * wait link init done before sending login - */ + + schedule_delayed_work(&vha->scan.scan_work, 5); } else { qla24xx_fcport_handle_login(vha, fcport); } From 3e4615a292b47632d409f0d53a23da85e039b031 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Wed, 26 Feb 2020 14:40:19 -0800 Subject: [PATCH 0967/4444] scsi: qla2xxx: Remove restriction of FC T10-PI and FC-NVMe T10-PI and FC-NVMe are not mutually exclusive. This patch removes restrictions where if FC-NVMe is enabled T10-PI defaults to disabled. Link: https://lore.kernel.org/r/20200226224022.24518-16-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 96b654c63aa4..3e65b8e9ed47 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -123,11 +123,7 @@ MODULE_PARM_DESC(ql2xmaxqdepth, "Maximum queue depth to set for each LUN. " "Default is 64."); -#if (IS_ENABLED(CONFIG_NVME_FC)) -int ql2xenabledif; -#else int ql2xenabledif = 2; -#endif module_param(ql2xenabledif, int, S_IRUGO); MODULE_PARM_DESC(ql2xenabledif, " Enable T10-CRC-DIF:\n" From 3d582b34992ba2fe4065f01019f0c08d12916faa Mon Sep 17 00:00:00 2001 From: Arun Easi Date: Wed, 26 Feb 2020 14:40:20 -0800 Subject: [PATCH 0968/4444] scsi: qla2xxx: Handle NVME status iocb correctly Certain state flags bit combinations are not checked and not handled correctly. Plus, do not log a normal underrun situation where there is no frame drop. Link: https://lore.kernel.org/r/20200226224022.24518-17-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Arun Easi Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_isr.c | 47 ++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 117bb2998f19..8d7a905f6247 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -2064,6 +2064,7 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, struct nvmefc_fcp_req *fd; uint16_t ret = QLA_SUCCESS; uint16_t comp_status = le16_to_cpu(sts->comp_status); + int logit = 0; iocb = &sp->u.iocb_cmd; fcport = sp->fcport; @@ -2074,6 +2075,12 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, if (unlikely(iocb->u.nvme.aen_op)) atomic_dec(&sp->vha->hw->nvme_active_aen_cnt); + if (unlikely(comp_status != CS_COMPLETE)) + logit = 1; + + fd->transferred_length = fd->payload_length - + le32_to_cpu(sts->residual_len); + /* * State flags: Bit 6 and 0. * If 0 is set, we don't care about 6. @@ -2084,8 +2091,20 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, */ if (!(state_flags & (SF_FCP_RSP_DMA | SF_NVME_ERSP))) { iocb->u.nvme.rsp_pyld_len = 0; - } else if ((state_flags & SF_FCP_RSP_DMA)) { + } else if ((state_flags & (SF_FCP_RSP_DMA | SF_NVME_ERSP)) == + (SF_FCP_RSP_DMA | SF_NVME_ERSP)) { + /* Response already DMA'd to fd->rspaddr. */ iocb->u.nvme.rsp_pyld_len = le16_to_cpu(sts->nvme_rsp_pyld_len); + } else if ((state_flags & SF_FCP_RSP_DMA)) { + /* + * Non-zero value in first 12 bytes of NVMe_RSP IU, treat this + * as an error. + */ + iocb->u.nvme.rsp_pyld_len = 0; + fd->transferred_length = 0; + ql_dbg(ql_dbg_io, fcport->vha, 0x307a, + "Unexpected values in NVMe_RSP IU.\n"); + logit = 1; } else if (state_flags & SF_NVME_ERSP) { uint32_t *inbuf, *outbuf; uint16_t iter; @@ -2108,16 +2127,28 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, iter = iocb->u.nvme.rsp_pyld_len >> 2; for (; iter; iter--) *outbuf++ = swab32(*inbuf++); - } else { /* unhandled case */ - ql_log(ql_log_warn, fcport->vha, 0x503a, - "NVME-%s error. Unhandled state_flags of %x\n", - sp->name, state_flags); } - fd->transferred_length = fd->payload_length - - le32_to_cpu(sts->residual_len); + if (state_flags & SF_NVME_ERSP) { + struct nvme_fc_ersp_iu *rsp_iu = fd->rspaddr; + u32 tgt_xfer_len; - if (unlikely(comp_status != CS_COMPLETE)) + tgt_xfer_len = be32_to_cpu(rsp_iu->xfrd_len); + if (fd->transferred_length != tgt_xfer_len) { + ql_dbg(ql_dbg_io, fcport->vha, 0x3079, + "Dropped frame(s) detected (sent/rcvd=%u/%u).\n", + tgt_xfer_len, fd->transferred_length); + logit = 1; + } else if (comp_status == CS_DATA_UNDERRUN) { + /* + * Do not log if this is just an underflow and there + * is no data loss. + */ + logit = 0; + } + } + + if (unlikely(logit)) ql_log(ql_log_warn, fcport->vha, 0x5060, "NVME-%s ERR Handling - hdl=%x status(%x) tr_len:%x resid=%x ox_id=%x\n", sp->name, sp->handle, comp_status, From ad8a260aa80d4dfa9588fd5d23b71ec922f61c8b Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Wed, 26 Feb 2020 14:40:21 -0800 Subject: [PATCH 0969/4444] scsi: qla2xxx: Set Nport ID for N2N When transitioning from loop to N2N, stale NPort ID is not re-assigned. Stale ID can collide with remote device. This patch will re-assign NPort ID on N2N is detected. Link: https://lore.kernel.org/r/20200226224022.24518-18-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_mbx.c | 42 +++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index dee7edc1a3f2..9fd83d1bffe0 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -3924,11 +3924,29 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, fcport->scan_state = QLA_FCPORT_SCAN; fcport->n2n_flag = 0; } + id.b24 = 0; + if (wwn_to_u64(vha->port_name) > + wwn_to_u64(rptid_entry->u.f1.port_name)) { + vha->d_id.b24 = 0; + vha->d_id.b.al_pa = 1; + ha->flags.n2n_bigger = 1; + + id.b.al_pa = 2; + ql_dbg(ql_dbg_async, vha, 0x5075, + "Format 1: assign local id %x remote id %x\n", + vha->d_id.b24, id.b24); + } else { + ql_dbg(ql_dbg_async, vha, 0x5075, + "Format 1: Remote login - Waiting for WWPN %8phC.\n", + rptid_entry->u.f1.port_name); + ha->flags.n2n_bigger = 0; + } fcport = qla2x00_find_fcport_by_wwpn(vha, rptid_entry->u.f1.port_name, 1); spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); + if (fcport) { fcport->plogi_nack_done_deadline = jiffies + HZ; fcport->dm_login_expire = jiffies + 2*HZ; @@ -3939,6 +3957,11 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, if (vha->flags.nvme_enabled) fcport->fc4_type |= FS_FC4TYPE_NVME; + if (wwn_to_u64(vha->port_name) > + wwn_to_u64(fcport->port_name)) { + fcport->d_id = id; + } + switch (fcport->disc_state) { case DSC_DELETED: set_bit(RELOGIN_NEEDED, @@ -3951,25 +3974,6 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, break; } } else { - id.b24 = 0; - if (wwn_to_u64(vha->port_name) > - wwn_to_u64(rptid_entry->u.f1.port_name)) { - vha->d_id.b24 = 0; - vha->d_id.b.al_pa = 1; - ha->flags.n2n_bigger = 1; - ha->flags.n2n_ae = 0; - - id.b.al_pa = 2; - ql_dbg(ql_dbg_async, vha, 0x5075, - "Format 1: assign local id %x remote id %x\n", - vha->d_id.b24, id.b24); - } else { - ql_dbg(ql_dbg_async, vha, 0x5075, - "Format 1: Remote login - Waiting for WWPN %8phC.\n", - rptid_entry->u.f1.port_name); - ha->flags.n2n_bigger = 0; - ha->flags.n2n_ae = 1; - } qla24xx_post_newsess_work(vha, &id, rptid_entry->u.f1.port_name, rptid_entry->u.f1.node_name, From 4cbca7ea9edaab268f344c2bcd22afcb7370569f Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Wed, 26 Feb 2020 14:40:22 -0800 Subject: [PATCH 0970/4444] scsi: qla2xxx: Update driver version to 10.01.00.25-k Link: https://lore.kernel.org/r/20200226224022.24518-19-hmadhani@marvell.com Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 6b4ca3ed8f22..8ccd9ba1ddef 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.01.00.24-k" +#define QLA2XXX_VERSION "10.01.00.25-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 1 From 492001990f641b0d0df4dbd45c759785fda76f5b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 21 Feb 2020 06:08:11 -0800 Subject: [PATCH 0971/4444] scsi: ufshcd: remove unused quirks Remove various quirks that don't have users, as well as the dead code keyed off them. Link: https://lore.kernel.org/r/20200221140812.476338-2-hch@lst.de Reviewed-by: Bart Van Assche Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 119 ++++---------------------------------- drivers/scsi/ufs/ufshcd.h | 22 ------- 2 files changed, 12 insertions(+), 129 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index f4aa10fdbb0c..b1387ea5ab89 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -645,11 +645,7 @@ static inline int ufshcd_get_tr_ocs(struct ufshcd_lrb *lrbp) */ static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos) { - if (hba->quirks & UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR) - ufshcd_writel(hba, (1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR); - else - ufshcd_writel(hba, ~(1 << pos), - REG_UTP_TRANSFER_REQ_LIST_CLEAR); + ufshcd_writel(hba, ~(1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR); } /** @@ -659,10 +655,7 @@ static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos) */ static inline void ufshcd_utmrl_clear(struct ufs_hba *hba, u32 pos) { - if (hba->quirks & UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR) - ufshcd_writel(hba, (1 << pos), REG_UTP_TASK_REQ_LIST_CLEAR); - else - ufshcd_writel(hba, ~(1 << pos), REG_UTP_TASK_REQ_LIST_CLEAR); + ufshcd_writel(hba, ~(1 << pos), REG_UTP_TASK_REQ_LIST_CLEAR); } /** @@ -2101,13 +2094,8 @@ static int ufshcd_map_sg(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) return sg_segments; if (sg_segments) { - if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN) - lrbp->utr_descriptor_ptr->prd_table_length = - cpu_to_le16((u16)(sg_segments * - sizeof(struct ufshcd_sg_entry))); - else - lrbp->utr_descriptor_ptr->prd_table_length = - cpu_to_le16((u16) (sg_segments)); + lrbp->utr_descriptor_ptr->prd_table_length = + cpu_to_le16((u16)sg_segments); prd_table = (struct ufshcd_sg_entry *)lrbp->ucd_prdt_ptr; @@ -3436,21 +3424,11 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba) cpu_to_le32(upper_32_bits(cmd_desc_element_addr)); /* Response upiu and prdt offset should be in double words */ - if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN) { - utrdlp[i].response_upiu_offset = - cpu_to_le16(response_offset); - utrdlp[i].prd_table_offset = - cpu_to_le16(prdt_offset); - utrdlp[i].response_upiu_length = - cpu_to_le16(ALIGNED_UPIU_SIZE); - } else { - utrdlp[i].response_upiu_offset = - cpu_to_le16((response_offset >> 2)); - utrdlp[i].prd_table_offset = - cpu_to_le16((prdt_offset >> 2)); - utrdlp[i].response_upiu_length = - cpu_to_le16(ALIGNED_UPIU_SIZE >> 2); - } + utrdlp[i].response_upiu_offset = + cpu_to_le16(response_offset >> 2); + utrdlp[i].prd_table_offset = cpu_to_le16(prdt_offset >> 2); + utrdlp[i].response_upiu_length = + cpu_to_le16(ALIGNED_UPIU_SIZE >> 2); hba->lrb[i].utr_descriptor_ptr = (utrdlp + i); hba->lrb[i].utrd_dma_addr = hba->utrdl_dma_addr + @@ -3493,52 +3471,6 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) "dme-link-startup: error code %d\n", ret); return ret; } -/** - * ufshcd_dme_reset - UIC command for DME_RESET - * @hba: per adapter instance - * - * DME_RESET command is issued in order to reset UniPro stack. - * This function now deal with cold reset. - * - * Returns 0 on success, non-zero value on failure - */ -static int ufshcd_dme_reset(struct ufs_hba *hba) -{ - struct uic_command uic_cmd = {0}; - int ret; - - uic_cmd.command = UIC_CMD_DME_RESET; - - ret = ufshcd_send_uic_cmd(hba, &uic_cmd); - if (ret) - dev_err(hba->dev, - "dme-reset: error code %d\n", ret); - - return ret; -} - -/** - * ufshcd_dme_enable - UIC command for DME_ENABLE - * @hba: per adapter instance - * - * DME_ENABLE command is issued in order to enable UniPro stack. - * - * Returns 0 on success, non-zero value on failure - */ -static int ufshcd_dme_enable(struct ufs_hba *hba) -{ - struct uic_command uic_cmd = {0}; - int ret; - - uic_cmd.command = UIC_CMD_DME_ENABLE; - - ret = ufshcd_send_uic_cmd(hba, &uic_cmd); - if (ret) - dev_err(hba->dev, - "dme-reset: error code %d\n", ret); - - return ret; -} static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba) { @@ -4250,7 +4182,7 @@ static inline void ufshcd_hba_stop(struct ufs_hba *hba, bool can_sleep) } /** - * ufshcd_hba_execute_hce - initialize the controller + * ufshcd_hba_enable - initialize the controller * @hba: per adapter instance * * The controller resets itself and controller firmware initialization @@ -4259,7 +4191,7 @@ static inline void ufshcd_hba_stop(struct ufs_hba *hba, bool can_sleep) * * Returns 0 on success, non-zero value on failure */ -static int ufshcd_hba_execute_hce(struct ufs_hba *hba) +int ufshcd_hba_enable(struct ufs_hba *hba) { int retry; @@ -4307,32 +4239,6 @@ static int ufshcd_hba_execute_hce(struct ufs_hba *hba) return 0; } - -int ufshcd_hba_enable(struct ufs_hba *hba) -{ - int ret; - - if (hba->quirks & UFSHCI_QUIRK_BROKEN_HCE) { - ufshcd_set_link_off(hba); - ufshcd_vops_hce_enable_notify(hba, PRE_CHANGE); - - /* enable UIC related interrupts */ - ufshcd_enable_intr(hba, UFSHCD_UIC_MASK); - ret = ufshcd_dme_reset(hba); - if (!ret) { - ret = ufshcd_dme_enable(hba); - if (!ret) - ufshcd_vops_hce_enable_notify(hba, POST_CHANGE); - if (ret) - dev_err(hba->dev, - "Host controller enable failed with non-hce\n"); - } - } else { - ret = ufshcd_hba_execute_hce(hba); - } - - return ret; -} EXPORT_SYMBOL_GPL(ufshcd_hba_enable); static int ufshcd_disable_tx_lcc(struct ufs_hba *hba, bool peer) @@ -4909,8 +4815,7 @@ static irqreturn_t ufshcd_transfer_req_compl(struct ufs_hba *hba) * false interrupt if device completes another request after resetting * aggregation and before reading the DB. */ - if (ufshcd_is_intr_aggr_allowed(hba) && - !(hba->quirks & UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR)) + if (ufshcd_is_intr_aggr_allowed(hba)) ufshcd_reset_intr_aggr(hba); tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 8f516b205c32..6f22f466668f 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -613,28 +613,6 @@ struct ufs_hba { */ #define UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION 0x20 - /* - * This quirk needs to be enabled if the host contoller regards - * resolution of the values of PRDTO and PRDTL in UTRD as byte. - */ - #define UFSHCD_QUIRK_PRDT_BYTE_GRAN 0x80 - - /* - * Clear handling for transfer/task request list is just opposite. - */ - #define UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR 0x100 - - /* - * This quirk needs to be enabled if host controller doesn't allow - * that the interrupt aggregation timer and counter are reset by s/w. - */ - #define UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR 0x200 - - /* - * This quirks needs to be enabled if host controller cannot be - * enabled via HCE register. - */ - #define UFSHCI_QUIRK_BROKEN_HCE 0x400 unsigned int quirks; /* Deviations from standard UFSHCI spec. */ /* Device deviations from standard UFS device spec. */ From c3f7d1fcb4a26a0f2a45e0e3bd8a1acc19481b8c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 21 Feb 2020 06:08:12 -0800 Subject: [PATCH 0972/4444] scsi: ufshcd: use an enum for quirks Use an enum to specify the various quirks instead of #defines inside the structure definition. [mkp: fix typo] Link: https://lore.kernel.org/r/20200221140812.476338-3-hch@lst.de Reviewed-by: Bart Van Assche Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.h | 82 ++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 6f22f466668f..d45a04444191 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -470,6 +470,48 @@ struct ufs_stats { struct ufs_err_reg_hist task_abort; }; +enum ufshcd_quirks { + /* Interrupt aggregation support is broken */ + UFSHCD_QUIRK_BROKEN_INTR_AGGR = 1 << 0, + + /* + * delay before each dme command is required as the unipro + * layer has shown instabilities + */ + UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS = 1 << 1, + + /* + * If UFS host controller is having issue in processing LCC (Line + * Control Command) coming from device then enable this quirk. + * When this quirk is enabled, host controller driver should disable + * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE + * attribute of device to 0). + */ + UFSHCD_QUIRK_BROKEN_LCC = 1 << 2, + + /* + * The attribute PA_RXHSUNTERMCAP specifies whether or not the + * inbound Link supports unterminated line in HS mode. Setting this + * attribute to 1 fixes moving to HS gear. + */ + UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP = 1 << 3, + + /* + * This quirk needs to be enabled if the host controller only allows + * accessing the peer dme attributes in AUTO mode (FAST AUTO or + * SLOW AUTO). + */ + UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE = 1 << 4, + + /* + * This quirk needs to be enabled if the host controller doesn't + * advertise the correct version in UFS_VER register. If this quirk + * is enabled, standard UFS host driver will call the vendor specific + * ops (get_ufs_hci_version) to get the correct version. + */ + UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION = 1 << 5, +}; + /** * struct ufs_hba - per adapter private structure * @mmio_base: UFSHCI base register address @@ -573,46 +615,6 @@ struct ufs_hba { bool is_irq_enabled; enum ufs_ref_clk_freq dev_ref_clk_freq; - /* Interrupt aggregation support is broken */ - #define UFSHCD_QUIRK_BROKEN_INTR_AGGR 0x1 - - /* - * delay before each dme command is required as the unipro - * layer has shown instabilities - */ - #define UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS 0x2 - - /* - * If UFS host controller is having issue in processing LCC (Line - * Control Command) coming from device then enable this quirk. - * When this quirk is enabled, host controller driver should disable - * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE - * attribute of device to 0). - */ - #define UFSHCD_QUIRK_BROKEN_LCC 0x4 - - /* - * The attribute PA_RXHSUNTERMCAP specifies whether or not the - * inbound Link supports unterminated line in HS mode. Setting this - * attribute to 1 fixes moving to HS gear. - */ - #define UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP 0x8 - - /* - * This quirk needs to be enabled if the host contoller only allows - * accessing the peer dme attributes in AUTO mode (FAST AUTO or - * SLOW AUTO). - */ - #define UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE 0x10 - - /* - * This quirk needs to be enabled if the host contoller doesn't - * advertise the correct version in UFS_VER register. If this quirk - * is enabled, standard UFS host driver will call the vendor specific - * ops (get_ufs_hci_version) to get the correct version. - */ - #define UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION 0x20 - unsigned int quirks; /* Deviations from standard UFSHCI spec. */ /* Device deviations from standard UFS device spec. */ From e91ed9e0e4fa4ff913edb6e29c53f6a365e95609 Mon Sep 17 00:00:00 2001 From: Can Guo Date: Sun, 23 Feb 2020 20:09:21 -0800 Subject: [PATCH 0973/4444] scsi: ufs: Allow vendor device quirks to be applied early Currently ufshcd_vops_apply_dev_quirks() comes after all UniPro parameters have been tuned. Move it up so that vendors have a chance to apply device quirks in advance. Link: https://lore.kernel.org/r/1582517363-11536-2-git-send-email-cang@codeaurora.org Reviewed-by: Stanley Chu Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index b1387ea5ab89..68fbbdeefbfa 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6761,14 +6761,14 @@ static void ufshcd_tune_unipro_params(struct ufs_hba *hba) ufshcd_tune_pa_hibern8time(hba); } + ufshcd_vops_apply_dev_quirks(hba); + if (hba->dev_quirks & UFS_DEVICE_QUIRK_PA_TACTIVATE) /* set 1ms timeout for PA_TACTIVATE */ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 10); if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE) ufshcd_quirk_tune_host_pa_tactivate(hba); - - ufshcd_vops_apply_dev_quirks(hba); } static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba) From 27ff2c60e095fb541251d0f90f9ea41f2b5f0f4f Mon Sep 17 00:00:00 2001 From: Can Guo Date: Sun, 23 Feb 2020 20:09:22 -0800 Subject: [PATCH 0974/4444] scsi: ufs-qcom: Apply QUIRK_HOST_TACTIVATE for WDC UFS devices Western Digital UFS devices require host's PA_TACTIVATE to be lower than device's PA_TACTIVATE, otherwise it may get stuck during hibern8 sequence. Link: https://lore.kernel.org/r/1582517363-11536-3-git-send-email-cang@codeaurora.org Reviewed-by: Asutosh Das Acked-by: Avri Altman Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-qcom.c | 3 +++ drivers/scsi/ufs/ufs_quirks.h | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 8339050f0af2..6115ac62d46c 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1012,6 +1012,9 @@ static int ufs_qcom_apply_dev_quirks(struct ufs_hba *hba) if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME) err = ufs_qcom_quirk_host_pa_saveconfigtime(hba); + if (hba->dev_info.wmanufacturerid == UFS_VENDOR_WDC) + hba->dev_quirks |= UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE; + return err; } diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h index d0ab147f98d3..df7a1e6805a3 100644 --- a/drivers/scsi/ufs/ufs_quirks.h +++ b/drivers/scsi/ufs/ufs_quirks.h @@ -15,6 +15,7 @@ #define UFS_VENDOR_TOSHIBA 0x198 #define UFS_VENDOR_SAMSUNG 0x1CE #define UFS_VENDOR_SKHYNIX 0x1AD +#define UFS_VENDOR_WDC 0x145 /** * ufs_dev_fix - ufs device quirk info From b3222c326c965f94b2e8e8ac73dc395ca82cd088 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Thu, 20 Feb 2020 21:48:48 +0800 Subject: [PATCH 0975/4444] scsi: ufs: ufs-mediatek: add waiting time for reference clock Some delays may be required either after gating or before ungating reference clock for device according to vendor requirements. Note that in UFS 3.0, the delay time after gating reference clock can be defined by attribute bRefClkGatingWaitTime. Use the formal value instead if it can be queried from device. Link: https://lore.kernel.org/r/20200220134848.8807-2-stanley.chu@mediatek.com Reviewed-by: Bean Huo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-mediatek.c | 46 +++++++++++++++++++++++++++++++-- drivers/scsi/ufs/ufs-mediatek.h | 2 ++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 9d05962feb15..de650822c9d9 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -100,6 +100,17 @@ static int ufs_mtk_bind_mphy(struct ufs_hba *hba) return err; } +static void ufs_mtk_udelay(unsigned long us) +{ + if (!us) + return; + + if (us < 10) + udelay(us); + else + usleep_range(us, us + 10); +} + static int ufs_mtk_setup_ref_clk(struct ufs_hba *hba, bool on) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); @@ -112,6 +123,7 @@ static int ufs_mtk_setup_ref_clk(struct ufs_hba *hba, bool on) if (on) { ufs_mtk_ref_clk_notify(on, res); + ufs_mtk_udelay(host->ref_clk_ungating_wait_us); ufshcd_writel(hba, REFCLK_REQUEST, REG_UFS_REFCLK_CTRL); } else { ufshcd_writel(hba, REFCLK_RELEASE, REG_UFS_REFCLK_CTRL); @@ -137,12 +149,29 @@ static int ufs_mtk_setup_ref_clk(struct ufs_hba *hba, bool on) out: host->ref_clk_enabled = on; - if (!on) + if (!on) { + ufs_mtk_udelay(host->ref_clk_gating_wait_us); ufs_mtk_ref_clk_notify(on, res); + } return 0; } +static void ufs_mtk_setup_ref_clk_wait_us(struct ufs_hba *hba, + u16 gating_us, u16 ungating_us) +{ + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + + if (hba->dev_info.clk_gating_wait_us) { + host->ref_clk_gating_wait_us = + hba->dev_info.clk_gating_wait_us; + } else { + host->ref_clk_gating_wait_us = gating_us; + } + + host->ref_clk_ungating_wait_us = ungating_us; +} + static u32 ufs_mtk_link_get_state(struct ufs_hba *hba) { u32 val; @@ -502,10 +531,23 @@ static void ufs_mtk_dbg_register_dump(struct ufs_hba *hba) static int ufs_mtk_apply_dev_quirks(struct ufs_hba *hba) { struct ufs_dev_info *dev_info = &hba->dev_info; + u16 mid = dev_info->wmanufacturerid; - if (dev_info->wmanufacturerid == UFS_VENDOR_SAMSUNG) + if (mid == UFS_VENDOR_SAMSUNG) ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 6); + /* + * Decide waiting time before gating reference clock and + * after ungating reference clock according to vendors' + * requirements. + */ + if (mid == UFS_VENDOR_SAMSUNG) + ufs_mtk_setup_ref_clk_wait_us(hba, 1, 1); + else if (mid == UFS_VENDOR_SKHYNIX) + ufs_mtk_setup_ref_clk_wait_us(hba, 30, 30); + else if (mid == UFS_VENDOR_TOSHIBA) + ufs_mtk_setup_ref_clk_wait_us(hba, 100, 32); + return 0; } diff --git a/drivers/scsi/ufs/ufs-mediatek.h b/drivers/scsi/ufs/ufs-mediatek.h index 492414e5f481..4c787b99fe41 100644 --- a/drivers/scsi/ufs/ufs-mediatek.h +++ b/drivers/scsi/ufs/ufs-mediatek.h @@ -92,6 +92,8 @@ struct ufs_mtk_host { struct ufs_hba *hba; struct phy *mphy; bool ref_clk_enabled; + u16 ref_clk_ungating_wait_us; + u16 ref_clk_gating_wait_us; }; #endif /* !_UFS_MEDIATEK_H */ From 9e7bd945b9a95267872099c03a00e134951062c0 Mon Sep 17 00:00:00 2001 From: Guosong Su Date: Tue, 25 Feb 2020 18:04:11 +0800 Subject: [PATCH 0976/4444] scsi: core: use kobj_to_dev Use kobj_to_dev to instead of open-coding it. Link: https://lore.kernel.org/r/20200225100411.10250-1-guosongsu@gmail.com Reviewed-by: Bart Van Assche Signed-off-by: Guosong Su Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_sysfs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 677b5c5403d2..c3a30ba4ae08 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -856,7 +856,7 @@ show_vpd_##_page(struct file *filp, struct kobject *kobj, \ struct bin_attribute *bin_attr, \ char *buf, loff_t off, size_t count) \ { \ - struct device *dev = container_of(kobj, struct device, kobj); \ + struct device *dev = kobj_to_dev(kobj); \ struct scsi_device *sdev = to_scsi_device(dev); \ struct scsi_vpd *vpd_page; \ int ret = -EINVAL; \ @@ -884,7 +884,7 @@ static ssize_t show_inquiry(struct file *filep, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct scsi_device *sdev = to_scsi_device(dev); if (!sdev->inquiry) @@ -1181,7 +1181,7 @@ static DEVICE_ATTR(queue_ramp_up_period, S_IRUGO | S_IWUSR, static umode_t scsi_sdev_attr_is_visible(struct kobject *kobj, struct attribute *attr, int i) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct scsi_device *sdev = to_scsi_device(dev); @@ -1207,7 +1207,7 @@ static umode_t scsi_sdev_attr_is_visible(struct kobject *kobj, static umode_t scsi_sdev_bin_attr_is_visible(struct kobject *kobj, struct bin_attribute *attr, int i) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct scsi_device *sdev = to_scsi_device(dev); From 22f0ba4a2825f9cb87c142f7fcd3bf3d496ded0f Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 28 Feb 2020 08:53:06 +0100 Subject: [PATCH 0977/4444] scsi: dpt_i2o: rename adpt_i2o_to_scsi() to adpt_i2o_scsi_complete() Rename the badly named function into adpt_i2o_scsi_complete(), and make it a void function as the return value is never used. This also fixes a potential use-after-free as the return value might be evaluated from the command result after the command has been freed. Link: https://lore.kernel.org/r/20200228075318.91255-2-hare@suse.de Reviewed-by: Christoph Hellwig Reviewed-by: Bart Van Assche Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/dpt_i2o.c | 5 ++--- drivers/scsi/dpti.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index abc74fd474dc..c30ace9f251e 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -2173,7 +2173,7 @@ static irqreturn_t adpt_isr(int irq, void *dev_id) readl(reply + 12) - 1); if(cmd != NULL){ scsi_dma_unmap(cmd); - adpt_i2o_to_scsi(reply, cmd); + adpt_i2o_scsi_complete(reply, cmd); } } writel(m, pHba->reply_port); @@ -2341,7 +2341,7 @@ static s32 adpt_scsi_host_alloc(adpt_hba* pHba, struct scsi_host_template *sht) } -static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) +static void adpt_i2o_scsi_complete(void __iomem *reply, struct scsi_cmnd *cmd) { adpt_hba* pHba; u32 hba_status; @@ -2459,7 +2459,6 @@ static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) if(cmd->scsi_done != NULL){ cmd->scsi_done(cmd); } - return cmd->result; } diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h index 42b1e28b5884..3ec391134bb0 100644 --- a/drivers/scsi/dpti.h +++ b/drivers/scsi/dpti.h @@ -286,7 +286,7 @@ static s32 adpt_i2o_status_get(adpt_hba* pHba); static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba); static s32 adpt_i2o_hrt_get(adpt_hba* pHba); static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* dptdevice); -static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd); +static void adpt_i2o_scsi_complete(void __iomem *reply, struct scsi_cmnd *cmd); static s32 adpt_scsi_host_alloc(adpt_hba* pHba,struct scsi_host_template * sht); static s32 adpt_hba_reset(adpt_hba* pHba); static s32 adpt_i2o_reset_hba(adpt_hba* pHba); From 466552b9f3730f06fee75776a208f5fa9c06c6a3 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 28 Feb 2020 08:53:07 +0100 Subject: [PATCH 0978/4444] scsi: core: add scsi_host_complete_all_commands() helper Add a helper scsi_host_complete_all_commands() to terminate all outstanding commands on a SCSI host. Link: https://lore.kernel.org/r/20200228075318.91255-3-hare@suse.de Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/hosts.c | 28 ++++++++++++++++++++++++++++ include/scsi/scsi_host.h | 2 ++ 2 files changed, 30 insertions(+) diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 1d669e47b692..00ae9d43ce9f 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -650,3 +650,31 @@ void scsi_flush_work(struct Scsi_Host *shost) flush_workqueue(shost->work_q); } EXPORT_SYMBOL_GPL(scsi_flush_work); + +static bool complete_all_cmds_iter(struct request *rq, void *data, bool rsvd) +{ + struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq); + int status = *(int *)data; + + scsi_dma_unmap(scmd); + scmd->result = status << 16; + scmd->scsi_done(scmd); + return true; +} + +/** + * scsi_host_complete_all_commands - Terminate all running commands + * @shost: Scsi Host on which commands should be terminated + * @status: Status to be set for the terminated commands + * + * There is no protection against modification of the number + * of outstanding commands. It is the responsibility of the + * caller to ensure that concurrent I/O submission and/or + * completion is stopped when calling this function. + */ +void scsi_host_complete_all_commands(struct Scsi_Host *shost, int status) +{ + blk_mq_tagset_busy_iter(&shost->tag_set, complete_all_cmds_iter, + &status); +} +EXPORT_SYMBOL_GPL(scsi_host_complete_all_commands); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 7a97fb8104cf..25bef781cbe1 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -732,6 +732,8 @@ extern int scsi_host_busy(struct Scsi_Host *shost); extern void scsi_host_put(struct Scsi_Host *t); extern struct Scsi_Host *scsi_host_lookup(unsigned short); extern const char *scsi_host_state_name(enum scsi_host_state); +extern void scsi_host_complete_all_commands(struct Scsi_Host *shost, + int status); static inline int __must_check scsi_add_host(struct Scsi_Host *host, struct device *dev) From 84ff9532e5308d04f97f032a434021ba1b01b6a3 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 28 Feb 2020 08:53:08 +0100 Subject: [PATCH 0979/4444] scsi: dpt_i2o: use scsi_host_complete_all_commands() to abort outstanding commands Rather than traversing all outstanding commands manually, use the scsi_host_complete_all_commands() helper to terminate all commands during reset. With that we can drop the cmd_list usage from the midlayer. Link: https://lore.kernel.org/r/20200228075318.91255-4-hare@suse.de Reviewed-by: Christoph Hellwig Reviewed-by: Bart Van Assche Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/dpt_i2o.c | 20 +------------------- drivers/scsi/dpti.h | 1 - 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index c30ace9f251e..ac27323ea135 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -817,7 +817,7 @@ static int adpt_hba_reset(adpt_hba* pHba) } pHba->state &= ~DPTI_STATE_RESET; - adpt_fail_posted_scbs(pHba); + scsi_host_complete_all_commands(pHba->host, DID_RESET); return 0; /* return success */ } @@ -2335,7 +2335,6 @@ static s32 adpt_scsi_host_alloc(adpt_hba* pHba, struct scsi_host_template *sht) host->unique_id = (u32)sys_tbl_pa + pHba->unit; host->sg_tablesize = pHba->sg_tablesize; host->can_queue = pHba->post_fifo_size; - host->use_cmd_list = 1; return 0; } @@ -2646,23 +2645,6 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) return 0; } -static void adpt_fail_posted_scbs(adpt_hba* pHba) -{ - struct scsi_cmnd* cmd = NULL; - struct scsi_device* d = NULL; - - shost_for_each_device(d, pHba->host) { - unsigned long flags; - spin_lock_irqsave(&d->list_lock, flags); - list_for_each_entry(cmd, &d->cmd_list, list) { - cmd->result = (DID_OK << 16) | (QUEUE_FULL <<1); - cmd->scsi_done(cmd); - } - spin_unlock_irqrestore(&d->list_lock, flags); - } -} - - /*============================================================================ * Routines from i2o subsystem *============================================================================ diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h index 3ec391134bb0..72293b8450b6 100644 --- a/drivers/scsi/dpti.h +++ b/drivers/scsi/dpti.h @@ -295,7 +295,6 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba); static s32 adpt_send_nop(adpt_hba*pHba,u32 m); static void adpt_i2o_delete_hba(adpt_hba* pHba); static void adpt_inquiry(adpt_hba* pHba); -static void adpt_fail_posted_scbs(adpt_hba* pHba); static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u64 lun); static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) ; static int adpt_i2o_online_hba(adpt_hba* pHba); From 2c644b1d70f55cca58bb58a5a58652ee25afb28c Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 28 Feb 2020 08:53:09 +0100 Subject: [PATCH 0980/4444] scsi: aacraid: Do not wait for outstanding write commands on synchronize_cache There is no need to wait for outstanding write commands on synchronize cache; the block layer is responsible for I/O scheduling, no need to out-guess it in the driver layer. Link: https://lore.kernel.org/r/20200228075318.91255-5-hare@suse.de Reviewed-by: Christoph Hellwig Acked-by: Balsundar P Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/aachba.c | 76 +---------------------------------- 1 file changed, 2 insertions(+), 74 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 33dbc051bff9..474d48eb1348 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -2601,9 +2601,7 @@ static int aac_write(struct scsi_cmnd * scsicmd) static void synchronize_callback(void *context, struct fib *fibptr) { struct aac_synchronize_reply *synchronizereply; - struct scsi_cmnd *cmd; - - cmd = context; + struct scsi_cmnd *cmd = context; if (!aac_valid_context(cmd, fibptr)) return; @@ -2644,77 +2642,8 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) int status; struct fib *cmd_fibcontext; struct aac_synchronize *synchronizecmd; - struct scsi_cmnd *cmd; struct scsi_device *sdev = scsicmd->device; - int active = 0; struct aac_dev *aac; - u64 lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | - (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; - u32 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; - unsigned long flags; - - /* - * Wait for all outstanding queued commands to complete to this - * specific target (block). - */ - spin_lock_irqsave(&sdev->list_lock, flags); - list_for_each_entry(cmd, &sdev->cmd_list, list) - if (cmd->SCp.phase == AAC_OWNER_FIRMWARE) { - u64 cmnd_lba; - u32 cmnd_count; - - if (cmd->cmnd[0] == WRITE_6) { - cmnd_lba = ((cmd->cmnd[1] & 0x1F) << 16) | - (cmd->cmnd[2] << 8) | - cmd->cmnd[3]; - cmnd_count = cmd->cmnd[4]; - if (cmnd_count == 0) - cmnd_count = 256; - } else if (cmd->cmnd[0] == WRITE_16) { - cmnd_lba = ((u64)cmd->cmnd[2] << 56) | - ((u64)cmd->cmnd[3] << 48) | - ((u64)cmd->cmnd[4] << 40) | - ((u64)cmd->cmnd[5] << 32) | - ((u64)cmd->cmnd[6] << 24) | - (cmd->cmnd[7] << 16) | - (cmd->cmnd[8] << 8) | - cmd->cmnd[9]; - cmnd_count = (cmd->cmnd[10] << 24) | - (cmd->cmnd[11] << 16) | - (cmd->cmnd[12] << 8) | - cmd->cmnd[13]; - } else if (cmd->cmnd[0] == WRITE_12) { - cmnd_lba = ((u64)cmd->cmnd[2] << 24) | - (cmd->cmnd[3] << 16) | - (cmd->cmnd[4] << 8) | - cmd->cmnd[5]; - cmnd_count = (cmd->cmnd[6] << 24) | - (cmd->cmnd[7] << 16) | - (cmd->cmnd[8] << 8) | - cmd->cmnd[9]; - } else if (cmd->cmnd[0] == WRITE_10) { - cmnd_lba = ((u64)cmd->cmnd[2] << 24) | - (cmd->cmnd[3] << 16) | - (cmd->cmnd[4] << 8) | - cmd->cmnd[5]; - cmnd_count = (cmd->cmnd[7] << 8) | - cmd->cmnd[8]; - } else - continue; - if (((cmnd_lba + cmnd_count) < lba) || - (count && ((lba + count) < cmnd_lba))) - continue; - ++active; - break; - } - - spin_unlock_irqrestore(&sdev->list_lock, flags); - - /* - * Yield the processor (requeue for later) - */ - if (active) - return SCSI_MLQUEUE_DEVICE_BUSY; aac = (struct aac_dev *)sdev->host->hostdata; if (aac->in_reset) @@ -2723,8 +2652,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) /* * Allocate and initialize a Fib */ - if (!(cmd_fibcontext = aac_fib_alloc(aac))) - return SCSI_MLQUEUE_HOST_BUSY; + cmd_fibcontext = aac_fib_alloc_tag(aac, scsicmd); aac_fib_init(cmd_fibcontext); From a1855f612686077411af282a6957c745d98de021 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 28 Feb 2020 08:53:10 +0100 Subject: [PATCH 0981/4444] scsi: aacraid: use scsi_host_complete_all_commands() to terminate outstanding commands Use scsi_host_complete_all_commands() to terminate all outstanding commands and change the command result for terminated commands to the more common 'DID_RESET' instead of 'QUEUE_FULL'. Link: https://lore.kernel.org/r/20200228075318.91255-6-hare@suse.de Reviewed-by: Christoph Hellwig Reviewed-by: Bart Van Assche Acked-by: Balsundar P Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/commsup.c | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 5a8a999606ea..8736a540a048 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -1478,8 +1478,6 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) int retval; struct Scsi_Host *host; struct scsi_device *dev; - struct scsi_cmnd *command; - struct scsi_cmnd *command_list; int jafo = 0; int bled; u64 dmamask; @@ -1607,26 +1605,8 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) * This is where the assumption that the Adapter is quiesced * is important. */ - command_list = NULL; - __shost_for_each_device(dev, host) { - unsigned long flags; - spin_lock_irqsave(&dev->list_lock, flags); - list_for_each_entry(command, &dev->cmd_list, list) - if (command->SCp.phase == AAC_OWNER_FIRMWARE) { - command->SCp.buffer = (struct scatterlist *)command_list; - command_list = command; - } - spin_unlock_irqrestore(&dev->list_lock, flags); - } - while ((command = command_list)) { - command_list = (struct scsi_cmnd *)command->SCp.buffer; - command->SCp.buffer = NULL; - command->result = DID_OK << 16 - | COMMAND_COMPLETE << 8 - | SAM_STAT_TASK_SET_FULL; - command->SCp.phase = AAC_OWNER_ERROR_HANDLER; - command->scsi_done(command); - } + scsi_host_complete_all_commands(host, DID_RESET); + /* * Any Device that was already marked offline needs to be marked * running From b64f239e6116857e8ec4f4effa2f9deff2758889 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 28 Feb 2020 08:53:11 +0100 Subject: [PATCH 0982/4444] scsi: aacraid: replace aac_flush_ios() with midlayer helper Use the midlayer helper scsi_host_complete_all_commands() to flush all outstanding commands. Link: https://lore.kernel.org/r/20200228075318.91255-7-hare@suse.de Reviewed-by: Christoph Hellwig Reviewed-by: Bart Van Assche Acked-by: Balsundar P Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/linit.c | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index ee6bc2f9b80a..4d5b34e0d3a9 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -1977,26 +1977,6 @@ static void aac_remove_one(struct pci_dev *pdev) } } -static void aac_flush_ios(struct aac_dev *aac) -{ - int i; - struct scsi_cmnd *cmd; - - for (i = 0; i < aac->scsi_host_ptr->can_queue; i++) { - cmd = (struct scsi_cmnd *)aac->fibs[i].callback_data; - if (cmd && (cmd->SCp.phase == AAC_OWNER_FIRMWARE)) { - scsi_dma_unmap(cmd); - - if (aac->handle_pci_error) - cmd->result = DID_NO_CONNECT << 16; - else - cmd->result = DID_RESET << 16; - - cmd->scsi_done(cmd); - } - } -} - static pci_ers_result_t aac_pci_error_detected(struct pci_dev *pdev, enum pci_channel_state error) { @@ -2013,7 +1993,7 @@ static pci_ers_result_t aac_pci_error_detected(struct pci_dev *pdev, scsi_block_requests(aac->scsi_host_ptr); aac_cancel_rescan_worker(aac); - aac_flush_ios(aac); + scsi_host_complete_all_commands(shost, DID_NO_CONNECT); aac_release_resources(aac); pci_disable_pcie_error_reporting(pdev); @@ -2023,7 +2003,7 @@ static pci_ers_result_t aac_pci_error_detected(struct pci_dev *pdev, case pci_channel_io_perm_failure: aac->handle_pci_error = 1; - aac_flush_ios(aac); + scsi_host_complete_all_commands(shost, DID_NO_CONNECT); return PCI_ERS_RESULT_DISCONNECT; } From 5646e13a95502a6944f369f8542df3d3ab871972 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 28 Feb 2020 08:53:12 +0100 Subject: [PATCH 0983/4444] scsi: aacraid: move scsi_(block,unblock)_requests out of _aac_reset_adapter() _aac_reset_adapter() only has one caller, and that one already calls scsi_block_requests(). Move the calls out of _aac_reset_adapter() to avoid calling scsi_block_requests() twice. Link: https://lore.kernel.org/r/20200228075318.91255-8-hare@suse.de Reviewed-by: Christoph Hellwig Acked-by: Balsundar P < Balsundar.P@microchip.com> Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/commsup.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 8736a540a048..fee13a778198 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -1476,7 +1476,7 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) { int index, quirks; int retval; - struct Scsi_Host *host; + struct Scsi_Host *host = aac->scsi_host_ptr; struct scsi_device *dev; int jafo = 0; int bled; @@ -1493,8 +1493,6 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) * - The card is dead, or will be very shortly ;-/ so no new * commands are completing in the interrupt service. */ - host = aac->scsi_host_ptr; - scsi_block_requests(host); aac_adapter_disable_int(aac); if (aac->thread && aac->thread->pid != current->pid) { spin_unlock_irq(host->host_lock); @@ -1619,7 +1617,6 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) out: aac->in_reset = 0; - scsi_unblock_requests(host); /* * Issue bus rescan to catch any configuration that might have @@ -1640,7 +1637,7 @@ int aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) { unsigned long flagv = 0; int retval; - struct Scsi_Host * host; + struct Scsi_Host *host = aac->scsi_host_ptr; int bled; if (spin_trylock_irqsave(&aac->fib_lock, flagv) == 0) @@ -1658,7 +1655,6 @@ int aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) * target (block maximum 60 seconds). Although not necessary, * it does make us a good storage citizen. */ - host = aac->scsi_host_ptr; scsi_block_requests(host); /* Quiesce build, flush cache, write through mode */ @@ -1670,6 +1666,8 @@ int aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) retval = _aac_reset_adapter(aac, bled, reset_type); spin_unlock_irqrestore(host->host_lock, flagv); + scsi_unblock_requests(host); + if ((forced < 2) && (retval == -ENODEV)) { /* Unwind aac_send_shutdown() IOP_RESET unsupported/disabled */ struct fib * fibctx = aac_fib_alloc(aac); From 2bb955840c1dc44746af8a7873d9a0ba70debbd6 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 28 Feb 2020 08:53:13 +0100 Subject: [PATCH 0984/4444] scsi: core: add scsi_host_(block,unblock) helper function Add helper functions to call scsi_internal_device_block()/ scsi_internal_device_unblock() for all attached devices on a SCSI host. Link: https://lore.kernel.org/r/20200228075318.91255-9-hare@suse.de Reviewed-by: Christoph Hellwig Reviewed-by: Bart Van Assche Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 30 ++++++++++++++++++++++++++++++ include/scsi/scsi_host.h | 2 ++ 2 files changed, 32 insertions(+) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 610ee41fa54c..a48a5727831b 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2845,6 +2845,36 @@ scsi_target_unblock(struct device *dev, enum scsi_device_state new_state) } EXPORT_SYMBOL_GPL(scsi_target_unblock); +int +scsi_host_block(struct Scsi_Host *shost) +{ + struct scsi_device *sdev; + int ret = 0; + + shost_for_each_device(sdev, shost) { + ret = scsi_internal_device_block(sdev); + if (ret) + break; + } + return ret; +} +EXPORT_SYMBOL_GPL(scsi_host_block); + +int +scsi_host_unblock(struct Scsi_Host *shost, int new_state) +{ + struct scsi_device *sdev; + int ret = 0; + + shost_for_each_device(sdev, shost) { + ret = scsi_internal_device_unblock(sdev, new_state); + if (ret) + break; + } + return ret; +} +EXPORT_SYMBOL_GPL(scsi_host_unblock); + /** * scsi_kmap_atomic_sg - find and atomically map an sg-elemnt * @sgl: scatter-gather list diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 25bef781cbe1..613c3820028e 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -758,6 +758,8 @@ static inline int scsi_host_scan_allowed(struct Scsi_Host *shost) extern void scsi_unblock_requests(struct Scsi_Host *); extern void scsi_block_requests(struct Scsi_Host *); +extern int scsi_host_block(struct Scsi_Host *shost); +extern int scsi_host_unblock(struct Scsi_Host *shost, int new_state); struct class_container; From 3d3ca53b163914c1397289d0c2ee6d2f52362dcc Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 28 Feb 2020 08:53:14 +0100 Subject: [PATCH 0985/4444] scsi: aacraid: use scsi_host_(block,unblock) to block I/O Use scsi_host_block() and scsi_host_unblock() instead of scsi_block_requests()/scsi_unblock_requests() to block and unblock I/O. This has the advantage that the block layer will stop sending I/O to the adapter instead of having the SCSI midlayer requeueing I/O internally. Link: https://lore.kernel.org/r/20200228075318.91255-10-hare@suse.de Reviewed-by: Christoph Hellwig Acked-by: Balsundar P < Balsundar.P@microchip.com> Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/commsup.c | 14 ++------------ drivers/scsi/aacraid/linit.c | 15 ++++++--------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index fee13a778198..bb14a05f6d77 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -1477,7 +1477,6 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) int index, quirks; int retval; struct Scsi_Host *host = aac->scsi_host_ptr; - struct scsi_device *dev; int jafo = 0; int bled; u64 dmamask; @@ -1605,16 +1604,7 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) */ scsi_host_complete_all_commands(host, DID_RESET); - /* - * Any Device that was already marked offline needs to be marked - * running - */ - __shost_for_each_device(dev, host) { - if (!scsi_device_online(dev)) - scsi_device_set_state(dev, SDEV_RUNNING); - } retval = 0; - out: aac->in_reset = 0; @@ -1655,7 +1645,7 @@ int aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) * target (block maximum 60 seconds). Although not necessary, * it does make us a good storage citizen. */ - scsi_block_requests(host); + scsi_host_block(host); /* Quiesce build, flush cache, write through mode */ if (forced < 2) @@ -1666,7 +1656,7 @@ int aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) retval = _aac_reset_adapter(aac, bled, reset_type); spin_unlock_irqrestore(host->host_lock, flagv); - scsi_unblock_requests(host); + retval = scsi_host_unblock(host, SDEV_RUNNING); if ((forced < 2) && (retval == -ENODEV)) { /* Unwind aac_send_shutdown() IOP_RESET unsupported/disabled */ diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 4d5b34e0d3a9..877464e9d520 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -1894,7 +1894,7 @@ static int aac_suspend(struct pci_dev *pdev, pm_message_t state) struct Scsi_Host *shost = pci_get_drvdata(pdev); struct aac_dev *aac = (struct aac_dev *)shost->hostdata; - scsi_block_requests(shost); + scsi_host_block(shost); aac_cancel_rescan_worker(aac); aac_send_shutdown(aac); @@ -1930,7 +1930,7 @@ static int aac_resume(struct pci_dev *pdev) * aac_send_shutdown() to block ioctls from upperlayer */ aac->adapter_shutdown = 0; - scsi_unblock_requests(shost); + scsi_host_unblock(shost, SDEV_RUNNING); return 0; @@ -1945,7 +1945,8 @@ fail_device: static void aac_shutdown(struct pci_dev *dev) { struct Scsi_Host *shost = pci_get_drvdata(dev); - scsi_block_requests(shost); + + scsi_host_block(shost); __aac_shutdown((struct aac_dev *)shost->hostdata); } @@ -1991,7 +1992,7 @@ static pci_ers_result_t aac_pci_error_detected(struct pci_dev *pdev, case pci_channel_io_frozen: aac->handle_pci_error = 1; - scsi_block_requests(aac->scsi_host_ptr); + scsi_host_block(shost); aac_cancel_rescan_worker(aac); scsi_host_complete_all_commands(shost, DID_NO_CONNECT); aac_release_resources(aac); @@ -2044,7 +2045,6 @@ fail_device: static void aac_pci_resume(struct pci_dev *pdev) { struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct scsi_device *sdev = NULL; struct aac_dev *aac = (struct aac_dev *)shost_priv(shost); if (aac_adapter_ioremap(aac, aac->base_size)) { @@ -2071,10 +2071,7 @@ static void aac_pci_resume(struct pci_dev *pdev) aac->adapter_shutdown = 0; aac->handle_pci_error = 0; - shost_for_each_device(sdev, shost) - if (sdev->sdev_state == SDEV_OFFLINE) - sdev->sdev_state = SDEV_RUNNING; - scsi_unblock_requests(aac->scsi_host_ptr); + scsi_host_unblock(shost, SDEV_RUNNING); aac_scan_host(aac); pci_save_state(pdev); From dcece99e86b1191d2789fb5b5caa4c5b7fc2bfef Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 28 Feb 2020 08:53:15 +0100 Subject: [PATCH 0986/4444] scsi: core: add scsi_host_busy_iter() Add an iterator scsi_host_busy_iter() to traverse all busy commands. If locking against concurrent command completions is required, it has to be provided by the caller. Link: https://lore.kernel.org/r/20200228075318.91255-11-hare@suse.de Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/hosts.c | 37 +++++++++++++++++++++++++++++++++++++ include/scsi/scsi_host.h | 3 +++ 2 files changed, 40 insertions(+) diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 00ae9d43ce9f..7ec91c3a66ca 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -678,3 +678,40 @@ void scsi_host_complete_all_commands(struct Scsi_Host *shost, int status) &status); } EXPORT_SYMBOL_GPL(scsi_host_complete_all_commands); + +struct scsi_host_busy_iter_data { + bool (*fn)(struct scsi_cmnd *, void *, bool); + void *priv; +}; + +static bool __scsi_host_busy_iter_fn(struct request *req, void *priv, + bool reserved) +{ + struct scsi_host_busy_iter_data *iter_data = priv; + struct scsi_cmnd *sc = blk_mq_rq_to_pdu(req); + + return iter_data->fn(sc, iter_data->priv, reserved); +} + +/** + * scsi_host_busy_iter - Iterate over all busy commands + * @shost: Pointer to Scsi_Host. + * @fn: Function to call on each busy command + * @priv: Data pointer passed to @fn + * + * If locking against concurrent command completions is required + * ithas to be provided by the caller + **/ +void scsi_host_busy_iter(struct Scsi_Host *shost, + bool (*fn)(struct scsi_cmnd *, void *, bool), + void *priv) +{ + struct scsi_host_busy_iter_data iter_data = { + .fn = fn, + .priv = priv, + }; + + blk_mq_tagset_busy_iter(&shost->tag_set, __scsi_host_busy_iter_fn, + &iter_data); +} +EXPORT_SYMBOL_GPL(scsi_host_busy_iter); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 613c3820028e..eff12445b823 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -761,6 +761,9 @@ extern void scsi_block_requests(struct Scsi_Host *); extern int scsi_host_block(struct Scsi_Host *shost); extern int scsi_host_unblock(struct Scsi_Host *shost, int new_state); +void scsi_host_busy_iter(struct Scsi_Host *, + bool (*fn)(struct scsi_cmnd *, void *, bool), void *priv); + struct class_container; /* From f4a0c9dbc665764e10cd603fe6a6a9ece26dc41d Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 28 Feb 2020 08:53:16 +0100 Subject: [PATCH 0987/4444] scsi: aacraid: use scsi_host_busy_iter() to wait for outstanding commands Instead of traversing the list of possible commands by hands we should be using scsi_host_busy_iter() to figure out if there are outstanding commands. Link: https://lore.kernel.org/r/20200228075318.91255-12-hare@suse.de Reviewed-by: Christoph Hellwig Acked-by: Balsundar P < Balsundar.P@microchip.com> Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/comminit.c | 35 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index f75878d773cf..355b16f0b145 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -272,36 +272,35 @@ static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, q->entries = qsize; } +static bool wait_for_io_iter(struct scsi_cmnd *cmd, void *data, bool rsvd) +{ + int *active = data; + + if (cmd->SCp.phase == AAC_OWNER_FIRMWARE) + *active = *active + 1; + return true; +} static void aac_wait_for_io_completion(struct aac_dev *aac) { - unsigned long flagv = 0; - int i = 0; + int i = 0, active; for (i = 60; i; --i) { - struct scsi_device *dev; - struct scsi_cmnd *command; - int active = 0; - __shost_for_each_device(dev, aac->scsi_host_ptr) { - spin_lock_irqsave(&dev->list_lock, flagv); - list_for_each_entry(command, &dev->cmd_list, list) { - if (command->SCp.phase == AAC_OWNER_FIRMWARE) { - active++; - break; - } - } - spin_unlock_irqrestore(&dev->list_lock, flagv); - if (active) - break; - - } + active = 0; + scsi_host_busy_iter(aac->scsi_host_ptr, + wait_for_io_iter, &active); /* * We can exit If all the commands are complete */ if (active == 0) break; + dev_info(&aac->pdev->dev, + "Wait for %d commands to complete\n", active); ssleep(1); } + if (active) + dev_err(&aac->pdev->dev, + "%d outstanding commands during shutdown\n", active); } /** From 35d2ce0b6570aa399184b5dfe7e5a821e5ff9f05 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 28 Feb 2020 08:53:17 +0100 Subject: [PATCH 0988/4444] scsi: aacraid: use scsi_host_busy_iter() in get_num_of_incomplete_fibs() Use the SCSI midlayer helper to traverse the number of outstanding commands. This also eliminates the last usage for the cmd_list functionality so we can drop it. Link: https://lore.kernel.org/r/20200228075318.91255-13-hare@suse.de Reviewed-by: Christoph Hellwig Acked-by: Balsundar P Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/linit.c | 81 ++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 877464e9d520..d0d1f3072c0c 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -622,54 +622,56 @@ static int aac_ioctl(struct scsi_device *sdev, unsigned int cmd, return aac_do_ioctl(dev, cmd, arg); } +struct fib_count_data { + int mlcnt; + int llcnt; + int ehcnt; + int fwcnt; + int krlcnt; +}; + +static bool fib_count_iter(struct scsi_cmnd *scmnd, void *data, bool reserved) +{ + struct fib_count_data *fib_count = data; + + switch (scmnd->SCp.phase) { + case AAC_OWNER_FIRMWARE: + fib_count->fwcnt++; + break; + case AAC_OWNER_ERROR_HANDLER: + fib_count->ehcnt++; + break; + case AAC_OWNER_LOWLEVEL: + fib_count->llcnt++; + break; + case AAC_OWNER_MIDLEVEL: + fib_count->mlcnt++; + break; + default: + fib_count->krlcnt++; + break; + } + return true; +} + +/* Called during SCSI EH, so we don't need to block requests */ static int get_num_of_incomplete_fibs(struct aac_dev *aac) { - - unsigned long flags; - struct scsi_device *sdev = NULL; struct Scsi_Host *shost = aac->scsi_host_ptr; - struct scsi_cmnd *scmnd = NULL; struct device *ctrl_dev; + struct fib_count_data fcnt = { }; - int mlcnt = 0; - int llcnt = 0; - int ehcnt = 0; - int fwcnt = 0; - int krlcnt = 0; - - __shost_for_each_device(sdev, shost) { - spin_lock_irqsave(&sdev->list_lock, flags); - list_for_each_entry(scmnd, &sdev->cmd_list, list) { - switch (scmnd->SCp.phase) { - case AAC_OWNER_FIRMWARE: - fwcnt++; - break; - case AAC_OWNER_ERROR_HANDLER: - ehcnt++; - break; - case AAC_OWNER_LOWLEVEL: - llcnt++; - break; - case AAC_OWNER_MIDLEVEL: - mlcnt++; - break; - default: - krlcnt++; - break; - } - } - spin_unlock_irqrestore(&sdev->list_lock, flags); - } + scsi_host_busy_iter(shost, fib_count_iter, &fcnt); ctrl_dev = &aac->pdev->dev; - dev_info(ctrl_dev, "outstanding cmd: midlevel-%d\n", mlcnt); - dev_info(ctrl_dev, "outstanding cmd: lowlevel-%d\n", llcnt); - dev_info(ctrl_dev, "outstanding cmd: error handler-%d\n", ehcnt); - dev_info(ctrl_dev, "outstanding cmd: firmware-%d\n", fwcnt); - dev_info(ctrl_dev, "outstanding cmd: kernel-%d\n", krlcnt); + dev_info(ctrl_dev, "outstanding cmd: midlevel-%d\n", fcnt.mlcnt); + dev_info(ctrl_dev, "outstanding cmd: lowlevel-%d\n", fcnt.llcnt); + dev_info(ctrl_dev, "outstanding cmd: error handler-%d\n", fcnt.ehcnt); + dev_info(ctrl_dev, "outstanding cmd: firmware-%d\n", fcnt.fwcnt); + dev_info(ctrl_dev, "outstanding cmd: kernel-%d\n", fcnt.krlcnt); - return mlcnt + llcnt + ehcnt + fwcnt; + return fcnt.mlcnt + fcnt.llcnt + fcnt.ehcnt + fcnt.fwcnt; } static int aac_eh_abort(struct scsi_cmnd* cmd) @@ -1675,7 +1677,6 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) shost->irq = pdev->irq; shost->unique_id = unique_id; shost->max_cmd_len = 16; - shost->use_cmd_list = 1; if (aac_cfg_major == AAC_CHARDEV_NEEDS_REINIT) aac_init_char(); From c5a9707672fe22865d90fc04ac2fbc4f812666f3 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 28 Feb 2020 08:53:18 +0100 Subject: [PATCH 0989/4444] scsi: core: Remove cmd_list functionality Remove cmd_list functionality; no users left. With that the scsi_put_command() becomes empty, so remove that one, too. Link: https://lore.kernel.org/r/20200228075318.91255-14-hare@suse.de Reviewed-by: Christoph Hellwig Reviewed-by: Bart van Assche Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi.c | 14 -------------- drivers/scsi/scsi_error.c | 1 - drivers/scsi/scsi_lib.c | 31 ------------------------------- drivers/scsi/scsi_priv.h | 2 -- drivers/scsi/scsi_scan.c | 1 - include/scsi/scsi_cmnd.h | 1 - include/scsi/scsi_device.h | 1 - include/scsi/scsi_host.h | 2 -- 8 files changed, 53 deletions(-) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 4b9fdfab77d9..56c24a73e0c7 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -94,20 +94,6 @@ EXPORT_SYMBOL(scsi_logging_level); ASYNC_DOMAIN_EXCLUSIVE(scsi_sd_pm_domain); EXPORT_SYMBOL(scsi_sd_pm_domain); -/** - * scsi_put_command - Free a scsi command block - * @cmd: command block to free - * - * Returns: Nothing. - * - * Notes: The command must not belong to any lists. - */ -void scsi_put_command(struct scsi_cmnd *cmd) -{ - scsi_del_cmd_from_list(cmd); - BUG_ON(delayed_work_pending(&cmd->abort_work)); -} - #ifdef CONFIG_SCSI_LOGGING void scsi_log_send(struct scsi_cmnd *cmd) { diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index ae2fa170f6ad..978be1602f71 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -2412,7 +2412,6 @@ scsi_ioctl_reset(struct scsi_device *dev, int __user *arg) wake_up(&shost->host_wait); scsi_run_host_queues(shost); - scsi_put_command(scmd); kfree(rq); out_put_autopm_host: diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index a48a5727831b..258a428a0a3f 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -562,7 +562,6 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) { scsi_mq_free_sgtables(cmd); scsi_uninit_cmd(cmd); - scsi_del_cmd_from_list(cmd); } /* Returns false when no more bytes to process, true if there are more */ @@ -1098,35 +1097,6 @@ static void scsi_cleanup_rq(struct request *rq) } } -/* Add a command to the list used by the aacraid and dpt_i2o drivers */ -void scsi_add_cmd_to_list(struct scsi_cmnd *cmd) -{ - struct scsi_device *sdev = cmd->device; - struct Scsi_Host *shost = sdev->host; - unsigned long flags; - - if (shost->use_cmd_list) { - spin_lock_irqsave(&sdev->list_lock, flags); - list_add_tail(&cmd->list, &sdev->cmd_list); - spin_unlock_irqrestore(&sdev->list_lock, flags); - } -} - -/* Remove a command from the list used by the aacraid and dpt_i2o drivers */ -void scsi_del_cmd_from_list(struct scsi_cmnd *cmd) -{ - struct scsi_device *sdev = cmd->device; - struct Scsi_Host *shost = sdev->host; - unsigned long flags; - - if (shost->use_cmd_list) { - spin_lock_irqsave(&sdev->list_lock, flags); - BUG_ON(list_empty(&cmd->list)); - list_del_init(&cmd->list); - spin_unlock_irqrestore(&sdev->list_lock, flags); - } -} - /* Called after a request has been started. */ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd) { @@ -1160,7 +1130,6 @@ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd) if (in_flight) __set_bit(SCMD_STATE_INFLIGHT, &cmd->state); - scsi_add_cmd_to_list(cmd); } static blk_status_t scsi_setup_scsi_cmnd(struct scsi_device *sdev, diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 25b0aaaf5ae8..22b6585e28b4 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -83,8 +83,6 @@ int scsi_eh_get_sense(struct list_head *work_q, int scsi_noretry_cmd(struct scsi_cmnd *scmd); /* scsi_lib.c */ -extern void scsi_add_cmd_to_list(struct scsi_cmnd *cmd); -extern void scsi_del_cmd_from_list(struct scsi_cmnd *cmd); extern int scsi_maybe_unblock_host(struct scsi_device *sdev); extern void scsi_device_unbusy(struct scsi_device *sdev, struct scsi_cmnd *cmd); extern void scsi_queue_insert(struct scsi_cmnd *cmd, int reason); diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 058079f915f1..f2437a7570ce 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -236,7 +236,6 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, sdev->sdev_state = SDEV_CREATED; INIT_LIST_HEAD(&sdev->siblings); INIT_LIST_HEAD(&sdev->same_target_siblings); - INIT_LIST_HEAD(&sdev->cmd_list); INIT_LIST_HEAD(&sdev->starved_entry); INIT_LIST_HEAD(&sdev->event_list); spin_lock_init(&sdev->list_lock); diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index a2849bb9cd19..80ac89e47b47 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -159,7 +159,6 @@ static inline struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd) return *(struct scsi_driver **)cmd->request->rq_disk->private_data; } -extern void scsi_put_command(struct scsi_cmnd *); extern void scsi_finish_command(struct scsi_cmnd *cmd); extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index f8312a3e5b42..f146a4557787 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -110,7 +110,6 @@ struct scsi_device { atomic_t device_blocked; /* Device returned QUEUE_FULL. */ spinlock_t list_lock; - struct list_head cmd_list; /* queue of in use SCSI Command structures */ struct list_head starved_entry; unsigned short queue_depth; /* How deep of a queue we want */ unsigned short max_queue_depth; /* max queue depth */ diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index eff12445b823..74dc7d4f2a96 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -624,8 +624,6 @@ struct Scsi_Host { /* The controller does not support WRITE SAME */ unsigned no_write_same:1; - unsigned use_cmd_list:1; - /* Host responded with short (<36 bytes) INQUIRY result */ unsigned short_inquiry:1; From 65ca846a53149a1a72cd8d02e7b2e73dd545b834 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 22 Jan 2020 19:56:34 -0800 Subject: [PATCH 0990/4444] scsi: core: Introduce {init,exit}_cmd_priv() The current behavior of the SCSI core is to clear driver-private data before preparing a request for submission to the SCSI LLD. Make it possible for SCSI LLDs to disable clearing of driver-private data. These hooks will be used by a later patch, namely "scsi: ufs: Let the SCSI core allocate per-command UFS data". Link: https://lore.kernel.org/r/20200123035637.21848-2-bvanassche@acm.org Cc: Tomas Winkler Cc: Stanley Chu Cc: Bean Huo Cc: Avri Altman Cc: Can Guo Cc: Ming Lei Cc: Johannes Thumshirn Cc: Hannes Reinecke Cc: Christoph Hellwig Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 29 +++++++++++++++++++++++------ include/scsi/scsi_host.h | 3 +++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 258a428a0a3f..9f201194c46a 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1097,7 +1097,7 @@ static void scsi_cleanup_rq(struct request *rq) } } -/* Called after a request has been started. */ +/* Called before a request is prepared. See also scsi_mq_prep_fn(). */ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd) { void *buf = cmd->sense_buffer; @@ -1105,7 +1105,7 @@ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd) struct request *rq = blk_mq_rq_from_pdu(cmd); unsigned int flags = cmd->flags & SCMD_PRESERVED_FLAGS; unsigned long jiffies_at_alloc; - int retries; + int retries, to_clear; bool in_flight; if (!blk_rq_is_scsi(rq) && !(flags & SCMD_INITIALIZED)) { @@ -1116,9 +1116,15 @@ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd) jiffies_at_alloc = cmd->jiffies_at_alloc; retries = cmd->retries; in_flight = test_bit(SCMD_STATE_INFLIGHT, &cmd->state); - /* zero out the cmd, except for the embedded scsi_request */ - memset((char *)cmd + sizeof(cmd->req), 0, - sizeof(*cmd) - sizeof(cmd->req) + dev->host->hostt->cmd_size); + /* + * Zero out the cmd, except for the embedded scsi_request. Only clear + * the driver-private command data if the LLD does not supply a + * function to initialize that data. + */ + to_clear = sizeof(*cmd) - sizeof(cmd->req); + if (!dev->host->hostt->init_cmd_priv) + to_clear += dev->host->hostt->cmd_size; + memset((char *)cmd + sizeof(cmd->req), 0, to_clear); cmd->device = dev; cmd->sense_buffer = buf; @@ -1711,6 +1717,7 @@ static int scsi_mq_init_request(struct blk_mq_tag_set *set, struct request *rq, const bool unchecked_isa_dma = shost->unchecked_isa_dma; struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq); struct scatterlist *sg; + int ret = 0; if (unchecked_isa_dma) cmd->flags |= SCMD_UNCHECKED_ISA_DMA; @@ -1726,14 +1733,24 @@ static int scsi_mq_init_request(struct blk_mq_tag_set *set, struct request *rq, cmd->prot_sdb = (void *)sg + scsi_mq_inline_sgl_size(shost); } - return 0; + if (shost->hostt->init_cmd_priv) { + ret = shost->hostt->init_cmd_priv(shost, cmd); + if (ret < 0) + scsi_free_sense_buffer(unchecked_isa_dma, + cmd->sense_buffer); + } + + return ret; } static void scsi_mq_exit_request(struct blk_mq_tag_set *set, struct request *rq, unsigned int hctx_idx) { + struct Scsi_Host *shost = set->driver_data; struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq); + if (shost->hostt->exit_cmd_priv) + shost->hostt->exit_cmd_priv(shost, cmd); scsi_free_sense_buffer(cmd->flags & SCMD_UNCHECKED_ISA_DMA, cmd->sense_buffer); } diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 74dc7d4f2a96..7464394e7d01 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -62,6 +62,9 @@ struct scsi_host_template { void __user *arg); #endif + int (*init_cmd_priv)(struct Scsi_Host *shost, struct scsi_cmnd *cmd); + int (*exit_cmd_priv)(struct Scsi_Host *shost, struct scsi_cmnd *cmd); + /* * The queuecommand function is used to queue up a scsi * command block to the LLDD. When the driver finished From 4d2b8d40dd754e4e6db003a817cd0fa9f3c58c65 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 22 Jan 2020 19:56:35 -0800 Subject: [PATCH 0991/4444] scsi: ufs: Introduce ufshcd_init_lrb() This patch does not change any functionality but makes the next patch in this series easier to read. Link: https://lore.kernel.org/r/20200123035637.21848-3-bvanassche@acm.org Cc: Tomas Winkler Cc: Stanley Chu Cc: Bean Huo Cc: Can Guo Reviewed-by: Alim Akhtar Reviewed-by: Avri Altman Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 68fbbdeefbfa..1d9ba6990973 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2359,6 +2359,27 @@ static inline u16 ufshcd_upiu_wlun_to_scsi_wlun(u8 upiu_wlun_id) return (upiu_wlun_id & ~UFS_UPIU_WLUN_ID) | SCSI_W_LUN_BASE; } +static void ufshcd_init_lrb(struct ufs_hba *hba, struct ufshcd_lrb *lrb, int i) +{ + struct utp_transfer_cmd_desc *cmd_descp = hba->ucdl_base_addr; + struct utp_transfer_req_desc *utrdlp = hba->utrdl_base_addr; + dma_addr_t cmd_desc_element_addr = hba->ucdl_dma_addr + + i * sizeof(struct utp_transfer_cmd_desc); + u16 response_offset = offsetof(struct utp_transfer_cmd_desc, + response_upiu); + u16 prdt_offset = offsetof(struct utp_transfer_cmd_desc, prd_table); + + lrb->utr_descriptor_ptr = utrdlp + i; + lrb->utrd_dma_addr = hba->utrdl_dma_addr + + i * sizeof(struct utp_transfer_req_desc); + lrb->ucd_req_ptr = (struct utp_upiu_req *)(cmd_descp + i); + lrb->ucd_req_dma_addr = cmd_desc_element_addr; + lrb->ucd_rsp_ptr = (struct utp_upiu_rsp *)cmd_descp[i].response_upiu; + lrb->ucd_rsp_dma_addr = cmd_desc_element_addr + response_offset; + lrb->ucd_prdt_ptr = (struct ufshcd_sg_entry *)cmd_descp[i].prd_table; + lrb->ucd_prdt_dma_addr = cmd_desc_element_addr + prdt_offset; +} + /** * ufshcd_queuecommand - main entry point for SCSI requests * @host: SCSI host pointer @@ -3394,7 +3415,6 @@ out: */ static void ufshcd_host_memory_configure(struct ufs_hba *hba) { - struct utp_transfer_cmd_desc *cmd_descp; struct utp_transfer_req_desc *utrdlp; dma_addr_t cmd_desc_dma_addr; dma_addr_t cmd_desc_element_addr; @@ -3404,7 +3424,6 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba) int i; utrdlp = hba->utrdl_base_addr; - cmd_descp = hba->ucdl_base_addr; response_offset = offsetof(struct utp_transfer_cmd_desc, response_upiu); @@ -3430,20 +3449,7 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba) utrdlp[i].response_upiu_length = cpu_to_le16(ALIGNED_UPIU_SIZE >> 2); - hba->lrb[i].utr_descriptor_ptr = (utrdlp + i); - hba->lrb[i].utrd_dma_addr = hba->utrdl_dma_addr + - (i * sizeof(struct utp_transfer_req_desc)); - hba->lrb[i].ucd_req_ptr = - (struct utp_upiu_req *)(cmd_descp + i); - hba->lrb[i].ucd_req_dma_addr = cmd_desc_element_addr; - hba->lrb[i].ucd_rsp_ptr = - (struct utp_upiu_rsp *)cmd_descp[i].response_upiu; - hba->lrb[i].ucd_rsp_dma_addr = cmd_desc_element_addr + - response_offset; - hba->lrb[i].ucd_prdt_ptr = - (struct ufshcd_sg_entry *)cmd_descp[i].prd_table; - hba->lrb[i].ucd_prdt_dma_addr = cmd_desc_element_addr + - prdt_offset; + ufshcd_init_lrb(hba, &hba->lrb[i], i); } } From 5905d4648e7ec2cc9316b17290f21e8bd8a78c32 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 22 Jan 2020 19:56:36 -0800 Subject: [PATCH 0992/4444] scsi: ufs: Simplify two tests lrbp->cmd is set only for SCSI commands. Use this knowledge to simplify two boolean expressions. Link: https://lore.kernel.org/r/20200123035637.21848-4-bvanassche@acm.org Cc: Alim Akhtar Cc: Tomas Winkler Cc: Bean Huo Cc: Can Guo Reviewed-by: Stanley Chu Reviewed-by: Asutosh Das Reviewed-by: Avri Altman Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 1d9ba6990973..2a2a63b68a67 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2469,7 +2469,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) /* issue command to the controller */ spin_lock_irqsave(hba->host->host_lock, flags); - ufshcd_vops_setup_xfer_req(hba, tag, (lrbp->cmd ? true : false)); + ufshcd_vops_setup_xfer_req(hba, tag, true); ufshcd_send_command(hba, tag); out_unlock: spin_unlock_irqrestore(hba->host->host_lock, flags); @@ -2656,7 +2656,7 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, /* Make sure descriptors are ready before ringing the doorbell */ wmb(); spin_lock_irqsave(hba->host->host_lock, flags); - ufshcd_vops_setup_xfer_req(hba, tag, (lrbp->cmd ? true : false)); + ufshcd_vops_setup_xfer_req(hba, tag, false); ufshcd_send_command(hba, tag); spin_unlock_irqrestore(hba->host->host_lock, flags); From 01091c496f920e634ea84b689f480c39016752a8 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 25 Feb 2020 19:20:06 +0300 Subject: [PATCH 0993/4444] acpi/nfit: improve bounds checking for 'func' The 'func' variable can come from the user in the __nd_ioctl(). If it's too high then the (1 << func) shift in acpi_nfit_clear_to_send() is undefined. In acpi_nfit_ctl() we pass 'func' to test_bit(func, &dsm_mask) which could result in an out of bounds access. To fix these issues, I introduced the NVDIMM_CMD_MAX (31) define and updated nfit_dsm_revid() to use that define as well instead of magic numbers. Fixes: 11189c1089da ("acpi/nfit: Fix command-supported detection") Signed-off-by: Dan Carpenter Reviewed-by: Dan Williams Link: https://lore.kernel.org/r/20200225161927.hvftuq7kjn547fyj@kili.mountain Signed-off-by: Dan Williams --- drivers/acpi/nfit/core.c | 10 ++++++---- drivers/acpi/nfit/nfit.h | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index a3320f93616d..d0090f71585c 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -360,7 +360,7 @@ static union acpi_object *acpi_label_info(acpi_handle handle) static u8 nfit_dsm_revid(unsigned family, unsigned func) { - static const u8 revid_table[NVDIMM_FAMILY_MAX+1][32] = { + static const u8 revid_table[NVDIMM_FAMILY_MAX+1][NVDIMM_CMD_MAX+1] = { [NVDIMM_FAMILY_INTEL] = { [NVDIMM_INTEL_GET_MODES] = 2, [NVDIMM_INTEL_GET_FWINFO] = 2, @@ -386,7 +386,7 @@ static u8 nfit_dsm_revid(unsigned family, unsigned func) if (family > NVDIMM_FAMILY_MAX) return 0; - if (func > 31) + if (func > NVDIMM_CMD_MAX) return 0; id = revid_table[family][func]; if (id == 0) @@ -492,7 +492,8 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, * Check for a valid command. For ND_CMD_CALL, we also have to * make sure that the DSM function is supported. */ - if (cmd == ND_CMD_CALL && !test_bit(func, &dsm_mask)) + if (cmd == ND_CMD_CALL && + (func > NVDIMM_CMD_MAX || !test_bit(func, &dsm_mask))) return -ENOTTY; else if (!test_bit(cmd, &cmd_mask)) return -ENOTTY; @@ -3492,7 +3493,8 @@ static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc, if (nvdimm && cmd == ND_CMD_CALL && call_pkg->nd_family == NVDIMM_FAMILY_INTEL) { func = call_pkg->nd_command; - if ((1 << func) & NVDIMM_INTEL_SECURITY_CMDMASK) + if (func > NVDIMM_CMD_MAX || + (1 << func) & NVDIMM_INTEL_SECURITY_CMDMASK) return -EOPNOTSUPP; } diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h index 24241941181c..b317f4043705 100644 --- a/drivers/acpi/nfit/nfit.h +++ b/drivers/acpi/nfit/nfit.h @@ -34,6 +34,7 @@ | ACPI_NFIT_MEM_NOT_ARMED | ACPI_NFIT_MEM_MAP_FAILED) #define NVDIMM_FAMILY_MAX NVDIMM_FAMILY_HYPERV +#define NVDIMM_CMD_MAX 31 #define NVDIMM_STANDARD_CMDMASK \ (1 << ND_CMD_SMART | 1 << ND_CMD_SMART_THRESHOLD | 1 << ND_CMD_DIMM_FLAGS \ From f84afbdd3a9e5e10633695677b95422572f920dc Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 25 Feb 2020 19:20:56 +0300 Subject: [PATCH 0994/4444] libnvdimm: Out of bounds read in __nd_ioctl() The "cmd" comes from the user and it can be up to 255. It it's more than the number of bits in long, it results out of bounds read when we check test_bit(cmd, &cmd_mask). The highest valid value for "cmd" is ND_CMD_CALL (10) so I added a compare against that. Fixes: 62232e45f4a2 ("libnvdimm: control (ioctl) messages for nvdimm_bus and nvdimm devices") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/20200225162055.amtosfy7m35aivxg@kili.mountain Signed-off-by: Dan Williams --- drivers/nvdimm/bus.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index a8b515968569..09087c38fabd 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -1042,8 +1042,10 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, return -EFAULT; } - if (!desc || (desc->out_num + desc->in_num == 0) || - !test_bit(cmd, &cmd_mask)) + if (!desc || + (desc->out_num + desc->in_num == 0) || + cmd > ND_CMD_CALL || + !test_bit(cmd, &cmd_mask)) return -ENOTTY; /* fail write commands (when read-only) */ From 7c74e9087604dfb124c80f95bd03bdf790d99d84 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Feb 2020 15:44:42 +0900 Subject: [PATCH 0995/4444] ARM: dts: uniphier: change SD/eMMC node names to follow json-schema Follow the standard nodename pattern "^mmc(@.*)?$" defined in Documentation/devicetree/bindings/mmc/mmc-controller.yaml Otherwise, after the dt-binding is converted to json-schema, 'make ARCH=arm dtbs_check' will show warnings like this: sdhc@5a000000: $nodename:0: 'sdhc@5a000000' does not match '^mmc(@.*)?$' Signed-off-by: Masahiro Yamada --- arch/arm/boot/dts/uniphier-ld4.dtsi | 4 ++-- arch/arm/boot/dts/uniphier-pro4.dtsi | 6 +++--- arch/arm/boot/dts/uniphier-pro5.dtsi | 4 ++-- arch/arm/boot/dts/uniphier-pxs2.dtsi | 4 ++-- arch/arm/boot/dts/uniphier-sld8.dtsi | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/arch/arm/boot/dts/uniphier-ld4.dtsi b/arch/arm/boot/dts/uniphier-ld4.dtsi index 64ec46c72a4c..f3a20dc0b22b 100644 --- a/arch/arm/boot/dts/uniphier-ld4.dtsi +++ b/arch/arm/boot/dts/uniphier-ld4.dtsi @@ -245,7 +245,7 @@ #dma-cells = <1>; }; - sd: sdhc@5a400000 { + sd: mmc@5a400000 { compatible = "socionext,uniphier-sd-v2.91"; status = "disabled"; reg = <0x5a400000 0x200>; @@ -265,7 +265,7 @@ sd-uhs-sdr50; }; - emmc: sdhc@5a500000 { + emmc: mmc@5a500000 { compatible = "socionext,uniphier-sd-v2.91"; status = "disabled"; reg = <0x5a500000 0x200>; diff --git a/arch/arm/boot/dts/uniphier-pro4.dtsi b/arch/arm/boot/dts/uniphier-pro4.dtsi index 2ec04d7972ef..e96b5796f0f8 100644 --- a/arch/arm/boot/dts/uniphier-pro4.dtsi +++ b/arch/arm/boot/dts/uniphier-pro4.dtsi @@ -279,7 +279,7 @@ #dma-cells = <1>; }; - sd: sdhc@5a400000 { + sd: mmc@5a400000 { compatible = "socionext,uniphier-sd-v2.91"; status = "disabled"; reg = <0x5a400000 0x200>; @@ -299,7 +299,7 @@ sd-uhs-sdr50; }; - emmc: sdhc@5a500000 { + emmc: mmc@5a500000 { compatible = "socionext,uniphier-sd-v2.91"; status = "disabled"; reg = <0x5a500000 0x200>; @@ -317,7 +317,7 @@ non-removable; }; - sd1: sdhc@5a600000 { + sd1: mmc@5a600000 { compatible = "socionext,uniphier-sd-v2.91"; status = "disabled"; reg = <0x5a600000 0x200>; diff --git a/arch/arm/boot/dts/uniphier-pro5.dtsi b/arch/arm/boot/dts/uniphier-pro5.dtsi index ea3961f920a0..f794a0676760 100644 --- a/arch/arm/boot/dts/uniphier-pro5.dtsi +++ b/arch/arm/boot/dts/uniphier-pro5.dtsi @@ -469,7 +469,7 @@ resets = <&sys_rst 2>, <&sys_rst 2>; }; - emmc: sdhc@68400000 { + emmc: mmc@68400000 { compatible = "socionext,uniphier-sd-v3.1"; status = "disabled"; reg = <0x68400000 0x800>; @@ -485,7 +485,7 @@ non-removable; }; - sd: sdhc@68800000 { + sd: mmc@68800000 { compatible = "socionext,uniphier-sd-v3.1"; status = "disabled"; reg = <0x68800000 0x800>; diff --git a/arch/arm/boot/dts/uniphier-pxs2.dtsi b/arch/arm/boot/dts/uniphier-pxs2.dtsi index 13b0d4a7741f..04d6bef3a00f 100644 --- a/arch/arm/boot/dts/uniphier-pxs2.dtsi +++ b/arch/arm/boot/dts/uniphier-pxs2.dtsi @@ -446,7 +446,7 @@ }; }; - emmc: sdhc@5a000000 { + emmc: mmc@5a000000 { compatible = "socionext,uniphier-sd-v3.1.1"; status = "disabled"; reg = <0x5a000000 0x800>; @@ -462,7 +462,7 @@ non-removable; }; - sd: sdhc@5a400000 { + sd: mmc@5a400000 { compatible = "socionext,uniphier-sd-v3.1.1"; status = "disabled"; reg = <0x5a400000 0x800>; diff --git a/arch/arm/boot/dts/uniphier-sld8.dtsi b/arch/arm/boot/dts/uniphier-sld8.dtsi index 4fc6676f5486..beb1eac85436 100644 --- a/arch/arm/boot/dts/uniphier-sld8.dtsi +++ b/arch/arm/boot/dts/uniphier-sld8.dtsi @@ -249,7 +249,7 @@ #dma-cells = <1>; }; - sd: sdhc@5a400000 { + sd: mmc@5a400000 { compatible = "socionext,uniphier-sd-v2.91"; status = "disabled"; reg = <0x5a400000 0x200>; @@ -269,7 +269,7 @@ sd-uhs-sdr50; }; - emmc: sdhc@5a500000 { + emmc: mmc@5a500000 { compatible = "socionext,uniphier-sd-v2.91"; status = "disabled"; reg = <0x5a500000 0x200>; From a7142fe1b79217e6c56b9097ff8228a0236edc7e Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Feb 2020 15:44:44 +0900 Subject: [PATCH 0996/4444] ARM: dts: uniphier: rename aidet node names to follow json-schema Follow the standard nodename pattern "^interrupt-controller(@[0-9a-f,]+)*$" defined in schemas/interrupt-controller.yaml of dt-schema. Otherwise, after the dt-binding is converted to json-schema, make ARCH=arm dtbs_check' will show warnings like this: aidet@5fc20000: $nodename:0: 'aidet@5fc20000' does not match '^interrupt-controller(@[0-9a-f,]+)*$' Signed-off-by: Masahiro Yamada --- arch/arm/boot/dts/uniphier-ld4.dtsi | 2 +- arch/arm/boot/dts/uniphier-pro4.dtsi | 2 +- arch/arm/boot/dts/uniphier-pro5.dtsi | 2 +- arch/arm/boot/dts/uniphier-pxs2.dtsi | 2 +- arch/arm/boot/dts/uniphier-sld8.dtsi | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/uniphier-ld4.dtsi b/arch/arm/boot/dts/uniphier-ld4.dtsi index f3a20dc0b22b..23b8fd627c00 100644 --- a/arch/arm/boot/dts/uniphier-ld4.dtsi +++ b/arch/arm/boot/dts/uniphier-ld4.dtsi @@ -375,7 +375,7 @@ interrupt-controller; }; - aidet: aidet@61830000 { + aidet: interrupt-controller@61830000 { compatible = "socionext,uniphier-ld4-aidet"; reg = <0x61830000 0x200>; interrupt-controller; diff --git a/arch/arm/boot/dts/uniphier-pro4.dtsi b/arch/arm/boot/dts/uniphier-pro4.dtsi index e96b5796f0f8..eb06c353970f 100644 --- a/arch/arm/boot/dts/uniphier-pro4.dtsi +++ b/arch/arm/boot/dts/uniphier-pro4.dtsi @@ -426,7 +426,7 @@ }; }; - aidet: aidet@5fc20000 { + aidet: interrupt-controller@5fc20000 { compatible = "socionext,uniphier-pro4-aidet"; reg = <0x5fc20000 0x200>; interrupt-controller; diff --git a/arch/arm/boot/dts/uniphier-pro5.dtsi b/arch/arm/boot/dts/uniphier-pro5.dtsi index f794a0676760..c95eb44c816d 100644 --- a/arch/arm/boot/dts/uniphier-pro5.dtsi +++ b/arch/arm/boot/dts/uniphier-pro5.dtsi @@ -408,7 +408,7 @@ }; }; - aidet: aidet@5fc20000 { + aidet: interrupt-controller@5fc20000 { compatible = "socionext,uniphier-pro5-aidet"; reg = <0x5fc20000 0x200>; interrupt-controller; diff --git a/arch/arm/boot/dts/uniphier-pxs2.dtsi b/arch/arm/boot/dts/uniphier-pxs2.dtsi index 04d6bef3a00f..c054d0175df9 100644 --- a/arch/arm/boot/dts/uniphier-pxs2.dtsi +++ b/arch/arm/boot/dts/uniphier-pxs2.dtsi @@ -508,7 +508,7 @@ }; }; - aidet: aidet@5fc20000 { + aidet: interrupt-controller@5fc20000 { compatible = "socionext,uniphier-pxs2-aidet"; reg = <0x5fc20000 0x200>; interrupt-controller; diff --git a/arch/arm/boot/dts/uniphier-sld8.dtsi b/arch/arm/boot/dts/uniphier-sld8.dtsi index beb1eac85436..a05061038e78 100644 --- a/arch/arm/boot/dts/uniphier-sld8.dtsi +++ b/arch/arm/boot/dts/uniphier-sld8.dtsi @@ -379,7 +379,7 @@ interrupt-controller; }; - aidet: aidet@61830000 { + aidet: interrupt-controller@61830000 { compatible = "socionext,uniphier-sld8-aidet"; reg = <0x61830000 0x200>; interrupt-controller; From f215c5ef7c404c1926f5dd9bd2e6d58055268af3 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 26 Feb 2020 12:59:13 +0900 Subject: [PATCH 0997/4444] ARM: dts: uniphier: rename NAND node names to follow json-schema Follow the standard nodename pattern "^nand-controller(@.*)?" defined in Documentation/devicetree/bindings/mtd/nand-controller.yaml Otherwise, after the dt-binding is converted to json-schema, 'make ARCH=arm dtbs_check' will show warnings like this: nand@68000000: $nodename:0: 'nand@68000000' does not match '^nand-controller(@.*)?' Signed-off-by: Masahiro Yamada --- arch/arm/boot/dts/uniphier-ld4.dtsi | 2 +- arch/arm/boot/dts/uniphier-pro4.dtsi | 2 +- arch/arm/boot/dts/uniphier-pro5.dtsi | 2 +- arch/arm/boot/dts/uniphier-pxs2.dtsi | 2 +- arch/arm/boot/dts/uniphier-sld8.dtsi | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/uniphier-ld4.dtsi b/arch/arm/boot/dts/uniphier-ld4.dtsi index 23b8fd627c00..197bee7d8b7f 100644 --- a/arch/arm/boot/dts/uniphier-ld4.dtsi +++ b/arch/arm/boot/dts/uniphier-ld4.dtsi @@ -398,7 +398,7 @@ }; }; - nand: nand@68000000 { + nand: nand-controller@68000000 { compatible = "socionext,uniphier-denali-nand-v5a"; status = "disabled"; reg-names = "nand_data", "denali_reg"; diff --git a/arch/arm/boot/dts/uniphier-pro4.dtsi b/arch/arm/boot/dts/uniphier-pro4.dtsi index eb06c353970f..b02bc8a6346b 100644 --- a/arch/arm/boot/dts/uniphier-pro4.dtsi +++ b/arch/arm/boot/dts/uniphier-pro4.dtsi @@ -588,7 +588,7 @@ }; }; - nand: nand@68000000 { + nand: nand-controller@68000000 { compatible = "socionext,uniphier-denali-nand-v5a"; status = "disabled"; reg-names = "nand_data", "denali_reg"; diff --git a/arch/arm/boot/dts/uniphier-pro5.dtsi b/arch/arm/boot/dts/uniphier-pro5.dtsi index c95eb44c816d..f84a43a10f38 100644 --- a/arch/arm/boot/dts/uniphier-pro5.dtsi +++ b/arch/arm/boot/dts/uniphier-pro5.dtsi @@ -453,7 +453,7 @@ }; }; - nand: nand@68000000 { + nand: nand-controller@68000000 { compatible = "socionext,uniphier-denali-nand-v5b"; status = "disabled"; reg-names = "nand_data", "denali_reg"; diff --git a/arch/arm/boot/dts/uniphier-pxs2.dtsi b/arch/arm/boot/dts/uniphier-pxs2.dtsi index c054d0175df9..989b2a241822 100644 --- a/arch/arm/boot/dts/uniphier-pxs2.dtsi +++ b/arch/arm/boot/dts/uniphier-pxs2.dtsi @@ -761,7 +761,7 @@ }; }; - nand: nand@68000000 { + nand: nand-controller@68000000 { compatible = "socionext,uniphier-denali-nand-v5b"; status = "disabled"; reg-names = "nand_data", "denali_reg"; diff --git a/arch/arm/boot/dts/uniphier-sld8.dtsi b/arch/arm/boot/dts/uniphier-sld8.dtsi index a05061038e78..fbfd25050a04 100644 --- a/arch/arm/boot/dts/uniphier-sld8.dtsi +++ b/arch/arm/boot/dts/uniphier-sld8.dtsi @@ -402,7 +402,7 @@ }; }; - nand: nand@68000000 { + nand: nand-controller@68000000 { compatible = "socionext,uniphier-denali-nand-v5a"; status = "disabled"; reg-names = "nand_data", "denali_reg"; From bc350d1073bc4d1147697a68fac68e062dd9912f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 27 Feb 2020 21:37:26 +0900 Subject: [PATCH 0998/4444] ARM: dts: uniphier: rename cache controller nodes to follow json-schema Follow the standard nodename pattern "^(cache-controller|cpu)(@[0-9a-f,]+)*$" defined in schemas/cache-controller.yaml of dt-schema. Otherwise, after the dt-binding is converted to json-schema, 'make ARCH=arm dtbs_check' will show warnings like this: l2-cache@500c0000: $nodename:0: 'l2-cache@500c0000' does not match '^(cache-controller|cpu)(@[0-9a-f,]+)*$' Signed-off-by: Masahiro Yamada --- arch/arm/boot/dts/uniphier-ld4.dtsi | 2 +- arch/arm/boot/dts/uniphier-pro4.dtsi | 2 +- arch/arm/boot/dts/uniphier-pro5.dtsi | 4 ++-- arch/arm/boot/dts/uniphier-pxs2.dtsi | 2 +- arch/arm/boot/dts/uniphier-sld8.dtsi | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/uniphier-ld4.dtsi b/arch/arm/boot/dts/uniphier-ld4.dtsi index 197bee7d8b7f..06e7400d2940 100644 --- a/arch/arm/boot/dts/uniphier-ld4.dtsi +++ b/arch/arm/boot/dts/uniphier-ld4.dtsi @@ -51,7 +51,7 @@ ranges; interrupt-parent = <&intc>; - l2: l2-cache@500c0000 { + l2: cache-controller@500c0000 { compatible = "socionext,uniphier-system-cache"; reg = <0x500c0000 0x2000>, <0x503c0100 0x4>, <0x506c0000 0x400>; diff --git a/arch/arm/boot/dts/uniphier-pro4.dtsi b/arch/arm/boot/dts/uniphier-pro4.dtsi index b02bc8a6346b..1c866f0306fc 100644 --- a/arch/arm/boot/dts/uniphier-pro4.dtsi +++ b/arch/arm/boot/dts/uniphier-pro4.dtsi @@ -59,7 +59,7 @@ ranges; interrupt-parent = <&intc>; - l2: l2-cache@500c0000 { + l2: cache-controller@500c0000 { compatible = "socionext,uniphier-system-cache"; reg = <0x500c0000 0x2000>, <0x503c0100 0x4>, <0x506c0000 0x400>; diff --git a/arch/arm/boot/dts/uniphier-pro5.dtsi b/arch/arm/boot/dts/uniphier-pro5.dtsi index f84a43a10f38..da772429b55a 100644 --- a/arch/arm/boot/dts/uniphier-pro5.dtsi +++ b/arch/arm/boot/dts/uniphier-pro5.dtsi @@ -131,7 +131,7 @@ ranges; interrupt-parent = <&intc>; - l2: l2-cache@500c0000 { + l2: cache-controller@500c0000 { compatible = "socionext,uniphier-system-cache"; reg = <0x500c0000 0x2000>, <0x503c0100 0x8>, <0x506c0000 0x400>; @@ -144,7 +144,7 @@ next-level-cache = <&l3>; }; - l3: l3-cache@500c8000 { + l3: cache-controller@500c8000 { compatible = "socionext,uniphier-system-cache"; reg = <0x500c8000 0x2000>, <0x503c8100 0x8>, <0x506c8000 0x400>; diff --git a/arch/arm/boot/dts/uniphier-pxs2.dtsi b/arch/arm/boot/dts/uniphier-pxs2.dtsi index 989b2a241822..7044f8700cb2 100644 --- a/arch/arm/boot/dts/uniphier-pxs2.dtsi +++ b/arch/arm/boot/dts/uniphier-pxs2.dtsi @@ -157,7 +157,7 @@ ranges; interrupt-parent = <&intc>; - l2: l2-cache@500c0000 { + l2: cache-controller@500c0000 { compatible = "socionext,uniphier-system-cache"; reg = <0x500c0000 0x2000>, <0x503c0100 0x8>, <0x506c0000 0x400>; diff --git a/arch/arm/boot/dts/uniphier-sld8.dtsi b/arch/arm/boot/dts/uniphier-sld8.dtsi index fbfd25050a04..09992163e1f4 100644 --- a/arch/arm/boot/dts/uniphier-sld8.dtsi +++ b/arch/arm/boot/dts/uniphier-sld8.dtsi @@ -51,7 +51,7 @@ ranges; interrupt-parent = <&intc>; - l2: l2-cache@500c0000 { + l2: cache-controller@500c0000 { compatible = "socionext,uniphier-system-cache"; reg = <0x500c0000 0x2000>, <0x503c0100 0x4>, <0x506c0000 0x400>; From bb3f46726bb94292c672a5f34a544e398436af7f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Feb 2020 15:44:43 +0900 Subject: [PATCH 0999/4444] arm64: dts: uniphier: change SD/eMMC node names to follow json-schema Follow the standard nodename pattern "^mmc(@.*)?$" defined in Documentation/devicetree/bindings/mmc/mmc-controller.yaml Otherwise, after the dt-binding is converted to json-schema, 'make ARCH=arm64 dtbs_check' will show warnings like this: sdhc@5a000000: $nodename:0: 'sdhc@5a000000' does not match '^mmc(@.*)?$' Signed-off-by: Masahiro Yamada --- arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi | 2 +- arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi | 4 ++-- arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi index 5b18bda9c5a6..7510db465f33 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi @@ -433,7 +433,7 @@ }; }; - emmc: sdhc@5a000000 { + emmc: mmc@5a000000 { compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc"; reg = <0x5a000000 0x400>; interrupts = <0 78 4>; diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi index f2dc5f695020..8d360c5cc32b 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi @@ -559,7 +559,7 @@ }; }; - emmc: sdhc@5a000000 { + emmc: mmc@5a000000 { compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc"; reg = <0x5a000000 0x400>; interrupts = <0 78 4>; @@ -578,7 +578,7 @@ cdns,phy-dll-delay-sdclk-hsmmc = <21>; }; - sd: sdhc@5a400000 { + sd: mmc@5a400000 { compatible = "socionext,uniphier-sd-v3.1.1"; status = "disabled"; reg = <0x5a400000 0x800>; diff --git a/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi b/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi index 73e7e1203b09..d51b0735917c 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi @@ -353,7 +353,7 @@ }; }; - emmc: sdhc@5a000000 { + emmc: mmc@5a000000 { compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc"; reg = <0x5a000000 0x400>; interrupts = <0 78 4>; @@ -372,7 +372,7 @@ cdns,phy-dll-delay-sdclk-hsmmc = <21>; }; - sd: sdhc@5a400000 { + sd: mmc@5a400000 { compatible = "socionext,uniphier-sd-v3.1.1"; status = "disabled"; reg = <0x5a400000 0x800>; From 9ddc285b3a6f4d38ab7ba202b07246180213be77 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Feb 2020 15:44:45 +0900 Subject: [PATCH 1000/4444] arm64: dts: uniphier: rename aidet node names to follow json-schema Follow the standard nodename pattern "^interrupt-controller(@[0-9a-f,]+)*$" defined in schemas/interrupt-controller.yaml of dt-schema. Otherwise, after the dt-binding is converted to json-schema, 'make ARCH=arm64 dtbs_check' will show warnings like this: aidet@5fc20000: $nodename:0: 'aidet@5fc20000' does not match '^interrupt-controller(@[0-9a-f,]+)*$' Signed-off-by: Masahiro Yamada --- arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi | 2 +- arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi | 2 +- arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi index 7510db465f33..2e53daca9f5c 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi @@ -566,7 +566,7 @@ }; }; - aidet: aidet@5fc20000 { + aidet: interrupt-controller@5fc20000 { compatible = "socionext,uniphier-ld11-aidet"; reg = <0x5fc20000 0x200>; interrupt-controller; diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi index 8d360c5cc32b..be984200a70e 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi @@ -664,7 +664,7 @@ }; }; - aidet: aidet@5fc20000 { + aidet: interrupt-controller@5fc20000 { compatible = "socionext,uniphier-ld20-aidet"; reg = <0x5fc20000 0x200>; interrupt-controller; diff --git a/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi b/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi index d51b0735917c..994fea7b12c1 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi @@ -462,7 +462,7 @@ }; }; - aidet: aidet@5fc20000 { + aidet: interrupt-controller@5fc20000 { compatible = "socionext,uniphier-pxs3-aidet"; reg = <0x5fc20000 0x200>; interrupt-controller; From fcb0e53c226e20626890e885c3542f3fe4a26133 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 26 Feb 2020 12:59:14 +0900 Subject: [PATCH 1001/4444] arm64: dts: uniphier: rename NAND node names to follow json-schema Follow the standard nodename pattern "^nand-controller(@.*)?" defined in Documentation/devicetree/bindings/mtd/nand-controller.yaml Otherwise, after the dt-binding is converted to json-schema, 'make ARCH=arm64 dtbs_check' will show warnings like this: nand@68000000: $nodename:0: 'nand@68000000' does not match '^nand-controller(@.*)?' Signed-off-by: Masahiro Yamada --- arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi | 2 +- arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi | 2 +- arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi index 2e53daca9f5c..d61da3a62712 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi @@ -621,7 +621,7 @@ }; }; - nand: nand@68000000 { + nand: nand-controller@68000000 { compatible = "socionext,uniphier-denali-nand-v5b"; status = "disabled"; reg-names = "nand_data", "denali_reg"; diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi index be984200a70e..98f0f4eb0649 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi @@ -925,7 +925,7 @@ socionext,syscon = <&soc_glue>; }; - nand: nand@68000000 { + nand: nand-controller@68000000 { compatible = "socionext,uniphier-denali-nand-v5b"; status = "disabled"; reg-names = "nand_data", "denali_reg"; diff --git a/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi b/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi index 994fea7b12c1..4c6cd3ec541d 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi @@ -783,7 +783,7 @@ socionext,syscon = <&soc_glue>; }; - nand: nand@68000000 { + nand: nand-controller@68000000 { compatible = "socionext,uniphier-denali-nand-v5b"; status = "disabled"; reg-names = "nand_data", "denali_reg"; From 0d47370516b35efa4a220390083341af0bdb7601 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 28 Feb 2020 21:20:55 +0900 Subject: [PATCH 1002/4444] ARM: dts: uniphier: Add one more generic compatible string for I2C EEPROM Commit 73f9de0c7f5d ("ARM: dts: uniphier: Add generic compatible string for I2C EEPROM") did not touch this node. Add the compatible string prefixed "atmel," so that this matches to the OF table. Signed-off-by: Masahiro Yamada --- arch/arm/boot/dts/uniphier-ref-daughter.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/uniphier-ref-daughter.dtsi b/arch/arm/boot/dts/uniphier-ref-daughter.dtsi index 04e60c295319..a11897669c26 100644 --- a/arch/arm/boot/dts/uniphier-ref-daughter.dtsi +++ b/arch/arm/boot/dts/uniphier-ref-daughter.dtsi @@ -7,7 +7,7 @@ &i2c0 { eeprom@50 { - compatible = "microchip,24lc128"; + compatible = "microchip,24lc128", "atmel,24c128"; reg = <0x50>; pagesize = <64>; }; From 2f8caa9f8f3254cd4527ec6a71428107623b3fa8 Mon Sep 17 00:00:00 2001 From: Rajeshwari Date: Mon, 6 Jan 2020 18:59:29 +0530 Subject: [PATCH 1003/4444] dt-bindings: thermal: tsens: Add configuration in yaml Added configuration in dt-bindings for SC7180. Signed-off-by: Rajeshwari Reviewed-by: Bjorn Andersson Acked-by: Rob Herring Reviewed-by: Amit Kucheria Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/1578317369-16045-3-git-send-email-rkambl@codeaurora.org --- Documentation/devicetree/bindings/thermal/qcom-tsens.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml index eef13b9446a8..c0ed030d0960 100644 --- a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml +++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml @@ -38,6 +38,7 @@ properties: - enum: - qcom,msm8996-tsens - qcom,msm8998-tsens + - qcom,sc7180-tsens - qcom,sdm845-tsens - const: qcom,tsens-v2 From 182eb908b25030fbba1f585deb2b26fc42b40e81 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 26 Feb 2020 11:57:10 +0100 Subject: [PATCH 1004/4444] ARM: exynos_defconfig: Add more drivers for GalaxyS3/Trats2 Enable drivers for S5K6A3 and S5C73M3 camera sensors, AAT1290 flash LED, Midas-TouchKey and BRCMFMAC SDIO-WIFI modules used on Samsung Galaxy S3 and Trats2 boards. Signed-off-by: Marek Szyprowski Signed-off-by: Krzysztof Kozlowski --- arch/arm/configs/exynos_defconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig index 439d37197959..3c3a00fc71f6 100644 --- a/arch/arm/configs/exynos_defconfig +++ b/arch/arm/configs/exynos_defconfig @@ -113,11 +113,13 @@ CONFIG_USB_LAN78XX=m CONFIG_USB_USBNET=y CONFIG_USB_NET_SMSC75XX=y CONFIG_USB_NET_SMSC95XX=y +CONFIG_BRCMFMAC=m CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y CONFIG_KEYBOARD_SAMSUNG=y +CONFIG_KEYBOARD_TM2_TOUCHKEY=y CONFIG_KEYBOARD_CROS_EC=y # CONFIG_MOUSE_PS2 is not set CONFIG_MOUSE_CYAPA=y @@ -206,6 +208,9 @@ CONFIG_V4L_TEST_DRIVERS=y CONFIG_VIDEO_VIVID=m CONFIG_CEC_PLATFORM_DRIVERS=y CONFIG_VIDEO_SAMSUNG_S5P_CEC=m +# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set +CONFIG_VIDEO_S5K6A3=m +CONFIG_VIDEO_S5C73M3=m CONFIG_DRM=y CONFIG_DRM_EXYNOS=y CONFIG_DRM_EXYNOS_FIMD=y @@ -278,6 +283,7 @@ CONFIG_MMC_DW_EXYNOS=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y CONFIG_LEDS_CLASS_FLASH=y +CONFIG_LEDS_AAT1290=y CONFIG_LEDS_GPIO=y CONFIG_LEDS_PWM=y CONFIG_LEDS_MAX77693=y From fbec0a1f775aa03ebb86c16fa761e6f52bb299ea Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 28 Feb 2020 15:55:01 +0100 Subject: [PATCH 1005/4444] ARM: dts: exynos: Fix G3D power domain supply on Odroid XU3/XU4/HC1 boards G3D power domain in Exynos5422 SoC is supplied from VDD_G3D. Besides the main GPU MALI module it also contains the power domain control logic and clocks. Turning the VDD_G3D power supply off causes the power domain to fail to operate properly and breaks for example system suspend/resume. GPU should use VDD_G3D supply mainly to control the DVFS. Fixes: 1a5a85c56402 ("ARM: dts: exynos: Add Mali/GPU node on Exynos5420 and enable it on Odroid XU3/4") Signed-off-by: Marek Szyprowski Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos5422-odroid-core.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi b/arch/arm/boot/dts/exynos5422-odroid-core.dtsi index 5cf1aed20490..ab27ff8bc3dc 100644 --- a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroid-core.dtsi @@ -901,6 +901,7 @@ regulator-min-microvolt = <800000>; regulator-max-microvolt = <1400000>; regulator-boot-on; + regulator-always-on; regulator-state-mem { regulator-off-in-suspend; From 604e8b79c8864a308a459689c7054a508d52841f Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 28 Feb 2020 15:55:02 +0100 Subject: [PATCH 1006/4444] ARM: dts: exynos: Fix G3D power domain supply on Arndale Octa boards G3D power domain in Exynos5420 SoC is supplied from PVDD_G3DS_1V0 and PVDD_G3D_1V0. Besides the main GPU MALI module it also contains the power domain control logic and clocks. Turning the power supplies off causes the power domain to fail to operate properly if GPU drivers are loaded as modules. GPU should use PVDD_G3D_1V0 supply mainly to control the DVFS. Signed-off-by: Marek Szyprowski Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos5420-arndale-octa.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts b/arch/arm/boot/dts/exynos5420-arndale-octa.dts index ee28d30f5476..e9a09dd0a49b 100644 --- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts +++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts @@ -584,6 +584,7 @@ regulator-name = "PVDD_G3DS_1V0"; regulator-min-microvolt = <800000>; regulator-max-microvolt = <1100000>; + regulator-always-on; regulator-state-mem { regulator-on-in-suspend; @@ -697,6 +698,7 @@ regulator-name = "PVDD_G3D_1V0"; regulator-min-microvolt = <800000>; regulator-max-microvolt = <1400000>; + regulator-always-on; regulator-state-mem { regulator-off-in-suspend; From b5f3e42a613a8e84d59bd39464de82961e2c8c2c Mon Sep 17 00:00:00 2001 From: Mohammad Rasim Date: Fri, 14 Feb 2020 11:58:02 +0300 Subject: [PATCH 1007/4444] arm64: dts: amlogic: add rc-videostrong-kii-pro keymap videostrong kii pro comes with a nec rc, add the keymap to the dts Signed-off-by: Mohammad Rasim Signed-off-by: Kevin Hilman Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20200214085802.28742-4-mohammad.rasim96@gmail.com --- arch/arm64/boot/dts/amlogic/meson-gxbb-kii-pro.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-kii-pro.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-kii-pro.dts index 2f1f829450a2..6c9cc45fb417 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-kii-pro.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-kii-pro.dts @@ -76,3 +76,7 @@ }; }; }; + +&ir { + linux,rc-map-name = "rc-videostrong-kii-pro"; +}; From 9ef7a7920678b10431d88635f9a4a49bd23ca3a7 Mon Sep 17 00:00:00 2001 From: Jianxin Pan Date: Tue, 18 Feb 2020 00:12:13 +0800 Subject: [PATCH 1008/4444] soc: amlogic: fix compile failure with MESON_SECURE_PM_DOMAINS & !MESON_SM When MESON_SECURE_PM_DOMAINS & !MESON_SM, there will be compile failure: .../meson-secure-pwrc.o: In function `meson_secure_pwrc_on': .../meson-secure-pwrc.c:76: undefined reference to `meson_sm_call' Fix this by adding depends on MESON_SM for MESON_SECURE_PM_DOMAINS. Fixes: b3dde5013e13 ("soc: amlogic: Add support for Secure power domains controller") Reported-by: Stephen Rothwell Reported-by: patchwork-bot+linux-amlogic Reported-by: kbuild test robot Signed-off-by: Jianxin Pan Signed-off-by: Kevin Hilman Tested-by: Stephen Rothwell Link: https://lore.kernel.org/r/1581955933-69832-1-git-send-email-jianxin.pan@amlogic.com --- drivers/soc/amlogic/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/amlogic/Kconfig b/drivers/soc/amlogic/Kconfig index 6cb06e7b5e63..321c5e26a268 100644 --- a/drivers/soc/amlogic/Kconfig +++ b/drivers/soc/amlogic/Kconfig @@ -50,7 +50,7 @@ config MESON_EE_PM_DOMAINS config MESON_SECURE_PM_DOMAINS bool "Amlogic Meson Secure Power Domains driver" - depends on ARCH_MESON || COMPILE_TEST + depends on (ARCH_MESON || COMPILE_TEST) && MESON_SM depends on PM && OF depends on HAVE_ARM_SMCCC default ARCH_MESON From a81bcfb6ac20cdd2e8dec3da14c8bbe1d18f6321 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Fri, 21 Feb 2020 10:15:32 +0100 Subject: [PATCH 1009/4444] arm64: dts: g12-common: add parkmode_disable_ss_quirk on DWC3 controller When high load on the DWC3 SuperSpeed port, the controller crashes with: [ 221.141621] xhci-hcd xhci-hcd.0.auto: xHCI host not responding to stop endpoint command. [ 221.157631] xhci-hcd xhci-hcd.0.auto: Host halt failed, -110 [ 221.157635] xhci-hcd xhci-hcd.0.auto: xHCI host controller not responding, assume dead [ 221.159901] xhci-hcd xhci-hcd.0.auto: xHCI host not responding to stop endpoint command. [ 221.159961] hub 2-1.1:1.0: hub_ext_port_status failed (err = -22) [ 221.160076] xhci-hcd xhci-hcd.0.auto: HC died; cleaning up [ 221.165946] usb 2-1.1-port1: cannot reset (err = -22) Setting the parkmode_disable_ss_quirk quirk fixes the issue. Reported-by: Tim Signed-off-by: Neil Armstrong Signed-off-by: Kevin Hilman Cc: Jianxin Pan CC: Dongjin Kim Link: https://lore.kernel.org/r/20200221091532.8142-4-narmstrong@baylibre.com --- arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi index abe04f4ad7d8..87b9a47a51b9 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi @@ -2220,6 +2220,7 @@ dr_mode = "host"; snps,dis_u2_susphy_quirk; snps,quirk-frame-length-adjustment; + snps,parkmode-disable-ss-quirk; }; }; From ae5eed592c38608a7f67f72c21525ae075188c69 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 24 Feb 2020 16:08:10 +0100 Subject: [PATCH 1010/4444] arm64: dts: meson: add pdm reset line Add the reset line of the PDM device to g12 and sm1 SoCs. Signed-off-by: Jerome Brunet Signed-off-by: Kevin Hilman Link: https://lore.kernel.org/r/20200224150812.263980-2-jbrunet@baylibre.com --- arch/arm64/boot/dts/amlogic/meson-g12.dtsi | 1 + arch/arm64/boot/dts/amlogic/meson-sm1.dtsi | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/amlogic/meson-g12.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12.dtsi index 03054c478896..55d39020ec72 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12.dtsi @@ -56,6 +56,7 @@ <&clkc_audio AUD_CLKID_PDM_DCLK>, <&clkc_audio AUD_CLKID_PDM_SYSCLK>; clock-names = "pclk", "dclk", "sysclk"; + resets = <&clkc_audio AUD_RESET_PDM>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi b/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi index d847a3fcbc85..d4ec735fb1a5 100644 --- a/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi @@ -448,6 +448,7 @@ <&clkc_audio AUD_CLKID_PDM_DCLK>, <&clkc_audio AUD_CLKID_PDM_SYSCLK>; clock-names = "pclk", "dclk", "sysclk"; + resets = <&clkc_audio AUD_RESET_PDM>; status = "disabled"; }; }; From 430049239f91cc287b1e63a4e3f2e626adcb33cc Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 24 Feb 2020 16:08:11 +0100 Subject: [PATCH 1011/4444] arm64: dts: meson: s400: fix sound card codec nodes Some codec nodes of the s400 sound card are numbered with the pattern codec@XX. This pattern should be used only if there is a reg property in the node which is not case here. Change this to something acceptable. This change is only to better comply with the DT spec. No functional changes expected. Fixes: 6f59dc1afbb2 ("arm64: dts: meson-axg: s400: add sound card") Signed-off-by: Jerome Brunet Signed-off-by: Kevin Hilman Link: https://lore.kernel.org/r/20200224150812.263980-3-jbrunet@baylibre.com --- arch/arm64/boot/dts/amlogic/meson-axg-s400.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts b/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts index 4cd2d5951822..cb1360ae1211 100644 --- a/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts +++ b/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts @@ -313,15 +313,15 @@ dai-tdm-slot-rx-mask-1 = <1 1>; mclk-fs = <256>; - codec@0 { + codec-0 { sound-dai = <&lineout>; }; - codec@1 { + codec-1 { sound-dai = <&speaker_amp1>; }; - codec@2 { + codec-2 { sound-dai = <&linein>; }; From 65b41849e10ca6fa745ba1a5cf461911fa95267a Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 24 Feb 2020 16:08:12 +0100 Subject: [PATCH 1012/4444] arm64: dts: meson: sei510: fix sound card codec node A codec node of the sei510 sound card is numbered with the pattern codec@XX. This pattern should be used only if there is a reg property in the node which is not case here. Change this to something acceptable. This change is only to better comply with the DT spec. No functional changes expected. Fixes: 64c10554bf9c ("arm64: dts: meson: sei510: add sound card") Signed-off-by: Jerome Brunet Signed-off-by: Kevin Hilman Link: https://lore.kernel.org/r/20200224150812.263980-4-jbrunet@baylibre.com --- arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts index 2ac9e3a43b96..168f460e11fa 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts @@ -269,7 +269,7 @@ dai-tdm-slot-tx-mask-3 = <1 1>; mclk-fs = <256>; - codec@0 { + codec { sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; }; }; From c6677da13d5a83ded6de1629f18794712d19b42e Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Thu, 20 Feb 2020 19:33:10 +0400 Subject: [PATCH 1013/4444] arm64: dts: meson: fix gxm-khadas-vim2 wifi Fixes: adc52bf7ef16 ("arm64: dts: meson: fix mmc v2 chips max frequencies") before [6.418252] brcmfmac: F1 signature read @0x18000000=0x17224356 [6.435663] brcmfmac: brcmf_fw_alloc_request: using brcm/brcmfmac4356-sdio for chip BCM4356/2 [6.551259] brcmfmac: brcmf_sdiod_ramrw: membytes transfer failed [6.551275] brcmfmac: brcmf_sdio_verifymemory: error -84 on reading 2048 membytes at 0x00184000 [6.551352] brcmfmac: brcmf_sdio_download_firmware: dongle image file download failed after [6.657165] brcmfmac: F1 signature read @0x18000000=0x17224356 [6.660807] brcmfmac: brcmf_fw_alloc_request: using brcm/brcmfmac4356-sdio for chip BCM4356/2 [6.918643] brcmfmac: brcmf_fw_alloc_request: using brcm/brcmfmac4356-sdio for chip BCM4356/2 [6.918734] brcmfmac: brcmf_c_process_clm_blob: no clm_blob available (err=-2), device may have limited channels available [6.922724] brcmfmac: brcmf_c_preinit_dcmds: Firmware: BCM4356/2 wl0: Jun 16 2015 14:25:06 version 7.35.184.r1 (TOB) (r559293) FWID 01-b22ae69c Suggested-by: Art Nikpal Signed-off-by: Christian Hewitt Signed-off-by: Kevin Hilman Link: https://lore.kernel.org/r/1582212790-11402-1-git-send-email-christianshewitt@gmail.com --- arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts index f82f25c1a5f9..d5dc12878dfe 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts @@ -327,7 +327,7 @@ #size-cells = <0>; bus-width = <4>; - max-frequency = <50000000>; + max-frequency = <60000000>; non-removable; disable-wp; From 67c4dd59fe9f8c0d3f86e170cd20f1ec55660feb Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Thu, 20 Feb 2020 19:38:05 +0400 Subject: [PATCH 1014/4444] arm64: dts: meson-gxbb-odroid-c2: add rc-odroid ir keymap Add the rc-odroid keymap to the Odroid C2 device-tree. Signed-off-by: Christian Hewitt Signed-off-by: Kevin Hilman Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/1582213085-11656-1-git-send-email-christianshewitt@gmail.com --- arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts index 6ded279c40c8..b46ef985bb44 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts @@ -248,6 +248,7 @@ status = "okay"; pinctrl-0 = <&remote_input_ao_pins>; pinctrl-names = "default"; + linux,rc-map-name = "rc-odroid"; }; &gpio_ao { From 026c20e7b05f6a6a91720feb7492c0d9b90a9b8c Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Thu, 20 Feb 2020 20:32:46 +0400 Subject: [PATCH 1015/4444] arm64: dts: meson-gxl-s905x-p212: add bluetooth nodes This removes the uart_A alias (no longer required) and adds the bluetooth node to the P212 device tree. Signed-off-by: Christian Hewitt Signed-off-by: Kevin Hilman Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/1582216366-12964-1-git-send-email-christianshewitt@gmail.com --- arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi index 43eb7d149e36..6ac678f88bd8 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi @@ -15,7 +15,6 @@ / { aliases { serial0 = &uart_AO; - serial1 = &uart_A; ethernet0 = ðmac; }; @@ -180,6 +179,14 @@ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; pinctrl-names = "default"; uart-has-rtscts; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + max-speed = <2000000>; + clocks = <&wifi32k>; + clock-names = "lpo"; + }; }; &uart_AO { From 9929451857285db227433c3fb48ebe9e1d2bf9a2 Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Thu, 20 Feb 2020 21:44:02 +0400 Subject: [PATCH 1016/4444] arm64: dts: meson-gxbb-vega-s95: fix bluetooth node This was missed from the previous fix. Fixes: b07a11dbdfeb ("arm64: dts: meson-gxbb-vega-s95: fix WiFi/BT module support") Suggested-by: Oleg Ivanov Signed-off-by: Christian Hewitt Signed-off-by: Kevin Hilman Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/1582220642-14133-1-git-send-email-christianshewitt@gmail.com --- arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi index 5eab3dfdbd55..45cb83625951 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi @@ -245,6 +245,9 @@ bluetooth { compatible = "brcm,bcm43438-bt"; shutdown-gpios = <&gpio GPIOX_20 GPIO_ACTIVE_HIGH>; + max-speed = <2000000>; + clocks = <&wifi32k>; + clock-names = "lpo"; }; }; From 5236347bde421057b645cc2bcee4be0f1bc90243 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Sat, 29 Feb 2020 18:04:00 +0100 Subject: [PATCH 1017/4444] arm64: dts: mediatek: add dtsi for MT8516 The MT8516 SoC provides the following peripherals: GPIO, UART, USB2, SPI, eMMC, SDIO, NAND, Flash, ADC, I2C, PWM, Timers, IR, Ethernet, and Audio (I2S, SPDIF, TDM). This commit is adding the basic dtsi file with the support of the following IOs: GPIO, UART, SPI, eMMC, I2C, Timers. Signed-off-by: Fabien Parent Signed-off-by: Matthias Brugger --- arch/arm64/boot/dts/mediatek/mt8516-pinfunc.h | 663 ++++++++++++++++++ arch/arm64/boot/dts/mediatek/mt8516.dtsi | 457 ++++++++++++ 2 files changed, 1120 insertions(+) create mode 100644 arch/arm64/boot/dts/mediatek/mt8516-pinfunc.h create mode 100644 arch/arm64/boot/dts/mediatek/mt8516.dtsi diff --git a/arch/arm64/boot/dts/mediatek/mt8516-pinfunc.h b/arch/arm64/boot/dts/mediatek/mt8516-pinfunc.h new file mode 100644 index 000000000000..73339bb48f0d --- /dev/null +++ b/arch/arm64/boot/dts/mediatek/mt8516-pinfunc.h @@ -0,0 +1,663 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2019 MediaTek Inc. + */ +#ifndef __DTS_MT8516_PINFUNC_H +#define __DTS_MT8516_PINFUNC_H + +#include + +#define MT8516_PIN_0_EINT0__FUNC_GPIO0 (MTK_PIN_NO(0) | 0) +#define MT8516_PIN_0_EINT0__FUNC_PWM_B (MTK_PIN_NO(0) | 1) +#define MT8516_PIN_0_EINT0__FUNC_I2S2_BCK (MTK_PIN_NO(0) | 3) +#define MT8516_PIN_0_EINT0__FUNC_EXT_TXD0 (MTK_PIN_NO(0) | 4) +#define MT8516_PIN_0_EINT0__FUNC_SQICS (MTK_PIN_NO(0) | 6) +#define MT8516_PIN_0_EINT0__FUNC_DBG_MON_A_6 (MTK_PIN_NO(0) | 7) + +#define MT8516_PIN_1_EINT1__FUNC_GPIO1 (MTK_PIN_NO(1) | 0) +#define MT8516_PIN_1_EINT1__FUNC_PWM_C (MTK_PIN_NO(1) | 1) +#define MT8516_PIN_1_EINT1__FUNC_I2S2_DI (MTK_PIN_NO(1) | 3) +#define MT8516_PIN_1_EINT1__FUNC_EXT_TXD1 (MTK_PIN_NO(1) | 4) +#define MT8516_PIN_1_EINT1__FUNC_CONN_MCU_TDO (MTK_PIN_NO(1) | 5) +#define MT8516_PIN_1_EINT1__FUNC_SQISO (MTK_PIN_NO(1) | 6) +#define MT8516_PIN_1_EINT1__FUNC_DBG_MON_A_7 (MTK_PIN_NO(1) | 7) + +#define MT8516_PIN_2_EINT2__FUNC_GPIO2 (MTK_PIN_NO(2) | 0) +#define MT8516_PIN_2_EINT2__FUNC_CLKM0 (MTK_PIN_NO(2) | 1) +#define MT8516_PIN_2_EINT2__FUNC_I2S2_LRCK (MTK_PIN_NO(2) | 3) +#define MT8516_PIN_2_EINT2__FUNC_EXT_TXD2 (MTK_PIN_NO(2) | 4) +#define MT8516_PIN_2_EINT2__FUNC_CONN_MCU_DBGACK_N (MTK_PIN_NO(2) | 5) +#define MT8516_PIN_2_EINT2__FUNC_SQISI (MTK_PIN_NO(2) | 6) +#define MT8516_PIN_2_EINT2__FUNC_DBG_MON_A_8 (MTK_PIN_NO(2) | 7) + +#define MT8516_PIN_3_EINT3__FUNC_GPIO3 (MTK_PIN_NO(3) | 0) +#define MT8516_PIN_3_EINT3__FUNC_CLKM1 (MTK_PIN_NO(3) | 1) +#define MT8516_PIN_3_EINT3__FUNC_SPI_MI (MTK_PIN_NO(3) | 3) +#define MT8516_PIN_3_EINT3__FUNC_EXT_TXD3 (MTK_PIN_NO(3) | 4) +#define MT8516_PIN_3_EINT3__FUNC_CONN_MCU_DBGI_N (MTK_PIN_NO(3) | 5) +#define MT8516_PIN_3_EINT3__FUNC_SQIWP (MTK_PIN_NO(3) | 6) +#define MT8516_PIN_3_EINT3__FUNC_DBG_MON_A_9 (MTK_PIN_NO(3) | 7) + +#define MT8516_PIN_4_EINT4__FUNC_GPIO4 (MTK_PIN_NO(4) | 0) +#define MT8516_PIN_4_EINT4__FUNC_CLKM2 (MTK_PIN_NO(4) | 1) +#define MT8516_PIN_4_EINT4__FUNC_SPI_MO (MTK_PIN_NO(4) | 3) +#define MT8516_PIN_4_EINT4__FUNC_EXT_TXC (MTK_PIN_NO(4) | 4) +#define MT8516_PIN_4_EINT4__FUNC_CONN_MCU_TCK (MTK_PIN_NO(4) | 5) +#define MT8516_PIN_4_EINT4__FUNC_CONN_MCU_AICE_JCKC (MTK_PIN_NO(4) | 6) +#define MT8516_PIN_4_EINT4__FUNC_DBG_MON_A_10 (MTK_PIN_NO(4) | 7) + +#define MT8516_PIN_5_EINT5__FUNC_GPIO5 (MTK_PIN_NO(5) | 0) +#define MT8516_PIN_5_EINT5__FUNC_UCTS2 (MTK_PIN_NO(5) | 1) +#define MT8516_PIN_5_EINT5__FUNC_SPI_CSB (MTK_PIN_NO(5) | 3) +#define MT8516_PIN_5_EINT5__FUNC_EXT_RXER (MTK_PIN_NO(5) | 4) +#define MT8516_PIN_5_EINT5__FUNC_CONN_MCU_TDI (MTK_PIN_NO(5) | 5) +#define MT8516_PIN_5_EINT5__FUNC_CONN_TEST_CK (MTK_PIN_NO(5) | 6) +#define MT8516_PIN_5_EINT5__FUNC_DBG_MON_A_11 (MTK_PIN_NO(5) | 7) + +#define MT8516_PIN_6_EINT6__FUNC_GPIO6 (MTK_PIN_NO(6) | 0) +#define MT8516_PIN_6_EINT6__FUNC_URTS2 (MTK_PIN_NO(6) | 1) +#define MT8516_PIN_6_EINT6__FUNC_SPI_CLK (MTK_PIN_NO(6) | 3) +#define MT8516_PIN_6_EINT6__FUNC_EXT_RXC (MTK_PIN_NO(6) | 4) +#define MT8516_PIN_6_EINT6__FUNC_CONN_MCU_TRST_B (MTK_PIN_NO(6) | 5) +#define MT8516_PIN_6_EINT6__FUNC_DBG_MON_A_12 (MTK_PIN_NO(6) | 7) + +#define MT8516_PIN_7_EINT7__FUNC_GPIO7 (MTK_PIN_NO(7) | 0) +#define MT8516_PIN_7_EINT7__FUNC_SQIRST (MTK_PIN_NO(7) | 1) +#define MT8516_PIN_7_EINT7__FUNC_SDA1_0 (MTK_PIN_NO(7) | 3) +#define MT8516_PIN_7_EINT7__FUNC_EXT_RXDV (MTK_PIN_NO(7) | 4) +#define MT8516_PIN_7_EINT7__FUNC_CONN_MCU_TMS (MTK_PIN_NO(7) | 5) +#define MT8516_PIN_7_EINT7__FUNC_CONN_MCU_AICE_JMSC (MTK_PIN_NO(7) | 6) +#define MT8516_PIN_7_EINT7__FUNC_DBG_MON_A_13 (MTK_PIN_NO(7) | 7) + +#define MT8516_PIN_8_EINT8__FUNC_GPIO8 (MTK_PIN_NO(8) | 0) +#define MT8516_PIN_8_EINT8__FUNC_SQICK (MTK_PIN_NO(8) | 1) +#define MT8516_PIN_8_EINT8__FUNC_CLKM3 (MTK_PIN_NO(8) | 2) +#define MT8516_PIN_8_EINT8__FUNC_SCL1_0 (MTK_PIN_NO(8) | 3) +#define MT8516_PIN_8_EINT8__FUNC_EXT_RXD0 (MTK_PIN_NO(8) | 4) +#define MT8516_PIN_8_EINT8__FUNC_ANT_SEL0 (MTK_PIN_NO(8) | 5) +#define MT8516_PIN_8_EINT8__FUNC_DBG_MON_A_14 (MTK_PIN_NO(8) | 7) + +#define MT8516_PIN_9_EINT9__FUNC_GPIO9 (MTK_PIN_NO(9) | 0) +#define MT8516_PIN_9_EINT9__FUNC_CLKM4 (MTK_PIN_NO(9) | 1) +#define MT8516_PIN_9_EINT9__FUNC_SDA2_0 (MTK_PIN_NO(9) | 2) +#define MT8516_PIN_9_EINT9__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(9) | 3) +#define MT8516_PIN_9_EINT9__FUNC_EXT_RXD1 (MTK_PIN_NO(9) | 4) +#define MT8516_PIN_9_EINT9__FUNC_ANT_SEL1 (MTK_PIN_NO(9) | 5) +#define MT8516_PIN_9_EINT9__FUNC_DBG_MON_A_15 (MTK_PIN_NO(9) | 7) + +#define MT8516_PIN_10_EINT10__FUNC_GPIO10 (MTK_PIN_NO(10) | 0) +#define MT8516_PIN_10_EINT10__FUNC_CLKM5 (MTK_PIN_NO(10) | 1) +#define MT8516_PIN_10_EINT10__FUNC_SCL2_0 (MTK_PIN_NO(10) | 2) +#define MT8516_PIN_10_EINT10__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(10) | 3) +#define MT8516_PIN_10_EINT10__FUNC_EXT_RXD2 (MTK_PIN_NO(10) | 4) +#define MT8516_PIN_10_EINT10__FUNC_ANT_SEL2 (MTK_PIN_NO(10) | 5) +#define MT8516_PIN_10_EINT10__FUNC_DBG_MON_A_16 (MTK_PIN_NO(10) | 7) + +#define MT8516_PIN_11_EINT11__FUNC_GPIO11 (MTK_PIN_NO(11) | 0) +#define MT8516_PIN_11_EINT11__FUNC_CLKM4 (MTK_PIN_NO(11) | 1) +#define MT8516_PIN_11_EINT11__FUNC_PWM_C (MTK_PIN_NO(11) | 2) +#define MT8516_PIN_11_EINT11__FUNC_CONN_TEST_CK (MTK_PIN_NO(11) | 3) +#define MT8516_PIN_11_EINT11__FUNC_ANT_SEL3 (MTK_PIN_NO(11) | 4) +#define MT8516_PIN_11_EINT11__FUNC_EXT_RXD3 (MTK_PIN_NO(11) | 6) +#define MT8516_PIN_11_EINT11__FUNC_DBG_MON_A_17 (MTK_PIN_NO(11) | 7) + +#define MT8516_PIN_12_EINT12__FUNC_GPIO12 (MTK_PIN_NO(12) | 0) +#define MT8516_PIN_12_EINT12__FUNC_CLKM5 (MTK_PIN_NO(12) | 1) +#define MT8516_PIN_12_EINT12__FUNC_PWM_A (MTK_PIN_NO(12) | 2) +#define MT8516_PIN_12_EINT12__FUNC_SPDIF_OUT (MTK_PIN_NO(12) | 3) +#define MT8516_PIN_12_EINT12__FUNC_ANT_SEL4 (MTK_PIN_NO(12) | 4) +#define MT8516_PIN_12_EINT12__FUNC_EXT_TXEN (MTK_PIN_NO(12) | 6) +#define MT8516_PIN_12_EINT12__FUNC_DBG_MON_A_18 (MTK_PIN_NO(12) | 7) + +#define MT8516_PIN_13_EINT13__FUNC_GPIO13 (MTK_PIN_NO(13) | 0) +#define MT8516_PIN_13_EINT13__FUNC_TSF_IN (MTK_PIN_NO(13) | 3) +#define MT8516_PIN_13_EINT13__FUNC_ANT_SEL5 (MTK_PIN_NO(13) | 4) +#define MT8516_PIN_13_EINT13__FUNC_SPDIF_IN (MTK_PIN_NO(13) | 6) +#define MT8516_PIN_13_EINT13__FUNC_DBG_MON_A_19 (MTK_PIN_NO(13) | 7) + +#define MT8516_PIN_14_EINT14__FUNC_GPIO14 (MTK_PIN_NO(14) | 0) +#define MT8516_PIN_14_EINT14__FUNC_I2S_8CH_DO1 (MTK_PIN_NO(14) | 2) +#define MT8516_PIN_14_EINT14__FUNC_TDM_RX_MCK (MTK_PIN_NO(14) | 3) +#define MT8516_PIN_14_EINT14__FUNC_ANT_SEL1 (MTK_PIN_NO(14) | 4) +#define MT8516_PIN_14_EINT14__FUNC_CONN_MCU_DBGACK_N (MTK_PIN_NO(14) | 5) +#define MT8516_PIN_14_EINT14__FUNC_NCLE (MTK_PIN_NO(14) | 6) +#define MT8516_PIN_14_EINT14__FUNC_DBG_MON_B_8 (MTK_PIN_NO(14) | 7) + +#define MT8516_PIN_15_EINT15__FUNC_GPIO15 (MTK_PIN_NO(15) | 0) +#define MT8516_PIN_15_EINT15__FUNC_I2S_8CH_LRCK (MTK_PIN_NO(15) | 2) +#define MT8516_PIN_15_EINT15__FUNC_TDM_RX_BCK (MTK_PIN_NO(15) | 3) +#define MT8516_PIN_15_EINT15__FUNC_ANT_SEL2 (MTK_PIN_NO(15) | 4) +#define MT8516_PIN_15_EINT15__FUNC_CONN_MCU_DBGI_N (MTK_PIN_NO(15) | 5) +#define MT8516_PIN_15_EINT15__FUNC_NCEB1 (MTK_PIN_NO(15) | 6) +#define MT8516_PIN_15_EINT15__FUNC_DBG_MON_B_9 (MTK_PIN_NO(15) | 7) + +#define MT8516_PIN_16_EINT16__FUNC_GPIO16 (MTK_PIN_NO(16) | 0) +#define MT8516_PIN_16_EINT16__FUNC_I2S_8CH_BCK (MTK_PIN_NO(16) | 2) +#define MT8516_PIN_16_EINT16__FUNC_TDM_RX_LRCK (MTK_PIN_NO(16) | 3) +#define MT8516_PIN_16_EINT16__FUNC_ANT_SEL3 (MTK_PIN_NO(16) | 4) +#define MT8516_PIN_16_EINT16__FUNC_CONN_MCU_TRST_B (MTK_PIN_NO(16) | 5) +#define MT8516_PIN_16_EINT16__FUNC_NCEB0 (MTK_PIN_NO(16) | 6) +#define MT8516_PIN_16_EINT16__FUNC_DBG_MON_B_10 (MTK_PIN_NO(16) | 7) + +#define MT8516_PIN_17_EINT17__FUNC_GPIO17 (MTK_PIN_NO(17) | 0) +#define MT8516_PIN_17_EINT17__FUNC_I2S_8CH_MCK (MTK_PIN_NO(17) | 2) +#define MT8516_PIN_17_EINT17__FUNC_TDM_RX_DI (MTK_PIN_NO(17) | 3) +#define MT8516_PIN_17_EINT17__FUNC_IDDIG (MTK_PIN_NO(17) | 4) +#define MT8516_PIN_17_EINT17__FUNC_ANT_SEL4 (MTK_PIN_NO(17) | 5) +#define MT8516_PIN_17_EINT17__FUNC_NREB (MTK_PIN_NO(17) | 6) +#define MT8516_PIN_17_EINT17__FUNC_DBG_MON_B_11 (MTK_PIN_NO(17) | 7) + +#define MT8516_PIN_18_EINT18__FUNC_GPIO18 (MTK_PIN_NO(18) | 0) +#define MT8516_PIN_18_EINT18__FUNC_USB_DRVVBUS (MTK_PIN_NO(18) | 2) +#define MT8516_PIN_18_EINT18__FUNC_I2S3_LRCK (MTK_PIN_NO(18) | 3) +#define MT8516_PIN_18_EINT18__FUNC_CLKM1 (MTK_PIN_NO(18) | 4) +#define MT8516_PIN_18_EINT18__FUNC_ANT_SEL3 (MTK_PIN_NO(18) | 5) +#define MT8516_PIN_18_EINT18__FUNC_I2S2_BCK (MTK_PIN_NO(18) | 6) +#define MT8516_PIN_18_EINT18__FUNC_DBG_MON_A_20 (MTK_PIN_NO(18) | 7) + +#define MT8516_PIN_19_EINT19__FUNC_GPIO19 (MTK_PIN_NO(19) | 0) +#define MT8516_PIN_19_EINT19__FUNC_UCTS1 (MTK_PIN_NO(19) | 1) +#define MT8516_PIN_19_EINT19__FUNC_IDDIG (MTK_PIN_NO(19) | 2) +#define MT8516_PIN_19_EINT19__FUNC_I2S3_BCK (MTK_PIN_NO(19) | 3) +#define MT8516_PIN_19_EINT19__FUNC_CLKM2 (MTK_PIN_NO(19) | 4) +#define MT8516_PIN_19_EINT19__FUNC_ANT_SEL4 (MTK_PIN_NO(19) | 5) +#define MT8516_PIN_19_EINT19__FUNC_I2S2_DI (MTK_PIN_NO(19) | 6) +#define MT8516_PIN_19_EINT19__FUNC_DBG_MON_A_21 (MTK_PIN_NO(19) | 7) + +#define MT8516_PIN_20_EINT20__FUNC_GPIO20 (MTK_PIN_NO(20) | 0) +#define MT8516_PIN_20_EINT20__FUNC_URTS1 (MTK_PIN_NO(20) | 1) +#define MT8516_PIN_20_EINT20__FUNC_I2S3_DO (MTK_PIN_NO(20) | 3) +#define MT8516_PIN_20_EINT20__FUNC_CLKM3 (MTK_PIN_NO(20) | 4) +#define MT8516_PIN_20_EINT20__FUNC_ANT_SEL5 (MTK_PIN_NO(20) | 5) +#define MT8516_PIN_20_EINT20__FUNC_I2S2_LRCK (MTK_PIN_NO(20) | 6) +#define MT8516_PIN_20_EINT20__FUNC_DBG_MON_A_22 (MTK_PIN_NO(20) | 7) + +#define MT8516_PIN_21_EINT21__FUNC_GPIO21 (MTK_PIN_NO(21) | 0) +#define MT8516_PIN_21_EINT21__FUNC_NRNB (MTK_PIN_NO(21) | 1) +#define MT8516_PIN_21_EINT21__FUNC_ANT_SEL0 (MTK_PIN_NO(21) | 2) +#define MT8516_PIN_21_EINT21__FUNC_I2S_8CH_DO4 (MTK_PIN_NO(21) | 3) +#define MT8516_PIN_21_EINT21__FUNC_DBG_MON_B_31 (MTK_PIN_NO(21) | 7) + +#define MT8516_PIN_22_EINT22__FUNC_GPIO22 (MTK_PIN_NO(22) | 0) +#define MT8516_PIN_22_EINT22__FUNC_I2S_8CH_DO2 (MTK_PIN_NO(22) | 2) +#define MT8516_PIN_22_EINT22__FUNC_TSF_IN (MTK_PIN_NO(22) | 3) +#define MT8516_PIN_22_EINT22__FUNC_USB_DRVVBUS (MTK_PIN_NO(22) | 4) +#define MT8516_PIN_22_EINT22__FUNC_SPDIF_OUT (MTK_PIN_NO(22) | 5) +#define MT8516_PIN_22_EINT22__FUNC_NRE_C (MTK_PIN_NO(22) | 6) +#define MT8516_PIN_22_EINT22__FUNC_DBG_MON_B_12 (MTK_PIN_NO(22) | 7) + +#define MT8516_PIN_23_EINT23__FUNC_GPIO23 (MTK_PIN_NO(23) | 0) +#define MT8516_PIN_23_EINT23__FUNC_I2S_8CH_DO3 (MTK_PIN_NO(23) | 2) +#define MT8516_PIN_23_EINT23__FUNC_CLKM0 (MTK_PIN_NO(23) | 3) +#define MT8516_PIN_23_EINT23__FUNC_IR (MTK_PIN_NO(23) | 4) +#define MT8516_PIN_23_EINT23__FUNC_SPDIF_IN (MTK_PIN_NO(23) | 5) +#define MT8516_PIN_23_EINT23__FUNC_NDQS_C (MTK_PIN_NO(23) | 6) +#define MT8516_PIN_23_EINT23__FUNC_DBG_MON_B_13 (MTK_PIN_NO(23) | 7) + +#define MT8516_PIN_24_EINT24__FUNC_GPIO24 (MTK_PIN_NO(24) | 0) +#define MT8516_PIN_24_EINT24__FUNC_ANT_SEL1 (MTK_PIN_NO(24) | 3) +#define MT8516_PIN_24_EINT24__FUNC_UCTS2 (MTK_PIN_NO(24) | 4) +#define MT8516_PIN_24_EINT24__FUNC_PWM_A (MTK_PIN_NO(24) | 5) +#define MT8516_PIN_24_EINT24__FUNC_I2S0_MCK (MTK_PIN_NO(24) | 6) +#define MT8516_PIN_24_EINT24__FUNC_DBG_MON_A_0 (MTK_PIN_NO(24) | 7) + +#define MT8516_PIN_25_EINT25__FUNC_GPIO25 (MTK_PIN_NO(25) | 0) +#define MT8516_PIN_25_EINT25__FUNC_ANT_SEL0 (MTK_PIN_NO(25) | 3) +#define MT8516_PIN_25_EINT25__FUNC_URTS2 (MTK_PIN_NO(25) | 4) +#define MT8516_PIN_25_EINT25__FUNC_PWM_B (MTK_PIN_NO(25) | 5) +#define MT8516_PIN_25_EINT25__FUNC_I2S_8CH_MCK (MTK_PIN_NO(25) | 6) +#define MT8516_PIN_25_EINT25__FUNC_DBG_MON_A_1 (MTK_PIN_NO(25) | 7) + +#define MT8516_PIN_26_PWRAP_SPI0_MI__FUNC_GPIO26 (MTK_PIN_NO(26) | 0) +#define MT8516_PIN_26_PWRAP_SPI0_MI__FUNC_PWRAP_SPI0_MO (MTK_PIN_NO(26) | 1) +#define MT8516_PIN_26_PWRAP_SPI0_MI__FUNC_PWRAP_SPI0_MI (MTK_PIN_NO(26) | 2) + +#define MT8516_PIN_27_PWRAP_SPI0_MO__FUNC_GPIO27 (MTK_PIN_NO(27) | 0) +#define MT8516_PIN_27_PWRAP_SPI0_MO__FUNC_PWRAP_SPI0_MI (MTK_PIN_NO(27) | 1) +#define MT8516_PIN_27_PWRAP_SPI0_MO__FUNC_PWRAP_SPI0_MO (MTK_PIN_NO(27) | 2) + +#define MT8516_PIN_28_PWRAP_INT__FUNC_GPIO28 (MTK_PIN_NO(28) | 0) +#define MT8516_PIN_28_PWRAP_INT__FUNC_I2S0_MCK (MTK_PIN_NO(28) | 1) +#define MT8516_PIN_28_PWRAP_INT__FUNC_I2S_8CH_MCK (MTK_PIN_NO(28) | 4) +#define MT8516_PIN_28_PWRAP_INT__FUNC_I2S2_MCK (MTK_PIN_NO(28) | 5) +#define MT8516_PIN_28_PWRAP_INT__FUNC_I2S3_MCK (MTK_PIN_NO(28) | 6) + +#define MT8516_PIN_29_PWRAP_SPI0_CK__FUNC_GPIO29 (MTK_PIN_NO(29) | 0) +#define MT8516_PIN_29_PWRAP_SPI0_CK__FUNC_PWRAP_SPI0_CK (MTK_PIN_NO(29) | 1) + +#define MT8516_PIN_30_PWRAP_SPI0_CSN__FUNC_GPIO30 (MTK_PIN_NO(30) | 0) +#define MT8516_PIN_30_PWRAP_SPI0_CSN__FUNC_PWRAP_SPI0_CSN (MTK_PIN_NO(30) | 1) + +#define MT8516_PIN_31_RTC32K_CK__FUNC_GPIO31 (MTK_PIN_NO(31) | 0) +#define MT8516_PIN_31_RTC32K_CK__FUNC_RTC32K_CK (MTK_PIN_NO(31) | 1) + +#define MT8516_PIN_32_WATCHDOG__FUNC_GPIO32 (MTK_PIN_NO(32) | 0) +#define MT8516_PIN_32_WATCHDOG__FUNC_WATCHDOG (MTK_PIN_NO(32) | 1) + +#define MT8516_PIN_33_SRCLKENA__FUNC_GPIO33 (MTK_PIN_NO(33) | 0) +#define MT8516_PIN_33_SRCLKENA__FUNC_SRCLKENA0 (MTK_PIN_NO(33) | 1) + +#define MT8516_PIN_34_URXD2__FUNC_GPIO34 (MTK_PIN_NO(34) | 0) +#define MT8516_PIN_34_URXD2__FUNC_URXD2 (MTK_PIN_NO(34) | 1) +#define MT8516_PIN_34_URXD2__FUNC_UTXD2 (MTK_PIN_NO(34) | 3) +#define MT8516_PIN_34_URXD2__FUNC_DBG_SCL (MTK_PIN_NO(34) | 4) +#define MT8516_PIN_34_URXD2__FUNC_I2S2_MCK (MTK_PIN_NO(34) | 6) +#define MT8516_PIN_34_URXD2__FUNC_DBG_MON_B_0 (MTK_PIN_NO(34) | 7) + +#define MT8516_PIN_35_UTXD2__FUNC_GPIO35 (MTK_PIN_NO(35) | 0) +#define MT8516_PIN_35_UTXD2__FUNC_UTXD2 (MTK_PIN_NO(35) | 1) +#define MT8516_PIN_35_UTXD2__FUNC_URXD2 (MTK_PIN_NO(35) | 3) +#define MT8516_PIN_35_UTXD2__FUNC_DBG_SDA (MTK_PIN_NO(35) | 4) +#define MT8516_PIN_35_UTXD2__FUNC_I2S3_MCK (MTK_PIN_NO(35) | 6) +#define MT8516_PIN_35_UTXD2__FUNC_DBG_MON_B_1 (MTK_PIN_NO(35) | 7) + +#define MT8516_PIN_36_MRG_CLK__FUNC_GPIO36 (MTK_PIN_NO(36) | 0) +#define MT8516_PIN_36_MRG_CLK__FUNC_MRG_CLK (MTK_PIN_NO(36) | 1) +#define MT8516_PIN_36_MRG_CLK__FUNC_I2S0_BCK (MTK_PIN_NO(36) | 3) +#define MT8516_PIN_36_MRG_CLK__FUNC_I2S3_BCK (MTK_PIN_NO(36) | 4) +#define MT8516_PIN_36_MRG_CLK__FUNC_PCM0_CLK (MTK_PIN_NO(36) | 5) +#define MT8516_PIN_36_MRG_CLK__FUNC_IR (MTK_PIN_NO(36) | 6) +#define MT8516_PIN_36_MRG_CLK__FUNC_DBG_MON_A_2 (MTK_PIN_NO(36) | 7) + +#define MT8516_PIN_37_MRG_SYNC__FUNC_GPIO37 (MTK_PIN_NO(37) | 0) +#define MT8516_PIN_37_MRG_SYNC__FUNC_MRG_SYNC (MTK_PIN_NO(37) | 1) +#define MT8516_PIN_37_MRG_SYNC__FUNC_I2S0_LRCK (MTK_PIN_NO(37) | 3) +#define MT8516_PIN_37_MRG_SYNC__FUNC_I2S3_LRCK (MTK_PIN_NO(37) | 4) +#define MT8516_PIN_37_MRG_SYNC__FUNC_PCM0_SYNC (MTK_PIN_NO(37) | 5) +#define MT8516_PIN_37_MRG_SYNC__FUNC_EXT_COL (MTK_PIN_NO(37) | 6) +#define MT8516_PIN_37_MRG_SYNC__FUNC_DBG_MON_A_3 (MTK_PIN_NO(37) | 7) + +#define MT8516_PIN_38_MRG_DI__FUNC_GPIO38 (MTK_PIN_NO(38) | 0) +#define MT8516_PIN_38_MRG_DI__FUNC_MRG_DI (MTK_PIN_NO(38) | 1) +#define MT8516_PIN_38_MRG_DI__FUNC_I2S0_DI (MTK_PIN_NO(38) | 3) +#define MT8516_PIN_38_MRG_DI__FUNC_I2S3_DO (MTK_PIN_NO(38) | 4) +#define MT8516_PIN_38_MRG_DI__FUNC_PCM0_DI (MTK_PIN_NO(38) | 5) +#define MT8516_PIN_38_MRG_DI__FUNC_EXT_MDIO (MTK_PIN_NO(38) | 6) +#define MT8516_PIN_38_MRG_DI__FUNC_DBG_MON_A_4 (MTK_PIN_NO(38) | 7) + +#define MT8516_PIN_39_MRG_DO__FUNC_GPIO39 (MTK_PIN_NO(39) | 0) +#define MT8516_PIN_39_MRG_DO__FUNC_MRG_DO (MTK_PIN_NO(39) | 1) +#define MT8516_PIN_39_MRG_DO__FUNC_I2S0_MCK (MTK_PIN_NO(39) | 3) +#define MT8516_PIN_39_MRG_DO__FUNC_I2S3_MCK (MTK_PIN_NO(39) | 4) +#define MT8516_PIN_39_MRG_DO__FUNC_PCM0_DO (MTK_PIN_NO(39) | 5) +#define MT8516_PIN_39_MRG_DO__FUNC_EXT_MDC (MTK_PIN_NO(39) | 6) +#define MT8516_PIN_39_MRG_DO__FUNC_DBG_MON_A_5 (MTK_PIN_NO(39) | 7) + +#define MT8516_PIN_40_KPROW0__FUNC_GPIO40 (MTK_PIN_NO(40) | 0) +#define MT8516_PIN_40_KPROW0__FUNC_KPROW0 (MTK_PIN_NO(40) | 1) +#define MT8516_PIN_40_KPROW0__FUNC_DBG_MON_B_4 (MTK_PIN_NO(40) | 7) + +#define MT8516_PIN_41_KPROW1__FUNC_GPIO41 (MTK_PIN_NO(41) | 0) +#define MT8516_PIN_41_KPROW1__FUNC_KPROW1 (MTK_PIN_NO(41) | 1) +#define MT8516_PIN_41_KPROW1__FUNC_IDDIG (MTK_PIN_NO(41) | 2) +#define MT8516_PIN_41_KPROW1__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(41) | 3) +#define MT8516_PIN_41_KPROW1__FUNC_DBG_MON_B_5 (MTK_PIN_NO(41) | 7) + +#define MT8516_PIN_42_KPCOL0__FUNC_GPIO42 (MTK_PIN_NO(42) | 0) +#define MT8516_PIN_42_KPCOL0__FUNC_KPCOL0 (MTK_PIN_NO(42) | 1) +#define MT8516_PIN_42_KPCOL0__FUNC_DBG_MON_B_6 (MTK_PIN_NO(42) | 7) + +#define MT8516_PIN_43_KPCOL1__FUNC_GPIO43 (MTK_PIN_NO(43) | 0) +#define MT8516_PIN_43_KPCOL1__FUNC_KPCOL1 (MTK_PIN_NO(43) | 1) +#define MT8516_PIN_43_KPCOL1__FUNC_USB_DRVVBUS (MTK_PIN_NO(43) | 2) +#define MT8516_PIN_43_KPCOL1__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(43) | 3) +#define MT8516_PIN_43_KPCOL1__FUNC_TSF_IN (MTK_PIN_NO(43) | 4) +#define MT8516_PIN_43_KPCOL1__FUNC_DBG_MON_B_7 (MTK_PIN_NO(43) | 7) + +#define MT8516_PIN_44_JTMS__FUNC_GPIO44 (MTK_PIN_NO(44) | 0) +#define MT8516_PIN_44_JTMS__FUNC_JTMS (MTK_PIN_NO(44) | 1) +#define MT8516_PIN_44_JTMS__FUNC_CONN_MCU_TMS (MTK_PIN_NO(44) | 2) +#define MT8516_PIN_44_JTMS__FUNC_CONN_MCU_AICE_JMSC (MTK_PIN_NO(44) | 3) +#define MT8516_PIN_44_JTMS__FUNC_DFD_TMS_XI (MTK_PIN_NO(44) | 5) +#define MT8516_PIN_44_JTMS__FUNC_UDI_TMS_XI (MTK_PIN_NO(44) | 6) + +#define MT8516_PIN_45_JTCK__FUNC_GPIO45 (MTK_PIN_NO(45) | 0) +#define MT8516_PIN_45_JTCK__FUNC_JTCK (MTK_PIN_NO(45) | 1) +#define MT8516_PIN_45_JTCK__FUNC_CONN_MCU_TCK (MTK_PIN_NO(45) | 2) +#define MT8516_PIN_45_JTCK__FUNC_CONN_MCU_AICE_JCKC (MTK_PIN_NO(45) | 3) + +#define MT8516_PIN_46_JTDI__FUNC_GPIO46 (MTK_PIN_NO(46) | 0) +#define MT8516_PIN_46_JTDI__FUNC_JTDI (MTK_PIN_NO(46) | 1) +#define MT8516_PIN_46_JTDI__FUNC_CONN_MCU_TDI (MTK_PIN_NO(46) | 2) + +#define MT8516_PIN_47_JTDO__FUNC_GPIO47 (MTK_PIN_NO(47) | 0) +#define MT8516_PIN_47_JTDO__FUNC_JTDO (MTK_PIN_NO(47) | 1) +#define MT8516_PIN_47_JTDO__FUNC_CONN_MCU_TDO (MTK_PIN_NO(47) | 2) + +#define MT8516_PIN_48_SPI_CS__FUNC_GPIO48 (MTK_PIN_NO(48) | 0) +#define MT8516_PIN_48_SPI_CS__FUNC_SPI_CSB (MTK_PIN_NO(48) | 1) +#define MT8516_PIN_48_SPI_CS__FUNC_I2S0_DI (MTK_PIN_NO(48) | 3) +#define MT8516_PIN_48_SPI_CS__FUNC_I2S2_BCK (MTK_PIN_NO(48) | 4) +#define MT8516_PIN_48_SPI_CS__FUNC_DBG_MON_A_23 (MTK_PIN_NO(48) | 7) + +#define MT8516_PIN_49_SPI_CK__FUNC_GPIO49 (MTK_PIN_NO(49) | 0) +#define MT8516_PIN_49_SPI_CK__FUNC_SPI_CLK (MTK_PIN_NO(49) | 1) +#define MT8516_PIN_49_SPI_CK__FUNC_I2S0_LRCK (MTK_PIN_NO(49) | 3) +#define MT8516_PIN_49_SPI_CK__FUNC_I2S2_DI (MTK_PIN_NO(49) | 4) +#define MT8516_PIN_49_SPI_CK__FUNC_DBG_MON_A_24 (MTK_PIN_NO(49) | 7) + +#define MT8516_PIN_50_SPI_MI__FUNC_GPIO50 (MTK_PIN_NO(50) | 0) +#define MT8516_PIN_50_SPI_MI__FUNC_SPI_MI (MTK_PIN_NO(50) | 1) +#define MT8516_PIN_50_SPI_MI__FUNC_SPI_MO (MTK_PIN_NO(50) | 2) +#define MT8516_PIN_50_SPI_MI__FUNC_I2S0_BCK (MTK_PIN_NO(50) | 3) +#define MT8516_PIN_50_SPI_MI__FUNC_I2S2_LRCK (MTK_PIN_NO(50) | 4) +#define MT8516_PIN_50_SPI_MI__FUNC_DBG_MON_A_25 (MTK_PIN_NO(50) | 7) + +#define MT8516_PIN_51_SPI_MO__FUNC_GPIO51 (MTK_PIN_NO(51) | 0) +#define MT8516_PIN_51_SPI_MO__FUNC_SPI_MO (MTK_PIN_NO(51) | 1) +#define MT8516_PIN_51_SPI_MO__FUNC_SPI_MI (MTK_PIN_NO(51) | 2) +#define MT8516_PIN_51_SPI_MO__FUNC_I2S0_MCK (MTK_PIN_NO(51) | 3) +#define MT8516_PIN_51_SPI_MO__FUNC_I2S2_MCK (MTK_PIN_NO(51) | 4) +#define MT8516_PIN_51_SPI_MO__FUNC_DBG_MON_A_26 (MTK_PIN_NO(51) | 7) + +#define MT8516_PIN_52_SDA1__FUNC_GPIO52 (MTK_PIN_NO(52) | 0) +#define MT8516_PIN_52_SDA1__FUNC_SDA1_0 (MTK_PIN_NO(52) | 1) + +#define MT8516_PIN_53_SCL1__FUNC_GPIO53 (MTK_PIN_NO(53) | 0) +#define MT8516_PIN_53_SCL1__FUNC_SCL1_0 (MTK_PIN_NO(53) | 1) + +#define MT8516_PIN_54_GPIO54__FUNC_GPIO54 (MTK_PIN_NO(54) | 0) +#define MT8516_PIN_54_GPIO54__FUNC_PWM_B (MTK_PIN_NO(54) | 2) +#define MT8516_PIN_54_GPIO54__FUNC_DBG_MON_B_2 (MTK_PIN_NO(54) | 7) + +#define MT8516_PIN_55_I2S_DATA_IN__FUNC_GPIO55 (MTK_PIN_NO(55) | 0) +#define MT8516_PIN_55_I2S_DATA_IN__FUNC_I2S0_DI (MTK_PIN_NO(55) | 1) +#define MT8516_PIN_55_I2S_DATA_IN__FUNC_UCTS0 (MTK_PIN_NO(55) | 2) +#define MT8516_PIN_55_I2S_DATA_IN__FUNC_I2S3_DO (MTK_PIN_NO(55) | 3) +#define MT8516_PIN_55_I2S_DATA_IN__FUNC_I2S_8CH_DO1 (MTK_PIN_NO(55) | 4) +#define MT8516_PIN_55_I2S_DATA_IN__FUNC_PWM_A (MTK_PIN_NO(55) | 5) +#define MT8516_PIN_55_I2S_DATA_IN__FUNC_I2S2_BCK (MTK_PIN_NO(55) | 6) +#define MT8516_PIN_55_I2S_DATA_IN__FUNC_DBG_MON_A_28 (MTK_PIN_NO(55) | 7) + +#define MT8516_PIN_56_I2S_LRCK__FUNC_GPIO56 (MTK_PIN_NO(56) | 0) +#define MT8516_PIN_56_I2S_LRCK__FUNC_I2S0_LRCK (MTK_PIN_NO(56) | 1) +#define MT8516_PIN_56_I2S_LRCK__FUNC_I2S3_LRCK (MTK_PIN_NO(56) | 3) +#define MT8516_PIN_56_I2S_LRCK__FUNC_I2S_8CH_LRCK (MTK_PIN_NO(56) | 4) +#define MT8516_PIN_56_I2S_LRCK__FUNC_PWM_B (MTK_PIN_NO(56) | 5) +#define MT8516_PIN_56_I2S_LRCK__FUNC_I2S2_DI (MTK_PIN_NO(56) | 6) +#define MT8516_PIN_56_I2S_LRCK__FUNC_DBG_MON_A_29 (MTK_PIN_NO(56) | 7) + +#define MT8516_PIN_57_I2S_BCK__FUNC_GPIO57 (MTK_PIN_NO(57) | 0) +#define MT8516_PIN_57_I2S_BCK__FUNC_I2S0_BCK (MTK_PIN_NO(57) | 1) +#define MT8516_PIN_57_I2S_BCK__FUNC_URTS0 (MTK_PIN_NO(57) | 2) +#define MT8516_PIN_57_I2S_BCK__FUNC_I2S3_BCK (MTK_PIN_NO(57) | 3) +#define MT8516_PIN_57_I2S_BCK__FUNC_I2S_8CH_BCK (MTK_PIN_NO(57) | 4) +#define MT8516_PIN_57_I2S_BCK__FUNC_PWM_C (MTK_PIN_NO(57) | 5) +#define MT8516_PIN_57_I2S_BCK__FUNC_I2S2_LRCK (MTK_PIN_NO(57) | 6) +#define MT8516_PIN_57_I2S_BCK__FUNC_DBG_MON_A_30 (MTK_PIN_NO(57) | 7) + +#define MT8516_PIN_58_SDA0__FUNC_GPIO58 (MTK_PIN_NO(58) | 0) +#define MT8516_PIN_58_SDA0__FUNC_SDA0_0 (MTK_PIN_NO(58) | 1) + +#define MT8516_PIN_59_SCL0__FUNC_GPIO59 (MTK_PIN_NO(59) | 0) +#define MT8516_PIN_59_SCL0__FUNC_SCL0_0 (MTK_PIN_NO(59) | 1) + +#define MT8516_PIN_60_SDA2__FUNC_GPIO60 (MTK_PIN_NO(60) | 0) +#define MT8516_PIN_60_SDA2__FUNC_SDA2_0 (MTK_PIN_NO(60) | 1) +#define MT8516_PIN_60_SDA2__FUNC_PWM_B (MTK_PIN_NO(60) | 2) + +#define MT8516_PIN_61_SCL2__FUNC_GPIO61 (MTK_PIN_NO(61) | 0) +#define MT8516_PIN_61_SCL2__FUNC_SCL2_0 (MTK_PIN_NO(61) | 1) +#define MT8516_PIN_61_SCL2__FUNC_PWM_C (MTK_PIN_NO(61) | 2) + +#define MT8516_PIN_62_URXD0__FUNC_GPIO62 (MTK_PIN_NO(62) | 0) +#define MT8516_PIN_62_URXD0__FUNC_URXD0 (MTK_PIN_NO(62) | 1) +#define MT8516_PIN_62_URXD0__FUNC_UTXD0 (MTK_PIN_NO(62) | 2) + +#define MT8516_PIN_63_UTXD0__FUNC_GPIO63 (MTK_PIN_NO(63) | 0) +#define MT8516_PIN_63_UTXD0__FUNC_UTXD0 (MTK_PIN_NO(63) | 1) +#define MT8516_PIN_63_UTXD0__FUNC_URXD0 (MTK_PIN_NO(63) | 2) + +#define MT8516_PIN_64_URXD1__FUNC_GPIO64 (MTK_PIN_NO(64) | 0) +#define MT8516_PIN_64_URXD1__FUNC_URXD1 (MTK_PIN_NO(64) | 1) +#define MT8516_PIN_64_URXD1__FUNC_UTXD1 (MTK_PIN_NO(64) | 2) +#define MT8516_PIN_64_URXD1__FUNC_DBG_MON_A_27 (MTK_PIN_NO(64) | 7) + +#define MT8516_PIN_65_UTXD1__FUNC_GPIO65 (MTK_PIN_NO(65) | 0) +#define MT8516_PIN_65_UTXD1__FUNC_UTXD1 (MTK_PIN_NO(65) | 1) +#define MT8516_PIN_65_UTXD1__FUNC_URXD1 (MTK_PIN_NO(65) | 2) +#define MT8516_PIN_65_UTXD1__FUNC_DBG_MON_A_31 (MTK_PIN_NO(65) | 7) + +#define MT8516_PIN_68_MSDC2_CMD__FUNC_GPIO68 (MTK_PIN_NO(68) | 0) +#define MT8516_PIN_68_MSDC2_CMD__FUNC_MSDC2_CMD (MTK_PIN_NO(68) | 1) +#define MT8516_PIN_68_MSDC2_CMD__FUNC_I2S_8CH_DO4 (MTK_PIN_NO(68) | 2) +#define MT8516_PIN_68_MSDC2_CMD__FUNC_SDA1_0 (MTK_PIN_NO(68) | 3) +#define MT8516_PIN_68_MSDC2_CMD__FUNC_USB_SDA (MTK_PIN_NO(68) | 5) +#define MT8516_PIN_68_MSDC2_CMD__FUNC_I2S3_BCK (MTK_PIN_NO(68) | 6) +#define MT8516_PIN_68_MSDC2_CMD__FUNC_DBG_MON_B_15 (MTK_PIN_NO(68) | 7) + +#define MT8516_PIN_69_MSDC2_CLK__FUNC_GPIO69 (MTK_PIN_NO(69) | 0) +#define MT8516_PIN_69_MSDC2_CLK__FUNC_MSDC2_CLK (MTK_PIN_NO(69) | 1) +#define MT8516_PIN_69_MSDC2_CLK__FUNC_I2S_8CH_DO3 (MTK_PIN_NO(69) | 2) +#define MT8516_PIN_69_MSDC2_CLK__FUNC_SCL1_0 (MTK_PIN_NO(69) | 3) +#define MT8516_PIN_69_MSDC2_CLK__FUNC_USB_SCL (MTK_PIN_NO(69) | 5) +#define MT8516_PIN_69_MSDC2_CLK__FUNC_I2S3_LRCK (MTK_PIN_NO(69) | 6) +#define MT8516_PIN_69_MSDC2_CLK__FUNC_DBG_MON_B_16 (MTK_PIN_NO(69) | 7) + +#define MT8516_PIN_70_MSDC2_DAT0__FUNC_GPIO70 (MTK_PIN_NO(70) | 0) +#define MT8516_PIN_70_MSDC2_DAT0__FUNC_MSDC2_DAT0 (MTK_PIN_NO(70) | 1) +#define MT8516_PIN_70_MSDC2_DAT0__FUNC_I2S_8CH_DO2 (MTK_PIN_NO(70) | 2) +#define MT8516_PIN_70_MSDC2_DAT0__FUNC_UTXD0 (MTK_PIN_NO(70) | 5) +#define MT8516_PIN_70_MSDC2_DAT0__FUNC_I2S3_DO (MTK_PIN_NO(70) | 6) +#define MT8516_PIN_70_MSDC2_DAT0__FUNC_DBG_MON_B_17 (MTK_PIN_NO(70) | 7) + +#define MT8516_PIN_71_MSDC2_DAT1__FUNC_GPIO71 (MTK_PIN_NO(71) | 0) +#define MT8516_PIN_71_MSDC2_DAT1__FUNC_MSDC2_DAT1 (MTK_PIN_NO(71) | 1) +#define MT8516_PIN_71_MSDC2_DAT1__FUNC_I2S_8CH_DO1 (MTK_PIN_NO(71) | 2) +#define MT8516_PIN_71_MSDC2_DAT1__FUNC_PWM_A (MTK_PIN_NO(71) | 3) +#define MT8516_PIN_71_MSDC2_DAT1__FUNC_I2S3_MCK (MTK_PIN_NO(71) | 4) +#define MT8516_PIN_71_MSDC2_DAT1__FUNC_URXD0 (MTK_PIN_NO(71) | 5) +#define MT8516_PIN_71_MSDC2_DAT1__FUNC_PWM_B (MTK_PIN_NO(71) | 6) +#define MT8516_PIN_71_MSDC2_DAT1__FUNC_DBG_MON_B_18 (MTK_PIN_NO(71) | 7) + +#define MT8516_PIN_72_MSDC2_DAT2__FUNC_GPIO72 (MTK_PIN_NO(72) | 0) +#define MT8516_PIN_72_MSDC2_DAT2__FUNC_MSDC2_DAT2 (MTK_PIN_NO(72) | 1) +#define MT8516_PIN_72_MSDC2_DAT2__FUNC_I2S_8CH_LRCK (MTK_PIN_NO(72) | 2) +#define MT8516_PIN_72_MSDC2_DAT2__FUNC_SDA2_0 (MTK_PIN_NO(72) | 3) +#define MT8516_PIN_72_MSDC2_DAT2__FUNC_UTXD1 (MTK_PIN_NO(72) | 5) +#define MT8516_PIN_72_MSDC2_DAT2__FUNC_PWM_C (MTK_PIN_NO(72) | 6) +#define MT8516_PIN_72_MSDC2_DAT2__FUNC_DBG_MON_B_19 (MTK_PIN_NO(72) | 7) + +#define MT8516_PIN_73_MSDC2_DAT3__FUNC_GPIO73 (MTK_PIN_NO(73) | 0) +#define MT8516_PIN_73_MSDC2_DAT3__FUNC_MSDC2_DAT3 (MTK_PIN_NO(73) | 1) +#define MT8516_PIN_73_MSDC2_DAT3__FUNC_I2S_8CH_BCK (MTK_PIN_NO(73) | 2) +#define MT8516_PIN_73_MSDC2_DAT3__FUNC_SCL2_0 (MTK_PIN_NO(73) | 3) +#define MT8516_PIN_73_MSDC2_DAT3__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(73) | 4) +#define MT8516_PIN_73_MSDC2_DAT3__FUNC_URXD1 (MTK_PIN_NO(73) | 5) +#define MT8516_PIN_73_MSDC2_DAT3__FUNC_PWM_A (MTK_PIN_NO(73) | 6) +#define MT8516_PIN_73_MSDC2_DAT3__FUNC_DBG_MON_B_20 (MTK_PIN_NO(73) | 7) + +#define MT8516_PIN_74_TDN3__FUNC_GPI74 (MTK_PIN_NO(74) | 0) +#define MT8516_PIN_74_TDN3__FUNC_TDN3 (MTK_PIN_NO(74) | 1) + +#define MT8516_PIN_75_TDP3__FUNC_GPI75 (MTK_PIN_NO(75) | 0) +#define MT8516_PIN_75_TDP3__FUNC_TDP3 (MTK_PIN_NO(75) | 1) + +#define MT8516_PIN_76_TDN2__FUNC_GPI76 (MTK_PIN_NO(76) | 0) +#define MT8516_PIN_76_TDN2__FUNC_TDN2 (MTK_PIN_NO(76) | 1) + +#define MT8516_PIN_77_TDP2__FUNC_GPI77 (MTK_PIN_NO(77) | 0) +#define MT8516_PIN_77_TDP2__FUNC_TDP2 (MTK_PIN_NO(77) | 1) + +#define MT8516_PIN_78_TCN__FUNC_GPI78 (MTK_PIN_NO(78) | 0) +#define MT8516_PIN_78_TCN__FUNC_TCN (MTK_PIN_NO(78) | 1) + +#define MT8516_PIN_79_TCP__FUNC_GPI79 (MTK_PIN_NO(79) | 0) +#define MT8516_PIN_79_TCP__FUNC_TCP (MTK_PIN_NO(79) | 1) + +#define MT8516_PIN_80_TDN1__FUNC_GPI80 (MTK_PIN_NO(80) | 0) +#define MT8516_PIN_80_TDN1__FUNC_TDN1 (MTK_PIN_NO(80) | 1) + +#define MT8516_PIN_81_TDP1__FUNC_GPI81 (MTK_PIN_NO(81) | 0) +#define MT8516_PIN_81_TDP1__FUNC_TDP1 (MTK_PIN_NO(81) | 1) + +#define MT8516_PIN_82_TDN0__FUNC_GPI82 (MTK_PIN_NO(82) | 0) +#define MT8516_PIN_82_TDN0__FUNC_TDN0 (MTK_PIN_NO(82) | 1) + +#define MT8516_PIN_83_TDP0__FUNC_GPI83 (MTK_PIN_NO(83) | 0) +#define MT8516_PIN_83_TDP0__FUNC_TDP0 (MTK_PIN_NO(83) | 1) + +#define MT8516_PIN_84_RDN0__FUNC_GPI84 (MTK_PIN_NO(84) | 0) +#define MT8516_PIN_84_RDN0__FUNC_RDN0 (MTK_PIN_NO(84) | 1) + +#define MT8516_PIN_85_RDP0__FUNC_GPI85 (MTK_PIN_NO(85) | 0) +#define MT8516_PIN_85_RDP0__FUNC_RDP0 (MTK_PIN_NO(85) | 1) + +#define MT8516_PIN_86_RDN1__FUNC_GPI86 (MTK_PIN_NO(86) | 0) +#define MT8516_PIN_86_RDN1__FUNC_RDN1 (MTK_PIN_NO(86) | 1) + +#define MT8516_PIN_87_RDP1__FUNC_GPI87 (MTK_PIN_NO(87) | 0) +#define MT8516_PIN_87_RDP1__FUNC_RDP1 (MTK_PIN_NO(87) | 1) + +#define MT8516_PIN_88_RCN__FUNC_GPI88 (MTK_PIN_NO(88) | 0) +#define MT8516_PIN_88_RCN__FUNC_RCN (MTK_PIN_NO(88) | 1) + +#define MT8516_PIN_89_RCP__FUNC_GPI89 (MTK_PIN_NO(89) | 0) +#define MT8516_PIN_89_RCP__FUNC_RCP (MTK_PIN_NO(89) | 1) + +#define MT8516_PIN_90_RDN2__FUNC_GPI90 (MTK_PIN_NO(90) | 0) +#define MT8516_PIN_90_RDN2__FUNC_RDN2 (MTK_PIN_NO(90) | 1) +#define MT8516_PIN_90_RDN2__FUNC_CMDAT8 (MTK_PIN_NO(90) | 2) + +#define MT8516_PIN_91_RDP2__FUNC_GPI91 (MTK_PIN_NO(91) | 0) +#define MT8516_PIN_91_RDP2__FUNC_RDP2 (MTK_PIN_NO(91) | 1) +#define MT8516_PIN_91_RDP2__FUNC_CMDAT9 (MTK_PIN_NO(91) | 2) + +#define MT8516_PIN_92_RDN3__FUNC_GPI92 (MTK_PIN_NO(92) | 0) +#define MT8516_PIN_92_RDN3__FUNC_RDN3 (MTK_PIN_NO(92) | 1) +#define MT8516_PIN_92_RDN3__FUNC_CMDAT4 (MTK_PIN_NO(92) | 2) + +#define MT8516_PIN_93_RDP3__FUNC_GPI93 (MTK_PIN_NO(93) | 0) +#define MT8516_PIN_93_RDP3__FUNC_RDP3 (MTK_PIN_NO(93) | 1) +#define MT8516_PIN_93_RDP3__FUNC_CMDAT5 (MTK_PIN_NO(93) | 2) + +#define MT8516_PIN_94_RCN_A__FUNC_GPI94 (MTK_PIN_NO(94) | 0) +#define MT8516_PIN_94_RCN_A__FUNC_RCN_A (MTK_PIN_NO(94) | 1) +#define MT8516_PIN_94_RCN_A__FUNC_CMDAT6 (MTK_PIN_NO(94) | 2) + +#define MT8516_PIN_95_RCP_A__FUNC_GPI95 (MTK_PIN_NO(95) | 0) +#define MT8516_PIN_95_RCP_A__FUNC_RCP_A (MTK_PIN_NO(95) | 1) +#define MT8516_PIN_95_RCP_A__FUNC_CMDAT7 (MTK_PIN_NO(95) | 2) + +#define MT8516_PIN_96_RDN1_A__FUNC_GPI96 (MTK_PIN_NO(96) | 0) +#define MT8516_PIN_96_RDN1_A__FUNC_RDN1_A (MTK_PIN_NO(96) | 1) +#define MT8516_PIN_96_RDN1_A__FUNC_CMDAT2 (MTK_PIN_NO(96) | 2) +#define MT8516_PIN_96_RDN1_A__FUNC_CMCSD2 (MTK_PIN_NO(96) | 3) + +#define MT8516_PIN_97_RDP1_A__FUNC_GPI97 (MTK_PIN_NO(97) | 0) +#define MT8516_PIN_97_RDP1_A__FUNC_RDP1_A (MTK_PIN_NO(97) | 1) +#define MT8516_PIN_97_RDP1_A__FUNC_CMDAT3 (MTK_PIN_NO(97) | 2) +#define MT8516_PIN_97_RDP1_A__FUNC_CMCSD3 (MTK_PIN_NO(97) | 3) + +#define MT8516_PIN_98_RDN0_A__FUNC_GPI98 (MTK_PIN_NO(98) | 0) +#define MT8516_PIN_98_RDN0_A__FUNC_RDN0_A (MTK_PIN_NO(98) | 1) +#define MT8516_PIN_98_RDN0_A__FUNC_CMHSYNC (MTK_PIN_NO(98) | 2) + +#define MT8516_PIN_99_RDP0_A__FUNC_GPI99 (MTK_PIN_NO(99) | 0) +#define MT8516_PIN_99_RDP0_A__FUNC_RDP0_A (MTK_PIN_NO(99) | 1) +#define MT8516_PIN_99_RDP0_A__FUNC_CMVSYNC (MTK_PIN_NO(99) | 2) + +#define MT8516_PIN_100_CMDAT0__FUNC_GPIO100 (MTK_PIN_NO(100) | 0) +#define MT8516_PIN_100_CMDAT0__FUNC_CMDAT0 (MTK_PIN_NO(100) | 1) +#define MT8516_PIN_100_CMDAT0__FUNC_CMCSD0 (MTK_PIN_NO(100) | 2) +#define MT8516_PIN_100_CMDAT0__FUNC_ANT_SEL2 (MTK_PIN_NO(100) | 3) +#define MT8516_PIN_100_CMDAT0__FUNC_TDM_RX_MCK (MTK_PIN_NO(100) | 5) +#define MT8516_PIN_100_CMDAT0__FUNC_DBG_MON_B_21 (MTK_PIN_NO(100) | 7) + +#define MT8516_PIN_101_CMDAT1__FUNC_GPIO101 (MTK_PIN_NO(101) | 0) +#define MT8516_PIN_101_CMDAT1__FUNC_CMDAT1 (MTK_PIN_NO(101) | 1) +#define MT8516_PIN_101_CMDAT1__FUNC_CMCSD1 (MTK_PIN_NO(101) | 2) +#define MT8516_PIN_101_CMDAT1__FUNC_ANT_SEL3 (MTK_PIN_NO(101) | 3) +#define MT8516_PIN_101_CMDAT1__FUNC_CMFLASH (MTK_PIN_NO(101) | 4) +#define MT8516_PIN_101_CMDAT1__FUNC_TDM_RX_BCK (MTK_PIN_NO(101) | 5) +#define MT8516_PIN_101_CMDAT1__FUNC_DBG_MON_B_22 (MTK_PIN_NO(101) | 7) + +#define MT8516_PIN_102_CMMCLK__FUNC_GPIO102 (MTK_PIN_NO(102) | 0) +#define MT8516_PIN_102_CMMCLK__FUNC_CMMCLK (MTK_PIN_NO(102) | 1) +#define MT8516_PIN_102_CMMCLK__FUNC_ANT_SEL4 (MTK_PIN_NO(102) | 3) +#define MT8516_PIN_102_CMMCLK__FUNC_TDM_RX_LRCK (MTK_PIN_NO(102) | 5) +#define MT8516_PIN_102_CMMCLK__FUNC_DBG_MON_B_23 (MTK_PIN_NO(102) | 7) + +#define MT8516_PIN_103_CMPCLK__FUNC_GPIO103 (MTK_PIN_NO(103) | 0) +#define MT8516_PIN_103_CMPCLK__FUNC_CMPCLK (MTK_PIN_NO(103) | 1) +#define MT8516_PIN_103_CMPCLK__FUNC_CMCSK (MTK_PIN_NO(103) | 2) +#define MT8516_PIN_103_CMPCLK__FUNC_ANT_SEL5 (MTK_PIN_NO(103) | 3) +#define MT8516_PIN_103_CMPCLK__FUNC_TDM_RX_DI (MTK_PIN_NO(103) | 5) +#define MT8516_PIN_103_CMPCLK__FUNC_DBG_MON_B_24 (MTK_PIN_NO(103) | 7) + +#define MT8516_PIN_104_MSDC1_CMD__FUNC_GPIO104 (MTK_PIN_NO(104) | 0) +#define MT8516_PIN_104_MSDC1_CMD__FUNC_MSDC1_CMD (MTK_PIN_NO(104) | 1) +#define MT8516_PIN_104_MSDC1_CMD__FUNC_SQICS (MTK_PIN_NO(104) | 4) +#define MT8516_PIN_104_MSDC1_CMD__FUNC_DBG_MON_B_25 (MTK_PIN_NO(104) | 7) + +#define MT8516_PIN_105_MSDC1_CLK__FUNC_GPIO105 (MTK_PIN_NO(105) | 0) +#define MT8516_PIN_105_MSDC1_CLK__FUNC_MSDC1_CLK (MTK_PIN_NO(105) | 1) +#define MT8516_PIN_105_MSDC1_CLK__FUNC_SQISO (MTK_PIN_NO(105) | 4) +#define MT8516_PIN_105_MSDC1_CLK__FUNC_DBG_MON_B_26 (MTK_PIN_NO(105) | 7) + +#define MT8516_PIN_106_MSDC1_DAT0__FUNC_GPIO106 (MTK_PIN_NO(106) | 0) +#define MT8516_PIN_106_MSDC1_DAT0__FUNC_MSDC1_DAT0 (MTK_PIN_NO(106) | 1) +#define MT8516_PIN_106_MSDC1_DAT0__FUNC_SQISI (MTK_PIN_NO(106) | 4) +#define MT8516_PIN_106_MSDC1_DAT0__FUNC_DBG_MON_B_27 (MTK_PIN_NO(106) | 7) + +#define MT8516_PIN_107_MSDC1_DAT1__FUNC_GPIO107 (MTK_PIN_NO(107) | 0) +#define MT8516_PIN_107_MSDC1_DAT1__FUNC_MSDC1_DAT1 (MTK_PIN_NO(107) | 1) +#define MT8516_PIN_107_MSDC1_DAT1__FUNC_SQIWP (MTK_PIN_NO(107) | 4) +#define MT8516_PIN_107_MSDC1_DAT1__FUNC_DBG_MON_B_28 (MTK_PIN_NO(107) | 7) + +#define MT8516_PIN_108_MSDC1_DAT2__FUNC_GPIO108 (MTK_PIN_NO(108) | 0) +#define MT8516_PIN_108_MSDC1_DAT2__FUNC_MSDC1_DAT2 (MTK_PIN_NO(108) | 1) +#define MT8516_PIN_108_MSDC1_DAT2__FUNC_SQIRST (MTK_PIN_NO(108) | 4) +#define MT8516_PIN_108_MSDC1_DAT2__FUNC_DBG_MON_B_29 (MTK_PIN_NO(108) | 7) + +#define MT8516_PIN_109_MSDC1_DAT3__FUNC_GPIO109 (MTK_PIN_NO(109) | 0) +#define MT8516_PIN_109_MSDC1_DAT3__FUNC_MSDC1_DAT3 (MTK_PIN_NO(109) | 1) +#define MT8516_PIN_109_MSDC1_DAT3__FUNC_SQICK (MTK_PIN_NO(109) | 4) +#define MT8516_PIN_109_MSDC1_DAT3__FUNC_DBG_MON_B_30 (MTK_PIN_NO(109) | 7) + +#define MT8516_PIN_110_MSDC0_DAT7__FUNC_GPIO110 (MTK_PIN_NO(110) | 0) +#define MT8516_PIN_110_MSDC0_DAT7__FUNC_MSDC0_DAT7 (MTK_PIN_NO(110) | 1) +#define MT8516_PIN_110_MSDC0_DAT7__FUNC_NLD7 (MTK_PIN_NO(110) | 4) + +#define MT8516_PIN_111_MSDC0_DAT6__FUNC_GPIO111 (MTK_PIN_NO(111) | 0) +#define MT8516_PIN_111_MSDC0_DAT6__FUNC_MSDC0_DAT6 (MTK_PIN_NO(111) | 1) +#define MT8516_PIN_111_MSDC0_DAT6__FUNC_NLD6 (MTK_PIN_NO(111) | 4) + +#define MT8516_PIN_112_MSDC0_DAT5__FUNC_GPIO112 (MTK_PIN_NO(112) | 0) +#define MT8516_PIN_112_MSDC0_DAT5__FUNC_MSDC0_DAT5 (MTK_PIN_NO(112) | 1) +#define MT8516_PIN_112_MSDC0_DAT5__FUNC_NLD4 (MTK_PIN_NO(112) | 4) + +#define MT8516_PIN_113_MSDC0_DAT4__FUNC_GPIO113 (MTK_PIN_NO(113) | 0) +#define MT8516_PIN_113_MSDC0_DAT4__FUNC_MSDC0_DAT4 (MTK_PIN_NO(113) | 1) +#define MT8516_PIN_113_MSDC0_DAT4__FUNC_NLD3 (MTK_PIN_NO(113) | 4) + +#define MT8516_PIN_114_MSDC0_RSTB__FUNC_GPIO114 (MTK_PIN_NO(114) | 0) +#define MT8516_PIN_114_MSDC0_RSTB__FUNC_MSDC0_RSTB (MTK_PIN_NO(114) | 1) +#define MT8516_PIN_114_MSDC0_RSTB__FUNC_NLD0 (MTK_PIN_NO(114) | 4) + +#define MT8516_PIN_115_MSDC0_CMD__FUNC_GPIO115 (MTK_PIN_NO(115) | 0) +#define MT8516_PIN_115_MSDC0_CMD__FUNC_MSDC0_CMD (MTK_PIN_NO(115) | 1) +#define MT8516_PIN_115_MSDC0_CMD__FUNC_NALE (MTK_PIN_NO(115) | 4) + +#define MT8516_PIN_116_MSDC0_CLK__FUNC_GPIO116 (MTK_PIN_NO(116) | 0) +#define MT8516_PIN_116_MSDC0_CLK__FUNC_MSDC0_CLK (MTK_PIN_NO(116) | 1) +#define MT8516_PIN_116_MSDC0_CLK__FUNC_NWEB (MTK_PIN_NO(116) | 4) + +#define MT8516_PIN_117_MSDC0_DAT3__FUNC_GPIO117 (MTK_PIN_NO(117) | 0) +#define MT8516_PIN_117_MSDC0_DAT3__FUNC_MSDC0_DAT3 (MTK_PIN_NO(117) | 1) +#define MT8516_PIN_117_MSDC0_DAT3__FUNC_NLD1 (MTK_PIN_NO(117) | 4) + +#define MT8516_PIN_118_MSDC0_DAT2__FUNC_GPIO118 (MTK_PIN_NO(118) | 0) +#define MT8516_PIN_118_MSDC0_DAT2__FUNC_MSDC0_DAT2 (MTK_PIN_NO(118) | 1) +#define MT8516_PIN_118_MSDC0_DAT2__FUNC_NLD5 (MTK_PIN_NO(118) | 4) + +#define MT8516_PIN_119_MSDC0_DAT1__FUNC_GPIO119 (MTK_PIN_NO(119) | 0) +#define MT8516_PIN_119_MSDC0_DAT1__FUNC_MSDC0_DAT1 (MTK_PIN_NO(119) | 1) +#define MT8516_PIN_119_MSDC0_DAT1__FUNC_NLD8 (MTK_PIN_NO(119) | 4) + +#define MT8516_PIN_120_MSDC0_DAT0__FUNC_GPIO120 (MTK_PIN_NO(120) | 0) +#define MT8516_PIN_120_MSDC0_DAT0__FUNC_MSDC0_DAT0 (MTK_PIN_NO(120) | 1) +#define MT8516_PIN_120_MSDC0_DAT0__FUNC_WATCHDOG (MTK_PIN_NO(120) | 4) +#define MT8516_PIN_120_MSDC0_DAT0__FUNC_NLD2 (MTK_PIN_NO(120) | 5) + +#endif /* __DTS_MT8516_PINFUNC_H */ diff --git a/arch/arm64/boot/dts/mediatek/mt8516.dtsi b/arch/arm64/boot/dts/mediatek/mt8516.dtsi new file mode 100644 index 000000000000..2f8adf042195 --- /dev/null +++ b/arch/arm64/boot/dts/mediatek/mt8516.dtsi @@ -0,0 +1,457 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + * Copyright (c) 2019 BayLibre, SAS. + * Author: Fabien Parent + */ + +#include +#include +#include +#include + +#include "mt8516-pinfunc.h" + +/ { + compatible = "mediatek,mt8516"; + interrupt-parent = <&sysirq>; + #address-cells = <2>; + #size-cells = <2>; + + cluster0_opp: opp-table-0 { + compatible = "operating-points-v2"; + opp-shared; + opp-598000000 { + opp-hz = /bits/ 64 <598000000>; + opp-microvolt = <1150000>; + }; + opp-747500000 { + opp-hz = /bits/ 64 <747500000>; + opp-microvolt = <1150000>; + }; + opp-1040000000 { + opp-hz = /bits/ 64 <1040000000>; + opp-microvolt = <1200000>; + }; + opp-1196000000 { + opp-hz = /bits/ 64 <1196000000>; + opp-microvolt = <1250000>; + }; + opp-1300000000 { + opp-hz = /bits/ 64 <1300000000>; + opp-microvolt = <1300000>; + }; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a35"; + reg = <0x0>; + enable-method = "psci"; + cpu-idle-states = <&CLUSTER_SLEEP_0 &CLUSTER_SLEEP_0>, + <&CPU_SLEEP_0_0 &CPU_SLEEP_0_0 &CPU_SLEEP_0_0>; + clocks = <&infracfg CLK_IFR_MUX1_SEL>, + <&topckgen CLK_TOP_MAINPLL_D2>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a35"; + reg = <0x1>; + enable-method = "psci"; + cpu-idle-states = <&CLUSTER_SLEEP_0 &CLUSTER_SLEEP_0>, + <&CPU_SLEEP_0_0 &CPU_SLEEP_0_0 &CPU_SLEEP_0_0>; + clocks = <&infracfg CLK_IFR_MUX1_SEL>, + <&topckgen CLK_TOP_MAINPLL_D2>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; + }; + + cpu2: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a35"; + reg = <0x2>; + enable-method = "psci"; + cpu-idle-states = <&CLUSTER_SLEEP_0 &CLUSTER_SLEEP_0>, + <&CPU_SLEEP_0_0 &CPU_SLEEP_0_0 &CPU_SLEEP_0_0>; + clocks = <&infracfg CLK_IFR_MUX1_SEL>, + <&topckgen CLK_TOP_MAINPLL_D2>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; + }; + + cpu3: cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a35"; + reg = <0x3>; + enable-method = "psci"; + cpu-idle-states = <&CLUSTER_SLEEP_0 &CLUSTER_SLEEP_0>, + <&CPU_SLEEP_0_0 &CPU_SLEEP_0_0 &CPU_SLEEP_0_0>; + clocks = <&infracfg CLK_IFR_MUX1_SEL>, + <&topckgen CLK_TOP_MAINPLL_D2>; + clock-names = "cpu", "intermediate", "armpll"; + operating-points-v2 = <&cluster0_opp>; + }; + + idle-states { + entry-method = "psci"; + + CPU_SLEEP_0_0: cpu-sleep-0-0 { + compatible = "arm,idle-state"; + entry-latency-us = <600>; + exit-latency-us = <600>; + min-residency-us = <1200>; + arm,psci-suspend-param = <0x0010000>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + entry-latency-us = <800>; + exit-latency-us = <1000>; + min-residency-us = <2000>; + arm,psci-suspend-param = <0x2010000>; + }; + }; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + clk26m: clk26m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <26000000>; + clock-output-names = "clk26m"; + }; + + clk32k: clk32k { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32000>; + clock-output-names = "clk32k"; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + /* 128 KiB reserved for ARM Trusted Firmware (BL31) */ + bl31_secmon_reserved: secmon@43000000 { + no-map; + reg = <0 0x43000000 0 0x20000>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupt-parent = <&gic>; + interrupts = , + , + , + ; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = , + , + , + ; + interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; + }; + + soc { + #address-cells = <2>; + #size-cells = <2>; + compatible = "simple-bus"; + ranges; + + topckgen: topckgen@10000000 { + compatible = "mediatek,mt8516-topckgen", "syscon"; + reg = <0 0x10000000 0 0x1000>; + #clock-cells = <1>; + }; + + infracfg: infracfg@10001000 { + compatible = "mediatek,mt8516-infracfg", "syscon"; + reg = <0 0x10001000 0 0x1000>; + #clock-cells = <1>; + }; + + apmixedsys: apmixedsys@10018000 { + compatible = "mediatek,mt8516-apmixedsys", "syscon"; + reg = <0 0x10018000 0 0x710>; + #clock-cells = <1>; + }; + + toprgu: toprgu@10007000 { + compatible = "mediatek,mt8516-wdt", + "mediatek,mt6589-wdt"; + reg = <0 0x10007000 0 0x1000>; + interrupts = ; + #reset-cells = <1>; + }; + + timer: timer@10008000 { + compatible = "mediatek,mt8516-timer", + "mediatek,mt6577-timer"; + reg = <0 0x10008000 0 0x1000>; + interrupts = ; + clocks = <&topckgen CLK_TOP_CLK26M_D2>, + <&topckgen CLK_TOP_APXGPT>; + clock-names = "clk13m", "bus"; + }; + + syscfg_pctl: syscfg-pctl@10005000 { + compatible = "syscon"; + reg = <0 0x10005000 0 0x1000>; + }; + + pio: pinctrl@1000b000 { + compatible = "mediatek,mt8516-pinctrl"; + reg = <0 0x1000b000 0 0x1000>; + mediatek,pctl-regmap = <&syscfg_pctl>; + pins-are-numbered; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = ; + }; + + pwrap: pwrap@1000f000 { + compatible = "mediatek,mt8516-pwrap"; + reg = <0 0x1000f000 0 0x1000>; + reg-names = "pwrap"; + interrupts = ; + clocks = <&topckgen CLK_TOP_PMICWRAP_26M>, + <&topckgen CLK_TOP_PMICWRAP_AP>; + clock-names = "spi", "wrap"; + }; + + sysirq: interrupt-controller@10200620 { + compatible = "mediatek,mt8516-sysirq", + "mediatek,mt6577-sysirq"; + interrupt-controller; + #interrupt-cells = <3>; + interrupt-parent = <&gic>; + reg = <0 0x10200620 0 0x20>; + }; + + gic: interrupt-controller@10310000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + interrupt-parent = <&gic>; + interrupt-controller; + reg = <0 0x10310000 0 0x1000>, + <0 0x10320000 0 0x1000>, + <0 0x10340000 0 0x2000>, + <0 0x10360000 0 0x2000>; + interrupts = ; + }; + + uart0: serial@11005000 { + compatible = "mediatek,mt8516-uart", + "mediatek,mt6577-uart"; + reg = <0 0x11005000 0 0x1000>; + interrupts = ; + clocks = <&topckgen CLK_TOP_UART0_SEL>, + <&topckgen CLK_TOP_UART0>; + clock-names = "baud", "bus"; + status = "disabled"; + }; + + uart1: serial@11006000 { + compatible = "mediatek,mt8516-uart", + "mediatek,mt6577-uart"; + reg = <0 0x11006000 0 0x1000>; + interrupts = ; + clocks = <&topckgen CLK_TOP_UART1_SEL>, + <&topckgen CLK_TOP_UART1>; + clock-names = "baud", "bus"; + status = "disabled"; + }; + + uart2: serial@11007000 { + compatible = "mediatek,mt8516-uart", + "mediatek,mt6577-uart"; + reg = <0 0x11007000 0 0x1000>; + interrupts = ; + clocks = <&topckgen CLK_TOP_UART2_SEL>, + <&topckgen CLK_TOP_UART2>; + clock-names = "baud", "bus"; + status = "disabled"; + }; + + i2c0: i2c@11009000 { + compatible = "mediatek,mt8516-i2c", + "mediatek,mt2712-i2c"; + reg = <0 0x11009000 0 0x90>, + <0 0x11000180 0 0x80>; + interrupts = ; + clocks = <&topckgen CLK_TOP_AHB_INFRA_D2>, + <&infracfg CLK_IFR_I2C0_SEL>, + <&topckgen CLK_TOP_I2C0>, + <&topckgen CLK_TOP_APDMA>; + clock-names = "main-source", + "main-sel", + "main", + "dma"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c1: i2c@1100a000 { + compatible = "mediatek,mt8516-i2c", + "mediatek,mt2712-i2c"; + reg = <0 0x1100a000 0 0x90>, + <0 0x11000200 0 0x80>; + interrupts = ; + clocks = <&topckgen CLK_TOP_AHB_INFRA_D2>, + <&infracfg CLK_IFR_I2C1_SEL>, + <&topckgen CLK_TOP_I2C1>, + <&topckgen CLK_TOP_APDMA>; + clock-names = "main-source", + "main-sel", + "main", + "dma"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c2: i2c@1100b000 { + compatible = "mediatek,mt8516-i2c", + "mediatek,mt2712-i2c"; + reg = <0 0x1100b000 0 0x90>, + <0 0x11000280 0 0x80>; + interrupts = ; + clocks = <&topckgen CLK_TOP_AHB_INFRA_D2>, + <&infracfg CLK_IFR_I2C2_SEL>, + <&topckgen CLK_TOP_I2C2>, + <&topckgen CLK_TOP_APDMA>; + clock-names = "main-source", + "main-sel", + "main", + "dma"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi: spi@1100c000 { + compatible = "mediatek,mt8516-spi", + "mediatek,mt2712-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0 0x1100c000 0 0x1000>; + interrupts = ; + clocks = <&topckgen CLK_TOP_UNIVPLL_D12>, + <&topckgen CLK_TOP_SPI_SEL>, + <&topckgen CLK_TOP_SPI>; + clock-names = "parent-clk", "sel-clk", "spi-clk"; + status = "disabled"; + }; + + mmc0: mmc@11120000 { + compatible = "mediatek,mt8516-mmc"; + reg = <0 0x11120000 0 0x1000>; + interrupts = ; + clocks = <&topckgen CLK_TOP_MSDC0>, + <&topckgen CLK_TOP_AHB_INFRA_SEL>, + <&topckgen CLK_TOP_MSDC0_INFRA>; + clock-names = "source", "hclk", "source_cg"; + status = "disabled"; + }; + + mmc1: mmc@11130000 { + compatible = "mediatek,mt8516-mmc"; + reg = <0 0x11130000 0 0x1000>; + interrupts = ; + clocks = <&topckgen CLK_TOP_MSDC1>, + <&topckgen CLK_TOP_AHB_INFRA_SEL>, + <&topckgen CLK_TOP_MSDC1_INFRA>; + clock-names = "source", "hclk", "source_cg"; + status = "disabled"; + }; + + mmc2: mmc@11170000 { + compatible = "mediatek,mt8516-mmc"; + reg = <0 0x11170000 0 0x1000>; + interrupts = ; + clocks = <&topckgen CLK_TOP_MSDC2>, + <&topckgen CLK_TOP_RG_MSDC2>, + <&topckgen CLK_TOP_MSDC2_INFRA>; + clock-names = "source", "hclk", "source_cg"; + status = "disabled"; + }; + + rng: rng@1020c000 { + compatible = "mediatek,mt8516-rng", + "mediatek,mt7623-rng"; + reg = <0 0x1020c000 0 0x100>; + clocks = <&topckgen CLK_TOP_TRNG>; + clock-names = "rng"; + }; + + pwm: pwm@11008000 { + compatible = "mediatek,mt8516-pwm"; + reg = <0 0x11008000 0 0x1000>; + #pwm-cells = <2>; + interrupts = ; + clocks = <&topckgen CLK_TOP_PWM>, + <&topckgen CLK_TOP_PWM_B>, + <&topckgen CLK_TOP_PWM1_FB>, + <&topckgen CLK_TOP_PWM2_FB>, + <&topckgen CLK_TOP_PWM3_FB>, + <&topckgen CLK_TOP_PWM4_FB>, + <&topckgen CLK_TOP_PWM5_FB>; + clock-names = "top", "main", "pwm1", "pwm2", "pwm3", + "pwm4", "pwm5"; + }; + + usb0: usb@11100000 { + compatible = "mediatek,mtk-musb"; + reg = <0 0x11100000 0 0x1000>; + interrupts = ; + interrupt-names = "mc"; + phys = <&usb0_port PHY_TYPE_USB2>; + clocks = <&topckgen CLK_TOP_USB>, + <&topckgen CLK_TOP_USBIF>, + <&topckgen CLK_TOP_USB_1P>; + clock-names = "main","mcu","univpll"; + status = "disabled"; + }; + + usb0_phy: usb@11110000 { + compatible = "mediatek,generic-tphy-v1"; + reg = <0 0x11110000 0 0x800>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + usb0_port: usb-phy@11110800 { + reg = <0 0x11110800 0 0x100>; + clocks = <&topckgen CLK_TOP_USB_PHY48M>; + clock-names = "ref"; + #phy-cells = <1>; + }; + }; + }; +}; From 9983822c8cf983352ac56f8f9d4b48dd5397d35e Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Sat, 29 Feb 2020 18:04:01 +0100 Subject: [PATCH 1018/4444] arm64: dts: mediatek: add pumpkin board dts The pumpkin board is made by Gossamer Engineering and is using a MediaTek SoC. The board currently comes in two available version: MT8516 SoC and MT8167 SoC. The board provides the following IOs: eMMC, NAND, SD card, USB type-A, Ethernet, Wi-Fi, Bluetooth, Audio (jack out, 2 PDM port, 1 analog in), serial over USB, and an expansion header. Additionally there is a HDMI port, DSI port, and camera port only on the MT8167 version of the board. The board can be powered by battery and/or via a USB Type-C port and is using a PMIC MT6392. The eMMC and NAND are sharing pins and cannot be used together. This commit is adding the basic boot support for the Pumpkin MT8516 board on the eMMC. Signed-off-by: Fabien Parent Signed-off-by: Matthias Brugger --- arch/arm64/boot/dts/mediatek/Makefile | 1 + .../boot/dts/mediatek/mt8516-pumpkin.dts | 20 ++ .../boot/dts/mediatek/pumpkin-common.dtsi | 221 ++++++++++++++++++ 3 files changed, 242 insertions(+) create mode 100644 arch/arm64/boot/dts/mediatek/mt8516-pumpkin.dts create mode 100644 arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile index 458bbc422a94..2f8967cb8717 100644 --- a/arch/arm64/boot/dts/mediatek/Makefile +++ b/arch/arm64/boot/dts/mediatek/Makefile @@ -8,3 +8,4 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-bananapi-bpi-r64.dtb dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-evb.dtb +dtb-$(CONFIG_ARCH_MEDIATEK) += mt8516-pumpkin.dtb diff --git a/arch/arm64/boot/dts/mediatek/mt8516-pumpkin.dts b/arch/arm64/boot/dts/mediatek/mt8516-pumpkin.dts new file mode 100644 index 000000000000..cce642c53812 --- /dev/null +++ b/arch/arm64/boot/dts/mediatek/mt8516-pumpkin.dts @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 BayLibre, SAS. + * Author: Fabien Parent + */ + +/dts-v1/; + +#include "mt8516.dtsi" +#include "pumpkin-common.dtsi" + +/ { + model = "Pumpkin MT8516"; + compatible = "mediatek,mt8516"; + + memory@40000000 { + device_type = "memory"; + reg = <0 0x40000000 0 0x40000000>; + }; +}; diff --git a/arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi b/arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi new file mode 100644 index 000000000000..a31093d7142b --- /dev/null +++ b/arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 BayLibre, SAS. + * Author: Fabien Parent + */ + +#include + +/ { + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:921600n8"; + }; + + firmware { + optee: optee@4fd00000 { + compatible = "linaro,optee-tz"; + method = "smc"; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + input-name = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&gpio_keys_default>; + + volume-up { + gpios = <&pio 42 GPIO_ACTIVE_LOW>; + label = "volume_up"; + linux,code = <115>; + wakeup-source; + debounce-interval = <15>; + }; + + volume-down { + gpios = <&pio 43 GPIO_ACTIVE_LOW>; + label = "volume_down"; + linux,code = <114>; + wakeup-source; + debounce-interval = <15>; + }; + }; +}; + +&i2c0 { + clock-div = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + tca6416: gpio@20 { + compatible = "ti,tca6416"; + reg = <0x20>; + rst-gpio = <&pio 65 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&tca6416_pins>; + + gpio-controller; + #gpio-cells = <2>; + + eint20_mux_sel0 { + gpio-hog; + gpios = <0 0>; + input; + line-name = "eint20_mux_sel0"; + }; + + expcon_mux_sel1 { + gpio-hog; + gpios = <1 0>; + input; + line-name = "expcon_mux_sel1"; + }; + + mrg_di_mux_sel2 { + gpio-hog; + gpios = <2 0>; + input; + line-name = "mrg_di_mux_sel2"; + }; + + sd_sdio_mux_sel3 { + gpio-hog; + gpios = <3 0>; + input; + line-name = "sd_sdio_mux_sel3"; + }; + + sd_sdio_mux_ctrl7 { + gpio-hog; + gpios = <7 0>; + output-low; + line-name = "sd_sdio_mux_ctrl7"; + }; + + hw_id0 { + gpio-hog; + gpios = <8 0>; + input; + line-name = "hw_id0"; + }; + + hw_id1 { + gpio-hog; + gpios = <9 0>; + input; + line-name = "hw_id1"; + }; + + hw_id2 { + gpio-hog; + gpios = <10 0>; + input; + line-name = "hw_id2"; + }; + + fg_int_n { + gpio-hog; + gpios = <11 0>; + input; + line-name = "fg_int_n"; + }; + + usba_pwr_en { + gpio-hog; + gpios = <12 0>; + output-high; + line-name = "usba_pwr_en"; + }; + + wifi_3v3_pg { + gpio-hog; + gpios = <13 0>; + input; + line-name = "wifi_3v3_pg"; + }; + + cam_rst { + gpio-hog; + gpios = <14 0>; + output-low; + line-name = "cam_rst"; + }; + + cam_pwdn { + gpio-hog; + gpios = <15 0>; + output-low; + line-name = "cam_pwdn"; + }; + }; +}; + +&i2c2 { + clock-div = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "peripheral"; + + usb_con: connector { + compatible = "usb-c-connector"; + label = "USB-C"; + }; +}; + +&usb0_phy { + status = "okay"; +}; + +&pio { + gpio_keys_default: gpiodefault { + pins_cmd_dat { + pinmux = , + ; + bias-pull-up; + input-enable; + }; + }; + + i2c0_pins_a: i2c0@0 { + pins1 { + pinmux = , + ; + bias-disable; + }; + }; + + i2c2_pins_a: i2c2@0 { + pins1 { + pinmux = , + ; + bias-disable; + }; + }; + + tca6416_pins: pinmux_tca6416_pins { + gpio_mux_rst_n_pin { + pinmux = ; + output-high; + }; + + gpio_mux_int_n_pin { + pinmux = ; + input-enable; + bias-pull-up; + }; + }; +}; From 612b25d2c0faaa34f12a112f6349dec82abe4573 Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Tue, 18 Feb 2020 21:32:00 +0000 Subject: [PATCH 1019/4444] arm64: dts: rockchip: Describe RK3328 GPIO_MUTE users Add explicit properties to describe existing boards' GPIO_MUTE usage for the analog codec. Signed-off-by: Robin Murphy Link: https://lore.kernel.org/r/53637c0359ad9473dc1391a8428ba21017ec467e.1581376744.git.robin.murphy@arm.com Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3328-a1.dts | 1 + arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3328-a1.dts b/arch/arm64/boot/dts/rockchip/rk3328-a1.dts index 16f1656d5203..797e90a3ac92 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328-a1.dts +++ b/arch/arm64/boot/dts/rockchip/rk3328-a1.dts @@ -60,6 +60,7 @@ }; &codec { + mute-gpios = <&grf_gpio 0 GPIO_ACTIVE_LOW>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts index 62936b432f9a..bf3e546f5266 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts +++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts @@ -104,6 +104,7 @@ }; &codec { + mute-gpios = <&grf_gpio 0 GPIO_ACTIVE_LOW>; status = "okay"; port@0 { From 98faae2b4b2d575a11c82735460caae225288d7c Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Fri, 28 Feb 2020 09:48:27 +0100 Subject: [PATCH 1020/4444] arm64: dts: rockchip: fix cpu compatible property for rk3308 A test with the command below gives for example these errors: arch/arm64/boot/dts/rockchip/rk3308-evb.dt.yaml: cpu@0: compatible: Additional items are not allowed ('arm,armv8' was unexpected) arch/arm64/boot/dts/rockchip/rk3308-evb.dt.yaml: cpu@0: compatible: ['arm,cortex-a35', 'arm,armv8'] is too long Fix these errors by removing the last argument of the cpu compatible property in rk3308.dtsi. make ARCH=arm64 dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/arm/cpus.yaml Signed-off-by: Johan Jonker Reviewed-by: Robin Murphy Link: https://lore.kernel.org/r/20200228084827.16198-1-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3308.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3308.dtsi b/arch/arm64/boot/dts/rockchip/rk3308.dtsi index 116f1900effb..3bd5bc86086b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3308.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3308.dtsi @@ -40,7 +40,7 @@ cpu0: cpu@0 { device_type = "cpu"; - compatible = "arm,cortex-a35", "arm,armv8"; + compatible = "arm,cortex-a35"; reg = <0x0 0x0>; enable-method = "psci"; clocks = <&cru ARMCLK>; @@ -53,7 +53,7 @@ cpu1: cpu@1 { device_type = "cpu"; - compatible = "arm,cortex-a35", "arm,armv8"; + compatible = "arm,cortex-a35"; reg = <0x0 0x1>; enable-method = "psci"; operating-points-v2 = <&cpu0_opp_table>; @@ -63,7 +63,7 @@ cpu2: cpu@2 { device_type = "cpu"; - compatible = "arm,cortex-a35", "arm,armv8"; + compatible = "arm,cortex-a35"; reg = <0x0 0x2>; enable-method = "psci"; operating-points-v2 = <&cpu0_opp_table>; @@ -73,7 +73,7 @@ cpu3: cpu@3 { device_type = "cpu"; - compatible = "arm,cortex-a35", "arm,armv8"; + compatible = "arm,cortex-a35"; reg = <0x0 0x3>; enable-method = "psci"; operating-points-v2 = <&cpu0_opp_table>; From e9b6044dceeff4ec93a538df9bef28574a4c3673 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Fri, 28 Feb 2020 12:39:22 +0100 Subject: [PATCH 1021/4444] arm64: dts: remove g-use-dma from rockchip usb nodes A test with the command below gives these errors: arch/arm64/boot/dts/rockchip/px30-evb.dt.yaml: usb@ff300000: 'g-use-dma', 'power-domains' do not match any of the regexes: 'pinctrl-[0-9]+' arch/arm64/boot/dts/rockchip/rk3328-a1.dt.yaml: usb@ff580000: 'g-use-dma' does not match any of the regexes: 'pinctrl-[0-9]+' arch/arm64/boot/dts/rockchip/rk3328-evb.dt.yaml: usb@ff580000: 'g-use-dma' does not match any of the regexes: 'pinctrl-[0-9]+' arch/arm64/boot/dts/rockchip/rk3328-rock64.dt.yaml: usb@ff580000: 'g-use-dma' does not match any of the regexes: 'pinctrl-[0-9]+' arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dt.yaml: usb@ff580000: 'g-use-dma' does not match any of the regexes: 'pinctrl-[0-9]+' 'g-use-dma' is not a valid option in dwc2.yaml, so remove it from all Rockchip dtsi files. make ARCH=arm64 dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/usb/dwc2.yaml g-use-dma was deprecated in november 2016, see https://patchwork.kernel.org/patch/9420553/ Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200228113922.20266-2-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/px30.dtsi | 1 - arch/arm64/boot/dts/rockchip/rk3328.dtsi | 1 - 2 files changed, 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 75908c587511..4f484119fe3f 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -870,7 +870,6 @@ g-np-tx-fifo-size = <16>; g-rx-fifo-size = <280>; g-tx-fifo-size = <256 128 128 64 32 16>; - g-use-dma; phys = <&u2phy_otg>; phy-names = "usb2-phy"; power-domains = <&power PX30_PD_USB>; diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi index 1f53ead52c7f..bad41bc6f2d5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi @@ -957,7 +957,6 @@ g-np-tx-fifo-size = <16>; g-rx-fifo-size = <280>; g-tx-fifo-size = <256 128 128 64 32 16>; - g-use-dma; phys = <&u2phy_otg>; phy-names = "usb2-phy"; status = "disabled"; From a0514bc16739c245714fc63d20c9facd711c6fe9 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Fri, 28 Feb 2020 12:39:21 +0100 Subject: [PATCH 1022/4444] ARM: dts: remove g-use-dma from rockchip usb nodes A test with the command below gives these errors: arch/arm/boot/dts/rv1108-elgin-r1.dt.yaml: usb@30180000: 'g-use-dma' does not match any of the regexes: 'pinctrl-[0-9]+' arch/arm/boot/dts/rv1108-evb.dt.yaml: usb@30180000: 'g-use-dma' does not match any of the regexes: 'pinctrl-[0-9]+' arch/arm/boot/dts/rk3228-evb.dt.yaml: usb@30040000: 'g-use-dma' does not match any of the regexes: 'pinctrl-[0-9]+' arch/arm/boot/dts/rk3229-evb.dt.yaml: usb@30040000: 'g-use-dma' does not match any of the regexes: 'pinctrl-[0-9]+' arch/arm/boot/dts/rk3229-xms6.dt.yaml: usb@30040000: 'g-use-dma' does not match any of the regexes: 'pinctrl-[0-9]+' 'g-use-dma' is not a valid option in dwc2.yaml, so remove it from all Rockchip dtsi files. make ARCH=arm dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/usb/dwc2.yaml g-use-dma was deprecated in november 2016, see https://patchwork.kernel.org/patch/9420553/ Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200228113922.20266-1-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk322x.dtsi | 1 - arch/arm/boot/dts/rv1108.dtsi | 1 - 2 files changed, 2 deletions(-) diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index 4e90efdc9630..dac930be3fe0 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -718,7 +718,6 @@ g-np-tx-fifo-size = <16>; g-rx-fifo-size = <280>; g-tx-fifo-size = <256 128 128 64 32 16>; - g-use-dma; phys = <&u2phy0_otg>; phy-names = "usb2-phy"; status = "disabled"; diff --git a/arch/arm/boot/dts/rv1108.dtsi b/arch/arm/boot/dts/rv1108.dtsi index 1fd06e7cb983..9bb109d668fa 100644 --- a/arch/arm/boot/dts/rv1108.dtsi +++ b/arch/arm/boot/dts/rv1108.dtsi @@ -527,7 +527,6 @@ g-np-tx-fifo-size = <16>; g-rx-fifo-size = <280>; g-tx-fifo-size = <256 128 128 64 32 16>; - g-use-dma; phys = <&u2phy_otg>; phy-names = "usb2-phy"; status = "disabled"; From 048e9a44dd93b31b1cac75092cf5d81163c9c465 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Fri, 28 Feb 2020 16:53:52 +0100 Subject: [PATCH 1023/4444] ARM: dts: rockchip: add sram to bus_intmem nodename for rv1108 A test with the command below gives these errors: arch/arm/boot/dts/rv1108-elgin-r1.dt.yaml: bus_intmem@10080000: $nodename:0: 'bus_intmem@10080000' does not match '^sram(@.*)?' arch/arm/boot/dts/rv1108-evb.dt.yaml: bus_intmem@10080000: $nodename:0: 'bus_intmem@10080000' does not match '^sram(@.*)?' Fix this error by adding sram to the bus_intmem nodename in rv1108.dtsi. make ARCH=arm dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/sram/sram.yaml Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200228155354.27206-1-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rv1108.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rv1108.dtsi b/arch/arm/boot/dts/rv1108.dtsi index 9bb109d668fa..c3621b3e6556 100644 --- a/arch/arm/boot/dts/rv1108.dtsi +++ b/arch/arm/boot/dts/rv1108.dtsi @@ -102,7 +102,7 @@ }; }; - bus_intmem@10080000 { + bus_intmem: sram@10080000 { compatible = "mmio-sram"; reg = <0x10080000 0x2000>; #address-cells = <1>; From 449f52e8612dc557e89545b63de3e2de062bca5b Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Fri, 28 Feb 2020 16:53:53 +0100 Subject: [PATCH 1024/4444] ARM: dts: rockchip: add sram to bus_intmem nodename for rk3036 A test with the command below gives these errors: arch/arm/boot/dts/rk3036-evb.dt.yaml: bus_intmem@10080000: $nodename:0: 'bus_intmem@10080000' does not match '^sram(@.*)?' arch/arm/boot/dts/rk3036-kylin.dt.yaml: bus_intmem@10080000: $nodename:0: 'bus_intmem@10080000' does not match '^sram(@.*)?' Fix this error by adding sram to the bus_intmem nodename in rk3036.dtsi. make ARCH=arm dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/sram/sram.yaml Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200228155354.27206-2-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3036.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index cf36e25195b4..b621385631a3 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -101,7 +101,7 @@ #clock-cells = <0>; }; - bus_intmem@10080000 { + bus_intmem: sram@10080000 { compatible = "mmio-sram"; reg = <0x10080000 0x2000>; #address-cells = <1>; From 2280f861cc9efb72ce1f42407ccd3645042a8e8b Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Fri, 28 Feb 2020 16:53:54 +0100 Subject: [PATCH 1025/4444] ARM: dts: rockchip: add sram to bus_intmem nodename for rk3288 A test with the command below gives for example these errors: arch/arm/boot/dts/rk3288-evb-act8846.dt.yaml: bus_intmem@ff700000: $nodename:0: 'bus_intmem@ff700000' does not match '^sram(@.*)?' arch/arm/boot/dts/rk3288-evb-rk808.dt.yaml: bus_intmem@ff700000: $nodename:0: 'bus_intmem@ff700000' does not match '^sram(@.*)?' 'rockchip-pmu-sram.txt' inherit properties from 'sram.yaml'. Fix this error by adding 'sram' to the bus_intmem nodename in 'rk3288.dtsi'. But 'sram' is also a node name already in use. To prevent confusion rename it to 'pmu_sram'. make ARCH=arm dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/sram/sram.yaml Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200228155354.27206-3-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 9beb662166aa..039e8aa70d2d 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -718,7 +718,7 @@ status = "disabled"; }; - bus_intmem@ff700000 { + bus_intmem: sram@ff700000 { compatible = "mmio-sram"; reg = <0x0 0xff700000 0x0 0x18000>; #address-cells = <1>; @@ -730,7 +730,7 @@ }; }; - sram@ff720000 { + pmu_sram: sram@ff720000 { compatible = "rockchip,rk3288-pmu-sram", "mmio-sram"; reg = <0x0 0xff720000 0x0 0x1000>; }; From 4e2e8418c4c6b1f95d61ccbf5ab354f44e202315 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Fri, 28 Feb 2020 07:14:36 +0100 Subject: [PATCH 1026/4444] arm64: dts: rockchip: fix compatible property for Radxa ROCK Pi N10 A test with the command below gives this error: arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dt.yaml: /: compatible: ['radxa,rockpi-n10', 'rockchip,rk3399pro'] is not valid under any of the given schemas During the review process the binding was changed, but the dts file was somehow not updated. Fix this error by adding 'vamrs,rk3399pro-vmarc-som' to the compatible property. make ARCH=arm64 dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/arm/rockchip.yaml Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200228061436.13506-4-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts b/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts index b42f94179538..a1783e7f769a 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts @@ -13,5 +13,6 @@ / { model = "Radxa ROCK Pi N10"; - compatible = "radxa,rockpi-n10", "rockchip,rk3399pro"; + compatible = "radxa,rockpi-n10", "vamrs,rk3399pro-vmarc-som", + "rockchip,rk3399pro"; }; From 8a469ee35606ba65448d54e5a2a23302f7e79e3c Mon Sep 17 00:00:00 2001 From: Carlos de Paula Date: Tue, 18 Feb 2020 17:10:37 -0500 Subject: [PATCH 1027/4444] arm64: dts: rockchip: Add txpbl node for RK3399/RK3328 Some rockchip SoCs like the RK3399 and RK3328 exhibit an issue where tx checksumming does not work with packets larger than 1498. The default Programmable Buffer Length for TX in these GMAC's is not suitable for MTUs higher than 1498. The workaround is to disable TX offloading with 'ethtool -K eth0 tx off rx off' causing performance impacts as it disables hardware checksumming. This patch sets snps,txpbl to 0x4 which is a safe number tested ok for the most popular MTU value of 1500. For reference, see https://lkml.org/lkml/2019/4/1/1382. Signed-off-by: Carlos de Paula Link: https://lore.kernel.org/r/20200218221040.10955-1-me@carlosedp.com Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3328.dtsi | 2 ++ arch/arm64/boot/dts/rockchip/rk3399.dtsi | 1 + 2 files changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi index bad41bc6f2d5..2aefb38f7368 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi @@ -906,6 +906,7 @@ resets = <&cru SRST_GMAC2IO_A>; reset-names = "stmmaceth"; rockchip,grf = <&grf>; + snps,txpbl = <0x4>; status = "disabled"; }; @@ -927,6 +928,7 @@ reset-names = "stmmaceth", "mac-phy"; phy-mode = "rmii"; phy-handle = <&phy>; + snps,txpbl = <0x4>; status = "disabled"; mdio { diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi index 33cc21fcf4c1..cd5415d7e559 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi @@ -288,6 +288,7 @@ resets = <&cru SRST_A_GMAC>; reset-names = "stmmaceth"; rockchip,grf = <&grf>; + snps,txpbl = <0x4>; status = "disabled"; }; From 8dd177410c6703fc28f586c79adf5d0734c3ac8d Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Thu, 23 Jan 2020 19:16:39 +0530 Subject: [PATCH 1028/4444] ARM: dts: rockchip: Fix vcc10_lcd name and voltage for rk3288-vyasa According to hardware schematics of Vyasa RK3288 the actual name used for vcc10_lcd is vdd10_lcd. regulator suspend voltage can rail upto 1.0V not 1.8V. Fix the name and suspend voltage for vcc10_lcd regulator. Signed-off-by: Jagan Teki Link: https://lore.kernel.org/r/20200123134641.30720-1-jagan@amarulasolutions.com Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288-vyasa.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/rk3288-vyasa.dts b/arch/arm/boot/dts/rk3288-vyasa.dts index ba06e9f97ddc..d2f79e5bee87 100644 --- a/arch/arm/boot/dts/rk3288-vyasa.dts +++ b/arch/arm/boot/dts/rk3288-vyasa.dts @@ -286,15 +286,15 @@ }; }; - vcc10_lcd: LDO_REG6 { - regulator-name = "vcc10_lcd"; + vdd10_lcd: LDO_REG6 { + regulator-name = "vdd10_lcd"; regulator-min-microvolt = <1000000>; regulator-max-microvolt = <1000000>; regulator-always-on; regulator-boot-on; regulator-state-mem { regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; + regulator-suspend-microvolt = <1000000>; }; }; From b38a9a3f44615ccd5a44bdda1025effb11b6a613 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Thu, 23 Jan 2020 19:16:40 +0530 Subject: [PATCH 1029/4444] ARM: dts: rockchip: Fix ddc-i2c-bus for rk3288-vyasa ddc-i2c-bus routed for HDMI is not i2c2 but i2c5 on Vyasa RK3288 board. Add support for fixing the same. Signed-off-by: Jagan Teki Link: https://lore.kernel.org/r/20200123134641.30720-2-jagan@amarulasolutions.com Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288-vyasa.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/rk3288-vyasa.dts b/arch/arm/boot/dts/rk3288-vyasa.dts index d2f79e5bee87..88c63946f2a3 100644 --- a/arch/arm/boot/dts/rk3288-vyasa.dts +++ b/arch/arm/boot/dts/rk3288-vyasa.dts @@ -150,7 +150,7 @@ }; &hdmi { - ddc-i2c-bus = <&i2c2>; + ddc-i2c-bus = <&i2c5>; status = "okay"; }; @@ -347,7 +347,7 @@ }; }; -&i2c2 { +&i2c5 { status = "okay"; }; From 385d567c13082b3f81c4e972b22d3f263452087f Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Thu, 23 Jan 2020 19:16:41 +0530 Subject: [PATCH 1030/4444] ARM: dts: rockchip: Add vcc50_hdmi for rk3288-vyasa Add vcc50_hdmi regulator for Vyasa RK3288 board. VCC50_HDMI is the real name used for this regulator as per the schematics. This regulator used for HDMI connector by detecting the cable via HDMI_EN gpio and input rails are sourced from VSUS_5V regulator. Signed-off-by: Jagan Teki Link: https://lore.kernel.org/r/20200123134641.30720-3-jagan@amarulasolutions.com Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288-vyasa.dts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-vyasa.dts b/arch/arm/boot/dts/rk3288-vyasa.dts index 88c63946f2a3..385dd59393e1 100644 --- a/arch/arm/boot/dts/rk3288-vyasa.dts +++ b/arch/arm/boot/dts/rk3288-vyasa.dts @@ -78,6 +78,18 @@ vin-supply = <&vcc_io>; }; + vcc50_hdmi: vcc50-hdmi { + compatible = "regulator-fixed"; + regulator-name = "vcc50_hdmi"; + enable-active-high; + gpio = <&gpio7 RK_PB4 GPIO_ACTIVE_HIGH>; /* HDMI_EN */ + pinctrl-names = "default"; + pinctrl-0 = <&vcc50_hdmi_en>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vsus_5v>; + }; + vusb1_5v: vusb1-5v { compatible = "regulator-fixed"; regulator-name = "vusb1_5v"; @@ -446,6 +458,12 @@ }; }; + hdmi { + vcc50_hdmi_en: vcc50-hdmi-en { + rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + pmic { pmic_int: pmic-int { rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>; From 186444c146dcfa03c7a516900bbfa26f7eb47ed6 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 21 Jan 2020 23:20:54 +0100 Subject: [PATCH 1031/4444] arm64: dts: rockchip: fix px30 lvds ports The lvds controller has two ports. port@0 for the connection to the display controller(s) and port@1 for the connection to the panel, so should have a ports node covering the port@x nodes. Signed-off-by: Heiko Stuebner Reviewed-by: Miquel Raynal Link: https://lore.kernel.org/r/20200121222055.4068166-1-heiko@sntech.de --- arch/arm64/boot/dts/rockchip/px30.dtsi | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 4f484119fe3f..495212c288cf 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -413,27 +413,30 @@ lvds: lvds { compatible = "rockchip,px30-lvds"; - #address-cells = <1>; - #size-cells = <0>; phys = <&dsi_dphy>; phy-names = "dphy"; rockchip,grf = <&grf>; rockchip,output = "lvds"; status = "disabled"; - port@0 { - reg = <0>; + ports { #address-cells = <1>; #size-cells = <0>; - lvds_vopb_in: endpoint@0 { + port@0 { reg = <0>; - remote-endpoint = <&vopb_out_lvds>; - }; + #address-cells = <1>; + #size-cells = <0>; - lvds_vopl_in: endpoint@1 { - reg = <1>; - remote-endpoint = <&vopl_out_lvds>; + lvds_vopb_in: endpoint@0 { + reg = <0>; + remote-endpoint = <&vopb_out_lvds>; + }; + + lvds_vopl_in: endpoint@1 { + reg = <1>; + remote-endpoint = <&vopl_out_lvds>; + }; }; }; }; From b391554c61cb353c279523a706734b090aaf9000 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Tue, 25 Feb 2020 09:47:46 -0700 Subject: [PATCH 1032/4444] dmaengine: idxd: check return result from check_vma() in cdev The returned result from the check_vma() function in the cdev ->mmap() call needs to be handled. Add the check and returning error. Fixes: 42d279f9137a ("dmaengine: idxd: add char driver to expose submission portal to userland") Reported-by: Vinod Koul Signed-off-by: Dave Jiang Link: https://lore.kernel.org/r/158264926659.9387.14325163515683047959.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul --- drivers/dma/idxd/cdev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c index 8dfdbe37e381..8f323e7855c4 100644 --- a/drivers/dma/idxd/cdev.c +++ b/drivers/dma/idxd/cdev.c @@ -137,6 +137,8 @@ static int idxd_cdev_mmap(struct file *filp, struct vm_area_struct *vma) dev_dbg(&pdev->dev, "%s called\n", __func__); rc = check_vma(wq, vma, __func__); + if (rc < 0) + return rc; vma->vm_flags |= VM_DONTCOPY; pfn = (base + idxd_get_wq_portal_full_offset(wq->id, From 9065958ee6dd752c7e1bbacbb79fe5f5f2218393 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Mon, 24 Feb 2020 11:01:34 -0700 Subject: [PATCH 1033/4444] dmaengine: idxd: expose general capabilities register in sysfs There are some capabilities for the device that are interesting to user apps that are interacting directly with the device. Expose gencap register in sysfs to allow that information. Signed-off-by: Dave Jiang Link: https://lore.kernel.org/r/158256729399.55526.10842505054968710547.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul --- drivers/dma/idxd/sysfs.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c index e4f35bdf252e..a74e99cb055d 100644 --- a/drivers/dma/idxd/sysfs.c +++ b/drivers/dma/idxd/sysfs.c @@ -1160,6 +1160,16 @@ static ssize_t op_cap_show(struct device *dev, } static DEVICE_ATTR_RO(op_cap); +static ssize_t gen_cap_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct idxd_device *idxd = + container_of(dev, struct idxd_device, conf_dev); + + return sprintf(buf, "%#llx\n", idxd->hw.gen_cap.bits); +} +static DEVICE_ATTR_RO(gen_cap); + static ssize_t configurable_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1297,6 +1307,7 @@ static struct attribute *idxd_device_attributes[] = { &dev_attr_max_batch_size.attr, &dev_attr_max_transfer_size.attr, &dev_attr_op_cap.attr, + &dev_attr_gen_cap.attr, &dev_attr_configurable.attr, &dev_attr_clients.attr, &dev_attr_state.attr, From 88ac039cbed125bd9ed132d27ec9f689c6442748 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 26 Feb 2020 12:18:38 +0200 Subject: [PATCH 1034/4444] dmaengine: Refactor dmaengine_check_align() to be bit operations only There is no need to have branch and temporary variable in the function. Simple convert it to be a set of bit and arithmetic operations. Signed-off-by: Andy Shevchenko Reviewed-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20200226101842.29426-1-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul --- include/linux/dmaengine.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 64461fc64e1b..9f3f5582816a 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -1155,14 +1155,7 @@ static inline dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc static inline bool dmaengine_check_align(enum dmaengine_alignment align, size_t off1, size_t off2, size_t len) { - size_t mask; - - if (!align) - return true; - mask = (1 << align) - 1; - if (mask & (off1 | off2 | len)) - return false; - return true; + return !(((1 << align) - 1) & (off1 | off2 | len)); } static inline bool is_dma_copy_aligned(struct dma_device *dev, size_t off1, From 3a92063be16873a10648a81be0b1be42a9d54ee9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 26 Feb 2020 12:18:39 +0200 Subject: [PATCH 1035/4444] dmaengine: Use negative condition for better readability When negative condition is in use we may decrease indentation level and make the main part of logic better visible. Signed-off-by: Andy Shevchenko Reviewed-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20200226101842.29426-2-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul --- include/linux/dmaengine.h | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 9f3f5582816a..ae56a91c2a05 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -618,10 +618,11 @@ static inline void dmaengine_unmap_put(struct dmaengine_unmap_data *unmap) static inline void dma_descriptor_unmap(struct dma_async_tx_descriptor *tx) { - if (tx->unmap) { - dmaengine_unmap_put(tx->unmap); - tx->unmap = NULL; - } + if (!tx->unmap) + return; + + dmaengine_unmap_put(tx->unmap); + tx->unmap = NULL; } #ifndef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH @@ -1408,11 +1409,12 @@ static inline enum dma_status dma_async_is_complete(dma_cookie_t cookie, static inline void dma_set_tx_state(struct dma_tx_state *st, dma_cookie_t last, dma_cookie_t used, u32 residue) { - if (st) { - st->last = last; - st->used = used; - st->residue = residue; - } + if (!st) + return; + + st->last = last; + st->used = used; + st->residue = residue; } #ifdef CONFIG_DMA_ENGINE @@ -1489,12 +1491,11 @@ static inline int dmaengine_desc_set_reuse(struct dma_async_tx_descriptor *tx) if (ret) return ret; - if (caps.descriptor_reuse) { - tx->flags |= DMA_CTRL_REUSE; - return 0; - } else { + if (!caps.descriptor_reuse) return -EPERM; - } + + tx->flags |= DMA_CTRL_REUSE; + return 0; } static inline void dmaengine_desc_clear_reuse(struct dma_async_tx_descriptor *tx) @@ -1510,10 +1511,10 @@ static inline bool dmaengine_desc_test_reuse(struct dma_async_tx_descriptor *tx) static inline int dmaengine_desc_free(struct dma_async_tx_descriptor *desc) { /* this is supported for reusable desc, so check that */ - if (dmaengine_desc_test_reuse(desc)) - return desc->desc_free(desc); - else + if (!dmaengine_desc_test_reuse(desc)) return -EPERM; + + return desc->desc_free(desc); } /* --- DMA device --- */ From 5f77dd850c0a32d4d5047d139077718ee7f1a8fe Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 26 Feb 2020 12:18:40 +0200 Subject: [PATCH 1036/4444] dmaengine: Drop redundant 'else' keyword It's obvious that 'else' keyword is redundant in the code like if (foo) return bar; else if (baz) ... Drop it for good. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200226101842.29426-3-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul --- include/linux/dmaengine.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index ae56a91c2a05..1bb5477ef7ec 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -1230,9 +1230,9 @@ static inline int dma_maxpq(struct dma_device *dma, enum dma_ctrl_flags flags) { if (dma_dev_has_pq_continue(dma) || !dmaf_continue(flags)) return dma_dev_to_maxpq(dma); - else if (dmaf_p_disabled_continue(flags)) + if (dmaf_p_disabled_continue(flags)) return dma_dev_to_maxpq(dma) - 1; - else if (dmaf_continue(flags)) + if (dmaf_continue(flags)) return dma_dev_to_maxpq(dma) - 3; BUG(); } @@ -1243,7 +1243,7 @@ static inline size_t dmaengine_get_icg(bool inc, bool sgl, size_t icg, if (inc) { if (dir_icg) return dir_icg; - else if (sgl) + if (sgl) return icg; } From 1873300afa6147a1882aeba1e8bc9a13c5487571 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 26 Feb 2020 12:18:41 +0200 Subject: [PATCH 1037/4444] dmaengine: consistently return string literal from switch-case There is no need to have 'break;' statement in the default case followed by return certain string literal when all other cases have returned the string literals. So, refactor it accordingly. Signed-off-by: Andy Shevchenko Reviewed-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20200226101842.29426-4-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul --- include/linux/dmaengine.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 1bb5477ef7ec..d3672f065a64 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -1560,9 +1560,7 @@ dmaengine_get_direction_text(enum dma_transfer_direction dir) case DMA_DEV_TO_DEV: return "DEV_TO_DEV"; default: - break; + return "invalid"; } - - return "invalid"; } #endif /* DMAENGINE_H */ From ec18d7e7d28625355bf2f5c18d47c09b1cde5cde Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 11 Feb 2020 15:06:18 -0600 Subject: [PATCH 1038/4444] gpio: uniphier: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertenly introduced[3] to the codebase from now on. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-uniphier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c index 7ec97499b7f7..f99f3c10bed0 100644 --- a/drivers/gpio/gpio-uniphier.c +++ b/drivers/gpio/gpio-uniphier.c @@ -30,7 +30,7 @@ struct uniphier_gpio_priv { struct irq_domain *domain; void __iomem *regs; spinlock_t lock; - u32 saved_vals[0]; + u32 saved_vals[]; }; static unsigned int uniphier_gpio_bank_to_reg(unsigned int bank) From df2cd589766cf7c35a73690fc22d6a6be179cb57 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 13 Feb 2020 19:09:04 +0200 Subject: [PATCH 1039/4444] gpiolib: Rename 'event' to 'ge' to be consistent with other use Rename 'event' to 'ge' to be consistent with other use. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 2253ab495349..2982d983c4fd 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -830,11 +830,11 @@ static ssize_t lineevent_read(struct file *filep, loff_t *f_ps) { struct lineevent_state *le = filep->private_data; - struct gpioevent_data event; + struct gpioevent_data ge; ssize_t bytes_read = 0; int ret; - if (count < sizeof(event)) + if (count < sizeof(ge)) return -EINVAL; do { @@ -858,7 +858,7 @@ static ssize_t lineevent_read(struct file *filep, } } - ret = kfifo_out(&le->events, &event, 1); + ret = kfifo_out(&le->events, &ge, 1); spin_unlock(&le->wait.lock); if (ret != 1) { /* @@ -870,10 +870,10 @@ static ssize_t lineevent_read(struct file *filep, break; } - if (copy_to_user(buf + bytes_read, &event, sizeof(event))) + if (copy_to_user(buf + bytes_read, &ge, sizeof(ge))) return -EFAULT; - bytes_read += sizeof(event); - } while (count >= bytes_read + sizeof(event)); + bytes_read += sizeof(ge); + } while (count >= bytes_read + sizeof(ge)); return bytes_read; } From 48543bd8e92880b1ca81b15cf392103dc82cd3e0 Mon Sep 17 00:00:00 2001 From: Kent Gibson Date: Mon, 24 Feb 2020 14:49:53 +0000 Subject: [PATCH 1040/4444] gpiolib: fix unwatch ioctl() Fix the field having a bit cleared by the unwatch ioctl(). Fixes: 51c1064e82e7 ("gpiolib: add new ioctl() for monitoring changes in line info") Signed-off-by: Kent Gibson Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 2982d983c4fd..20683695c598 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1276,7 +1276,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (IS_ERR(desc)) return PTR_ERR(desc); - clear_bit(desc_to_gpio(desc), &desc->flags); + clear_bit(desc_to_gpio(desc), priv->watched_lines); return 0; } return -EINVAL; From 1931479788c5e3c0396a0bde3606e517c64b9f95 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 26 Feb 2020 14:53:23 +0100 Subject: [PATCH 1041/4444] gpiolib: fix bitmap operations related to line event watching When operating on the bits of watched_lines bitmap, we're using desc_to_gpio() which returns the GPIO number from the global numberspace. This leads to all sorts of memory corruptions and invalid behavior. We should switch to using gpio_chip_hwgpio() instead. Fixes: 51c1064e82e7 ("gpiolib: add new ioctl() for monitoring changes in line info") Reported-by: Kent Gibson Signed-off-by: Bartosz Golaszewski Tested-by: Kent Gibson --- drivers/gpio/gpiolib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 20683695c598..bc71f05d5193 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1261,7 +1261,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -EFAULT; if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) - set_bit(desc_to_gpio(desc), priv->watched_lines); + set_bit(gpio_chip_hwgpio(desc), priv->watched_lines); return 0; } else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) { @@ -1276,7 +1276,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (IS_ERR(desc)) return PTR_ERR(desc); - clear_bit(desc_to_gpio(desc), priv->watched_lines); + clear_bit(gpio_chip_hwgpio(desc), priv->watched_lines); return 0; } return -EINVAL; @@ -1304,7 +1304,7 @@ static int lineinfo_changed_notify(struct notifier_block *nb, struct gpio_desc *desc = data; int ret; - if (!test_bit(desc_to_gpio(desc), priv->watched_lines)) + if (!test_bit(gpio_chip_hwgpio(desc), priv->watched_lines)) return NOTIFY_DONE; memset(&chg, 0, sizeof(chg)); From a0bb89e8446071d2fec95f75a1307a969578f288 Mon Sep 17 00:00:00 2001 From: Paul Boddie Date: Fri, 28 Feb 2020 19:19:30 +0100 Subject: [PATCH 1042/4444] pinctrl: ingenic: add hdmi-ddc pin control group Signed-off-by: Paul Boddie Signed-off-by: H. Nikolaus Schaller Link: https://lore.kernel.org/r/010d6ad3473fb4b1f1041888a071796180cdd838.1582913973.git.hns@goldelico.com Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-ingenic.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c index 34870f934563..7f5376ce7fb1 100644 --- a/drivers/pinctrl/pinctrl-ingenic.c +++ b/drivers/pinctrl/pinctrl-ingenic.c @@ -4,6 +4,7 @@ * * Copyright (c) 2017 Paul Cercueil * Copyright (c) 2019 周琰杰 (Zhou Yanjie) + * Copyright (c) 2017, 2019 Paul Boddie */ #include @@ -900,6 +901,7 @@ static int jz4780_mmc0_8bit_a_pins[] = { 0x04, 0x05, 0x06, 0x07, 0x18, }; static int jz4780_i2c3_pins[] = { 0x6a, 0x6b, }; static int jz4780_i2c4_e_pins[] = { 0x8c, 0x8d, }; static int jz4780_i2c4_f_pins[] = { 0xb9, 0xb8, }; +static int jz4780_hdmi_ddc_pins[] = { 0xb9, 0xb8, }; static int jz4780_uart2_data_funcs[] = { 1, 1, }; static int jz4780_uart2_hwflow_funcs[] = { 1, 1, }; @@ -908,6 +910,7 @@ static int jz4780_mmc0_8bit_a_funcs[] = { 1, 1, 1, 1, 1, }; static int jz4780_i2c3_funcs[] = { 1, 1, }; static int jz4780_i2c4_e_funcs[] = { 1, 1, }; static int jz4780_i2c4_f_funcs[] = { 1, 1, }; +static int jz4780_hdmi_ddc_funcs[] = { 0, 0, }; static const struct group_desc jz4780_groups[] = { INGENIC_PIN_GROUP("uart0-data", jz4770_uart0_data), @@ -950,6 +953,7 @@ static const struct group_desc jz4780_groups[] = { INGENIC_PIN_GROUP("i2c3-data", jz4780_i2c3), INGENIC_PIN_GROUP("i2c4-data-e", jz4780_i2c4_e), INGENIC_PIN_GROUP("i2c4-data-f", jz4780_i2c4_f), + INGENIC_PIN_GROUP("hdmi-ddc", jz4780_hdmi_ddc), INGENIC_PIN_GROUP("cim-data", jz4770_cim_8bit), INGENIC_PIN_GROUP("lcd-24bit", jz4770_lcd_24bit), { "lcd-no-pins", }, @@ -982,6 +986,7 @@ static const char *jz4780_nemc_groups[] = { static const char *jz4780_i2c3_groups[] = { "i2c3-data", }; static const char *jz4780_i2c4_groups[] = { "i2c4-data-e", "i2c4-data-f", }; static const char *jz4780_cim_groups[] = { "cim-data", }; +static const char *jz4780_hdmi_ddc_groups[] = { "hdmi-ddc", }; static const struct function_desc jz4780_functions[] = { { "uart0", jz4770_uart0_groups, ARRAY_SIZE(jz4770_uart0_groups), }, @@ -1014,6 +1019,8 @@ static const struct function_desc jz4780_functions[] = { { "pwm5", jz4770_pwm5_groups, ARRAY_SIZE(jz4770_pwm5_groups), }, { "pwm6", jz4770_pwm6_groups, ARRAY_SIZE(jz4770_pwm6_groups), }, { "pwm7", jz4770_pwm7_groups, ARRAY_SIZE(jz4770_pwm7_groups), }, + { "hdmi-ddc", jz4780_hdmi_ddc_groups, + ARRAY_SIZE(jz4780_hdmi_ddc_groups), }, }; static const struct ingenic_chip_info jz4780_chip_info = { From 0d4e1bb1062481c43c01dd20fd4c40544441739f Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Tue, 25 Feb 2020 19:04:17 +0900 Subject: [PATCH 1043/4444] openrisc: Convert copy_thread to copy_thread_tls This is required for clone3 which passes the TLS value through a struct rather than a register. Signed-off-by: Stafford Horne Acked-by: Christian Brauner --- arch/openrisc/Kconfig | 1 + arch/openrisc/kernel/process.c | 17 ++++++----------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig index 1928e061ff96..5debdbe6fc35 100644 --- a/arch/openrisc/Kconfig +++ b/arch/openrisc/Kconfig @@ -14,6 +14,7 @@ config OPENRISC select HANDLE_DOMAIN_IRQ select GPIOLIB select HAVE_ARCH_TRACEHOOK + select HAVE_COPY_THREAD_TLS select SPARSE_IRQ select GENERIC_IRQ_CHIP select GENERIC_IRQ_PROBE diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index b06f84f6676f..5caa47f7de4f 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c @@ -117,12 +117,13 @@ void release_thread(struct task_struct *dead_task) extern asmlinkage void ret_from_fork(void); /* - * copy_thread + * copy_thread_tls * @clone_flags: flags * @usp: user stack pointer or fn for kernel thread * @arg: arg to fn for kernel thread; always NULL for userspace thread * @p: the newly created task * @regs: CPU context to copy for userspace thread; always NULL for kthread + * @tls: the Thread Local Storage pointer for the new process * * At the top of a newly initialized kernel stack are two stacked pt_reg * structures. The first (topmost) is the userspace context of the thread. @@ -148,8 +149,8 @@ extern asmlinkage void ret_from_fork(void); */ int -copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, struct task_struct *p) +copy_thread_tls(unsigned long clone_flags, unsigned long usp, + unsigned long arg, struct task_struct *p, unsigned long tls) { struct pt_regs *userregs; struct pt_regs *kregs; @@ -179,16 +180,10 @@ copy_thread(unsigned long clone_flags, unsigned long usp, userregs->sp = usp; /* - * For CLONE_SETTLS set "tp" (r10) to the TLS pointer passed to sys_clone. - * - * The kernel entry is: - * int clone (long flags, void *child_stack, int *parent_tid, - * int *child_tid, struct void *tls) - * - * This makes the source r7 in the kernel registers. + * For CLONE_SETTLS set "tp" (r10) to the TLS pointer. */ if (clone_flags & CLONE_SETTLS) - userregs->gpr[10] = userregs->gpr[7]; + userregs->gpr[10] = tls; userregs->gpr[11] = 0; /* Result from fork() */ From 07e83dfbe16cd882afc1d221f4ef3a85b9818f9a Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Tue, 25 Feb 2020 19:04:45 +0900 Subject: [PATCH 1044/4444] openrisc: Enable the clone3 syscall Enable the clone3 syscall for OpenRISC. We use the generic version. This was tested with the clone3 test from selftests. Note, for all tests to pass it required enabling CONFIG_NAMESPACES which is not enabled in the default OpenRISC kernel config. Signed-off-by: Stafford Horne Acked-by: Christian Brauner --- arch/openrisc/include/uapi/asm/unistd.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/openrisc/include/uapi/asm/unistd.h b/arch/openrisc/include/uapi/asm/unistd.h index 566f8c4f8047..fae34c60fa88 100644 --- a/arch/openrisc/include/uapi/asm/unistd.h +++ b/arch/openrisc/include/uapi/asm/unistd.h @@ -24,6 +24,7 @@ #define __ARCH_WANT_SET_GET_RLIMIT #define __ARCH_WANT_SYS_FORK #define __ARCH_WANT_SYS_CLONE +#define __ARCH_WANT_SYS_CLONE3 #define __ARCH_WANT_TIME32_SYSCALLS #include From d95b56c77efdafec14d767bbf9730ff55907667d Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Tue, 25 Feb 2020 19:06:12 +0900 Subject: [PATCH 1045/4444] openrisc: Cleanup copy_thread_tls docs and comments Previously copy_thread_tls was copy_thread and before that something else. Remove the documentation about the regs parameter that didn't exist in either version. Next, fix comment wrapping and details about how TLS pointer gets to the copy_thread_tls function. Signed-off-by: Stafford Horne Acked-by: Christian Brauner --- arch/openrisc/kernel/process.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index 5caa47f7de4f..6bcdca424e11 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c @@ -122,7 +122,6 @@ extern asmlinkage void ret_from_fork(void); * @usp: user stack pointer or fn for kernel thread * @arg: arg to fn for kernel thread; always NULL for userspace thread * @p: the newly created task - * @regs: CPU context to copy for userspace thread; always NULL for kthread * @tls: the Thread Local Storage pointer for the new process * * At the top of a newly initialized kernel stack are two stacked pt_reg From 8c8b07cb08107abf11842ee7c29ba77ddc6ce568 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 18 Feb 2020 16:31:25 +0200 Subject: [PATCH 1046/4444] dt-bindings: dma: ti: k3-udma: Update for atype support (virtualization) In UDMA each channel can use different ATYPE value which tells UDMA how the addresses in the descriptors should be treated: 0: pointers are physical addresses (no translation) 1: pointers are intermediate addresses (PVU) 2: pointers are virtual addresses (SMMU) When virtualized environment is used then the dma binding should use additional cell to configure the desired ATYPE for the channel. Signed-off-by: Peter Ujfalusi Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20200218143126.11361-2-peter.ujfalusi@ti.com Signed-off-by: Vinod Koul --- .../devicetree/bindings/dma/ti/k3-udma.yaml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/dma/ti/k3-udma.yaml b/Documentation/devicetree/bindings/dma/ti/k3-udma.yaml index 8b5c346f23f6..567bb820b182 100644 --- a/Documentation/devicetree/bindings/dma/ti/k3-udma.yaml +++ b/Documentation/devicetree/bindings/dma/ti/k3-udma.yaml @@ -45,7 +45,8 @@ allOf: properties: "#dma-cells": - const: 1 + minimum: 1 + maximum: 2 description: | The cell is the PSI-L thread ID of the remote (to UDMAP) end. Valid ranges for thread ID depends on the data movement direction: @@ -55,6 +56,8 @@ properties: Please refer to the device documentation for the PSI-L thread map and also the PSI-L peripheral chapter for the correct thread ID. + When #dma-cells is 2, the second parameter is the channel ATYPE. + compatible: enum: - ti,am654-navss-main-udmap @@ -131,6 +134,20 @@ required: - ti,sci-rm-range-rchan - ti,sci-rm-range-rflow +if: + properties: + "#dma-cells": + const: 2 +then: + properties: + ti,udma-atype: + description: ATYPE value which should be used by non slave channels + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + + required: + - ti,udma-atype + examples: - |+ cbass_main { From 0ebcf1a274c5467c8ed55d0e01db4b414fe4518d Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 18 Feb 2020 16:31:26 +0200 Subject: [PATCH 1047/4444] dmaengine: ti: k3-udma: Implement support for atype (for virtualization) The DT for virtualized hosts have dma-cells == 2 where the second parameter is the ATYPE for the channel. In case of dma-cells == 1 we can configure the ATYPE as 0 (reset value). The ATYPE defined for j721e are: 0: pointers are physical addresses (no translation) 1: pointers are intermediate addresses (PVU) 2: pointers are virtual addresses (SMMU) Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20200218143126.11361-3-peter.ujfalusi@ti.com Signed-off-by: Vinod Koul --- drivers/dma/ti/k3-udma-glue.c | 18 +++++++++++-- drivers/dma/ti/k3-udma.c | 50 +++++++++++++++++++++++++++++------ 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/drivers/dma/ti/k3-udma-glue.c b/drivers/dma/ti/k3-udma-glue.c index c1511298ece2..dbccdc7c0ed5 100644 --- a/drivers/dma/ti/k3-udma-glue.c +++ b/drivers/dma/ti/k3-udma-glue.c @@ -32,6 +32,7 @@ struct k3_udma_glue_common { bool epib; u32 psdata_size; u32 swdata_size; + u32 atype; }; struct k3_udma_glue_tx_channel { @@ -121,6 +122,15 @@ static int of_k3_udma_glue_parse_chn(struct device_node *chn_np, return -ENOENT; thread_id = dma_spec.args[0]; + if (dma_spec.args_count == 2) { + if (dma_spec.args[1] > 2) { + dev_err(common->dev, "Invalid channel atype: %u\n", + dma_spec.args[1]); + ret = -EINVAL; + goto out_put_spec; + } + common->atype = dma_spec.args[1]; + } if (tx_chn && !(thread_id & K3_PSIL_DST_THREAD_ID_OFFSET)) { ret = -EINVAL; @@ -202,7 +212,8 @@ static int k3_udma_glue_cfg_tx_chn(struct k3_udma_glue_tx_channel *tx_chn) TI_SCI_MSG_VALUE_RM_UDMAP_CH_CHAN_TYPE_VALID | TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_SUPR_TDPKT_VALID | TI_SCI_MSG_VALUE_RM_UDMAP_CH_FETCH_SIZE_VALID | - TI_SCI_MSG_VALUE_RM_UDMAP_CH_CQ_QNUM_VALID; + TI_SCI_MSG_VALUE_RM_UDMAP_CH_CQ_QNUM_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_CH_ATYPE_VALID; req.nav_id = tisci_rm->tisci_dev_id; req.index = tx_chn->udma_tchan_id; if (tx_chn->tx_pause_on_err) @@ -216,6 +227,7 @@ static int k3_udma_glue_cfg_tx_chn(struct k3_udma_glue_tx_channel *tx_chn) req.tx_supr_tdpkt = 1; req.tx_fetch_size = tx_chn->common.hdesc_size >> 2; req.txcq_qnum = k3_ringacc_get_ring_id(tx_chn->ringtxcq); + req.tx_atype = tx_chn->common.atype; return tisci_rm->tisci_udmap_ops->tx_ch_cfg(tisci_rm->tisci, &req); } @@ -502,7 +514,8 @@ static int k3_udma_glue_cfg_rx_chn(struct k3_udma_glue_rx_channel *rx_chn) TI_SCI_MSG_VALUE_RM_UDMAP_CH_CQ_QNUM_VALID | TI_SCI_MSG_VALUE_RM_UDMAP_CH_CHAN_TYPE_VALID | TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_START_VALID | - TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_CNT_VALID; + TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_CNT_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_CH_ATYPE_VALID; req.nav_id = tisci_rm->tisci_dev_id; req.index = rx_chn->udma_rchan_id; @@ -519,6 +532,7 @@ static int k3_udma_glue_cfg_rx_chn(struct k3_udma_glue_rx_channel *rx_chn) req.flowid_cnt = rx_chn->flow_num; } req.rx_chan_type = TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR; + req.rx_atype = rx_chn->common.atype; ret = tisci_rm->tisci_udmap_ops->rx_ch_cfg(tisci_rm->tisci, &req); if (ret) diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index ea79c2df28e0..205141494fc1 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -128,6 +128,7 @@ struct udma_dev { struct udma_chan *channels; u32 psil_base; + u32 atype; }; struct udma_hwdesc { @@ -181,6 +182,7 @@ struct udma_chan_config { u32 hdesc_size; /* Size of a packet descriptor in packet mode */ bool notdpkt; /* Suppress sending TDC packet */ int remote_thread_id; + u32 atype; u32 src_thread; u32 dst_thread; enum psil_endpoint_type ep_type; @@ -1507,7 +1509,8 @@ err_rflow: TI_SCI_MSG_VALUE_RM_UDMAP_CH_CHAN_TYPE_VALID | \ TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_SUPR_TDPKT_VALID | \ TI_SCI_MSG_VALUE_RM_UDMAP_CH_FETCH_SIZE_VALID | \ - TI_SCI_MSG_VALUE_RM_UDMAP_CH_CQ_QNUM_VALID) + TI_SCI_MSG_VALUE_RM_UDMAP_CH_CQ_QNUM_VALID | \ + TI_SCI_MSG_VALUE_RM_UDMAP_CH_ATYPE_VALID) #define TISCI_RCHAN_VALID_PARAMS ( \ TI_SCI_MSG_VALUE_RM_UDMAP_CH_PAUSE_ON_ERR_VALID | \ @@ -1517,7 +1520,8 @@ err_rflow: TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_IGNORE_SHORT_VALID | \ TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_IGNORE_LONG_VALID | \ TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_START_VALID | \ - TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_CNT_VALID) + TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_CNT_VALID | \ + TI_SCI_MSG_VALUE_RM_UDMAP_CH_ATYPE_VALID) static int udma_tisci_m2m_channel_config(struct udma_chan *uc) { @@ -1539,6 +1543,7 @@ static int udma_tisci_m2m_channel_config(struct udma_chan *uc) req_tx.tx_chan_type = TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBRR; req_tx.tx_fetch_size = sizeof(struct cppi5_desc_hdr_t) >> 2; req_tx.txcq_qnum = tc_ring; + req_tx.tx_atype = ud->atype; ret = tisci_ops->tx_ch_cfg(tisci_rm->tisci, &req_tx); if (ret) { @@ -1552,6 +1557,7 @@ static int udma_tisci_m2m_channel_config(struct udma_chan *uc) req_rx.rx_fetch_size = sizeof(struct cppi5_desc_hdr_t) >> 2; req_rx.rxcq_qnum = tc_ring; req_rx.rx_chan_type = TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBRR; + req_rx.rx_atype = ud->atype; ret = tisci_ops->rx_ch_cfg(tisci_rm->tisci, &req_rx); if (ret) @@ -1587,6 +1593,7 @@ static int udma_tisci_tx_channel_config(struct udma_chan *uc) req_tx.tx_supr_tdpkt = uc->config.notdpkt; req_tx.tx_fetch_size = fetch_size >> 2; req_tx.txcq_qnum = tc_ring; + req_tx.tx_atype = uc->config.atype; ret = tisci_ops->tx_ch_cfg(tisci_rm->tisci, &req_tx); if (ret) @@ -1623,6 +1630,7 @@ static int udma_tisci_rx_channel_config(struct udma_chan *uc) req_rx.rx_fetch_size = fetch_size >> 2; req_rx.rxcq_qnum = rx_ring; req_rx.rx_chan_type = mode; + req_rx.rx_atype = uc->config.atype; ret = tisci_ops->rx_ch_cfg(tisci_rm->tisci, &req_rx); if (ret) { @@ -2930,13 +2938,18 @@ static void udma_free_chan_resources(struct dma_chan *chan) static struct platform_driver udma_driver; +struct udma_filter_param { + int remote_thread_id; + u32 atype; +}; + static bool udma_dma_filter_fn(struct dma_chan *chan, void *param) { struct udma_chan_config *ucc; struct psil_endpoint_config *ep_config; + struct udma_filter_param *filter_param; struct udma_chan *uc; struct udma_dev *ud; - u32 *args; if (chan->device->dev->driver != &udma_driver.driver) return false; @@ -2944,9 +2957,16 @@ static bool udma_dma_filter_fn(struct dma_chan *chan, void *param) uc = to_udma_chan(chan); ucc = &uc->config; ud = uc->ud; - args = param; + filter_param = param; - ucc->remote_thread_id = args[0]; + if (filter_param->atype > 2) { + dev_err(ud->dev, "Invalid channel atype: %u\n", + filter_param->atype); + return false; + } + + ucc->remote_thread_id = filter_param->remote_thread_id; + ucc->atype = filter_param->atype; if (ucc->remote_thread_id & K3_PSIL_DST_THREAD_ID_OFFSET) ucc->dir = DMA_MEM_TO_DEV; @@ -2959,6 +2979,7 @@ static bool udma_dma_filter_fn(struct dma_chan *chan, void *param) ucc->remote_thread_id); ucc->dir = DMA_MEM_TO_MEM; ucc->remote_thread_id = -1; + ucc->atype = 0; return false; } @@ -2997,13 +3018,20 @@ static struct dma_chan *udma_of_xlate(struct of_phandle_args *dma_spec, { struct udma_dev *ud = ofdma->of_dma_data; dma_cap_mask_t mask = ud->ddev.cap_mask; + struct udma_filter_param filter_param; struct dma_chan *chan; - if (dma_spec->args_count != 1) + if (dma_spec->args_count != 1 && dma_spec->args_count != 2) return NULL; - chan = __dma_request_channel(&mask, udma_dma_filter_fn, - &dma_spec->args[0], ofdma->of_node); + filter_param.remote_thread_id = dma_spec->args[0]; + if (dma_spec->args_count == 2) + filter_param.atype = dma_spec->args[1]; + else + filter_param.atype = 0; + + chan = __dma_request_channel(&mask, udma_dma_filter_fn, &filter_param, + ofdma->of_node); if (!chan) { dev_err(ud->dev, "get channel fail in %s.\n", __func__); return ERR_PTR(-EINVAL); @@ -3294,6 +3322,12 @@ static int udma_probe(struct platform_device *pdev) return ret; } + ret = of_property_read_u32(navss_node, "ti,udma-atype", &ud->atype); + if (!ret && ud->atype > 2) { + dev_err(dev, "Invalid atype: %u\n", ud->atype); + return -EINVAL; + } + ud->tisci_rm.tisci_udmap_ops = &ud->tisci_rm.tisci->ops.rm_udmap_ops; ud->tisci_rm.tisci_psil_ops = &ud->tisci_rm.tisci->ops.rm_psil_ops; From b9fb56b6ba8abc96484f007973ca00e30b104422 Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Fri, 21 Feb 2020 16:52:29 +0900 Subject: [PATCH 1048/4444] dt-bindings: dmaengine: Add UniPhier external DMA controller bindings Add devicetree binding documentation for external DMA controller implemented on Socionext UniPhier SOCs. Signed-off-by: Kunihiko Hayashi Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/1582271550-3403-2-git-send-email-hayashi.kunihiko@socionext.com Signed-off-by: Vinod Koul --- .../dma/socionext,uniphier-xdmac.yaml | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Documentation/devicetree/bindings/dma/socionext,uniphier-xdmac.yaml diff --git a/Documentation/devicetree/bindings/dma/socionext,uniphier-xdmac.yaml b/Documentation/devicetree/bindings/dma/socionext,uniphier-xdmac.yaml new file mode 100644 index 000000000000..86cfb599256e --- /dev/null +++ b/Documentation/devicetree/bindings/dma/socionext,uniphier-xdmac.yaml @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/socionext,uniphier-xdmac.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Socionext UniPhier external DMA controller + +description: | + This describes the devicetree bindings for an external DMA engine to perform + memory-to-memory or peripheral-to-memory data transfer capable of supporting + 16 channels, implemented in Socionext UniPhier SoCs. + +maintainers: + - Kunihiko Hayashi + +allOf: + - $ref: "dma-controller.yaml#" + +properties: + compatible: + const: socionext,uniphier-xdmac + + reg: + items: + - description: XDMAC base register region (offset and length) + - description: XDMAC extension register region (offset and length) + + interrupts: + maxItems: 1 + + "#dma-cells": + const: 2 + description: | + DMA request from clients consists of 2 cells: + 1. Channel index + 2. Transfer request factor number, If no transfer factor, use 0. + The number is SoC-specific, and this should be specified with + relation to the device to use the DMA controller. + + dma-channels: + minimum: 1 + maximum: 16 + +additionalProperties: false + +required: + - compatible + - reg + - interrupts + - "#dma-cells" + +examples: + - | + xdmac: dma-controller@5fc10000 { + compatible = "socionext,uniphier-xdmac"; + reg = <0x5fc10000 0x1000>, <0x5fc20000 0x800>; + interrupts = <0 188 4>; + #dma-cells = <2>; + dma-channels = <16>; + }; + +... From 667b9251440b762ebc8cd3348a6e6ab29401bb97 Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Fri, 21 Feb 2020 16:52:30 +0900 Subject: [PATCH 1049/4444] dmaengine: uniphier-xdmac: Add UniPhier external DMA controller driver This adds external DMA controller driver implemented in Socionext UniPhier SoCs. This driver supports DMA_MEMCPY and DMA_SLAVE modes. Since this driver does not support the the way to transfer size unaligned to burst width, 'src_maxburst' or 'dst_maxburst' of dma_slave_config must be 1 to transfer arbitrary size. If transfer size is unaligned to burst size, the transfer isn't started and the driver displays an error message. Signed-off-by: Kunihiko Hayashi Link: https://lore.kernel.org/r/1582271550-3403-3-git-send-email-hayashi.kunihiko@socionext.com Signed-off-by: Vinod Koul --- drivers/dma/Kconfig | 11 + drivers/dma/Makefile | 1 + drivers/dma/uniphier-xdmac.c | 611 +++++++++++++++++++++++++++++++++++ 3 files changed, 623 insertions(+) create mode 100644 drivers/dma/uniphier-xdmac.c diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 7fc725d928b2..092483644315 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -658,6 +658,17 @@ config UNIPHIER_MDMAC UniPhier platform. This DMA controller is used as the external DMA engine of the SD/eMMC controllers of the LD4, Pro4, sLD8 SoCs. +config UNIPHIER_XDMAC + tristate "UniPhier XDMAC support" + depends on ARCH_UNIPHIER || COMPILE_TEST + depends on OF + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + help + Enable support for the XDMAC (external DMA controller) on the + UniPhier platform. This DMA controller can transfer data from + memory to memory, memory to peripheral and peripheral to memory. + config XGENE_DMA tristate "APM X-Gene DMA support" depends on ARCH_XGENE || COMPILE_TEST diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 1d908394fbea..e60f81331d4c 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -78,6 +78,7 @@ obj-$(CONFIG_TEGRA20_APB_DMA) += tegra20-apb-dma.o obj-$(CONFIG_TEGRA210_ADMA) += tegra210-adma.o obj-$(CONFIG_TIMB_DMA) += timb_dma.o obj-$(CONFIG_UNIPHIER_MDMAC) += uniphier-mdmac.o +obj-$(CONFIG_UNIPHIER_XDMAC) += uniphier-xdmac.o obj-$(CONFIG_XGENE_DMA) += xgene-dma.o obj-$(CONFIG_ZX_DMA) += zx_dma.o obj-$(CONFIG_ST_FDMA) += st_fdma.o diff --git a/drivers/dma/uniphier-xdmac.c b/drivers/dma/uniphier-xdmac.c new file mode 100644 index 000000000000..2f6fd518d180 --- /dev/null +++ b/drivers/dma/uniphier-xdmac.c @@ -0,0 +1,611 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * External DMA controller driver for UniPhier SoCs + * Copyright 2019 Socionext Inc. + * Author: Kunihiko Hayashi + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "dmaengine.h" +#include "virt-dma.h" + +#define XDMAC_CH_WIDTH 0x100 + +#define XDMAC_TFA 0x08 +#define XDMAC_TFA_MCNT_MASK GENMASK(23, 16) +#define XDMAC_TFA_MASK GENMASK(5, 0) +#define XDMAC_SADM 0x10 +#define XDMAC_SADM_STW_MASK GENMASK(25, 24) +#define XDMAC_SADM_SAM BIT(4) +#define XDMAC_SADM_SAM_FIXED XDMAC_SADM_SAM +#define XDMAC_SADM_SAM_INC 0 +#define XDMAC_DADM 0x14 +#define XDMAC_DADM_DTW_MASK XDMAC_SADM_STW_MASK +#define XDMAC_DADM_DAM XDMAC_SADM_SAM +#define XDMAC_DADM_DAM_FIXED XDMAC_SADM_SAM_FIXED +#define XDMAC_DADM_DAM_INC XDMAC_SADM_SAM_INC +#define XDMAC_EXSAD 0x18 +#define XDMAC_EXDAD 0x1c +#define XDMAC_SAD 0x20 +#define XDMAC_DAD 0x24 +#define XDMAC_ITS 0x28 +#define XDMAC_ITS_MASK GENMASK(25, 0) +#define XDMAC_TNUM 0x2c +#define XDMAC_TNUM_MASK GENMASK(15, 0) +#define XDMAC_TSS 0x30 +#define XDMAC_TSS_REQ BIT(0) +#define XDMAC_IEN 0x34 +#define XDMAC_IEN_ERRIEN BIT(1) +#define XDMAC_IEN_ENDIEN BIT(0) +#define XDMAC_STAT 0x40 +#define XDMAC_STAT_TENF BIT(0) +#define XDMAC_IR 0x44 +#define XDMAC_IR_ERRF BIT(1) +#define XDMAC_IR_ENDF BIT(0) +#define XDMAC_ID 0x48 +#define XDMAC_ID_ERRIDF BIT(1) +#define XDMAC_ID_ENDIDF BIT(0) + +#define XDMAC_MAX_CHANS 16 +#define XDMAC_INTERVAL_CLKS 20 +#define XDMAC_MAX_WORDS XDMAC_TNUM_MASK + +/* cut lower bit for maintain alignment of maximum transfer size */ +#define XDMAC_MAX_WORD_SIZE (XDMAC_ITS_MASK & ~GENMASK(3, 0)) + +#define UNIPHIER_XDMAC_BUSWIDTHS \ + (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \ + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \ + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \ + BIT(DMA_SLAVE_BUSWIDTH_8_BYTES)) + +struct uniphier_xdmac_desc_node { + dma_addr_t src; + dma_addr_t dst; + u32 burst_size; + u32 nr_burst; +}; + +struct uniphier_xdmac_desc { + struct virt_dma_desc vd; + + unsigned int nr_node; + unsigned int cur_node; + enum dma_transfer_direction dir; + struct uniphier_xdmac_desc_node nodes[]; +}; + +struct uniphier_xdmac_chan { + struct virt_dma_chan vc; + struct uniphier_xdmac_device *xdev; + struct uniphier_xdmac_desc *xd; + void __iomem *reg_ch_base; + struct dma_slave_config sconfig; + int id; + unsigned int req_factor; +}; + +struct uniphier_xdmac_device { + struct dma_device ddev; + void __iomem *reg_base; + int nr_chans; + struct uniphier_xdmac_chan channels[]; +}; + +static struct uniphier_xdmac_chan * +to_uniphier_xdmac_chan(struct virt_dma_chan *vc) +{ + return container_of(vc, struct uniphier_xdmac_chan, vc); +} + +static struct uniphier_xdmac_desc * +to_uniphier_xdmac_desc(struct virt_dma_desc *vd) +{ + return container_of(vd, struct uniphier_xdmac_desc, vd); +} + +/* xc->vc.lock must be held by caller */ +static struct uniphier_xdmac_desc * +uniphier_xdmac_next_desc(struct uniphier_xdmac_chan *xc) +{ + struct virt_dma_desc *vd; + + vd = vchan_next_desc(&xc->vc); + if (!vd) + return NULL; + + list_del(&vd->node); + + return to_uniphier_xdmac_desc(vd); +} + +/* xc->vc.lock must be held by caller */ +static void uniphier_xdmac_chan_start(struct uniphier_xdmac_chan *xc, + struct uniphier_xdmac_desc *xd) +{ + u32 src_mode, src_addr, src_width; + u32 dst_mode, dst_addr, dst_width; + u32 val, its, tnum; + enum dma_slave_buswidth buswidth; + + src_addr = xd->nodes[xd->cur_node].src; + dst_addr = xd->nodes[xd->cur_node].dst; + its = xd->nodes[xd->cur_node].burst_size; + tnum = xd->nodes[xd->cur_node].nr_burst; + + /* + * The width of MEM side must be 4 or 8 bytes, that does not + * affect that of DEV side and transfer size. + */ + if (xd->dir == DMA_DEV_TO_MEM) { + src_mode = XDMAC_SADM_SAM_FIXED; + buswidth = xc->sconfig.src_addr_width; + } else { + src_mode = XDMAC_SADM_SAM_INC; + buswidth = DMA_SLAVE_BUSWIDTH_8_BYTES; + } + src_width = FIELD_PREP(XDMAC_SADM_STW_MASK, __ffs(buswidth)); + + if (xd->dir == DMA_MEM_TO_DEV) { + dst_mode = XDMAC_DADM_DAM_FIXED; + buswidth = xc->sconfig.dst_addr_width; + } else { + dst_mode = XDMAC_DADM_DAM_INC; + buswidth = DMA_SLAVE_BUSWIDTH_8_BYTES; + } + dst_width = FIELD_PREP(XDMAC_DADM_DTW_MASK, __ffs(buswidth)); + + /* setup transfer factor */ + val = FIELD_PREP(XDMAC_TFA_MCNT_MASK, XDMAC_INTERVAL_CLKS); + val |= FIELD_PREP(XDMAC_TFA_MASK, xc->req_factor); + writel(val, xc->reg_ch_base + XDMAC_TFA); + + /* setup the channel */ + writel(lower_32_bits(src_addr), xc->reg_ch_base + XDMAC_SAD); + writel(upper_32_bits(src_addr), xc->reg_ch_base + XDMAC_EXSAD); + + writel(lower_32_bits(dst_addr), xc->reg_ch_base + XDMAC_DAD); + writel(upper_32_bits(dst_addr), xc->reg_ch_base + XDMAC_EXDAD); + + src_mode |= src_width; + dst_mode |= dst_width; + writel(src_mode, xc->reg_ch_base + XDMAC_SADM); + writel(dst_mode, xc->reg_ch_base + XDMAC_DADM); + + writel(its, xc->reg_ch_base + XDMAC_ITS); + writel(tnum, xc->reg_ch_base + XDMAC_TNUM); + + /* enable interrupt */ + writel(XDMAC_IEN_ENDIEN | XDMAC_IEN_ERRIEN, + xc->reg_ch_base + XDMAC_IEN); + + /* start XDMAC */ + val = readl(xc->reg_ch_base + XDMAC_TSS); + val |= XDMAC_TSS_REQ; + writel(val, xc->reg_ch_base + XDMAC_TSS); +} + +/* xc->vc.lock must be held by caller */ +static int uniphier_xdmac_chan_stop(struct uniphier_xdmac_chan *xc) +{ + u32 val; + + /* disable interrupt */ + val = readl(xc->reg_ch_base + XDMAC_IEN); + val &= ~(XDMAC_IEN_ENDIEN | XDMAC_IEN_ERRIEN); + writel(val, xc->reg_ch_base + XDMAC_IEN); + + /* stop XDMAC */ + val = readl(xc->reg_ch_base + XDMAC_TSS); + val &= ~XDMAC_TSS_REQ; + writel(0, xc->reg_ch_base + XDMAC_TSS); + + /* wait until transfer is stopped */ + return readl_poll_timeout(xc->reg_ch_base + XDMAC_STAT, val, + !(val & XDMAC_STAT_TENF), 100, 1000); +} + +/* xc->vc.lock must be held by caller */ +static void uniphier_xdmac_start(struct uniphier_xdmac_chan *xc) +{ + struct uniphier_xdmac_desc *xd; + + xd = uniphier_xdmac_next_desc(xc); + if (xd) + uniphier_xdmac_chan_start(xc, xd); + + /* set desc to chan regardless of xd is null */ + xc->xd = xd; +} + +static void uniphier_xdmac_chan_irq(struct uniphier_xdmac_chan *xc) +{ + u32 stat; + int ret; + + spin_lock(&xc->vc.lock); + + stat = readl(xc->reg_ch_base + XDMAC_ID); + + if (stat & XDMAC_ID_ERRIDF) { + ret = uniphier_xdmac_chan_stop(xc); + if (ret) + dev_err(xc->xdev->ddev.dev, + "DMA transfer error with aborting issue\n"); + else + dev_err(xc->xdev->ddev.dev, + "DMA transfer error\n"); + + } else if ((stat & XDMAC_ID_ENDIDF) && xc->xd) { + xc->xd->cur_node++; + if (xc->xd->cur_node >= xc->xd->nr_node) { + vchan_cookie_complete(&xc->xd->vd); + uniphier_xdmac_start(xc); + } else { + uniphier_xdmac_chan_start(xc, xc->xd); + } + } + + /* write bits to clear */ + writel(stat, xc->reg_ch_base + XDMAC_IR); + + spin_unlock(&xc->vc.lock); +} + +static irqreturn_t uniphier_xdmac_irq_handler(int irq, void *dev_id) +{ + struct uniphier_xdmac_device *xdev = dev_id; + int i; + + for (i = 0; i < xdev->nr_chans; i++) + uniphier_xdmac_chan_irq(&xdev->channels[i]); + + return IRQ_HANDLED; +} + +static void uniphier_xdmac_free_chan_resources(struct dma_chan *chan) +{ + vchan_free_chan_resources(to_virt_chan(chan)); +} + +static struct dma_async_tx_descriptor * +uniphier_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst, + dma_addr_t src, size_t len, unsigned long flags) +{ + struct virt_dma_chan *vc = to_virt_chan(chan); + struct uniphier_xdmac_desc *xd; + unsigned int nr; + size_t burst_size, tlen; + int i; + + if (len > XDMAC_MAX_WORD_SIZE * XDMAC_MAX_WORDS) + return NULL; + + nr = 1 + len / XDMAC_MAX_WORD_SIZE; + + xd = kzalloc(struct_size(xd, nodes, nr), GFP_NOWAIT); + if (!xd) + return NULL; + + for (i = 0; i < nr; i++) { + burst_size = min_t(size_t, len, XDMAC_MAX_WORD_SIZE); + xd->nodes[i].src = src; + xd->nodes[i].dst = dst; + xd->nodes[i].burst_size = burst_size; + xd->nodes[i].nr_burst = len / burst_size; + tlen = rounddown(len, burst_size); + src += tlen; + dst += tlen; + len -= tlen; + } + + xd->dir = DMA_MEM_TO_MEM; + xd->nr_node = nr; + xd->cur_node = 0; + + return vchan_tx_prep(vc, &xd->vd, flags); +} + +static struct dma_async_tx_descriptor * +uniphier_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sg_len, + enum dma_transfer_direction direction, + unsigned long flags, void *context) +{ + struct virt_dma_chan *vc = to_virt_chan(chan); + struct uniphier_xdmac_chan *xc = to_uniphier_xdmac_chan(vc); + struct uniphier_xdmac_desc *xd; + struct scatterlist *sg; + enum dma_slave_buswidth buswidth; + u32 maxburst; + int i; + + if (!is_slave_direction(direction)) + return NULL; + + if (direction == DMA_DEV_TO_MEM) { + buswidth = xc->sconfig.src_addr_width; + maxburst = xc->sconfig.src_maxburst; + } else { + buswidth = xc->sconfig.dst_addr_width; + maxburst = xc->sconfig.dst_maxburst; + } + + if (!maxburst) + maxburst = 1; + if (maxburst > xc->xdev->ddev.max_burst) { + dev_err(xc->xdev->ddev.dev, + "Exceed maximum number of burst words\n"); + return NULL; + } + + xd = kzalloc(struct_size(xd, nodes, sg_len), GFP_NOWAIT); + if (!xd) + return NULL; + + for_each_sg(sgl, sg, sg_len, i) { + xd->nodes[i].src = (direction == DMA_DEV_TO_MEM) + ? xc->sconfig.src_addr : sg_dma_address(sg); + xd->nodes[i].dst = (direction == DMA_MEM_TO_DEV) + ? xc->sconfig.dst_addr : sg_dma_address(sg); + xd->nodes[i].burst_size = maxburst * buswidth; + xd->nodes[i].nr_burst = + sg_dma_len(sg) / xd->nodes[i].burst_size; + + /* + * Currently transfer that size doesn't align the unit size + * (the number of burst words * bus-width) is not allowed, + * because the driver does not support the way to transfer + * residue size. As a matter of fact, in order to transfer + * arbitrary size, 'src_maxburst' or 'dst_maxburst' of + * dma_slave_config must be 1. + */ + if (sg_dma_len(sg) % xd->nodes[i].burst_size) { + dev_err(xc->xdev->ddev.dev, + "Unaligned transfer size: %d", sg_dma_len(sg)); + kfree(xd); + return NULL; + } + + if (xd->nodes[i].nr_burst > XDMAC_MAX_WORDS) { + dev_err(xc->xdev->ddev.dev, + "Exceed maximum transfer size"); + kfree(xd); + return NULL; + } + } + + xd->dir = direction; + xd->nr_node = sg_len; + xd->cur_node = 0; + + return vchan_tx_prep(vc, &xd->vd, flags); +} + +static int uniphier_xdmac_slave_config(struct dma_chan *chan, + struct dma_slave_config *config) +{ + struct virt_dma_chan *vc = to_virt_chan(chan); + struct uniphier_xdmac_chan *xc = to_uniphier_xdmac_chan(vc); + + memcpy(&xc->sconfig, config, sizeof(*config)); + + return 0; +} + +static int uniphier_xdmac_terminate_all(struct dma_chan *chan) +{ + struct virt_dma_chan *vc = to_virt_chan(chan); + struct uniphier_xdmac_chan *xc = to_uniphier_xdmac_chan(vc); + unsigned long flags; + int ret = 0; + LIST_HEAD(head); + + spin_lock_irqsave(&vc->lock, flags); + + if (xc->xd) { + vchan_terminate_vdesc(&xc->xd->vd); + xc->xd = NULL; + ret = uniphier_xdmac_chan_stop(xc); + } + + vchan_get_all_descriptors(vc, &head); + + spin_unlock_irqrestore(&vc->lock, flags); + + vchan_dma_desc_free_list(vc, &head); + + return ret; +} + +static void uniphier_xdmac_synchronize(struct dma_chan *chan) +{ + vchan_synchronize(to_virt_chan(chan)); +} + +static void uniphier_xdmac_issue_pending(struct dma_chan *chan) +{ + struct virt_dma_chan *vc = to_virt_chan(chan); + struct uniphier_xdmac_chan *xc = to_uniphier_xdmac_chan(vc); + unsigned long flags; + + spin_lock_irqsave(&vc->lock, flags); + + if (vchan_issue_pending(vc) && !xc->xd) + uniphier_xdmac_start(xc); + + spin_unlock_irqrestore(&vc->lock, flags); +} + +static void uniphier_xdmac_desc_free(struct virt_dma_desc *vd) +{ + kfree(to_uniphier_xdmac_desc(vd)); +} + +static void uniphier_xdmac_chan_init(struct uniphier_xdmac_device *xdev, + int ch) +{ + struct uniphier_xdmac_chan *xc = &xdev->channels[ch]; + + xc->xdev = xdev; + xc->reg_ch_base = xdev->reg_base + XDMAC_CH_WIDTH * ch; + xc->vc.desc_free = uniphier_xdmac_desc_free; + + vchan_init(&xc->vc, &xdev->ddev); +} + +static struct dma_chan *of_dma_uniphier_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) +{ + struct uniphier_xdmac_device *xdev = ofdma->of_dma_data; + int chan_id = dma_spec->args[0]; + + if (chan_id >= xdev->nr_chans) + return NULL; + + xdev->channels[chan_id].id = chan_id; + xdev->channels[chan_id].req_factor = dma_spec->args[1]; + + return dma_get_slave_channel(&xdev->channels[chan_id].vc.chan); +} + +static int uniphier_xdmac_probe(struct platform_device *pdev) +{ + struct uniphier_xdmac_device *xdev; + struct device *dev = &pdev->dev; + struct dma_device *ddev; + int irq; + int nr_chans; + int i, ret; + + if (of_property_read_u32(dev->of_node, "dma-channels", &nr_chans)) + return -EINVAL; + if (nr_chans > XDMAC_MAX_CHANS) + nr_chans = XDMAC_MAX_CHANS; + + xdev = devm_kzalloc(dev, struct_size(xdev, channels, nr_chans), + GFP_KERNEL); + if (!xdev) + return -ENOMEM; + + xdev->nr_chans = nr_chans; + xdev->reg_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(xdev->reg_base)) + return PTR_ERR(xdev->reg_base); + + ddev = &xdev->ddev; + ddev->dev = dev; + dma_cap_zero(ddev->cap_mask); + dma_cap_set(DMA_MEMCPY, ddev->cap_mask); + dma_cap_set(DMA_SLAVE, ddev->cap_mask); + ddev->src_addr_widths = UNIPHIER_XDMAC_BUSWIDTHS; + ddev->dst_addr_widths = UNIPHIER_XDMAC_BUSWIDTHS; + ddev->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV) | + BIT(DMA_MEM_TO_MEM); + ddev->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; + ddev->max_burst = XDMAC_MAX_WORDS; + ddev->device_free_chan_resources = uniphier_xdmac_free_chan_resources; + ddev->device_prep_dma_memcpy = uniphier_xdmac_prep_dma_memcpy; + ddev->device_prep_slave_sg = uniphier_xdmac_prep_slave_sg; + ddev->device_config = uniphier_xdmac_slave_config; + ddev->device_terminate_all = uniphier_xdmac_terminate_all; + ddev->device_synchronize = uniphier_xdmac_synchronize; + ddev->device_tx_status = dma_cookie_status; + ddev->device_issue_pending = uniphier_xdmac_issue_pending; + INIT_LIST_HEAD(&ddev->channels); + + for (i = 0; i < nr_chans; i++) + uniphier_xdmac_chan_init(xdev, i); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(dev, "Failed to get IRQ\n"); + return irq; + } + + ret = devm_request_irq(dev, irq, uniphier_xdmac_irq_handler, + IRQF_SHARED, "xdmac", xdev); + if (ret) { + dev_err(dev, "Failed to request IRQ\n"); + return ret; + } + + ret = dma_async_device_register(ddev); + if (ret) { + dev_err(dev, "Failed to register XDMA device\n"); + return ret; + } + + ret = of_dma_controller_register(dev->of_node, + of_dma_uniphier_xlate, xdev); + if (ret) { + dev_err(dev, "Failed to register XDMA controller\n"); + goto out_unregister_dmac; + } + + platform_set_drvdata(pdev, xdev); + + dev_info(&pdev->dev, "UniPhier XDMAC driver (%d channels)\n", + nr_chans); + + return 0; + +out_unregister_dmac: + dma_async_device_unregister(ddev); + + return ret; +} + +static int uniphier_xdmac_remove(struct platform_device *pdev) +{ + struct uniphier_xdmac_device *xdev = platform_get_drvdata(pdev); + struct dma_device *ddev = &xdev->ddev; + struct dma_chan *chan; + int ret; + + /* + * Before reaching here, almost all descriptors have been freed by the + * ->device_free_chan_resources() hook. However, each channel might + * be still holding one descriptor that was on-flight at that moment. + * Terminate it to make sure this hardware is no longer running. Then, + * free the channel resources once again to avoid memory leak. + */ + list_for_each_entry(chan, &ddev->channels, device_node) { + ret = dmaengine_terminate_sync(chan); + if (ret) + return ret; + uniphier_xdmac_free_chan_resources(chan); + } + + of_dma_controller_free(pdev->dev.of_node); + dma_async_device_unregister(ddev); + + return 0; +} + +static const struct of_device_id uniphier_xdmac_match[] = { + { .compatible = "socionext,uniphier-xdmac" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, uniphier_xdmac_match); + +static struct platform_driver uniphier_xdmac_driver = { + .probe = uniphier_xdmac_probe, + .remove = uniphier_xdmac_remove, + .driver = { + .name = "uniphier-xdmac", + .of_match_table = uniphier_xdmac_match, + }, +}; +module_platform_driver(uniphier_xdmac_driver); + +MODULE_AUTHOR("Kunihiko Hayashi "); +MODULE_DESCRIPTION("UniPhier external DMA controller driver"); +MODULE_LICENSE("GPL v2"); From 3e0ca3c38dc2ff5424eefa01a3a91cc9c0f65f5a Mon Sep 17 00:00:00 2001 From: Peng Ma Date: Thu, 27 Feb 2020 12:28:41 +0800 Subject: [PATCH 1050/4444] dmaengine: fsl-dpaa2-qdma: Adding shutdown hook We need to ensure DMA engine could be stopped in order for kexec to start the next kernel. So add the shutdown operation support. Signed-off-by: Peng Ma Link: https://lore.kernel.org/r/20200227042841.18358-1-peng.ma@nxp.com Signed-off-by: Vinod Koul --- drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c | 17 +++++++++++++++++ drivers/dma/fsl-dpaa2-qdma/dpdmai.c | 21 +++++++++++++++++++++ drivers/dma/fsl-dpaa2-qdma/dpdmai.h | 2 ++ 3 files changed, 40 insertions(+) diff --git a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c index c70a7965f140..fabbbb90b2c7 100644 --- a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c +++ b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c @@ -790,6 +790,22 @@ static int dpaa2_qdma_remove(struct fsl_mc_device *ls_dev) return 0; } +static void dpaa2_qdma_shutdown(struct fsl_mc_device *ls_dev) +{ + struct dpaa2_qdma_engine *dpaa2_qdma; + struct dpaa2_qdma_priv *priv; + struct device *dev; + + dev = &ls_dev->dev; + priv = dev_get_drvdata(dev); + dpaa2_qdma = priv->dpaa2_qdma; + + dpdmai_disable(priv->mc_io, 0, ls_dev->mc_handle); + dpaa2_dpdmai_dpio_unbind(priv); + dpdmai_close(priv->mc_io, 0, ls_dev->mc_handle); + dpdmai_destroy(priv->mc_io, 0, ls_dev->mc_handle); +} + static const struct fsl_mc_device_id dpaa2_qdma_id_table[] = { { .vendor = FSL_MC_VENDOR_FREESCALE, @@ -805,6 +821,7 @@ static struct fsl_mc_driver dpaa2_qdma_driver = { }, .probe = dpaa2_qdma_probe, .remove = dpaa2_qdma_remove, + .shutdown = dpaa2_qdma_shutdown, .match_id_table = dpaa2_qdma_id_table }; diff --git a/drivers/dma/fsl-dpaa2-qdma/dpdmai.c b/drivers/dma/fsl-dpaa2-qdma/dpdmai.c index f8d22115154a..878662aaa1c2 100644 --- a/drivers/dma/fsl-dpaa2-qdma/dpdmai.c +++ b/drivers/dma/fsl-dpaa2-qdma/dpdmai.c @@ -159,6 +159,27 @@ int dpdmai_create(struct fsl_mc_io *mc_io, u32 cmd_flags, return 0; } +/** + * dpdmai_destroy() - Destroy the DPDMAI object and release all its resources. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPDMAI object + * + * Return: '0' on Success; error code otherwise. + */ +int dpdmai_destroy(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) +{ + struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_DESTROY, + cmd_flags, token); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} +EXPORT_SYMBOL_GPL(dpdmai_destroy); + /** * dpdmai_enable() - Enable the DPDMAI, allow sending and receiving frames. * @mc_io: Pointer to MC portal's I/O object diff --git a/drivers/dma/fsl-dpaa2-qdma/dpdmai.h b/drivers/dma/fsl-dpaa2-qdma/dpdmai.h index 6d785093da8e..b13b9bf0c003 100644 --- a/drivers/dma/fsl-dpaa2-qdma/dpdmai.h +++ b/drivers/dma/fsl-dpaa2-qdma/dpdmai.h @@ -18,6 +18,7 @@ #define DPDMAI_CMDID_CLOSE DPDMAI_CMDID_FORMAT(0x800) #define DPDMAI_CMDID_OPEN DPDMAI_CMDID_FORMAT(0x80E) #define DPDMAI_CMDID_CREATE DPDMAI_CMDID_FORMAT(0x90E) +#define DPDMAI_CMDID_DESTROY DPDMAI_CMDID_FORMAT(0x900) #define DPDMAI_CMDID_ENABLE DPDMAI_CMDID_FORMAT(0x002) #define DPDMAI_CMDID_DISABLE DPDMAI_CMDID_FORMAT(0x003) @@ -160,6 +161,7 @@ struct dpdmai_rx_queue_attr { int dpdmai_open(struct fsl_mc_io *mc_io, u32 cmd_flags, int dpdmai_id, u16 *token); int dpdmai_close(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token); +int dpdmai_destroy(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token); int dpdmai_create(struct fsl_mc_io *mc_io, u32 cmd_flags, const struct dpdmai_cfg *cfg, u16 *token); int dpdmai_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token); From f775ac78fcfc6bdc96bdda07029d11f2a5e84869 Mon Sep 17 00:00:00 2001 From: Pi-Hsun Shih Date: Fri, 14 Feb 2020 16:26:38 +0800 Subject: [PATCH 1051/4444] platform/chrome: cros_ec_rpmsg: Fix race with host event Host event can be sent by remoteproc by any time, and cros_ec_rpmsg_callback would be called after cros_ec_rpmsg_create_ept. But the cros_ec_device is initialized after that, which cause host event handler to use cros_ec_device that are not initialized properly yet. Fix this by don't schedule host event handler before cros_ec_register returns. Instead, remember that we have a pending host event, and schedule host event handler after cros_ec_register. Fixes: 71cddb7097e2 ("platform/chrome: cros_ec_rpmsg: Fix race with host command when probe failed.") Signed-off-by: Pi-Hsun Shih Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_rpmsg.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/platform/chrome/cros_ec_rpmsg.c b/drivers/platform/chrome/cros_ec_rpmsg.c index dbc3f5523b83..7e8629e3db74 100644 --- a/drivers/platform/chrome/cros_ec_rpmsg.c +++ b/drivers/platform/chrome/cros_ec_rpmsg.c @@ -44,6 +44,8 @@ struct cros_ec_rpmsg { struct completion xfer_ack; struct work_struct host_event_work; struct rpmsg_endpoint *ept; + bool has_pending_host_event; + bool probe_done; }; /** @@ -177,7 +179,14 @@ static int cros_ec_rpmsg_callback(struct rpmsg_device *rpdev, void *data, memcpy(ec_dev->din, resp->data, len); complete(&ec_rpmsg->xfer_ack); } else if (resp->type == HOST_EVENT_MARK) { - schedule_work(&ec_rpmsg->host_event_work); + /* + * If the host event is sent before cros_ec_register is + * finished, queue the host event. + */ + if (ec_rpmsg->probe_done) + schedule_work(&ec_rpmsg->host_event_work); + else + ec_rpmsg->has_pending_host_event = true; } else { dev_warn(ec_dev->dev, "rpmsg received invalid type = %d", resp->type); @@ -240,6 +249,11 @@ static int cros_ec_rpmsg_probe(struct rpmsg_device *rpdev) return ret; } + ec_rpmsg->probe_done = true; + + if (ec_rpmsg->has_pending_host_event) + schedule_work(&ec_rpmsg->host_event_work); + return 0; } From 7d3ca507fda9b60544bb86b9ef89cadc14755d70 Mon Sep 17 00:00:00 2001 From: Sergiu Cuciurean Date: Thu, 27 Feb 2020 16:09:17 +0200 Subject: [PATCH 1052/4444] platform/chrome: cros_ec_spi: Use new structure for SPI transfer delays In a recent change to the SPI subsystem [1], a new `delay` struct was added to replace the `delay_usecs`. This change replaces the current `delay_usecs` with `delay` for this driver. The `spi_transfer_delay_exec()` function [in the SPI framework] makes sure that both `delay_usecs` & `delay` are used (in this order to preserve backwards compatibility). [1] commit bebcfd272df6 ("spi: introduce `delay` field for `spi_transfer` + spi_transfer_delay_exec()") Signed-off-by: Sergiu Cuciurean Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_spi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_spi.c b/drivers/platform/chrome/cros_ec_spi.c index 46786d2d679a..665ab154bb4f 100644 --- a/drivers/platform/chrome/cros_ec_spi.c +++ b/drivers/platform/chrome/cros_ec_spi.c @@ -127,7 +127,8 @@ static int terminate_request(struct cros_ec_device *ec_dev) */ spi_message_init(&msg); memset(&trans, 0, sizeof(trans)); - trans.delay_usecs = ec_spi->end_of_msg_delay; + trans.delay.value = ec_spi->end_of_msg_delay; + trans.delay.unit = SPI_DELAY_UNIT_NSECS; spi_message_add_tail(&trans, &msg); ret = spi_sync_locked(ec_spi->spi, &msg); @@ -416,7 +417,8 @@ static int do_cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev, spi_message_init(&msg); if (ec_spi->start_of_msg_delay) { memset(&trans_delay, 0, sizeof(trans_delay)); - trans_delay.delay_usecs = ec_spi->start_of_msg_delay; + trans_delay.delay.value = ec_spi->start_of_msg_delay; + trans_delay.delay.unit = SPI_DELAY_UNIT_USECS; spi_message_add_tail(&trans_delay, &msg); } From c5cd2b47b203f63682778c2a1783198e6b644294 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 20 Feb 2020 16:58:52 +0100 Subject: [PATCH 1053/4444] platform/chrome: cros_ec_proto: Report command not supported In practice most drivers that use the EC protocol what really care is if the result was successful or not, hence, we introduced a cros_ec_cmd_xfer_status() function that converts EC errors to standard Linux error codes. On some few cases, though, we are interested on know if the command is supported or not, and in such cases, just ignore the error. To achieve this, return a -ENOTSUPP error when the command is not supported. This will allow us to finish the conversion of all users to use the cros_ec_cmd_xfer_status() function instead of cros_ec_cmd_xfer() and make the latest private to the protocol driver, so users of the protocol are not confused in which function they should use. Signed-off-by: Enric Balletbo i Serra Tested-by: Prashant Malani --- drivers/platform/chrome/cros_ec_proto.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index 3cfa643f1d07..3e745e0fe092 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -553,7 +553,10 @@ EXPORT_SYMBOL(cros_ec_cmd_xfer); * replied with success status. It's not necessary to check msg->result when * using this function. * - * Return: The number of bytes transferred on success or negative error code. + * Return: + * >=0 - The number of bytes transferred + * -ENOTSUPP - Operation not supported + * -EPROTO - Protocol error */ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev, struct cros_ec_command *msg) @@ -563,6 +566,10 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev, ret = cros_ec_cmd_xfer(ec_dev, msg); if (ret < 0) { dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret); + } else if (msg->result == EC_RES_INVALID_VERSION) { + dev_dbg(ec_dev->dev, "Command invalid version (err:%d)\n", + msg->result); + return -ENOTSUPP; } else if (msg->result != EC_RES_SUCCESS) { dev_dbg(ec_dev->dev, "Command result (err: %d)\n", msg->result); return -EPROTO; From 6bc15ad784ed9607ecf06e4fa3451383d2778d47 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 20 Feb 2020 16:58:54 +0100 Subject: [PATCH 1054/4444] platform/chrome: cros_ec_vbc: Use cros_ec_cmd_xfer_status helper This patch makes use of cros_ec_cmd_xfer_status() instead of cros_ec_cmd_xfer(). In this case the change is trivial and the only reason to do it is because we want to make cros_ec_cmd_xfer() a private function for the EC protocol and let people only use the cros_ec_cmd_xfer_status() to return Linux standard error codes. Signed-off-by: Enric Balletbo i Serra Tested-by: Prashant Malani --- drivers/platform/chrome/cros_ec_vbc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_vbc.c b/drivers/platform/chrome/cros_ec_vbc.c index 8edae465105c..46482d12cffe 100644 --- a/drivers/platform/chrome/cros_ec_vbc.c +++ b/drivers/platform/chrome/cros_ec_vbc.c @@ -40,7 +40,7 @@ static ssize_t vboot_context_read(struct file *filp, struct kobject *kobj, msg->outsize = para_sz; msg->insize = resp_sz; - err = cros_ec_cmd_xfer(ecdev, msg); + err = cros_ec_cmd_xfer_status(ecdev, msg); if (err < 0) { dev_err(dev, "Error sending read request: %d\n", err); kfree(msg); @@ -83,7 +83,7 @@ static ssize_t vboot_context_write(struct file *filp, struct kobject *kobj, msg->outsize = para_sz; msg->insize = 0; - err = cros_ec_cmd_xfer(ecdev, msg); + err = cros_ec_cmd_xfer_status(ecdev, msg); if (err < 0) { dev_err(dev, "Error sending write request: %d\n", err); kfree(msg); From 413dda8f2c6f1ba90e93ba7b4214b1d8cf8ec171 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 20 Feb 2020 16:58:55 +0100 Subject: [PATCH 1055/4444] platform/chrome: cros_ec_chardev: Use cros_ec_cmd_xfer_status helper This patch makes use of cros_ec_cmd_xfer_status() instead of cros_ec_cmd_xfer(). In this case the change is trivial and the only reason to do it is because we want to make cros_ec_cmd_xfer() a private function for the EC protocol and let people only use the cros_ec_cmd_xfer_status() to return Linux standard error codes. Signed-off-by: Enric Balletbo i Serra Tested-by: Prashant Malani --- drivers/platform/chrome/cros_ec_chardev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/chrome/cros_ec_chardev.c b/drivers/platform/chrome/cros_ec_chardev.c index c65e70bc168d..b51ab24055f3 100644 --- a/drivers/platform/chrome/cros_ec_chardev.c +++ b/drivers/platform/chrome/cros_ec_chardev.c @@ -301,7 +301,7 @@ static long cros_ec_chardev_ioctl_xcmd(struct cros_ec_dev *ec, void __user *arg) } s_cmd->command += ec->cmd_offset; - ret = cros_ec_cmd_xfer(ec->ec_dev, s_cmd); + ret = cros_ec_cmd_xfer_status(ec->ec_dev, s_cmd); /* Only copy data to userland if data was received. */ if (ret < 0) goto exit; From 72540a57165392b8d4eea6c076886d3128849604 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 20 Feb 2020 16:58:56 +0100 Subject: [PATCH 1056/4444] platform/chrome: cros_ec_sysfs: Use cros_ec_cmd_xfer_status helper This patch makes use of cros_ec_cmd_xfer_status() instead of cros_ec_cmd_xfer(). In this case the change is trivial and the only reason to do it is because we want to make cros_ec_cmd_xfer() a private function for the EC protocol and let people only use the cros_ec_cmd_xfer_status() to return Linux standard error codes. Looking at the code I am even unsure that makes sense differentiate these two errors but let's not change the behaviour for now. Signed-off-by: Enric Balletbo i Serra Tested-by: Prashant Malani --- drivers/platform/chrome/cros_ec_sysfs.c | 36 ++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_sysfs.c b/drivers/platform/chrome/cros_ec_sysfs.c index 07dac97ad57c..d45ea5d5bfa4 100644 --- a/drivers/platform/chrome/cros_ec_sysfs.c +++ b/drivers/platform/chrome/cros_ec_sysfs.c @@ -149,14 +149,14 @@ static ssize_t version_show(struct device *dev, /* Get build info. */ msg->command = EC_CMD_GET_BUILD_INFO + ec->cmd_offset; msg->insize = EC_HOST_PARAM_SIZE; - ret = cros_ec_cmd_xfer(ec->ec_dev, msg); - if (ret < 0) - count += scnprintf(buf + count, PAGE_SIZE - count, - "Build info: XFER ERROR %d\n", ret); - else if (msg->result != EC_RES_SUCCESS) + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); + if (ret == -EPROTO) { count += scnprintf(buf + count, PAGE_SIZE - count, "Build info: EC error %d\n", msg->result); - else { + } else if (ret < 0) { + count += scnprintf(buf + count, PAGE_SIZE - count, + "Build info: XFER ERROR %d\n", ret); + } else { msg->data[EC_HOST_PARAM_SIZE - 1] = '\0'; count += scnprintf(buf + count, PAGE_SIZE - count, "Build info: %s\n", msg->data); @@ -165,14 +165,14 @@ static ssize_t version_show(struct device *dev, /* Get chip info. */ msg->command = EC_CMD_GET_CHIP_INFO + ec->cmd_offset; msg->insize = sizeof(*r_chip); - ret = cros_ec_cmd_xfer(ec->ec_dev, msg); - if (ret < 0) - count += scnprintf(buf + count, PAGE_SIZE - count, - "Chip info: XFER ERROR %d\n", ret); - else if (msg->result != EC_RES_SUCCESS) + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); + if (ret == -EPROTO) { count += scnprintf(buf + count, PAGE_SIZE - count, "Chip info: EC error %d\n", msg->result); - else { + } else if (ret < 0) { + count += scnprintf(buf + count, PAGE_SIZE - count, + "Chip info: XFER ERROR %d\n", ret); + } else { r_chip = (struct ec_response_get_chip_info *)msg->data; r_chip->vendor[sizeof(r_chip->vendor) - 1] = '\0'; @@ -189,14 +189,14 @@ static ssize_t version_show(struct device *dev, /* Get board version */ msg->command = EC_CMD_GET_BOARD_VERSION + ec->cmd_offset; msg->insize = sizeof(*r_board); - ret = cros_ec_cmd_xfer(ec->ec_dev, msg); - if (ret < 0) - count += scnprintf(buf + count, PAGE_SIZE - count, - "Board version: XFER ERROR %d\n", ret); - else if (msg->result != EC_RES_SUCCESS) + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); + if (ret == -EPROTO) { count += scnprintf(buf + count, PAGE_SIZE - count, "Board version: EC error %d\n", msg->result); - else { + } else if (ret < 0) { + count += scnprintf(buf + count, PAGE_SIZE - count, + "Board version: XFER ERROR %d\n", ret); + } else { r_board = (struct ec_response_board_version *)msg->data; count += scnprintf(buf + count, PAGE_SIZE - count, From cff38b0c58fc738ad559582c13878aa882da6a56 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 20 Feb 2020 16:58:57 +0100 Subject: [PATCH 1057/4444] platform/chrome: cros_ec_lightbar: Use cros_ec_cmd_xfer_status helper This patch makes use of cros_ec_cmd_xfer_status() instead of cros_ec_cmd_xfer(). It allows us to remove some redundand code. In this case, though, we are changing a bit the behaviour because of returning -EINVAL on protocol error we propagate the error return for cros_ec_cmd_xfer_status() function, but I think it will be fine, even more clear as we don't mask the Linux error code. Signed-off-by: Enric Balletbo i Serra Tested-by: Prashant Malani --- drivers/platform/chrome/cros_ec_lightbar.c | 50 ++++++---------------- 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_lightbar.c b/drivers/platform/chrome/cros_ec_lightbar.c index b4c110c5fee0..b59180bff5a3 100644 --- a/drivers/platform/chrome/cros_ec_lightbar.c +++ b/drivers/platform/chrome/cros_ec_lightbar.c @@ -116,7 +116,7 @@ static int get_lightbar_version(struct cros_ec_dev *ec, param = (struct ec_params_lightbar *)msg->data; param->cmd = LIGHTBAR_CMD_VERSION; - ret = cros_ec_cmd_xfer(ec->ec_dev, msg); + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); if (ret < 0) { ret = 0; goto exit; @@ -193,15 +193,10 @@ static ssize_t brightness_store(struct device *dev, if (ret) goto exit; - ret = cros_ec_cmd_xfer(ec->ec_dev, msg); + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); if (ret < 0) goto exit; - if (msg->result != EC_RES_SUCCESS) { - ret = -EINVAL; - goto exit; - } - ret = count; exit: kfree(msg); @@ -258,13 +253,10 @@ static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr, goto exit; } - ret = cros_ec_cmd_xfer(ec->ec_dev, msg); + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); if (ret < 0) goto exit; - if (msg->result != EC_RES_SUCCESS) - goto exit; - i = 0; ok = 1; } @@ -305,14 +297,13 @@ static ssize_t sequence_show(struct device *dev, if (ret) goto exit; - ret = cros_ec_cmd_xfer(ec->ec_dev, msg); - if (ret < 0) - goto exit; - - if (msg->result != EC_RES_SUCCESS) { + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); + if (ret == -EPROTO) { ret = scnprintf(buf, PAGE_SIZE, "ERROR: EC returned %d\n", msg->result); goto exit; + } else if (ret < 0) { + goto exit; } resp = (struct ec_response_lightbar *)msg->data; @@ -344,13 +335,10 @@ static int lb_send_empty_cmd(struct cros_ec_dev *ec, uint8_t cmd) if (ret) goto error; - ret = cros_ec_cmd_xfer(ec->ec_dev, msg); + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); if (ret < 0) goto error; - if (msg->result != EC_RES_SUCCESS) { - ret = -EINVAL; - goto error; - } + ret = 0; error: kfree(msg); @@ -377,13 +365,10 @@ static int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable) if (ret) goto error; - ret = cros_ec_cmd_xfer(ec->ec_dev, msg); + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); if (ret < 0) goto error; - if (msg->result != EC_RES_SUCCESS) { - ret = -EINVAL; - goto error; - } + ret = 0; error: kfree(msg); @@ -425,15 +410,10 @@ static ssize_t sequence_store(struct device *dev, struct device_attribute *attr, if (ret) goto exit; - ret = cros_ec_cmd_xfer(ec->ec_dev, msg); + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); if (ret < 0) goto exit; - if (msg->result != EC_RES_SUCCESS) { - ret = -EINVAL; - goto exit; - } - ret = count; exit: kfree(msg); @@ -487,13 +467,9 @@ static ssize_t program_store(struct device *dev, struct device_attribute *attr, */ msg->outsize = count + extra_bytes; - ret = cros_ec_cmd_xfer(ec->ec_dev, msg); + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); if (ret < 0) goto exit; - if (msg->result != EC_RES_SUCCESS) { - ret = -EINVAL; - goto exit; - } ret = count; exit: From c06e58b6b7336d717b1ec9a5c7f825a94b67386e Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 20 Feb 2020 16:58:58 +0100 Subject: [PATCH 1058/4444] platform/chrome: cros_ec: Use cros_ec_cmd_xfer_status helper This patch makes use of cros_ec_cmd_xfer_status() instead of cros_ec_cmd_xfer(). In this case the change is trivial and the only reason to do it is because we want to make cros_ec_cmd_xfer() a private function for the EC protocol and let people only use the cros_ec_cmd_xfer_status() to return Linux standard error codes. Signed-off-by: Enric Balletbo i Serra Tested-by: Prashant Malani --- drivers/platform/chrome/cros_ec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c index 7ee43b2e0654..3104680b7485 100644 --- a/drivers/platform/chrome/cros_ec.c +++ b/drivers/platform/chrome/cros_ec.c @@ -120,7 +120,7 @@ static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event) buf.msg.command = EC_CMD_HOST_SLEEP_EVENT; - ret = cros_ec_cmd_xfer(ec_dev, &buf.msg); + ret = cros_ec_cmd_xfer_status(ec_dev, &buf.msg); /* For now, report failure to transition to S0ix with a warning. */ if (ret >= 0 && ec_dev->host_sleep_v1 && From 13a892d4aa2499f22b0be7f25ecd484ed026cdb8 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 26 Feb 2020 18:59:21 +0000 Subject: [PATCH 1059/4444] dmaengine: ti: edma: fix null dereference because of a typo in pointer name Currently there is a dereference of the null pointer m_ddev. This appears to be a typo on the pointer, I believe s_ddev should be used instead. Fix this by using the correct pointer. Fixes: eb0249d50153 ("dmaengine: ti: edma: Support for interleaved mem to mem transfer") Signed-off-by: Colin Ian King Acked-by: Peter Ujfalusi Addresses-Coverity: ("Explicit null dereferenced") Link: https://lore.kernel.org/r/20200226185921.351693-1-colin.king@canonical.com Signed-off-by: Vinod Koul --- drivers/dma/ti/edma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/ti/edma.c b/drivers/dma/ti/edma.c index 2b1fdd438e7f..c4a5c170c1f9 100644 --- a/drivers/dma/ti/edma.c +++ b/drivers/dma/ti/edma.c @@ -1992,7 +1992,7 @@ static void edma_dma_init(struct edma_cc *ecc, bool legacy_mode) "Legacy memcpy is enabled, things might not work\n"); dma_cap_set(DMA_MEMCPY, s_ddev->cap_mask); - dma_cap_set(DMA_INTERLEAVE, m_ddev->cap_mask); + dma_cap_set(DMA_INTERLEAVE, s_ddev->cap_mask); s_ddev->device_prep_dma_memcpy = edma_prep_dma_memcpy; s_ddev->device_prep_interleaved_dma = edma_prep_dma_interleaved; s_ddev->directions = BIT(DMA_MEM_TO_MEM); From fa1c76df5dcd15a839bda750248ddb1a9c438f77 Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Wed, 26 Feb 2020 13:54:00 +0000 Subject: [PATCH 1060/4444] MAINTAINERS: Cover Arm SMMU DT bindings We'd like to be aware of proposed DT binding changes even when they don't directly touch the drivers themselves. Signed-off-by: Robin Murphy Signed-off-by: Will Deacon --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index fcd79fc38928..ac6f6e9e1c6f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1426,6 +1426,7 @@ M: Will Deacon R: Robin Murphy L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained +F: Documentation/devicetree/bindings/iommu/arm,smmu* F: drivers/iommu/arm-smmu* F: drivers/iommu/io-pgtable-arm.c F: drivers/iommu/io-pgtable-arm-v7s.c From 57b57ebc3f338a7c5cfc41d6577ff72aa3677e38 Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Mon, 2 Mar 2020 11:44:11 +0400 Subject: [PATCH 1061/4444] arm64: dts: meson-g12b: fix N2/VIM3 audio card model names This is largely cosmetic, but Odroid N2 and Khadas VIM3 are G12B devices so correct the card model names to reflect this. Fixes: aa7d5873bf6e ("arm64: dts: meson-g12b-odroid-n2: add sound card") Fixes: c6d29c66e582 ("arm64: dts: meson-g12b-khadas-vim3: add initial device-tree") Signed-off-by: Christian Hewitt [khilman: fix whitespace in commit log trailers] Signed-off-by: Kevin Hilman Link: https://lore.kernel.org/r/1583135051-95529-1-git-send-email-christianshewitt@gmail.com --- arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi | 2 +- arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi index 554863429aa6..b1fab5749ca8 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi @@ -48,7 +48,7 @@ sound { compatible = "amlogic,axg-sound-card"; - model = "G12A-KHADAS-VIM3"; + model = "G12B-KHADAS-VIM3"; audio-aux-devs = <&tdmout_b>; audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", "TDMOUT_B IN 1", "FRDDR_B OUT 1", diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts index 0e54c1dc2842..8830d3844885 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts @@ -208,7 +208,7 @@ sound { compatible = "amlogic,axg-sound-card"; - model = "G12A-ODROIDN2"; + model = "G12B-ODROID-N2"; audio-aux-devs = <&tdmout_b>; audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", "TDMOUT_B IN 1", "FRDDR_B OUT 1", From e582f4832a9ee27d92502b58f3a1b3331457e8bb Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 28 Feb 2020 17:18:47 -0600 Subject: [PATCH 1062/4444] ASoC: SOF: pcm: skip DMA buffer pre-allocation As discussion in ALSA https://patchwork.kernel.org/patch/11336023/, it is suggested to skip DMA buffer pre-allocation with passing size=0 when calling snd_pcm_set_managed_buffer(), to make the full buffer_bytes range configured in topology file selectable from user space, here do the corresponding change in SOF PCM driver to implement it. This change doesn't have dependency to the change that Takashi will do in the ALSA core by adding total_pcm_alloc_bytes limitation to the struct snd_card, it passes tests both with or without Takashi's coming change on SOF CML platform. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Keyon Jie Link: https://lore.kernel.org/r/20200228231850.9226-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index b239bbff4b5c..f4769e19965a 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -601,8 +601,7 @@ static int sof_pcm_new(struct snd_soc_component *component, snd_pcm_set_managed_buffer(pcm->streams[stream].substream, SNDRV_DMA_TYPE_DEV_SG, sdev->dev, - le32_to_cpu(caps->buffer_size_min), - le32_to_cpu(caps->buffer_size_max)); + 0, le32_to_cpu(caps->buffer_size_max)); capture: stream = SNDRV_PCM_STREAM_CAPTURE; @@ -624,8 +623,7 @@ capture: snd_pcm_set_managed_buffer(pcm->streams[stream].substream, SNDRV_DMA_TYPE_DEV_SG, sdev->dev, - le32_to_cpu(caps->buffer_size_min), - le32_to_cpu(caps->buffer_size_max)); + 0, le32_to_cpu(caps->buffer_size_max)); return 0; } From 1919b42ca4ad75a2397081164661af3ce5a7b8f4 Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Fri, 28 Feb 2020 17:18:48 -0600 Subject: [PATCH 1063/4444] ASoC: SOF: ipc: check ipc return value before data copy In tx_wait_done the ipc payload is copied before the DSP transaction error code is checked. This might lead to corrupted data in kernel side even though the error would be handled later. It is also pointless to copy the data in case of error. So change the order of error check and copy. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Jaska Uimonen Link: https://lore.kernel.org/r/20200228231850.9226-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 22d296f95761..cc5762706c9c 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -214,15 +214,17 @@ static int tx_wait_done(struct snd_sof_ipc *ipc, struct snd_sof_ipc_msg *msg, snd_sof_handle_fw_exception(ipc->sdev); ret = -ETIMEDOUT; } else { - /* copy the data returned from DSP */ ret = msg->reply_error; - if (msg->reply_size) - memcpy(reply_data, msg->reply_data, msg->reply_size); - if (ret < 0) + if (ret < 0) { dev_err(sdev->dev, "error: ipc error for 0x%x size %zu\n", hdr->cmd, msg->reply_size); - else + } else { ipc_log_header(sdev->dev, "ipc tx succeeded", hdr->cmd); + if (msg->reply_size) + /* copy the data returned from DSP */ + memcpy(reply_data, msg->reply_data, + msg->reply_size); + } } return ret; From 8354d9b44530b5f534146668ae641572dede79a4 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 28 Feb 2020 17:18:49 -0600 Subject: [PATCH 1064/4444] ASoC: SOF: Intel: hda-loader: clear the IPC ack bit after FW_PURGE done Set DONE bit after the FW_PURGE IPC is polled successfully, to clear the interrupt and avoid the arrival of the confusing unexpected ipc. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Keyon Jie Link: https://lore.kernel.org/r/20200228231850.9226-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 8852184a2569..03b05d7f66da 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -131,6 +131,12 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, const void *fwdata, goto err; } + /* set DONE bit to clear the reply IPC message */ + snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, + chip->ipc_ack, + chip->ipc_ack_mask, + chip->ipc_ack_mask); + /* step 5: power down corex */ ret = hda_dsp_core_power_down(sdev, chip->cores_mask & ~(HDA_DSP_CORE_MASK(0))); From 1a2289fdf678b780b2d68f408523c09b7074982e Mon Sep 17 00:00:00 2001 From: Tomasz Lauda Date: Fri, 28 Feb 2020 17:18:50 -0600 Subject: [PATCH 1065/4444] ASoC: SOF: add core id to sof_ipc_comp Adds core id to sof_ipc_comp. The intention of this change is to inform FW on which core that particular component should run. Right now core id is only passed when pipeline is created, which is not flexible enough and doesn't allow for FW to handle this the right way. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Tomasz Lauda Link: https://lore.kernel.org/r/20200228231850.9226-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/topology.h | 3 ++- include/uapi/sound/sof/abi.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h index 8e76178fedf0..402e0250c508 100644 --- a/include/sound/sof/topology.h +++ b/include/sound/sof/topology.h @@ -53,9 +53,10 @@ struct sof_ipc_comp { uint32_t id; enum sof_comp_type type; uint32_t pipeline_id; + uint32_t core; /* reserved for future use */ - uint32_t reserved[2]; + uint32_t reserved[1]; } __packed; /* diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h index c0ef1643c753..5995b79d6df1 100644 --- a/include/uapi/sound/sof/abi.h +++ b/include/uapi/sound/sof/abi.h @@ -26,7 +26,7 @@ /* SOF ABI version major, minor and patch numbers */ #define SOF_ABI_MAJOR 3 -#define SOF_ABI_MINOR 12 +#define SOF_ABI_MINOR 13 #define SOF_ABI_PATCH 0 /* SOF ABI version number. Format within 32bit word is MMmmmppp */ From 787c5214ea6f6e9b7c75ae670d6b6a7deecb2d45 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Fri, 28 Feb 2020 15:42:25 -0800 Subject: [PATCH 1066/4444] ASoC: SOF: Intel: hda: use snd_sof_dsp_set_power_state() op Replace the calls to hda_dsp_set_power_state() with the top-level SOF op snd_sof_set_power_state(). Along with this, modify the hda_dsp_resume() function to return the value of snd_sof_set_power_state() directly. Signed-off-by: Ranjani Sridharan Reviewed-by: Jaska Uimonen Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200228234225.6963-1-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 0e61c27785a3..79ce52c32ef1 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -662,7 +662,7 @@ int hda_dsp_resume(struct snd_sof_dev *sdev) hda_codec_i915_display_power(sdev, true); /* Set DSP power state */ - ret = hda_dsp_set_power_state(sdev, &target_state); + ret = snd_sof_dsp_set_power_state(sdev, &target_state); if (ret < 0) { dev_err(sdev->dev, "error: setting dsp state %d substate %d\n", target_state.state, target_state.substate); @@ -686,8 +686,7 @@ int hda_dsp_resume(struct snd_sof_dev *sdev) if (ret < 0) return ret; - hda_dsp_set_power_state(sdev, &target_state); - return ret; + return snd_sof_dsp_set_power_state(sdev, &target_state); } int hda_dsp_runtime_resume(struct snd_sof_dev *sdev) @@ -702,7 +701,7 @@ int hda_dsp_runtime_resume(struct snd_sof_dev *sdev) if (ret < 0) return ret; - return hda_dsp_set_power_state(sdev, &target_state); + return snd_sof_dsp_set_power_state(sdev, &target_state); } int hda_dsp_runtime_idle(struct snd_sof_dev *sdev) @@ -730,7 +729,7 @@ int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev) if (ret < 0) return ret; - return hda_dsp_set_power_state(sdev, &target_state); + return snd_sof_dsp_set_power_state(sdev, &target_state); } int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) @@ -753,7 +752,7 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) hda_codec_i915_display_power(sdev, false); /* Set DSP power state */ - ret = hda_dsp_set_power_state(sdev, &target_dsp_state); + ret = snd_sof_dsp_set_power_state(sdev, &target_dsp_state); if (ret < 0) { dev_err(sdev->dev, "error: setting dsp state %d substate %d\n", target_dsp_state.state, @@ -781,7 +780,7 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) return ret; } - return hda_dsp_set_power_state(sdev, &target_dsp_state); + return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); } int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) @@ -849,7 +848,7 @@ void hda_dsp_d0i3_work(struct work_struct *work) return; /* This can fail but error cannot be propagated */ - ret = hda_dsp_set_power_state(sdev, &target_state); + ret = snd_sof_dsp_set_power_state(sdev, &target_state); if (ret < 0) dev_err_ratelimited(sdev->dev, "error: failed to set DSP state %d substate %d\n", From 72c3b2b09fcdaa6a63e17e9a715e2a8236af529a Mon Sep 17 00:00:00 2001 From: Akshu Agrawal Date: Mon, 2 Mar 2020 13:54:36 +0530 Subject: [PATCH 1067/4444] ASoc: amd: Add DMIC switch capability to machine driver Switch between DMIC0 and DMIC1 based on recording device selected. This is done by toggling the dmic select gpio. Signed-off-by: Akshu Agrawal Link: https://lore.kernel.org/r/20200302082443.51587-1-akshu.agrawal@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp3x-rt5682-max9836.c | 53 ++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c index 96fbcd29e3ed..511b8b1722aa 100644 --- a/sound/soc/amd/acp3x-rt5682-max9836.c +++ b/sound/soc/amd/acp3x-rt5682-max9836.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ static struct snd_soc_jack pco_jack; static struct clk *rt5682_dai_wclk; static struct clk *rt5682_dai_bclk; +static struct gpio_desc *dmic_sel; static int acp3x_5682_init(struct snd_soc_pcm_runtime *rtd) { @@ -176,7 +178,7 @@ static int acp3x_max_startup(struct snd_pcm_substream *substream) return rt5682_clk_enable(substream); } -static int acp3x_ec_startup(struct snd_pcm_substream *substream) +static int acp3x_ec_dmic0_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_card *card = rtd->card; @@ -185,6 +187,23 @@ static int acp3x_ec_startup(struct snd_pcm_substream *substream) machine->cap_i2s_instance = I2S_BT_INSTANCE; snd_soc_dai_set_bclk_ratio(codec_dai, 64); + if (dmic_sel) + gpiod_set_value(dmic_sel, 0); + + return rt5682_clk_enable(substream); +} + +static int acp3x_ec_dmic1_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card); + + machine->cap_i2s_instance = I2S_BT_INSTANCE; + snd_soc_dai_set_bclk_ratio(codec_dai, 64); + if (dmic_sel) + gpiod_set_value(dmic_sel, 1); return rt5682_clk_enable(substream); } @@ -204,8 +223,13 @@ static const struct snd_soc_ops acp3x_max_play_ops = { .shutdown = rt5682_shutdown, }; -static const struct snd_soc_ops acp3x_ec_cap_ops = { - .startup = acp3x_ec_startup, +static const struct snd_soc_ops acp3x_ec_cap0_ops = { + .startup = acp3x_ec_dmic0_startup, + .shutdown = rt5682_shutdown, +}; + +static const struct snd_soc_ops acp3x_ec_cap1_ops = { + .startup = acp3x_ec_dmic1_startup, .shutdown = rt5682_shutdown, }; @@ -246,12 +270,21 @@ static struct snd_soc_dai_link acp3x_dai_5682_98357[] = { SND_SOC_DAILINK_REG(acp3x_bt, max, platform), }, { - .name = "acp3x-ec-capture", - .stream_name = "Capture", + .name = "acp3x-ec-dmic0-capture", + .stream_name = "Capture DMIC0", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .dpcm_capture = 1, - .ops = &acp3x_ec_cap_ops, + .ops = &acp3x_ec_cap0_ops, + SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform), + }, + { + .name = "acp3x-ec-dmic1-capture", + .stream_name = "Capture DMIC1", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBS_CFS, + .dpcm_capture = 1, + .ops = &acp3x_ec_cap1_ops, SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform), }, }; @@ -302,6 +335,14 @@ static int acp3x_probe(struct platform_device *pdev) acp3x_card.dev = &pdev->dev; platform_set_drvdata(pdev, card); snd_soc_card_set_drvdata(card, machine); + + dmic_sel = devm_gpiod_get(&pdev->dev, "dmic", GPIOD_OUT_LOW); + if (IS_ERR(dmic_sel)) { + dev_err(&pdev->dev, "DMIC gpio failed err=%d\n", + PTR_ERR(dmic_sel)); + return PTR_ERR(dmic_sel); + } + ret = devm_snd_soc_register_card(&pdev->dev, &acp3x_card); if (ret) { dev_err(&pdev->dev, From a79ee2e095c0a60c32d5b1fce39d58e0fc4d9ec5 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Mon, 2 Mar 2020 15:05:22 +0800 Subject: [PATCH 1068/4444] ASoC: rt1015: set snd_soc_dai_ops in rt1015_dai driver snd_soc_dai_driver should set ops in rt1015_dai driver. Also make the two variable static to fix sparse warnings. Fixes: df31007400c3 ("ASoC: rt1015: add rt1015 amplifier driver") Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20200302070522.48104-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index c118d030bd2d..100b8c89d537 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -857,6 +857,7 @@ static struct snd_soc_dai_driver rt1015_dai[] = { .rates = RT1015_STEREO_RATES, .formats = RT1015_FORMATS, }, + .ops = &rt1015_aif_dai_ops, } }; From 485bb19d0b3eb3b679211800e3fd61e8b33ebb20 Mon Sep 17 00:00:00 2001 From: Frank Rowand Date: Thu, 27 Feb 2020 22:16:29 -0600 Subject: [PATCH 1069/4444] of: unittest: make gpio overlay test dependent on CONFIG_OF_GPIO Randconfig testing found compile errors in drivers/of/unittest.c if CONFIG_GPIOLIB is not set because CONFIG_OF_GPIO depends on CONFIG_GPIOLIB. Make the gpio overlay test depend on CONFIG_OF_GPIO. No code is modified, it is only moved to a different location and protected with #ifdef CONFIG_OF_GPIO. An empty of_unittest_overlay_gpio() is added in the #else. Fixes: f4056e705b2e ("of: unittest: add overlay gpio test to catch gpio hog problem") Reported-by: Randy Dunlap Signed-off-by: Frank Rowand Acked-by: Randy Dunlap # build-tested Signed-off-by: Rob Herring --- drivers/of/unittest.c | 465 +++++++++++++++++++++--------------------- 1 file changed, 238 insertions(+), 227 deletions(-) diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 96ae8a762a9e..1e5a2e4d893e 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -61,86 +61,6 @@ static struct unittest_results { #define EXPECT_END(level, fmt, ...) \ printk(level pr_fmt("EXPECT / : ") fmt, ##__VA_ARGS__) -struct unittest_gpio_dev { - struct gpio_chip chip; -}; - -static int unittest_gpio_chip_request_count; -static int unittest_gpio_probe_count; -static int unittest_gpio_probe_pass_count; - -static int unittest_gpio_chip_request(struct gpio_chip *chip, unsigned int offset) -{ - unittest_gpio_chip_request_count++; - - pr_debug("%s(): %s %d %d\n", __func__, chip->label, offset, - unittest_gpio_chip_request_count); - return 0; -} - -static int unittest_gpio_probe(struct platform_device *pdev) -{ - struct unittest_gpio_dev *devptr; - int ret; - - unittest_gpio_probe_count++; - - devptr = kzalloc(sizeof(*devptr), GFP_KERNEL); - if (!devptr) - return -ENOMEM; - - platform_set_drvdata(pdev, devptr); - - devptr->chip.of_node = pdev->dev.of_node; - devptr->chip.label = "of-unittest-gpio"; - devptr->chip.base = -1; /* dynamic allocation */ - devptr->chip.ngpio = 5; - devptr->chip.request = unittest_gpio_chip_request; - - ret = gpiochip_add_data(&devptr->chip, NULL); - - unittest(!ret, - "gpiochip_add_data() for node @%pOF failed, ret = %d\n", devptr->chip.of_node, ret); - - if (!ret) - unittest_gpio_probe_pass_count++; - return ret; -} - -static int unittest_gpio_remove(struct platform_device *pdev) -{ - struct unittest_gpio_dev *gdev = platform_get_drvdata(pdev); - struct device *dev = &pdev->dev; - struct device_node *np = pdev->dev.of_node; - - dev_dbg(dev, "%s for node @%pOF\n", __func__, np); - - if (!gdev) - return -EINVAL; - - if (gdev->chip.base != -1) - gpiochip_remove(&gdev->chip); - - platform_set_drvdata(pdev, NULL); - kfree(pdev); - - return 0; -} - -static const struct of_device_id unittest_gpio_id[] = { - { .compatible = "unittest-gpio", }, - {} -}; - -static struct platform_driver unittest_gpio_driver = { - .probe = unittest_gpio_probe, - .remove = unittest_gpio_remove, - .driver = { - .name = "unittest-gpio", - .of_match_table = of_match_ptr(unittest_gpio_id), - }, -}; - static void __init of_unittest_find_node_by_name(void) { struct device_node *np; @@ -1588,6 +1508,244 @@ static int of_path_platform_device_exists(const char *path) return pdev != NULL; } +#ifdef CONFIG_OF_GPIO + +struct unittest_gpio_dev { + struct gpio_chip chip; +}; + +static int unittest_gpio_chip_request_count; +static int unittest_gpio_probe_count; +static int unittest_gpio_probe_pass_count; + +static int unittest_gpio_chip_request(struct gpio_chip *chip, unsigned int offset) +{ + unittest_gpio_chip_request_count++; + + pr_debug("%s(): %s %d %d\n", __func__, chip->label, offset, + unittest_gpio_chip_request_count); + return 0; +} + +static int unittest_gpio_probe(struct platform_device *pdev) +{ + struct unittest_gpio_dev *devptr; + int ret; + + unittest_gpio_probe_count++; + + devptr = kzalloc(sizeof(*devptr), GFP_KERNEL); + if (!devptr) + return -ENOMEM; + + platform_set_drvdata(pdev, devptr); + + devptr->chip.of_node = pdev->dev.of_node; + devptr->chip.label = "of-unittest-gpio"; + devptr->chip.base = -1; /* dynamic allocation */ + devptr->chip.ngpio = 5; + devptr->chip.request = unittest_gpio_chip_request; + + ret = gpiochip_add_data(&devptr->chip, NULL); + + unittest(!ret, + "gpiochip_add_data() for node @%pOF failed, ret = %d\n", devptr->chip.of_node, ret); + + if (!ret) + unittest_gpio_probe_pass_count++; + return ret; +} + +static int unittest_gpio_remove(struct platform_device *pdev) +{ + struct unittest_gpio_dev *gdev = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; + struct device_node *np = pdev->dev.of_node; + + dev_dbg(dev, "%s for node @%pOF\n", __func__, np); + + if (!gdev) + return -EINVAL; + + if (gdev->chip.base != -1) + gpiochip_remove(&gdev->chip); + + platform_set_drvdata(pdev, NULL); + kfree(pdev); + + return 0; +} + +static const struct of_device_id unittest_gpio_id[] = { + { .compatible = "unittest-gpio", }, + {} +}; + +static struct platform_driver unittest_gpio_driver = { + .probe = unittest_gpio_probe, + .remove = unittest_gpio_remove, + .driver = { + .name = "unittest-gpio", + .of_match_table = of_match_ptr(unittest_gpio_id), + }, +}; + +static void __init of_unittest_overlay_gpio(void) +{ + int chip_request_count; + int probe_pass_count; + int ret; + + /* + * tests: apply overlays before registering driver + * Similar to installing a driver as a module, the + * driver is registered after applying the overlays. + * + * - apply overlay_gpio_01 + * - apply overlay_gpio_02a + * - apply overlay_gpio_02b + * - register driver + * + * register driver will result in + * - probe and processing gpio hog for overlay_gpio_01 + * - probe for overlay_gpio_02a + * - processing gpio for overlay_gpio_02b + */ + + probe_pass_count = unittest_gpio_probe_pass_count; + chip_request_count = unittest_gpio_chip_request_count; + + /* + * overlay_gpio_01 contains gpio node and child gpio hog node + * overlay_gpio_02a contains gpio node + * overlay_gpio_02b contains child gpio hog node + */ + + unittest(overlay_data_apply("overlay_gpio_01", NULL), + "Adding overlay 'overlay_gpio_01' failed\n"); + + unittest(overlay_data_apply("overlay_gpio_02a", NULL), + "Adding overlay 'overlay_gpio_02a' failed\n"); + + unittest(overlay_data_apply("overlay_gpio_02b", NULL), + "Adding overlay 'overlay_gpio_02b' failed\n"); + + /* + * messages are the result of the probes, after the + * driver is registered + */ + + EXPECT_BEGIN(KERN_INFO, + "GPIO line <> (line-B-input) hogged as input\n"); + + EXPECT_BEGIN(KERN_INFO, + "GPIO line <> (line-A-input) hogged as input\n"); + + ret = platform_driver_register(&unittest_gpio_driver); + if (unittest(ret == 0, "could not register unittest gpio driver\n")) + return; + + EXPECT_END(KERN_INFO, + "GPIO line <> (line-A-input) hogged as input\n"); + EXPECT_END(KERN_INFO, + "GPIO line <> (line-B-input) hogged as input\n"); + + unittest(probe_pass_count + 2 == unittest_gpio_probe_pass_count, + "unittest_gpio_probe() failed or not called\n"); + + unittest(chip_request_count + 2 == unittest_gpio_chip_request_count, + "unittest_gpio_chip_request() called %d times (expected 1 time)\n", + unittest_gpio_chip_request_count - chip_request_count); + + /* + * tests: apply overlays after registering driver + * + * Similar to a driver built-in to the kernel, the + * driver is registered before applying the overlays. + * + * overlay_gpio_03 contains gpio node and child gpio hog node + * + * - apply overlay_gpio_03 + * + * apply overlay will result in + * - probe and processing gpio hog. + */ + + probe_pass_count = unittest_gpio_probe_pass_count; + chip_request_count = unittest_gpio_chip_request_count; + + EXPECT_BEGIN(KERN_INFO, + "GPIO line <> (line-D-input) hogged as input\n"); + + /* overlay_gpio_03 contains gpio node and child gpio hog node */ + + unittest(overlay_data_apply("overlay_gpio_03", NULL), + "Adding overlay 'overlay_gpio_03' failed\n"); + + EXPECT_END(KERN_INFO, + "GPIO line <> (line-D-input) hogged as input\n"); + + unittest(probe_pass_count + 1 == unittest_gpio_probe_pass_count, + "unittest_gpio_probe() failed or not called\n"); + + unittest(chip_request_count + 1 == unittest_gpio_chip_request_count, + "unittest_gpio_chip_request() called %d times (expected 1 time)\n", + unittest_gpio_chip_request_count - chip_request_count); + + /* + * overlay_gpio_04a contains gpio node + * + * - apply overlay_gpio_04a + * + * apply the overlay will result in + * - probe for overlay_gpio_04a + */ + + probe_pass_count = unittest_gpio_probe_pass_count; + chip_request_count = unittest_gpio_chip_request_count; + + /* overlay_gpio_04a contains gpio node */ + + unittest(overlay_data_apply("overlay_gpio_04a", NULL), + "Adding overlay 'overlay_gpio_04a' failed\n"); + + unittest(probe_pass_count + 1 == unittest_gpio_probe_pass_count, + "unittest_gpio_probe() failed or not called\n"); + + /* + * overlay_gpio_04b contains child gpio hog node + * + * - apply overlay_gpio_04b + * + * apply the overlay will result in + * - processing gpio for overlay_gpio_04b + */ + + EXPECT_BEGIN(KERN_INFO, + "GPIO line <> (line-C-input) hogged as input\n"); + + /* overlay_gpio_04b contains child gpio hog node */ + + unittest(overlay_data_apply("overlay_gpio_04b", NULL), + "Adding overlay 'overlay_gpio_04b' failed\n"); + + EXPECT_END(KERN_INFO, + "GPIO line <> (line-C-input) hogged as input\n"); + + unittest(chip_request_count + 1 == unittest_gpio_chip_request_count, + "unittest_gpio_chip_request() called %d times (expected 1 time)\n", + unittest_gpio_chip_request_count - chip_request_count); +} + +#else + +static void __init of_unittest_overlay_gpio(void) +{ + /* skip tests */ +} + +#endif + #if IS_BUILTIN(CONFIG_I2C) /* get the i2c client device instantiated at the path */ @@ -2517,153 +2675,6 @@ static inline void of_unittest_overlay_i2c_15(void) { } #endif -static void __init of_unittest_overlay_gpio(void) -{ - int chip_request_count; - int probe_pass_count; - int ret; - - /* - * tests: apply overlays before registering driver - * Similar to installing a driver as a module, the - * driver is registered after applying the overlays. - * - * - apply overlay_gpio_01 - * - apply overlay_gpio_02a - * - apply overlay_gpio_02b - * - register driver - * - * register driver will result in - * - probe and processing gpio hog for overlay_gpio_01 - * - probe for overlay_gpio_02a - * - processing gpio for overlay_gpio_02b - */ - - probe_pass_count = unittest_gpio_probe_pass_count; - chip_request_count = unittest_gpio_chip_request_count; - - /* - * overlay_gpio_01 contains gpio node and child gpio hog node - * overlay_gpio_02a contains gpio node - * overlay_gpio_02b contains child gpio hog node - */ - - unittest(overlay_data_apply("overlay_gpio_01", NULL), - "Adding overlay 'overlay_gpio_01' failed\n"); - - unittest(overlay_data_apply("overlay_gpio_02a", NULL), - "Adding overlay 'overlay_gpio_02a' failed\n"); - - unittest(overlay_data_apply("overlay_gpio_02b", NULL), - "Adding overlay 'overlay_gpio_02b' failed\n"); - - /* - * messages are the result of the probes, after the - * driver is registered - */ - - EXPECT_BEGIN(KERN_INFO, - "GPIO line <> (line-B-input) hogged as input\n"); - - EXPECT_BEGIN(KERN_INFO, - "GPIO line <> (line-A-input) hogged as input\n"); - - ret = platform_driver_register(&unittest_gpio_driver); - if (unittest(ret == 0, "could not register unittest gpio driver\n")) - return; - - EXPECT_END(KERN_INFO, - "GPIO line <> (line-A-input) hogged as input\n"); - EXPECT_END(KERN_INFO, - "GPIO line <> (line-B-input) hogged as input\n"); - - unittest(probe_pass_count + 2 == unittest_gpio_probe_pass_count, - "unittest_gpio_probe() failed or not called\n"); - - unittest(chip_request_count + 2 == unittest_gpio_chip_request_count, - "unittest_gpio_chip_request() called %d times (expected 1 time)\n", - unittest_gpio_chip_request_count - chip_request_count); - - /* - * tests: apply overlays after registering driver - * - * Similar to a driver built-in to the kernel, the - * driver is registered before applying the overlays. - * - * overlay_gpio_03 contains gpio node and child gpio hog node - * - * - apply overlay_gpio_03 - * - * apply overlay will result in - * - probe and processing gpio hog. - */ - - probe_pass_count = unittest_gpio_probe_pass_count; - chip_request_count = unittest_gpio_chip_request_count; - - EXPECT_BEGIN(KERN_INFO, - "GPIO line <> (line-D-input) hogged as input\n"); - - /* overlay_gpio_03 contains gpio node and child gpio hog node */ - - unittest(overlay_data_apply("overlay_gpio_03", NULL), - "Adding overlay 'overlay_gpio_03' failed\n"); - - EXPECT_END(KERN_INFO, - "GPIO line <> (line-D-input) hogged as input\n"); - - unittest(probe_pass_count + 1 == unittest_gpio_probe_pass_count, - "unittest_gpio_probe() failed or not called\n"); - - unittest(chip_request_count + 1 == unittest_gpio_chip_request_count, - "unittest_gpio_chip_request() called %d times (expected 1 time)\n", - unittest_gpio_chip_request_count - chip_request_count); - - /* - * overlay_gpio_04a contains gpio node - * - * - apply overlay_gpio_04a - * - * apply the overlay will result in - * - probe for overlay_gpio_04a - */ - - probe_pass_count = unittest_gpio_probe_pass_count; - chip_request_count = unittest_gpio_chip_request_count; - - /* overlay_gpio_04a contains gpio node */ - - unittest(overlay_data_apply("overlay_gpio_04a", NULL), - "Adding overlay 'overlay_gpio_04a' failed\n"); - - unittest(probe_pass_count + 1 == unittest_gpio_probe_pass_count, - "unittest_gpio_probe() failed or not called\n"); - - /* - * overlay_gpio_04b contains child gpio hog node - * - * - apply overlay_gpio_04b - * - * apply the overlay will result in - * - processing gpio for overlay_gpio_04b - */ - - EXPECT_BEGIN(KERN_INFO, - "GPIO line <> (line-C-input) hogged as input\n"); - - /* overlay_gpio_04b contains child gpio hog node */ - - unittest(overlay_data_apply("overlay_gpio_04b", NULL), - "Adding overlay 'overlay_gpio_04b' failed\n"); - - EXPECT_END(KERN_INFO, - "GPIO line <> (line-C-input) hogged as input\n"); - - unittest(chip_request_count + 1 == unittest_gpio_chip_request_count, - "unittest_gpio_chip_request() called %d times (expected 1 time)\n", - unittest_gpio_chip_request_count - chip_request_count); -} - static void __init of_unittest_overlay(void) { struct device_node *bus_np = NULL; From a3958323f5fea2c400e40473f79f6816c0a2eb6b Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 28 Feb 2020 09:40:27 +0100 Subject: [PATCH 1070/4444] of: overlay: log the error cause on resolver failure When a DT overlay has a node label that is not present in the live devicetree symbols table, this error is printed: OF: resolver: overlay phandle fixup failed: -22 create_overlay: Failed to create overlay (err=-22) which does not help much in finding the node label that caused the problem and fix the overlay source. Add an error message with the name of the node label that caused the error. The new output is: OF: resolver: node label 'gpio9' not found in live devicetree symbols table OF: resolver: overlay phandle fixup failed: -22 create_overlay: Failed to create overlay (err=-22) Signed-off-by: Luca Ceresoli Reviewed-by: Frank Rowand Reviewed-by: Geert Uytterhoeven Signed-off-by: Rob Herring --- drivers/of/resolver.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c index 83c766233181..b278ab4338ce 100644 --- a/drivers/of/resolver.c +++ b/drivers/of/resolver.c @@ -321,8 +321,11 @@ int of_resolve_phandles(struct device_node *overlay) err = of_property_read_string(tree_symbols, prop->name, &refpath); - if (err) + if (err) { + pr_err("node label '%s' not found in live devicetree symbols table\n", + prop->name); goto out; + } refnode = of_find_node_by_path(refpath); if (!refnode) { From 76897807dc79747161429c984528cf8c6670b328 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 25 Feb 2020 10:03:28 +0900 Subject: [PATCH 1071/4444] dt-bindings: clock: Convert UniPhier clock to json-schema Convert the UniPhier clock controller binding to DT schema format. Signed-off-by: Masahiro Yamada Signed-off-by: Rob Herring --- .../clock/socionext,uniphier-clock.yaml | 94 +++++++++++++ .../bindings/clock/uniphier-clock.txt | 132 ------------------ 2 files changed, 94 insertions(+), 132 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/socionext,uniphier-clock.yaml delete mode 100644 Documentation/devicetree/bindings/clock/uniphier-clock.txt diff --git a/Documentation/devicetree/bindings/clock/socionext,uniphier-clock.yaml b/Documentation/devicetree/bindings/clock/socionext,uniphier-clock.yaml new file mode 100644 index 000000000000..c3930edc410f --- /dev/null +++ b/Documentation/devicetree/bindings/clock/socionext,uniphier-clock.yaml @@ -0,0 +1,94 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/socionext,uniphier-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: UniPhier clock controller + +maintainers: + - Masahiro Yamada + +properties: + compatible: + oneOf: + - description: System clock + enum: + - socionext,uniphier-ld4-clock + - socionext,uniphier-pro4-clock + - socionext,uniphier-sld8-clock + - socionext,uniphier-pro5-clock + - socionext,uniphier-pxs2-clock + - socionext,uniphier-ld6b-clock + - socionext,uniphier-ld11-clock + - socionext,uniphier-ld20-clock + - socionext,uniphier-pxs3-clock + - description: Media I/O (MIO) clock, SD clock + enum: + - socionext,uniphier-ld4-mio-clock + - socionext,uniphier-pro4-mio-clock + - socionext,uniphier-sld8-mio-clock + - socionext,uniphier-pro5-sd-clock + - socionext,uniphier-pxs2-sd-clock + - socionext,uniphier-ld11-mio-clock + - socionext,uniphier-ld20-sd-clock + - socionext,uniphier-pxs3-sd-clock + - description: Peripheral clock + enum: + - socionext,uniphier-ld4-peri-clock + - socionext,uniphier-pro4-peri-clock + - socionext,uniphier-sld8-peri-clock + - socionext,uniphier-pro5-peri-clock + - socionext,uniphier-pxs2-peri-clock + - socionext,uniphier-ld11-peri-clock + - socionext,uniphier-ld20-peri-clock + - socionext,uniphier-pxs3-peri-clock + + "#clock-cells": + const: 1 + +additionalProperties: false + +required: + - compatible + - "#clock-cells" + +examples: + - | + sysctrl@61840000 { + compatible = "socionext,uniphier-sysctrl", "simple-mfd", "syscon"; + reg = <0x61840000 0x4000>; + + clock { + compatible = "socionext,uniphier-ld11-clock"; + #clock-cells = <1>; + }; + + // other nodes ... + }; + + - | + mioctrl@59810000 { + compatible = "socionext,uniphier-mioctrl", "simple-mfd", "syscon"; + reg = <0x59810000 0x800>; + + clock { + compatible = "socionext,uniphier-ld11-mio-clock"; + #clock-cells = <1>; + }; + + // other nodes ... + }; + + - | + perictrl@59820000 { + compatible = "socionext,uniphier-perictrl", "simple-mfd", "syscon"; + reg = <0x59820000 0x200>; + + clock { + compatible = "socionext,uniphier-ld11-peri-clock"; + #clock-cells = <1>; + }; + + // other nodes ... + }; diff --git a/Documentation/devicetree/bindings/clock/uniphier-clock.txt b/Documentation/devicetree/bindings/clock/uniphier-clock.txt deleted file mode 100644 index 7b5f602765fe..000000000000 --- a/Documentation/devicetree/bindings/clock/uniphier-clock.txt +++ /dev/null @@ -1,132 +0,0 @@ -UniPhier clock controller - - -System clock ------------- - -Required properties: -- compatible: should be one of the following: - "socionext,uniphier-ld4-clock" - for LD4 SoC. - "socionext,uniphier-pro4-clock" - for Pro4 SoC. - "socionext,uniphier-sld8-clock" - for sLD8 SoC. - "socionext,uniphier-pro5-clock" - for Pro5 SoC. - "socionext,uniphier-pxs2-clock" - for PXs2/LD6b SoC. - "socionext,uniphier-ld11-clock" - for LD11 SoC. - "socionext,uniphier-ld20-clock" - for LD20 SoC. - "socionext,uniphier-pxs3-clock" - for PXs3 SoC -- #clock-cells: should be 1. - -Example: - - sysctrl@61840000 { - compatible = "socionext,uniphier-sysctrl", - "simple-mfd", "syscon"; - reg = <0x61840000 0x4000>; - - clock { - compatible = "socionext,uniphier-ld11-clock"; - #clock-cells = <1>; - }; - - other nodes ... - }; - -Provided clocks: - - 8: ST DMAC -12: GIO (Giga bit stream I/O) -14: USB3 ch0 host -15: USB3 ch1 host -16: USB3 ch0 PHY0 -17: USB3 ch0 PHY1 -20: USB3 ch1 PHY0 -21: USB3 ch1 PHY1 - - -Media I/O (MIO) clock, SD clock -------------------------------- - -Required properties: -- compatible: should be one of the following: - "socionext,uniphier-ld4-mio-clock" - for LD4 SoC. - "socionext,uniphier-pro4-mio-clock" - for Pro4 SoC. - "socionext,uniphier-sld8-mio-clock" - for sLD8 SoC. - "socionext,uniphier-pro5-sd-clock" - for Pro5 SoC. - "socionext,uniphier-pxs2-sd-clock" - for PXs2/LD6b SoC. - "socionext,uniphier-ld11-mio-clock" - for LD11 SoC. - "socionext,uniphier-ld20-sd-clock" - for LD20 SoC. - "socionext,uniphier-pxs3-sd-clock" - for PXs3 SoC -- #clock-cells: should be 1. - -Example: - - mioctrl@59810000 { - compatible = "socionext,uniphier-mioctrl", - "simple-mfd", "syscon"; - reg = <0x59810000 0x800>; - - clock { - compatible = "socionext,uniphier-ld11-mio-clock"; - #clock-cells = <1>; - }; - - other nodes ... - }; - -Provided clocks: - - 0: SD ch0 host - 1: eMMC host - 2: SD ch1 host - 7: MIO DMAC - 8: USB2 ch0 host - 9: USB2 ch1 host -10: USB2 ch2 host -12: USB2 ch0 PHY -13: USB2 ch1 PHY -14: USB2 ch2 PHY - - -Peripheral clock ----------------- - -Required properties: -- compatible: should be one of the following: - "socionext,uniphier-ld4-peri-clock" - for LD4 SoC. - "socionext,uniphier-pro4-peri-clock" - for Pro4 SoC. - "socionext,uniphier-sld8-peri-clock" - for sLD8 SoC. - "socionext,uniphier-pro5-peri-clock" - for Pro5 SoC. - "socionext,uniphier-pxs2-peri-clock" - for PXs2/LD6b SoC. - "socionext,uniphier-ld11-peri-clock" - for LD11 SoC. - "socionext,uniphier-ld20-peri-clock" - for LD20 SoC. - "socionext,uniphier-pxs3-peri-clock" - for PXs3 SoC -- #clock-cells: should be 1. - -Example: - - perictrl@59820000 { - compatible = "socionext,uniphier-perictrl", - "simple-mfd", "syscon"; - reg = <0x59820000 0x200>; - - clock { - compatible = "socionext,uniphier-ld11-peri-clock"; - #clock-cells = <1>; - }; - - other nodes ... - }; - -Provided clocks: - - 0: UART ch0 - 1: UART ch1 - 2: UART ch2 - 3: UART ch3 - 4: I2C ch0 - 5: I2C ch1 - 6: I2C ch2 - 7: I2C ch3 - 8: I2C ch4 - 9: I2C ch5 -10: I2C ch6 From cb6176ef25cef7a54ac1e8701f9dde822fce5cee Mon Sep 17 00:00:00 2001 From: Dirk Behme Date: Tue, 4 Feb 2020 08:10:43 +0100 Subject: [PATCH 1072/4444] mtd: hyperbus: Add proper error message for missing compatible In case the compatible "cypress,hyperflash" is not given output a proper error message. Signed-off-by: Dirk Behme Signed-off-by: Vignesh Raghavendra --- drivers/mtd/hyperbus/hyperbus-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/hyperbus/hyperbus-core.c b/drivers/mtd/hyperbus/hyperbus-core.c index 6af9ea34117d..c1916cca1701 100644 --- a/drivers/mtd/hyperbus/hyperbus-core.c +++ b/drivers/mtd/hyperbus/hyperbus-core.c @@ -73,8 +73,10 @@ int hyperbus_register_device(struct hyperbus_device *hbdev) np = hbdev->np; ctlr = hbdev->ctlr; - if (!of_device_is_compatible(np, "cypress,hyperflash")) + if (!of_device_is_compatible(np, "cypress,hyperflash")) { + dev_err(ctlr->dev, "\"cypress,hyperflash\" compatible missing\n"); return -ENODEV; + } hbdev->memtype = HYPERFLASH; From b6fe8bc67d2d33a9eff1b0785482bccd14979115 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 29 Jan 2020 23:37:37 +0300 Subject: [PATCH 1073/4444] mtd: hyperbus: move direct mapping setup to AM654 HBMC driver The Hyperbus core expects that HyperFlash is always directly mapped for both read and write, but in reality this may not always be the case, e.g. Renesas RPC-IF has read only direct mapping. Move the code setting up the direct mapping from the Hyperbus core to thh TI AM554 HBMC driver. Signed-off-by: Sergei Shtylyov Signed-off-by: Vignesh Raghavendra --- drivers/mtd/hyperbus/hbmc-am654.c | 12 ++++++++++++ drivers/mtd/hyperbus/hyperbus-core.c | 11 ----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/mtd/hyperbus/hbmc-am654.c b/drivers/mtd/hyperbus/hbmc-am654.c index 08d543b124cd..f350a0809f88 100644 --- a/drivers/mtd/hyperbus/hbmc-am654.c +++ b/drivers/mtd/hyperbus/hbmc-am654.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -57,8 +58,10 @@ static const struct hyperbus_ops am654_hbmc_ops = { static int am654_hbmc_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; struct am654_hbmc_priv *priv; + struct resource res; int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -67,6 +70,10 @@ static int am654_hbmc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); + ret = of_address_to_resource(np, 0, &res); + if (ret) + return ret; + if (of_property_read_bool(dev->of_node, "mux-controls")) { struct mux_control *control = devm_mux_control_get(dev, NULL); @@ -88,6 +95,11 @@ static int am654_hbmc_probe(struct platform_device *pdev) goto disable_pm; } + priv->hbdev.map.size = resource_size(&res); + priv->hbdev.map.virt = devm_ioremap_resource(dev, &res); + if (IS_ERR(priv->hbdev.map.virt)) + return PTR_ERR(priv->hbdev.map.virt); + priv->ctlr.dev = dev; priv->ctlr.ops = &am654_hbmc_ops; priv->hbdev.ctlr = &priv->ctlr; diff --git a/drivers/mtd/hyperbus/hyperbus-core.c b/drivers/mtd/hyperbus/hyperbus-core.c index c1916cca1701..32685e8dd278 100644 --- a/drivers/mtd/hyperbus/hyperbus-core.c +++ b/drivers/mtd/hyperbus/hyperbus-core.c @@ -10,7 +10,6 @@ #include #include #include -#include #include static struct hyperbus_device *map_to_hbdev(struct map_info *map) @@ -62,7 +61,6 @@ int hyperbus_register_device(struct hyperbus_device *hbdev) struct hyperbus_ctlr *ctlr; struct device_node *np; struct map_info *map; - struct resource res; struct device *dev; int ret; @@ -80,17 +78,8 @@ int hyperbus_register_device(struct hyperbus_device *hbdev) hbdev->memtype = HYPERFLASH; - ret = of_address_to_resource(np, 0, &res); - if (ret) - return ret; - dev = ctlr->dev; map = &hbdev->map; - map->size = resource_size(&res); - map->virt = devm_ioremap_resource(dev, &res); - if (IS_ERR(map->virt)) - return PTR_ERR(map->virt); - map->name = dev_name(dev); map->bankwidth = 2; map->device_node = np; From 5de79ba865d7770c3bdde7c266ed425832764aac Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 27 Feb 2020 16:09:49 -0600 Subject: [PATCH 1074/4444] soundwire: bus: provide correct return value on error It seems to be a typo. It makes more sense to return the return value of sdw_update() instead of the value we want to update. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200227220949.4013-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/bus.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index ccaa590df61e..488c3c9e4947 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -1056,13 +1056,10 @@ static int sdw_initialize_slave(struct sdw_slave *slave) val |= SDW_DP0_INT_PORT_READY | SDW_DP0_INT_BRA_FAILURE; ret = sdw_update(slave, SDW_DP0_INTMASK, val, val); - if (ret < 0) { + if (ret < 0) dev_err(slave->bus->dev, "SDW_DP0_INTMASK read failed:%d\n", ret); - return val; - } - - return 0; + return ret; } static int sdw_handle_dp0_interrupt(struct sdw_slave *slave, u8 *slave_status) From d85eed038ef4919933b7f4f9d3b4f49ede4092aa Mon Sep 17 00:00:00 2001 From: Jianxin Pan Date: Mon, 2 Mar 2020 23:54:08 +0800 Subject: [PATCH 1075/4444] dt-bindings: power: Fix dt_binding_check error Missing ';' in the end of secure-monitor example node. Fixes: 165b5fb294e8 ("dt-bindings: power: add Amlogic secure power domains bindings") Reported-by: Rob Herring Signed-off-by: Jianxin Pan Reviewed-by: Neil Armstrong Acked-by: Rob Herring Signed-off-by: Kevin Hilman Link: https://lore.kernel.org/r/1583164448-83438-1-git-send-email-jianxin.pan@amlogic.com --- .../devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml b/Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml index af32209218bb..bc4e037f3f73 100644 --- a/Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml +++ b/Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml @@ -36,5 +36,5 @@ examples: compatible = "amlogic,meson-a1-pwrc"; #power-domain-cells = <1>; }; - } + }; From 66e4f4a9cc389b277e187c115a285fad2cba5485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 21 Feb 2020 16:47:39 +0200 Subject: [PATCH 1076/4444] rtc: cmos: Use spin_lock_irqsave() in cmos_interrupt() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cmos_interrupt() isn't always called from hardirq context, so we must use spin_lock_irqsave() & co. ================================ WARNING: inconsistent lock state 5.6.0-rc2-CI-CI_DRM_7981+ #1 Tainted: G U -------------------------------- inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage. rtcwake/4315 [HC0[0]:SC0[0]:HE1:SE1] takes: ffffffff82635198 (rtc_lock){?...}, at: cmos_interrupt+0x18/0x100 {IN-HARDIRQ-W} state was registered at: lock_acquire+0xa7/0x1c0 _raw_spin_lock+0x2a/0x40 cmos_interrupt+0x18/0x100 rtc_handler+0x75/0xc0 acpi_ev_fixed_event_detect+0xf9/0x132 acpi_ev_sci_xrupt_handler+0xb/0x28 acpi_irq+0x13/0x30 __handle_irq_event_percpu+0x41/0x2c0 handle_irq_event_percpu+0x2b/0x70 handle_irq_event+0x2f/0x50 handle_fasteoi_irq+0x8e/0x150 do_IRQ+0x7e/0x160 ret_from_intr+0x0/0x35 mwait_idle+0x7e/0x200 do_idle+0x1bb/0x260 cpu_startup_entry+0x14/0x20 start_secondary+0x15f/0x1b0 secondary_startup_64+0xa4/0xb0 irq event stamp: 42003 hardirqs last enabled at (42003): [] _raw_spin_unlock_irqrestore+0x47/0x60 hardirqs last disabled at (42002): [] _raw_spin_lock_irqsave+0xd/0x50 softirqs last enabled at (41848): [] __do_softirq+0x385/0x47f softirqs last disabled at (41841): [] irq_exit+0xba/0xc0 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(rtc_lock); lock(rtc_lock); *** DEADLOCK *** 6 locks held by rtcwake/4315: #0: ffff888175dc9408 (sb_writers#5){.+.+}, at: vfs_write+0x1a4/0x1d0 #1: ffff88817406ca80 (&of->mutex){+.+.}, at: kernfs_fop_write+0xdd/0x1b0 #2: ffff888179be85e0 (kn->count#236){.+.+}, at: kernfs_fop_write+0xe6/0x1b0 #3: ffffffff82641e00 (system_transition_mutex){+.+.}, at: pm_suspend+0xb3/0x3b0 #4: ffffffff826b3ee0 (acpi_scan_lock){+.+.}, at: acpi_suspend_begin+0x47/0x80 #5: ffff888178fc3960 (&dev->mutex){....}, at: device_resume+0x92/0x1c0 stack backtrace: CPU: 3 PID: 4315 Comm: rtcwake Tainted: G U 5.6.0-rc2-CI-CI_DRM_7981+ #1 Hardware name: Google Soraka/Soraka, BIOS MrChromebox-4.10 08/25/2019 Call Trace: dump_stack+0x71/0x9b mark_lock+0x49a/0x500 ? print_shortest_lock_dependencies+0x200/0x200 __lock_acquire+0x6d4/0x15d0 ? __lock_acquire+0x460/0x15d0 lock_acquire+0xa7/0x1c0 ? cmos_interrupt+0x18/0x100 _raw_spin_lock+0x2a/0x40 ? cmos_interrupt+0x18/0x100 cmos_interrupt+0x18/0x100 cmos_resume+0x1fd/0x290 ? __acpi_pm_set_device_wakeup+0x24/0x100 pnp_bus_resume+0x5e/0x90 ? pnp_bus_suspend+0x10/0x10 dpm_run_callback+0x64/0x280 device_resume+0xd4/0x1c0 ? dpm_watchdog_set+0x60/0x60 dpm_resume+0x106/0x410 ? dpm_resume_early+0x38c/0x3e0 dpm_resume_end+0x8/0x10 suspend_devices_and_enter+0x16f/0xbe0 ? rcu_read_lock_sched_held+0x4d/0x80 pm_suspend+0x344/0x3b0 state_store+0x78/0xe0 kernfs_fop_write+0x112/0x1b0 vfs_write+0xb9/0x1d0 ksys_write+0x9f/0xe0 do_syscall_64+0x4f/0x220 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x7ff934307154 Code: 89 02 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 8d 05 b1 07 2e 00 8b 00 85 c0 75 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 f3 c3 66 90 41 54 55 49 89 d4 53 48 89 f5 RSP: 002b:00007ffe2647c168 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 RAX: ffffffffffffffda RBX: 0000000000000004 RCX: 00007ff934307154 RDX: 0000000000000004 RSI: 000055de3ec4e5a0 RDI: 000000000000000a RBP: 000055de3ec4e5a0 R08: 000055de3ec4c5e0 R09: 00007ff9349f3740 R10: 000055de3ec4a010 R11: 0000000000000246 R12: 000055de3ec4c500 R13: 0000000000000004 R14: 00007ff9345df2a0 R15: 00007ff9345de760 Fixes: c6d3a278cc12 ("rtc: cmos: acknowledge ACPI driven wake alarms upon resume") Fixes: 311ee9c151ad ("rtc: cmos: allow using ACPI for RTC alarm instead of HPET") Signed-off-by: Ville Syrjälä Link: https://lore.kernel.org/r/20200221144739.11746-1-ville.syrjala@linux.intel.com Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-cmos.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index b795fe4cbd2e..fb13993fad31 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -649,10 +649,11 @@ static struct cmos_rtc cmos_rtc; static irqreturn_t cmos_interrupt(int irq, void *p) { + unsigned long flags; u8 irqstat; u8 rtc_control; - spin_lock(&rtc_lock); + spin_lock_irqsave(&rtc_lock, flags); /* When the HPET interrupt handler calls us, the interrupt * status is passed as arg1 instead of the irq number. But @@ -686,7 +687,7 @@ static irqreturn_t cmos_interrupt(int irq, void *p) hpet_mask_rtc_irq_bit(RTC_AIE); CMOS_READ(RTC_INTR_FLAGS); } - spin_unlock(&rtc_lock); + spin_unlock_irqrestore(&rtc_lock, flags); if (is_intr(irqstat)) { rtc_update_irq(p, 1, irqstat); From ca18a852ee3696ea625efa13b1fac3c33f025a53 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 2 Mar 2020 09:24:48 +0100 Subject: [PATCH 1077/4444] gpiolib: Fix inverted check in gpiochip_remove() The optimization to check for requested lines actually optimized for the uncomon error case, where one of the GPIO lines is still in use. Hence the error message must be printed when the loop is terminated early, not when it went through all available GPIO lines. Fixes: 869233f81337bfb3 ("gpiolib: Optimize gpiochip_remove() when check for requested line") Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200302082448.11795-1-geert+renesas@glider.be Acked-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 2253ab495349..0879731caf25 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1823,7 +1823,7 @@ void gpiochip_remove(struct gpio_chip *chip) } spin_unlock_irqrestore(&gpio_lock, flags); - if (i == gdev->ngpio) + if (i != gdev->ngpio) dev_crit(&gdev->dev, "REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED\n"); From 9eb81d69ad6bcd8a81933d02d402e80c8472ccf9 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Tue, 3 Mar 2020 11:32:15 +0800 Subject: [PATCH 1078/4444] pinctrl: sprd: Fix the kconfig warning On X86 plaform, if the CONFIG_OF is not selected, and set the CONFIG_SPRD_SC9860 as 'm', that will cause below waring: WARNING: unmet direct dependencies detected for PINCTRL_SPRD Depends on [n]: PINCTRL [=y] && OF [=n] && (ARCH_SPRD || COMPILE_TEST [=y]) Selected by [m]: - PINCTRL_SPRD_SC9860 [=m] && PINCTRL [=y] Thus move the configuration dependency under CONFIG_PINCTRL_SPRD_SC9860 to fix the warning. Reported-by: Randy Dunlap Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/eeb12d7843fb06f80e19f98eb25711231c3b610f.1583205650.git.baolin.wang7@gmail.com Acked-by: Randy Dunlap # build-tested Signed-off-by: Linus Walleij --- drivers/pinctrl/sprd/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pinctrl/sprd/Kconfig b/drivers/pinctrl/sprd/Kconfig index c9e7f0bb1145..eef35d01b770 100644 --- a/drivers/pinctrl/sprd/Kconfig +++ b/drivers/pinctrl/sprd/Kconfig @@ -4,9 +4,7 @@ # config PINCTRL_SPRD - tristate "Spreadtrum pinctrl driver" - depends on OF - depends on ARCH_SPRD || COMPILE_TEST + tristate select PINMUX select PINCONF select GENERIC_PINCONF @@ -16,6 +14,8 @@ config PINCTRL_SPRD config PINCTRL_SPRD_SC9860 tristate "Spreadtrum SC9860 pinctrl driver" + depends on OF + depends on ARCH_SPRD || COMPILE_TEST select PINCTRL_SPRD help Say Y here to enable Spreadtrum SC9860 pinctrl driver From e7e2afeacaa6e6b3d428ca8dd0507f1098bafe5d Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Tue, 3 Mar 2020 12:05:14 +0100 Subject: [PATCH 1079/4444] ASoC: amd: AMD RV RT5682 should depends on CROS_EC If SND_SOC_AMD_RV_RT5682_MACH=y, below kconfig and build errors can be seen: WARNING: unmet direct dependencies detected for SND_SOC_CROS_EC_CODEC WARNING: unmet direct dependencies detected for I2C_CROS_EC_TUNNEL ld: drivers/i2c/busses/i2c-cros-ec-tunnel.o: in function `ec_i2c_xfer': i2c-cros-ec-tunnel.c:(.text+0x2fc): undefined reference to `cros_ec_cmd_xfer_status' ld: sound/soc/codecs/cros_ec_codec.o: in function `wov_host_event': cros_ec_codec.c:(.text+0x4fb): undefined reference to `cros_ec_get_host_event' ld: sound/soc/codecs/cros_ec_codec.o: in function `send_ec_host_command': cros_ec_codec.c:(.text+0x831): undefined reference to `cros_ec_cmd_xfer_status' This is because it will select SND_SOC_CROS_EC_CODEC and I2c_CROS_EC_TUNNEL but both depends on CROS_EC. Fixes: 6b8e4e7db3cd ("ASoC: amd: Add machine driver for Raven based platform") Reported-by: Randy Dunlap Signed-off-by: Enric Balletbo i Serra Link: https://lore.kernel.org/r/20200303110514.3267126-1-enric.balletbo@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index b29ef1373946..bce4cee5cb54 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -33,6 +33,6 @@ config SND_SOC_AMD_RV_RT5682_MACH select SND_SOC_MAX98357A select SND_SOC_CROS_EC_CODEC select I2C_CROS_EC_TUNNEL - depends on SND_SOC_AMD_ACP3x && I2C + depends on SND_SOC_AMD_ACP3x && I2C && CROS_EC help This option enables machine driver for RT5682 and MAX9835. From d7729c40b376ab7c1ad4b0498a8bbf44bed3cbf4 Mon Sep 17 00:00:00 2001 From: Akshu Agrawal Date: Tue, 3 Mar 2020 14:34:37 +0530 Subject: [PATCH 1080/4444] ASoC: amd: Fix compile warning of argument type Fixes: >> sound/soc//amd/acp3x-rt5682-max9836.c:341:23: warning: format '%d' >> expects argument of type 'int', but argument 3 has type 'long int' >> [-Wformat=] dev_err(&pdev->dev, "DMIC gpio failed err=%d\n", Reported-by: kbuild test robot Signed-off-by: Akshu Agrawal Link: https://lore.kernel.org/r/20200303090444.95805-1-akshu.agrawal@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp3x-rt5682-max9836.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c index 511b8b1722aa..521c9ab4c29c 100644 --- a/sound/soc/amd/acp3x-rt5682-max9836.c +++ b/sound/soc/amd/acp3x-rt5682-max9836.c @@ -338,7 +338,7 @@ static int acp3x_probe(struct platform_device *pdev) dmic_sel = devm_gpiod_get(&pdev->dev, "dmic", GPIOD_OUT_LOW); if (IS_ERR(dmic_sel)) { - dev_err(&pdev->dev, "DMIC gpio failed err=%d\n", + dev_err(&pdev->dev, "DMIC gpio failed err=%ld\n", PTR_ERR(dmic_sel)); return PTR_ERR(dmic_sel); } From 69e60903aaf5aa56548656897d2b0fbe4431a7fe Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 3 Mar 2020 07:17:43 -0800 Subject: [PATCH 1081/4444] bus: ti-sysc: Fix wrong offset for display subsystem reset quirk Commit 7324a7a0d5e2 ("bus: ti-sysc: Implement display subsystem reset quirk") added support for DSS reset, but is using dispc offset also for DSS also registers as reported by Tomi Valkeinen . Also, we're not using dispc_offset for dispc IRQSTATUS register so let's fix that too. Fixes: 7324a7a0d5e2 ("bus: ti-sysc: Implement display subsystem reset quirk") Reported-by: Tomi Valkeinen Reviewed-by: Tomi Valkeinen Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index e30c97ca5579..46b25fa4237f 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1566,7 +1566,7 @@ static void sysc_pre_reset_quirk_dss(struct sysc *ddata) return; /* Clear IRQSTATUS */ - sysc_write(ddata, 0x1000 + 0x18, irq_mask); + sysc_write(ddata, dispc_offset + 0x18, irq_mask); /* Disable outputs */ val = sysc_quirk_dispc(ddata, dispc_offset, true); @@ -1580,14 +1580,14 @@ static void sysc_pre_reset_quirk_dss(struct sysc *ddata) if (sysc_soc->soc == SOC_3430) { /* Clear DSS_SDI_CONTROL */ - sysc_write(ddata, dispc_offset + 0x44, 0); + sysc_write(ddata, 0x44, 0); /* Clear DSS_PLL_CONTROL */ - sysc_write(ddata, dispc_offset + 0x48, 0); + sysc_write(ddata, 0x48, 0); } /* Clear DSS_CONTROL to switch DSS clock sources to PRCM if not */ - sysc_write(ddata, dispc_offset + 0x40, 0); + sysc_write(ddata, 0x40, 0); } /* 1-wire needs module's internal clocks enabled for reset */ From c77af39bdb8b0f0605b484428a65ec0d97ba18dc Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Tue, 3 Mar 2020 19:02:52 +0200 Subject: [PATCH 1082/4444] dt-bindings: interconnect: Add Qualcomm SC7180 DT bindings The Qualcomm SC7180 platform has several bus fabrics that could be controlled and tuned dynamically according to the bandwidth demand. Signed-off-by: Odelu Kukatla Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/1583241493-21212-2-git-send-email-okukatla@codeaurora.org Signed-off-by: Georgi Djakov --- .../bindings/interconnect/qcom,sc7180.yaml | 85 +++++++++ .../dt-bindings/interconnect/qcom,sc7180.h | 161 ++++++++++++++++++ 2 files changed, 246 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/qcom,sc7180.yaml create mode 100644 include/dt-bindings/interconnect/qcom,sc7180.h diff --git a/Documentation/devicetree/bindings/interconnect/qcom,sc7180.yaml b/Documentation/devicetree/bindings/interconnect/qcom,sc7180.yaml new file mode 100644 index 000000000000..50f78f87f3fb --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/qcom,sc7180.yaml @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interconnect/qcom,sc7180.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SC7180 Network-On-Chip Interconnect + +maintainers: + - Odelu Kukatla + +description: | + SC7180 interconnect providers support system bandwidth requirements through + RPMh hardware accelerators known as Bus Clock Manager (BCM). The provider is + able to communicate with the BCM through the Resource State Coordinator (RSC) + associated with each execution environment. Provider nodes must point to at + least one RPMh device child node pertaining to their RSC and each provider + can map to multiple RPMh resources. + +properties: + reg: + maxItems: 1 + + compatible: + enum: + - qcom,sc7180-aggre1-noc + - qcom,sc7180-aggre2-noc + - qcom,sc7180-camnoc-virt + - qcom,sc7180-compute-noc + - qcom,sc7180-config-noc + - qcom,sc7180-dc-noc + - qcom,sc7180-gem-noc + - qcom,sc7180-ipa-virt + - qcom,sc7180-mc-virt + - qcom,sc7180-mmss-noc + - qcom,sc7180-npu-noc + - qcom,sc7180-qup-virt + - qcom,sc7180-system-noc + + '#interconnect-cells': + const: 1 + + qcom,bcm-voters: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: | + List of phandles to qcom,bcm-voter nodes that are required by + this interconnect to send RPMh commands. + + qcom,bcm-voter-names: + $ref: /schemas/types.yaml#/definitions/string-array + description: | + Names for each of the qcom,bcm-voters specified. + +required: + - compatible + - reg + - '#interconnect-cells' + - qcom,bcm-voters + +additionalProperties: false + +examples: + - | + #include + + config_noc: interconnect@1500000 { + compatible = "qcom,sc7180-config-noc"; + reg = <0 0x01500000 0 0x28000>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + system_noc: interconnect@1620000 { + compatible = "qcom,sc7180-system-noc"; + reg = <0 0x01620000 0 0x17080>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + mmss_noc: interconnect@1740000 { + compatible = "qcom,sc7180-mmss-noc"; + reg = <0 0x01740000 0 0x1c100>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; diff --git a/include/dt-bindings/interconnect/qcom,sc7180.h b/include/dt-bindings/interconnect/qcom,sc7180.h new file mode 100644 index 000000000000..f9970f6032eb --- /dev/null +++ b/include/dt-bindings/interconnect/qcom,sc7180.h @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Qualcomm SC7180 interconnect IDs + * + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_SC7180_H +#define __DT_BINDINGS_INTERCONNECT_QCOM_SC7180_H + +#define MASTER_A1NOC_CFG 0 +#define MASTER_QSPI 1 +#define MASTER_QUP_0 2 +#define MASTER_SDCC_2 3 +#define MASTER_EMMC 4 +#define MASTER_UFS_MEM 5 +#define SLAVE_A1NOC_SNOC 6 +#define SLAVE_SERVICE_A1NOC 7 + +#define MASTER_A2NOC_CFG 0 +#define MASTER_QDSS_BAM 1 +#define MASTER_QUP_1 2 +#define MASTER_USB3 3 +#define MASTER_CRYPTO 4 +#define MASTER_IPA 5 +#define MASTER_QDSS_ETR 6 +#define SLAVE_A2NOC_SNOC 7 +#define SLAVE_SERVICE_A2NOC 8 + +#define MASTER_CAMNOC_HF0_UNCOMP 0 +#define MASTER_CAMNOC_HF1_UNCOMP 1 +#define MASTER_CAMNOC_SF_UNCOMP 2 +#define SLAVE_CAMNOC_UNCOMP 3 + +#define MASTER_NPU 0 +#define MASTER_NPU_PROC 1 +#define SLAVE_CDSP_GEM_NOC 2 + +#define MASTER_SNOC_CNOC 0 +#define MASTER_QDSS_DAP 1 +#define SLAVE_A1NOC_CFG 2 +#define SLAVE_A2NOC_CFG 3 +#define SLAVE_AHB2PHY_SOUTH 4 +#define SLAVE_AHB2PHY_CENTER 5 +#define SLAVE_AOP 6 +#define SLAVE_AOSS 7 +#define SLAVE_BOOT_ROM 8 +#define SLAVE_CAMERA_CFG 9 +#define SLAVE_CAMERA_NRT_THROTTLE_CFG 10 +#define SLAVE_CAMERA_RT_THROTTLE_CFG 11 +#define SLAVE_CLK_CTL 12 +#define SLAVE_RBCPR_CX_CFG 13 +#define SLAVE_RBCPR_MX_CFG 14 +#define SLAVE_CRYPTO_0_CFG 15 +#define SLAVE_DCC_CFG 16 +#define SLAVE_CNOC_DDRSS 17 +#define SLAVE_DISPLAY_CFG 18 +#define SLAVE_DISPLAY_RT_THROTTLE_CFG 19 +#define SLAVE_DISPLAY_THROTTLE_CFG 20 +#define SLAVE_EMMC_CFG 21 +#define SLAVE_GLM 22 +#define SLAVE_GFX3D_CFG 23 +#define SLAVE_IMEM_CFG 24 +#define SLAVE_IPA_CFG 25 +#define SLAVE_CNOC_MNOC_CFG 26 +#define SLAVE_CNOC_MSS 27 +#define SLAVE_NPU_CFG 28 +#define SLAVE_NPU_DMA_BWMON_CFG 29 +#define SLAVE_NPU_PROC_BWMON_CFG 30 +#define SLAVE_PDM 31 +#define SLAVE_PIMEM_CFG 32 +#define SLAVE_PRNG 33 +#define SLAVE_QDSS_CFG 34 +#define SLAVE_QM_CFG 35 +#define SLAVE_QM_MPU_CFG 36 +#define SLAVE_QSPI_0 37 +#define SLAVE_QUP_0 38 +#define SLAVE_QUP_1 39 +#define SLAVE_SDCC_2 40 +#define SLAVE_SECURITY 41 +#define SLAVE_SNOC_CFG 42 +#define SLAVE_TCSR 43 +#define SLAVE_TLMM_WEST 44 +#define SLAVE_TLMM_NORTH 45 +#define SLAVE_TLMM_SOUTH 46 +#define SLAVE_UFS_MEM_CFG 47 +#define SLAVE_USB3 48 +#define SLAVE_VENUS_CFG 49 +#define SLAVE_VENUS_THROTTLE_CFG 50 +#define SLAVE_VSENSE_CTRL_CFG 51 +#define SLAVE_SERVICE_CNOC 52 + +#define MASTER_CNOC_DC_NOC 0 +#define SLAVE_GEM_NOC_CFG 1 +#define SLAVE_LLCC_CFG 2 + +#define MASTER_APPSS_PROC 0 +#define MASTER_SYS_TCU 1 +#define MASTER_GEM_NOC_CFG 2 +#define MASTER_COMPUTE_NOC 3 +#define MASTER_MNOC_HF_MEM_NOC 4 +#define MASTER_MNOC_SF_MEM_NOC 5 +#define MASTER_SNOC_GC_MEM_NOC 6 +#define MASTER_SNOC_SF_MEM_NOC 7 +#define MASTER_GFX3D 8 +#define SLAVE_MSS_PROC_MS_MPU_CFG 9 +#define SLAVE_GEM_NOC_SNOC 10 +#define SLAVE_LLCC 11 +#define SLAVE_SERVICE_GEM_NOC 12 + +#define MASTER_IPA_CORE 0 +#define SLAVE_IPA_CORE 1 + +#define MASTER_LLCC 0 +#define SLAVE_EBI1 1 + +#define MASTER_CNOC_MNOC_CFG 0 +#define MASTER_CAMNOC_HF0 1 +#define MASTER_CAMNOC_HF1 2 +#define MASTER_CAMNOC_SF 3 +#define MASTER_MDP0 4 +#define MASTER_ROTATOR 5 +#define MASTER_VIDEO_P0 6 +#define MASTER_VIDEO_PROC 7 +#define SLAVE_MNOC_HF_MEM_NOC 8 +#define SLAVE_MNOC_SF_MEM_NOC 9 +#define SLAVE_SERVICE_MNOC 10 + +#define MASTER_NPU_SYS 0 +#define MASTER_NPU_NOC_CFG 1 +#define SLAVE_NPU_CAL_DP0 2 +#define SLAVE_NPU_CP 3 +#define SLAVE_NPU_INT_DMA_BWMON_CFG 4 +#define SLAVE_NPU_DPM 5 +#define SLAVE_ISENSE_CFG 6 +#define SLAVE_NPU_LLM_CFG 7 +#define SLAVE_NPU_TCM 8 +#define SLAVE_NPU_COMPUTE_NOC 9 +#define SLAVE_SERVICE_NPU_NOC 10 + +#define MASTER_QUP_CORE_0 0 +#define MASTER_QUP_CORE_1 1 +#define SLAVE_QUP_CORE_0 2 +#define SLAVE_QUP_CORE_1 3 + +#define MASTER_SNOC_CFG 0 +#define MASTER_A1NOC_SNOC 1 +#define MASTER_A2NOC_SNOC 2 +#define MASTER_GEM_NOC_SNOC 3 +#define MASTER_PIMEM 4 +#define SLAVE_APPSS 5 +#define SLAVE_SNOC_CNOC 6 +#define SLAVE_SNOC_GEM_NOC_GC 7 +#define SLAVE_SNOC_GEM_NOC_SF 8 +#define SLAVE_IMEM 9 +#define SLAVE_PIMEM 10 +#define SLAVE_SERVICE_SNOC 11 +#define SLAVE_QDSS_STM 12 +#define SLAVE_TCU 13 + +#endif From 2d1f95ab9feb4f5373f81c3805bfbc126670812d Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Tue, 3 Mar 2020 19:02:52 +0200 Subject: [PATCH 1083/4444] interconnect: qcom: Add SC7180 interconnect provider driver Add driver for the Qualcomm interconnect buses found in SC7180 based platforms. The topology consists of several NoCs that are controlled by a remote processor that collects the aggregated bandwidth for each master-slave pairs. Signed-off-by: Odelu Kukatla Link: https://lore.kernel.org/r/1583241493-21212-3-git-send-email-okukatla@codeaurora.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/Kconfig | 10 + drivers/interconnect/qcom/Makefile | 2 + drivers/interconnect/qcom/sc7180.c | 641 +++++++++++++++++++++++++++++ drivers/interconnect/qcom/sc7180.h | 149 +++++++ 4 files changed, 802 insertions(+) create mode 100644 drivers/interconnect/qcom/sc7180.c create mode 100644 drivers/interconnect/qcom/sc7180.h diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig index 87c926897e78..c36155611434 100644 --- a/drivers/interconnect/qcom/Kconfig +++ b/drivers/interconnect/qcom/Kconfig @@ -38,6 +38,16 @@ config INTERCONNECT_QCOM_QCS404 config INTERCONNECT_QCOM_RPMH tristate +config INTERCONNECT_QCOM_SC7180 + tristate "Qualcomm SC7180 interconnect driver" + depends on INTERCONNECT_QCOM + depends on (QCOM_RPMH && QCOM_COMMAND_DB && OF) || COMPILE_TEST + select INTERCONNECT_QCOM_RPMH + select INTERCONNECT_QCOM_BCM_VOTER + help + This is a driver for the Qualcomm Network-on-Chip on sc7180-based + platforms. + config INTERCONNECT_QCOM_SDM845 tristate "Qualcomm SDM845 interconnect driver" depends on INTERCONNECT_QCOM diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile index d591bb56273b..532555812ef6 100644 --- a/drivers/interconnect/qcom/Makefile +++ b/drivers/interconnect/qcom/Makefile @@ -5,6 +5,7 @@ qnoc-msm8916-objs := msm8916.o qnoc-msm8974-objs := msm8974.o qnoc-qcs404-objs := qcs404.o icc-rpmh-obj := icc-rpmh.o +qnoc-sc7180-objs := sc7180.o qnoc-sdm845-objs := sdm845.o icc-smd-rpm-objs := smd-rpm.o @@ -13,5 +14,6 @@ obj-$(CONFIG_INTERCONNECT_QCOM_MSM8916) += qnoc-msm8916.o obj-$(CONFIG_INTERCONNECT_QCOM_MSM8974) += qnoc-msm8974.o obj-$(CONFIG_INTERCONNECT_QCOM_QCS404) += qnoc-qcs404.o obj-$(CONFIG_INTERCONNECT_QCOM_RPMH) += icc-rpmh.o +obj-$(CONFIG_INTERCONNECT_QCOM_SC7180) += qnoc-sc7180.o obj-$(CONFIG_INTERCONNECT_QCOM_SDM845) += qnoc-sdm845.o obj-$(CONFIG_INTERCONNECT_QCOM_SMD_RPM) += icc-smd-rpm.o diff --git a/drivers/interconnect/qcom/sc7180.c b/drivers/interconnect/qcom/sc7180.c new file mode 100644 index 000000000000..dcf493d07928 --- /dev/null +++ b/drivers/interconnect/qcom/sc7180.c @@ -0,0 +1,641 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "bcm-voter.h" +#include "icc-rpmh.h" +#include "sc7180.h" + +DEFINE_QNODE(qhm_a1noc_cfg, SC7180_MASTER_A1NOC_CFG, 1, 4, SC7180_SLAVE_SERVICE_A1NOC); +DEFINE_QNODE(qhm_qspi, SC7180_MASTER_QSPI, 1, 4, SC7180_SLAVE_A1NOC_SNOC); +DEFINE_QNODE(qhm_qup_0, SC7180_MASTER_QUP_0, 1, 4, SC7180_SLAVE_A1NOC_SNOC); +DEFINE_QNODE(xm_sdc2, SC7180_MASTER_SDCC_2, 1, 8, SC7180_SLAVE_A1NOC_SNOC); +DEFINE_QNODE(xm_emmc, SC7180_MASTER_EMMC, 1, 8, SC7180_SLAVE_A1NOC_SNOC); +DEFINE_QNODE(xm_ufs_mem, SC7180_MASTER_UFS_MEM, 1, 8, SC7180_SLAVE_A1NOC_SNOC); +DEFINE_QNODE(qhm_a2noc_cfg, SC7180_MASTER_A2NOC_CFG, 1, 4, SC7180_SLAVE_SERVICE_A2NOC); +DEFINE_QNODE(qhm_qdss_bam, SC7180_MASTER_QDSS_BAM, 1, 4, SC7180_SLAVE_A2NOC_SNOC); +DEFINE_QNODE(qhm_qup_1, SC7180_MASTER_QUP_1, 1, 4, SC7180_SLAVE_A2NOC_SNOC); +DEFINE_QNODE(qxm_crypto, SC7180_MASTER_CRYPTO, 1, 8, SC7180_SLAVE_A2NOC_SNOC); +DEFINE_QNODE(qxm_ipa, SC7180_MASTER_IPA, 1, 8, SC7180_SLAVE_A2NOC_SNOC); +DEFINE_QNODE(xm_qdss_etr, SC7180_MASTER_QDSS_ETR, 1, 8, SC7180_SLAVE_A2NOC_SNOC); +DEFINE_QNODE(qhm_usb3, SC7180_MASTER_USB3, 1, 8, SC7180_SLAVE_A2NOC_SNOC); +DEFINE_QNODE(qxm_camnoc_hf0_uncomp, SC7180_MASTER_CAMNOC_HF0_UNCOMP, 1, 32, SC7180_SLAVE_CAMNOC_UNCOMP); +DEFINE_QNODE(qxm_camnoc_hf1_uncomp, SC7180_MASTER_CAMNOC_HF1_UNCOMP, 1, 32, SC7180_SLAVE_CAMNOC_UNCOMP); +DEFINE_QNODE(qxm_camnoc_sf_uncomp, SC7180_MASTER_CAMNOC_SF_UNCOMP, 1, 32, SC7180_SLAVE_CAMNOC_UNCOMP); +DEFINE_QNODE(qnm_npu, SC7180_MASTER_NPU, 2, 32, SC7180_SLAVE_CDSP_GEM_NOC); +DEFINE_QNODE(qxm_npu_dsp, SC7180_MASTER_NPU_PROC, 1, 8, SC7180_SLAVE_CDSP_GEM_NOC); +DEFINE_QNODE(qnm_snoc, SC7180_MASTER_SNOC_CNOC, 1, 8, SC7180_SLAVE_A1NOC_CFG, SC7180_SLAVE_A2NOC_CFG, SC7180_SLAVE_AHB2PHY_SOUTH, SC7180_SLAVE_AHB2PHY_CENTER, SC7180_SLAVE_AOP, SC7180_SLAVE_AOSS, SC7180_SLAVE_BOOT_ROM, SC7180_SLAVE_CAMERA_CFG, SC7180_SLAVE_CAMERA_NRT_THROTTLE_CFG, SC7180_SLAVE_CAMERA_RT_THROTTLE_CFG, SC7180_SLAVE_CLK_CTL, SC7180_SLAVE_RBCPR_CX_CFG, SC7180_SLAVE_RBCPR_MX_CFG, SC7180_SLAVE_CRYPTO_0_CFG, SC7180_SLAVE_DCC_CFG, SC7180_SLAVE_CNOC_DDRSS, SC7180_SLAVE_DISPLAY_CFG, SC7180_SLAVE_DISPLAY_RT_THROTTLE_CFG, SC7180_SLAVE_DISPLAY_THROTTLE_CFG, SC7180_SLAVE_EMMC_CFG, SC7180_SLAVE_GLM, + SC7180_SLAVE_GFX3D_CFG, SC7180_SLAVE_IMEM_CFG, SC7180_SLAVE_IPA_CFG, SC7180_SLAVE_CNOC_MNOC_CFG, SC7180_SLAVE_CNOC_MSS, SC7180_SLAVE_NPU_CFG, SC7180_SLAVE_NPU_DMA_BWMON_CFG, SC7180_SLAVE_NPU_PROC_BWMON_CFG, SC7180_SLAVE_PDM, SC7180_SLAVE_PIMEM_CFG, SC7180_SLAVE_PRNG, SC7180_SLAVE_QDSS_CFG, SC7180_SLAVE_QM_CFG, SC7180_SLAVE_QM_MPU_CFG, SC7180_SLAVE_QSPI_0, SC7180_SLAVE_QUP_0, SC7180_SLAVE_QUP_1, SC7180_SLAVE_SDCC_2, SC7180_SLAVE_SECURITY, SC7180_SLAVE_SNOC_CFG, SC7180_SLAVE_TCSR, SC7180_SLAVE_TLMM_WEST, SC7180_SLAVE_TLMM_NORTH, SC7180_SLAVE_TLMM_SOUTH, SC7180_SLAVE_UFS_MEM_CFG, SC7180_SLAVE_USB3, SC7180_SLAVE_VENUS_CFG, SC7180_SLAVE_VENUS_THROTTLE_CFG, SC7180_SLAVE_VSENSE_CTRL_CFG, SC7180_SLAVE_SERVICE_CNOC); +DEFINE_QNODE(xm_qdss_dap, SC7180_MASTER_QDSS_DAP, 1, 8, SC7180_SLAVE_A1NOC_CFG, SC7180_SLAVE_A2NOC_CFG, SC7180_SLAVE_AHB2PHY_SOUTH, SC7180_SLAVE_AHB2PHY_CENTER, SC7180_SLAVE_AOP, SC7180_SLAVE_AOSS, SC7180_SLAVE_BOOT_ROM, SC7180_SLAVE_CAMERA_CFG, SC7180_SLAVE_CAMERA_NRT_THROTTLE_CFG, SC7180_SLAVE_CAMERA_RT_THROTTLE_CFG, SC7180_SLAVE_CLK_CTL, SC7180_SLAVE_RBCPR_CX_CFG, SC7180_SLAVE_RBCPR_MX_CFG, SC7180_SLAVE_CRYPTO_0_CFG, SC7180_SLAVE_DCC_CFG, SC7180_SLAVE_CNOC_DDRSS, SC7180_SLAVE_DISPLAY_CFG, SC7180_SLAVE_DISPLAY_RT_THROTTLE_CFG, SC7180_SLAVE_DISPLAY_THROTTLE_CFG, SC7180_SLAVE_EMMC_CFG, SC7180_SLAVE_GLM, SC7180_SLAVE_GFX3D_CFG, SC7180_SLAVE_IMEM_CFG, SC7180_SLAVE_IPA_CFG, SC7180_SLAVE_CNOC_MNOC_CFG, SC7180_SLAVE_CNOC_MSS, SC7180_SLAVE_NPU_CFG, SC7180_SLAVE_NPU_DMA_BWMON_CFG, +SC7180_SLAVE_NPU_PROC_BWMON_CFG, SC7180_SLAVE_PDM, SC7180_SLAVE_PIMEM_CFG, SC7180_SLAVE_PRNG, SC7180_SLAVE_QDSS_CFG, SC7180_SLAVE_QM_CFG, SC7180_SLAVE_QM_MPU_CFG, SC7180_SLAVE_QSPI_0, SC7180_SLAVE_QUP_0, SC7180_SLAVE_QUP_1, SC7180_SLAVE_SDCC_2, SC7180_SLAVE_SECURITY, SC7180_SLAVE_SNOC_CFG, SC7180_SLAVE_TCSR, SC7180_SLAVE_TLMM_WEST, SC7180_SLAVE_TLMM_NORTH, SC7180_SLAVE_TLMM_SOUTH, SC7180_SLAVE_UFS_MEM_CFG, SC7180_SLAVE_USB3, SC7180_SLAVE_VENUS_CFG, SC7180_SLAVE_VENUS_THROTTLE_CFG, SC7180_SLAVE_VSENSE_CTRL_CFG, SC7180_SLAVE_SERVICE_CNOC); +DEFINE_QNODE(qhm_cnoc_dc_noc, SC7180_MASTER_CNOC_DC_NOC, 1, 4, SC7180_SLAVE_GEM_NOC_CFG, SC7180_SLAVE_LLCC_CFG); +DEFINE_QNODE(acm_apps0, SC7180_MASTER_APPSS_PROC, 1, 16, SC7180_SLAVE_GEM_NOC_SNOC, SC7180_SLAVE_LLCC); +DEFINE_QNODE(acm_sys_tcu, SC7180_MASTER_SYS_TCU, 1, 8, SC7180_SLAVE_GEM_NOC_SNOC, SC7180_SLAVE_LLCC); +DEFINE_QNODE(qhm_gemnoc_cfg, SC7180_MASTER_GEM_NOC_CFG, 1, 4, SC7180_SLAVE_MSS_PROC_MS_MPU_CFG, SC7180_SLAVE_SERVICE_GEM_NOC); +DEFINE_QNODE(qnm_cmpnoc, SC7180_MASTER_COMPUTE_NOC, 1, 32, SC7180_SLAVE_GEM_NOC_SNOC, SC7180_SLAVE_LLCC); +DEFINE_QNODE(qnm_mnoc_hf, SC7180_MASTER_MNOC_HF_MEM_NOC, 1, 32, SC7180_SLAVE_LLCC); +DEFINE_QNODE(qnm_mnoc_sf, SC7180_MASTER_MNOC_SF_MEM_NOC, 1, 32, SC7180_SLAVE_GEM_NOC_SNOC, SC7180_SLAVE_LLCC); +DEFINE_QNODE(qnm_snoc_gc, SC7180_MASTER_SNOC_GC_MEM_NOC, 1, 8, SC7180_SLAVE_LLCC); +DEFINE_QNODE(qnm_snoc_sf, SC7180_MASTER_SNOC_SF_MEM_NOC, 1, 16, SC7180_SLAVE_LLCC); +DEFINE_QNODE(qxm_gpu, SC7180_MASTER_GFX3D, 2, 32, SC7180_SLAVE_GEM_NOC_SNOC, SC7180_SLAVE_LLCC); +DEFINE_QNODE(ipa_core_master, SC7180_MASTER_IPA_CORE, 1, 8, SC7180_SLAVE_IPA_CORE); +DEFINE_QNODE(llcc_mc, SC7180_MASTER_LLCC, 2, 4, SC7180_SLAVE_EBI1); +DEFINE_QNODE(qhm_mnoc_cfg, SC7180_MASTER_CNOC_MNOC_CFG, 1, 4, SC7180_SLAVE_SERVICE_MNOC); +DEFINE_QNODE(qxm_camnoc_hf0, SC7180_MASTER_CAMNOC_HF0, 2, 32, SC7180_SLAVE_MNOC_HF_MEM_NOC); +DEFINE_QNODE(qxm_camnoc_hf1, SC7180_MASTER_CAMNOC_HF1, 2, 32, SC7180_SLAVE_MNOC_HF_MEM_NOC); +DEFINE_QNODE(qxm_camnoc_sf, SC7180_MASTER_CAMNOC_SF, 1, 32, SC7180_SLAVE_MNOC_SF_MEM_NOC); +DEFINE_QNODE(qxm_mdp0, SC7180_MASTER_MDP0, 1, 32, SC7180_SLAVE_MNOC_HF_MEM_NOC); +DEFINE_QNODE(qxm_rot, SC7180_MASTER_ROTATOR, 1, 16, SC7180_SLAVE_MNOC_SF_MEM_NOC); +DEFINE_QNODE(qxm_venus0, SC7180_MASTER_VIDEO_P0, 1, 32, SC7180_SLAVE_MNOC_SF_MEM_NOC); +DEFINE_QNODE(qxm_venus_arm9, SC7180_MASTER_VIDEO_PROC, 1, 8, SC7180_SLAVE_MNOC_SF_MEM_NOC); +DEFINE_QNODE(amm_npu_sys, SC7180_MASTER_NPU_SYS, 2, 32, SC7180_SLAVE_NPU_COMPUTE_NOC); +DEFINE_QNODE(qhm_npu_cfg, SC7180_MASTER_NPU_NOC_CFG, 1, 4, SC7180_SLAVE_NPU_CAL_DP0, SC7180_SLAVE_NPU_CP, SC7180_SLAVE_NPU_INT_DMA_BWMON_CFG, SC7180_SLAVE_NPU_DPM, SC7180_SLAVE_ISENSE_CFG, SC7180_SLAVE_NPU_LLM_CFG, SC7180_SLAVE_NPU_TCM, SC7180_SLAVE_SERVICE_NPU_NOC); +DEFINE_QNODE(qup_core_master_1, SC7180_MASTER_QUP_CORE_0, 1, 4, SC7180_SLAVE_QUP_CORE_0); +DEFINE_QNODE(qup_core_master_2, SC7180_MASTER_QUP_CORE_1, 1, 4, SC7180_SLAVE_QUP_CORE_1); +DEFINE_QNODE(qhm_snoc_cfg, SC7180_MASTER_SNOC_CFG, 1, 4, SC7180_SLAVE_SERVICE_SNOC); +DEFINE_QNODE(qnm_aggre1_noc, SC7180_MASTER_A1NOC_SNOC, 1, 16, SC7180_SLAVE_APPSS, SC7180_SLAVE_SNOC_CNOC, SC7180_SLAVE_SNOC_GEM_NOC_SF, SC7180_SLAVE_IMEM, SC7180_SLAVE_PIMEM, SC7180_SLAVE_QDSS_STM); +DEFINE_QNODE(qnm_aggre2_noc, SC7180_MASTER_A2NOC_SNOC, 1, 16, SC7180_SLAVE_APPSS, SC7180_SLAVE_SNOC_CNOC, SC7180_SLAVE_SNOC_GEM_NOC_SF, SC7180_SLAVE_IMEM, SC7180_SLAVE_PIMEM, SC7180_SLAVE_QDSS_STM, SC7180_SLAVE_TCU); +DEFINE_QNODE(qnm_gemnoc, SC7180_MASTER_GEM_NOC_SNOC, 1, 8, SC7180_SLAVE_APPSS, SC7180_SLAVE_SNOC_CNOC, SC7180_SLAVE_IMEM, SC7180_SLAVE_PIMEM, SC7180_SLAVE_QDSS_STM, SC7180_SLAVE_TCU); +DEFINE_QNODE(qxm_pimem, SC7180_MASTER_PIMEM, 1, 8, SC7180_SLAVE_SNOC_GEM_NOC_GC, SC7180_SLAVE_IMEM); +DEFINE_QNODE(qns_a1noc_snoc, SC7180_SLAVE_A1NOC_SNOC, 1, 16, SC7180_MASTER_A1NOC_SNOC); +DEFINE_QNODE(srvc_aggre1_noc, SC7180_SLAVE_SERVICE_A1NOC, 1, 4); +DEFINE_QNODE(qns_a2noc_snoc, SC7180_SLAVE_A2NOC_SNOC, 1, 16, SC7180_MASTER_A2NOC_SNOC); +DEFINE_QNODE(srvc_aggre2_noc, SC7180_SLAVE_SERVICE_A2NOC, 1, 4); +DEFINE_QNODE(qns_camnoc_uncomp, SC7180_SLAVE_CAMNOC_UNCOMP, 1, 32); +DEFINE_QNODE(qns_cdsp_gemnoc, SC7180_SLAVE_CDSP_GEM_NOC, 1, 32, SC7180_MASTER_COMPUTE_NOC); +DEFINE_QNODE(qhs_a1_noc_cfg, SC7180_SLAVE_A1NOC_CFG, 1, 4, SC7180_MASTER_A1NOC_CFG); +DEFINE_QNODE(qhs_a2_noc_cfg, SC7180_SLAVE_A2NOC_CFG, 1, 4, SC7180_MASTER_A2NOC_CFG); +DEFINE_QNODE(qhs_ahb2phy0, SC7180_SLAVE_AHB2PHY_SOUTH, 1, 4); +DEFINE_QNODE(qhs_ahb2phy2, SC7180_SLAVE_AHB2PHY_CENTER, 1, 4); +DEFINE_QNODE(qhs_aop, SC7180_SLAVE_AOP, 1, 4); +DEFINE_QNODE(qhs_aoss, SC7180_SLAVE_AOSS, 1, 4); +DEFINE_QNODE(qhs_boot_rom, SC7180_SLAVE_BOOT_ROM, 1, 4); +DEFINE_QNODE(qhs_camera_cfg, SC7180_SLAVE_CAMERA_CFG, 1, 4); +DEFINE_QNODE(qhs_camera_nrt_throttle_cfg, SC7180_SLAVE_CAMERA_NRT_THROTTLE_CFG, 1, 4); +DEFINE_QNODE(qhs_camera_rt_throttle_cfg, SC7180_SLAVE_CAMERA_RT_THROTTLE_CFG, 1, 4); +DEFINE_QNODE(qhs_clk_ctl, SC7180_SLAVE_CLK_CTL, 1, 4); +DEFINE_QNODE(qhs_cpr_cx, SC7180_SLAVE_RBCPR_CX_CFG, 1, 4); +DEFINE_QNODE(qhs_cpr_mx, SC7180_SLAVE_RBCPR_MX_CFG, 1, 4); +DEFINE_QNODE(qhs_crypto0_cfg, SC7180_SLAVE_CRYPTO_0_CFG, 1, 4); +DEFINE_QNODE(qhs_dcc_cfg, SC7180_SLAVE_DCC_CFG, 1, 4); +DEFINE_QNODE(qhs_ddrss_cfg, SC7180_SLAVE_CNOC_DDRSS, 1, 4, SC7180_MASTER_CNOC_DC_NOC); +DEFINE_QNODE(qhs_display_cfg, SC7180_SLAVE_DISPLAY_CFG, 1, 4); +DEFINE_QNODE(qhs_display_rt_throttle_cfg, SC7180_SLAVE_DISPLAY_RT_THROTTLE_CFG, 1, 4); +DEFINE_QNODE(qhs_display_throttle_cfg, SC7180_SLAVE_DISPLAY_THROTTLE_CFG, 1, 4); +DEFINE_QNODE(qhs_emmc_cfg, SC7180_SLAVE_EMMC_CFG, 1, 4); +DEFINE_QNODE(qhs_glm, SC7180_SLAVE_GLM, 1, 4); +DEFINE_QNODE(qhs_gpuss_cfg, SC7180_SLAVE_GFX3D_CFG, 1, 8); +DEFINE_QNODE(qhs_imem_cfg, SC7180_SLAVE_IMEM_CFG, 1, 4); +DEFINE_QNODE(qhs_ipa, SC7180_SLAVE_IPA_CFG, 1, 4); +DEFINE_QNODE(qhs_mnoc_cfg, SC7180_SLAVE_CNOC_MNOC_CFG, 1, 4, SC7180_MASTER_CNOC_MNOC_CFG); +DEFINE_QNODE(qhs_mss_cfg, SC7180_SLAVE_CNOC_MSS, 1, 4); +DEFINE_QNODE(qhs_npu_cfg, SC7180_SLAVE_NPU_CFG, 1, 4, SC7180_MASTER_NPU_NOC_CFG); +DEFINE_QNODE(qhs_npu_dma_throttle_cfg, SC7180_SLAVE_NPU_DMA_BWMON_CFG, 1, 4); +DEFINE_QNODE(qhs_npu_dsp_throttle_cfg, SC7180_SLAVE_NPU_PROC_BWMON_CFG, 1, 4); +DEFINE_QNODE(qhs_pdm, SC7180_SLAVE_PDM, 1, 4); +DEFINE_QNODE(qhs_pimem_cfg, SC7180_SLAVE_PIMEM_CFG, 1, 4); +DEFINE_QNODE(qhs_prng, SC7180_SLAVE_PRNG, 1, 4); +DEFINE_QNODE(qhs_qdss_cfg, SC7180_SLAVE_QDSS_CFG, 1, 4); +DEFINE_QNODE(qhs_qm_cfg, SC7180_SLAVE_QM_CFG, 1, 4); +DEFINE_QNODE(qhs_qm_mpu_cfg, SC7180_SLAVE_QM_MPU_CFG, 1, 4); +DEFINE_QNODE(qhs_qspi, SC7180_SLAVE_QSPI_0, 1, 4); +DEFINE_QNODE(qhs_qup0, SC7180_SLAVE_QUP_0, 1, 4); +DEFINE_QNODE(qhs_qup1, SC7180_SLAVE_QUP_1, 1, 4); +DEFINE_QNODE(qhs_sdc2, SC7180_SLAVE_SDCC_2, 1, 4); +DEFINE_QNODE(qhs_security, SC7180_SLAVE_SECURITY, 1, 4); +DEFINE_QNODE(qhs_snoc_cfg, SC7180_SLAVE_SNOC_CFG, 1, 4, SC7180_MASTER_SNOC_CFG); +DEFINE_QNODE(qhs_tcsr, SC7180_SLAVE_TCSR, 1, 4); +DEFINE_QNODE(qhs_tlmm_1, SC7180_SLAVE_TLMM_WEST, 1, 4); +DEFINE_QNODE(qhs_tlmm_2, SC7180_SLAVE_TLMM_NORTH, 1, 4); +DEFINE_QNODE(qhs_tlmm_3, SC7180_SLAVE_TLMM_SOUTH, 1, 4); +DEFINE_QNODE(qhs_ufs_mem_cfg, SC7180_SLAVE_UFS_MEM_CFG, 1, 4); +DEFINE_QNODE(qhs_usb3, SC7180_SLAVE_USB3, 1, 4); +DEFINE_QNODE(qhs_venus_cfg, SC7180_SLAVE_VENUS_CFG, 1, 4); +DEFINE_QNODE(qhs_venus_throttle_cfg, SC7180_SLAVE_VENUS_THROTTLE_CFG, 1, 4); +DEFINE_QNODE(qhs_vsense_ctrl_cfg, SC7180_SLAVE_VSENSE_CTRL_CFG, 1, 4); +DEFINE_QNODE(srvc_cnoc, SC7180_SLAVE_SERVICE_CNOC, 1, 4); +DEFINE_QNODE(qhs_gemnoc, SC7180_SLAVE_GEM_NOC_CFG, 1, 4, SC7180_MASTER_GEM_NOC_CFG); +DEFINE_QNODE(qhs_llcc, SC7180_SLAVE_LLCC_CFG, 1, 4); +DEFINE_QNODE(qhs_mdsp_ms_mpu_cfg, SC7180_SLAVE_MSS_PROC_MS_MPU_CFG, 1, 4); +DEFINE_QNODE(qns_gem_noc_snoc, SC7180_SLAVE_GEM_NOC_SNOC, 1, 8, SC7180_MASTER_GEM_NOC_SNOC); +DEFINE_QNODE(qns_llcc, SC7180_SLAVE_LLCC, 1, 16, SC7180_MASTER_LLCC); +DEFINE_QNODE(srvc_gemnoc, SC7180_SLAVE_SERVICE_GEM_NOC, 1, 4); +DEFINE_QNODE(ipa_core_slave, SC7180_SLAVE_IPA_CORE, 1, 8); +DEFINE_QNODE(ebi, SC7180_SLAVE_EBI1, 2, 4); +DEFINE_QNODE(qns_mem_noc_hf, SC7180_SLAVE_MNOC_HF_MEM_NOC, 1, 32, SC7180_MASTER_MNOC_HF_MEM_NOC); +DEFINE_QNODE(qns_mem_noc_sf, SC7180_SLAVE_MNOC_SF_MEM_NOC, 1, 32, SC7180_MASTER_MNOC_SF_MEM_NOC); +DEFINE_QNODE(srvc_mnoc, SC7180_SLAVE_SERVICE_MNOC, 1, 4); +DEFINE_QNODE(qhs_cal_dp0, SC7180_SLAVE_NPU_CAL_DP0, 1, 4); +DEFINE_QNODE(qhs_cp, SC7180_SLAVE_NPU_CP, 1, 4); +DEFINE_QNODE(qhs_dma_bwmon, SC7180_SLAVE_NPU_INT_DMA_BWMON_CFG, 1, 4); +DEFINE_QNODE(qhs_dpm, SC7180_SLAVE_NPU_DPM, 1, 4); +DEFINE_QNODE(qhs_isense, SC7180_SLAVE_ISENSE_CFG, 1, 4); +DEFINE_QNODE(qhs_llm, SC7180_SLAVE_NPU_LLM_CFG, 1, 4); +DEFINE_QNODE(qhs_tcm, SC7180_SLAVE_NPU_TCM, 1, 4); +DEFINE_QNODE(qns_npu_sys, SC7180_SLAVE_NPU_COMPUTE_NOC, 2, 32); +DEFINE_QNODE(srvc_noc, SC7180_SLAVE_SERVICE_NPU_NOC, 1, 4); +DEFINE_QNODE(qup_core_slave_1, SC7180_SLAVE_QUP_CORE_0, 1, 4); +DEFINE_QNODE(qup_core_slave_2, SC7180_SLAVE_QUP_CORE_1, 1, 4); +DEFINE_QNODE(qhs_apss, SC7180_SLAVE_APPSS, 1, 8); +DEFINE_QNODE(qns_cnoc, SC7180_SLAVE_SNOC_CNOC, 1, 8, SC7180_MASTER_SNOC_CNOC); +DEFINE_QNODE(qns_gemnoc_gc, SC7180_SLAVE_SNOC_GEM_NOC_GC, 1, 8, SC7180_MASTER_SNOC_GC_MEM_NOC); +DEFINE_QNODE(qns_gemnoc_sf, SC7180_SLAVE_SNOC_GEM_NOC_SF, 1, 16, SC7180_MASTER_SNOC_SF_MEM_NOC); +DEFINE_QNODE(qxs_imem, SC7180_SLAVE_IMEM, 1, 8); +DEFINE_QNODE(qxs_pimem, SC7180_SLAVE_PIMEM, 1, 8); +DEFINE_QNODE(srvc_snoc, SC7180_SLAVE_SERVICE_SNOC, 1, 4); +DEFINE_QNODE(xs_qdss_stm, SC7180_SLAVE_QDSS_STM, 1, 4); +DEFINE_QNODE(xs_sys_tcu_cfg, SC7180_SLAVE_TCU, 1, 8); + +DEFINE_QBCM(bcm_acv, "ACV", false, &ebi); +DEFINE_QBCM(bcm_mc0, "MC0", true, &ebi); +DEFINE_QBCM(bcm_sh0, "SH0", true, &qns_llcc); +DEFINE_QBCM(bcm_mm0, "MM0", false, &qns_mem_noc_hf); +DEFINE_QBCM(bcm_ce0, "CE0", false, &qxm_crypto); +DEFINE_QBCM(bcm_ip0, "IP0", false, &ipa_core_slave); +DEFINE_QBCM(bcm_cn0, "CN0", true, &qnm_snoc, &xm_qdss_dap, &qhs_a1_noc_cfg, &qhs_a2_noc_cfg, &qhs_ahb2phy0, &qhs_aop, &qhs_aoss, &qhs_boot_rom, &qhs_camera_cfg, &qhs_camera_nrt_throttle_cfg, &qhs_camera_rt_throttle_cfg, &qhs_clk_ctl, &qhs_cpr_cx, &qhs_cpr_mx, &qhs_crypto0_cfg, &qhs_dcc_cfg, &qhs_ddrss_cfg, &qhs_display_cfg, &qhs_display_rt_throttle_cfg, &qhs_display_throttle_cfg, &qhs_glm, &qhs_gpuss_cfg, &qhs_imem_cfg, &qhs_ipa, &qhs_mnoc_cfg, &qhs_mss_cfg, &qhs_npu_cfg, &qhs_npu_dma_throttle_cfg, &qhs_npu_dsp_throttle_cfg, &qhs_pimem_cfg, &qhs_prng, &qhs_qdss_cfg, &qhs_qm_cfg, &qhs_qm_mpu_cfg, &qhs_qup0, &qhs_qup1, &qhs_security, &qhs_snoc_cfg, &qhs_tcsr, &qhs_tlmm_1, &qhs_tlmm_2, &qhs_tlmm_3, &qhs_ufs_mem_cfg, &qhs_usb3, &qhs_venus_cfg, &qhs_venus_throttle_cfg, &qhs_vsense_ctrl_cfg, &srvc_cnoc); +DEFINE_QBCM(bcm_mm1, "MM1", false, &qxm_camnoc_hf0_uncomp, &qxm_camnoc_hf1_uncomp, &qxm_camnoc_sf_uncomp, &qhm_mnoc_cfg, &qxm_mdp0, &qxm_rot, &qxm_venus0, &qxm_venus_arm9); +DEFINE_QBCM(bcm_sh2, "SH2", false, &acm_sys_tcu); +DEFINE_QBCM(bcm_mm2, "MM2", false, &qns_mem_noc_sf); +DEFINE_QBCM(bcm_qup0, "QUP0", false, &qup_core_master_1, &qup_core_master_2); +DEFINE_QBCM(bcm_sh3, "SH3", false, &qnm_cmpnoc); +DEFINE_QBCM(bcm_sh4, "SH4", false, &acm_apps0); +DEFINE_QBCM(bcm_sn0, "SN0", true, &qns_gemnoc_sf); +DEFINE_QBCM(bcm_co0, "CO0", false, &qns_cdsp_gemnoc); +DEFINE_QBCM(bcm_sn1, "SN1", false, &qxs_imem); +DEFINE_QBCM(bcm_cn1, "CN1", false, &qhm_qspi, &xm_sdc2, &xm_emmc, &qhs_ahb2phy2, &qhs_emmc_cfg, &qhs_pdm, &qhs_qspi, &qhs_sdc2); +DEFINE_QBCM(bcm_sn2, "SN2", false, &qxm_pimem, &qns_gemnoc_gc); +DEFINE_QBCM(bcm_co2, "CO2", false, &qnm_npu); +DEFINE_QBCM(bcm_sn3, "SN3", false, &qxs_pimem); +DEFINE_QBCM(bcm_co3, "CO3", false, &qxm_npu_dsp); +DEFINE_QBCM(bcm_sn4, "SN4", false, &xs_qdss_stm); +DEFINE_QBCM(bcm_sn7, "SN7", false, &qnm_aggre1_noc); +DEFINE_QBCM(bcm_sn9, "SN9", false, &qnm_aggre2_noc); +DEFINE_QBCM(bcm_sn12, "SN12", false, &qnm_gemnoc); + +static struct qcom_icc_bcm *aggre1_noc_bcms[] = { + &bcm_cn1, +}; + +static struct qcom_icc_node *aggre1_noc_nodes[] = { + [MASTER_A1NOC_CFG] = &qhm_a1noc_cfg, + [MASTER_QSPI] = &qhm_qspi, + [MASTER_QUP_0] = &qhm_qup_0, + [MASTER_SDCC_2] = &xm_sdc2, + [MASTER_EMMC] = &xm_emmc, + [MASTER_UFS_MEM] = &xm_ufs_mem, + [SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc, + [SLAVE_SERVICE_A1NOC] = &srvc_aggre1_noc, +}; + +static struct qcom_icc_desc sc7180_aggre1_noc = { + .nodes = aggre1_noc_nodes, + .num_nodes = ARRAY_SIZE(aggre1_noc_nodes), + .bcms = aggre1_noc_bcms, + .num_bcms = ARRAY_SIZE(aggre1_noc_bcms), +}; + +static struct qcom_icc_bcm *aggre2_noc_bcms[] = { + &bcm_ce0, +}; + +static struct qcom_icc_node *aggre2_noc_nodes[] = { + [MASTER_A2NOC_CFG] = &qhm_a2noc_cfg, + [MASTER_QDSS_BAM] = &qhm_qdss_bam, + [MASTER_QUP_1] = &qhm_qup_1, + [MASTER_USB3] = &qhm_usb3, + [MASTER_CRYPTO] = &qxm_crypto, + [MASTER_IPA] = &qxm_ipa, + [MASTER_QDSS_ETR] = &xm_qdss_etr, + [SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc, + [SLAVE_SERVICE_A2NOC] = &srvc_aggre2_noc, +}; + +static struct qcom_icc_desc sc7180_aggre2_noc = { + .nodes = aggre2_noc_nodes, + .num_nodes = ARRAY_SIZE(aggre2_noc_nodes), + .bcms = aggre2_noc_bcms, + .num_bcms = ARRAY_SIZE(aggre2_noc_bcms), +}; + +static struct qcom_icc_bcm *camnoc_virt_bcms[] = { + &bcm_mm1, +}; + +static struct qcom_icc_node *camnoc_virt_nodes[] = { + [MASTER_CAMNOC_HF0_UNCOMP] = &qxm_camnoc_hf0_uncomp, + [MASTER_CAMNOC_HF1_UNCOMP] = &qxm_camnoc_hf1_uncomp, + [MASTER_CAMNOC_SF_UNCOMP] = &qxm_camnoc_sf_uncomp, + [SLAVE_CAMNOC_UNCOMP] = &qns_camnoc_uncomp, +}; + +static struct qcom_icc_desc sc7180_camnoc_virt = { + .nodes = camnoc_virt_nodes, + .num_nodes = ARRAY_SIZE(camnoc_virt_nodes), + .bcms = camnoc_virt_bcms, + .num_bcms = ARRAY_SIZE(camnoc_virt_bcms), +}; + +static struct qcom_icc_bcm *compute_noc_bcms[] = { + &bcm_co0, + &bcm_co2, + &bcm_co3, +}; + +static struct qcom_icc_node *compute_noc_nodes[] = { + [MASTER_NPU] = &qnm_npu, + [MASTER_NPU_PROC] = &qxm_npu_dsp, + [SLAVE_CDSP_GEM_NOC] = &qns_cdsp_gemnoc, +}; + +static struct qcom_icc_desc sc7180_compute_noc = { + .nodes = compute_noc_nodes, + .num_nodes = ARRAY_SIZE(compute_noc_nodes), + .bcms = compute_noc_bcms, + .num_bcms = ARRAY_SIZE(compute_noc_bcms), +}; + +static struct qcom_icc_bcm *config_noc_bcms[] = { + &bcm_cn0, + &bcm_cn1, +}; + +static struct qcom_icc_node *config_noc_nodes[] = { + [MASTER_SNOC_CNOC] = &qnm_snoc, + [MASTER_QDSS_DAP] = &xm_qdss_dap, + [SLAVE_A1NOC_CFG] = &qhs_a1_noc_cfg, + [SLAVE_A2NOC_CFG] = &qhs_a2_noc_cfg, + [SLAVE_AHB2PHY_SOUTH] = &qhs_ahb2phy0, + [SLAVE_AHB2PHY_CENTER] = &qhs_ahb2phy2, + [SLAVE_AOP] = &qhs_aop, + [SLAVE_AOSS] = &qhs_aoss, + [SLAVE_BOOT_ROM] = &qhs_boot_rom, + [SLAVE_CAMERA_CFG] = &qhs_camera_cfg, + [SLAVE_CAMERA_NRT_THROTTLE_CFG] = &qhs_camera_nrt_throttle_cfg, + [SLAVE_CAMERA_RT_THROTTLE_CFG] = &qhs_camera_rt_throttle_cfg, + [SLAVE_CLK_CTL] = &qhs_clk_ctl, + [SLAVE_RBCPR_CX_CFG] = &qhs_cpr_cx, + [SLAVE_RBCPR_MX_CFG] = &qhs_cpr_mx, + [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg, + [SLAVE_DCC_CFG] = &qhs_dcc_cfg, + [SLAVE_CNOC_DDRSS] = &qhs_ddrss_cfg, + [SLAVE_DISPLAY_CFG] = &qhs_display_cfg, + [SLAVE_DISPLAY_RT_THROTTLE_CFG] = &qhs_display_rt_throttle_cfg, + [SLAVE_DISPLAY_THROTTLE_CFG] = &qhs_display_throttle_cfg, + [SLAVE_EMMC_CFG] = &qhs_emmc_cfg, + [SLAVE_GLM] = &qhs_glm, + [SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg, + [SLAVE_IMEM_CFG] = &qhs_imem_cfg, + [SLAVE_IPA_CFG] = &qhs_ipa, + [SLAVE_CNOC_MNOC_CFG] = &qhs_mnoc_cfg, + [SLAVE_CNOC_MSS] = &qhs_mss_cfg, + [SLAVE_NPU_CFG] = &qhs_npu_cfg, + [SLAVE_NPU_DMA_BWMON_CFG] = &qhs_npu_dma_throttle_cfg, + [SLAVE_NPU_PROC_BWMON_CFG] = &qhs_npu_dsp_throttle_cfg, + [SLAVE_PDM] = &qhs_pdm, + [SLAVE_PIMEM_CFG] = &qhs_pimem_cfg, + [SLAVE_PRNG] = &qhs_prng, + [SLAVE_QDSS_CFG] = &qhs_qdss_cfg, + [SLAVE_QM_CFG] = &qhs_qm_cfg, + [SLAVE_QM_MPU_CFG] = &qhs_qm_mpu_cfg, + [SLAVE_QSPI_0] = &qhs_qspi, + [SLAVE_QUP_0] = &qhs_qup0, + [SLAVE_QUP_1] = &qhs_qup1, + [SLAVE_SDCC_2] = &qhs_sdc2, + [SLAVE_SECURITY] = &qhs_security, + [SLAVE_SNOC_CFG] = &qhs_snoc_cfg, + [SLAVE_TCSR] = &qhs_tcsr, + [SLAVE_TLMM_WEST] = &qhs_tlmm_1, + [SLAVE_TLMM_NORTH] = &qhs_tlmm_2, + [SLAVE_TLMM_SOUTH] = &qhs_tlmm_3, + [SLAVE_UFS_MEM_CFG] = &qhs_ufs_mem_cfg, + [SLAVE_USB3] = &qhs_usb3, + [SLAVE_VENUS_CFG] = &qhs_venus_cfg, + [SLAVE_VENUS_THROTTLE_CFG] = &qhs_venus_throttle_cfg, + [SLAVE_VSENSE_CTRL_CFG] = &qhs_vsense_ctrl_cfg, + [SLAVE_SERVICE_CNOC] = &srvc_cnoc, +}; + +static struct qcom_icc_desc sc7180_config_noc = { + .nodes = config_noc_nodes, + .num_nodes = ARRAY_SIZE(config_noc_nodes), + .bcms = config_noc_bcms, + .num_bcms = ARRAY_SIZE(config_noc_bcms), +}; + +static struct qcom_icc_node *dc_noc_nodes[] = { + [MASTER_CNOC_DC_NOC] = &qhm_cnoc_dc_noc, + [SLAVE_GEM_NOC_CFG] = &qhs_gemnoc, + [SLAVE_LLCC_CFG] = &qhs_llcc, +}; + +static struct qcom_icc_desc sc7180_dc_noc = { + .nodes = dc_noc_nodes, + .num_nodes = ARRAY_SIZE(dc_noc_nodes), +}; + +static struct qcom_icc_bcm *gem_noc_bcms[] = { + &bcm_sh0, + &bcm_sh2, + &bcm_sh3, + &bcm_sh4, +}; + +static struct qcom_icc_node *gem_noc_nodes[] = { + [MASTER_APPSS_PROC] = &acm_apps0, + [MASTER_SYS_TCU] = &acm_sys_tcu, + [MASTER_GEM_NOC_CFG] = &qhm_gemnoc_cfg, + [MASTER_COMPUTE_NOC] = &qnm_cmpnoc, + [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf, + [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf, + [MASTER_SNOC_GC_MEM_NOC] = &qnm_snoc_gc, + [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf, + [MASTER_GFX3D] = &qxm_gpu, + [SLAVE_MSS_PROC_MS_MPU_CFG] = &qhs_mdsp_ms_mpu_cfg, + [SLAVE_GEM_NOC_SNOC] = &qns_gem_noc_snoc, + [SLAVE_LLCC] = &qns_llcc, + [SLAVE_SERVICE_GEM_NOC] = &srvc_gemnoc, +}; + +static struct qcom_icc_desc sc7180_gem_noc = { + .nodes = gem_noc_nodes, + .num_nodes = ARRAY_SIZE(gem_noc_nodes), + .bcms = gem_noc_bcms, + .num_bcms = ARRAY_SIZE(gem_noc_bcms), +}; + +static struct qcom_icc_bcm *ipa_virt_bcms[] = { + &bcm_ip0, +}; + +static struct qcom_icc_node *ipa_virt_nodes[] = { + [MASTER_IPA_CORE] = &ipa_core_master, + [SLAVE_IPA_CORE] = &ipa_core_slave, +}; + +static struct qcom_icc_desc sc7180_ipa_virt = { + .nodes = ipa_virt_nodes, + .num_nodes = ARRAY_SIZE(ipa_virt_nodes), + .bcms = ipa_virt_bcms, + .num_bcms = ARRAY_SIZE(ipa_virt_bcms), +}; + +static struct qcom_icc_bcm *mc_virt_bcms[] = { + &bcm_acv, + &bcm_mc0, +}; + +static struct qcom_icc_node *mc_virt_nodes[] = { + [MASTER_LLCC] = &llcc_mc, + [SLAVE_EBI1] = &ebi, +}; + +static struct qcom_icc_desc sc7180_mc_virt = { + .nodes = mc_virt_nodes, + .num_nodes = ARRAY_SIZE(mc_virt_nodes), + .bcms = mc_virt_bcms, + .num_bcms = ARRAY_SIZE(mc_virt_bcms), +}; + +static struct qcom_icc_bcm *mmss_noc_bcms[] = { + &bcm_mm0, + &bcm_mm1, + &bcm_mm2, +}; + +static struct qcom_icc_node *mmss_noc_nodes[] = { + [MASTER_CNOC_MNOC_CFG] = &qhm_mnoc_cfg, + [MASTER_CAMNOC_HF0] = &qxm_camnoc_hf0, + [MASTER_CAMNOC_HF1] = &qxm_camnoc_hf1, + [MASTER_CAMNOC_SF] = &qxm_camnoc_sf, + [MASTER_MDP0] = &qxm_mdp0, + [MASTER_ROTATOR] = &qxm_rot, + [MASTER_VIDEO_P0] = &qxm_venus0, + [MASTER_VIDEO_PROC] = &qxm_venus_arm9, + [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf, + [SLAVE_MNOC_SF_MEM_NOC] = &qns_mem_noc_sf, + [SLAVE_SERVICE_MNOC] = &srvc_mnoc, +}; + +static struct qcom_icc_desc sc7180_mmss_noc = { + .nodes = mmss_noc_nodes, + .num_nodes = ARRAY_SIZE(mmss_noc_nodes), + .bcms = mmss_noc_bcms, + .num_bcms = ARRAY_SIZE(mmss_noc_bcms), +}; + +static struct qcom_icc_node *npu_noc_nodes[] = { + [MASTER_NPU_SYS] = &amm_npu_sys, + [MASTER_NPU_NOC_CFG] = &qhm_npu_cfg, + [SLAVE_NPU_CAL_DP0] = &qhs_cal_dp0, + [SLAVE_NPU_CP] = &qhs_cp, + [SLAVE_NPU_INT_DMA_BWMON_CFG] = &qhs_dma_bwmon, + [SLAVE_NPU_DPM] = &qhs_dpm, + [SLAVE_ISENSE_CFG] = &qhs_isense, + [SLAVE_NPU_LLM_CFG] = &qhs_llm, + [SLAVE_NPU_TCM] = &qhs_tcm, + [SLAVE_NPU_COMPUTE_NOC] = &qns_npu_sys, + [SLAVE_SERVICE_NPU_NOC] = &srvc_noc, +}; + +static struct qcom_icc_desc sc7180_npu_noc = { + .nodes = npu_noc_nodes, + .num_nodes = ARRAY_SIZE(npu_noc_nodes), +}; + +static struct qcom_icc_bcm *qup_virt_bcms[] = { + &bcm_qup0, +}; + +static struct qcom_icc_node *qup_virt_nodes[] = { + [MASTER_QUP_CORE_0] = &qup_core_master_1, + [MASTER_QUP_CORE_1] = &qup_core_master_2, + [SLAVE_QUP_CORE_0] = &qup_core_slave_1, + [SLAVE_QUP_CORE_1] = &qup_core_slave_2, +}; + +static struct qcom_icc_desc sc7180_qup_virt = { + .nodes = qup_virt_nodes, + .num_nodes = ARRAY_SIZE(qup_virt_nodes), + .bcms = qup_virt_bcms, + .num_bcms = ARRAY_SIZE(qup_virt_bcms), +}; + +static struct qcom_icc_bcm *system_noc_bcms[] = { + &bcm_sn0, + &bcm_sn1, + &bcm_sn2, + &bcm_sn3, + &bcm_sn4, + &bcm_sn7, + &bcm_sn9, + &bcm_sn12, +}; + +static struct qcom_icc_node *system_noc_nodes[] = { + [MASTER_SNOC_CFG] = &qhm_snoc_cfg, + [MASTER_A1NOC_SNOC] = &qnm_aggre1_noc, + [MASTER_A2NOC_SNOC] = &qnm_aggre2_noc, + [MASTER_GEM_NOC_SNOC] = &qnm_gemnoc, + [MASTER_PIMEM] = &qxm_pimem, + [SLAVE_APPSS] = &qhs_apss, + [SLAVE_SNOC_CNOC] = &qns_cnoc, + [SLAVE_SNOC_GEM_NOC_GC] = &qns_gemnoc_gc, + [SLAVE_SNOC_GEM_NOC_SF] = &qns_gemnoc_sf, + [SLAVE_IMEM] = &qxs_imem, + [SLAVE_PIMEM] = &qxs_pimem, + [SLAVE_SERVICE_SNOC] = &srvc_snoc, + [SLAVE_QDSS_STM] = &xs_qdss_stm, + [SLAVE_TCU] = &xs_sys_tcu_cfg, +}; + +static struct qcom_icc_desc sc7180_system_noc = { + .nodes = system_noc_nodes, + .num_nodes = ARRAY_SIZE(system_noc_nodes), + .bcms = system_noc_bcms, + .num_bcms = ARRAY_SIZE(system_noc_bcms), +}; + +static int qnoc_probe(struct platform_device *pdev) +{ + const struct qcom_icc_desc *desc; + struct icc_onecell_data *data; + struct icc_provider *provider; + struct qcom_icc_node **qnodes; + struct qcom_icc_provider *qp; + struct icc_node *node; + size_t num_nodes, i; + int ret; + + desc = device_get_match_data(&pdev->dev); + if (!desc) + return -EINVAL; + + qnodes = desc->nodes; + num_nodes = desc->num_nodes; + + qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL); + if (!qp) + return -ENOMEM; + + data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL); + if (!data) + return -ENOMEM; + + provider = &qp->provider; + provider->dev = &pdev->dev; + provider->set = qcom_icc_set; + provider->pre_aggregate = qcom_icc_pre_aggregate; + provider->aggregate = qcom_icc_aggregate; + provider->xlate = of_icc_xlate_onecell; + INIT_LIST_HEAD(&provider->nodes); + provider->data = data; + + qp->dev = &pdev->dev; + qp->bcms = desc->bcms; + qp->num_bcms = desc->num_bcms; + + qp->voter = of_bcm_voter_get(qp->dev, NULL); + if (IS_ERR(qp->voter)) + return PTR_ERR(qp->voter); + + ret = icc_provider_add(provider); + if (ret) { + dev_err(&pdev->dev, "error adding interconnect provider\n"); + return ret; + } + + for (i = 0; i < num_nodes; i++) { + size_t j; + + if (!qnodes[i]) + continue; + + node = icc_node_create(qnodes[i]->id); + if (IS_ERR(node)) { + ret = PTR_ERR(node); + goto err; + } + + node->name = qnodes[i]->name; + node->data = qnodes[i]; + icc_node_add(node, provider); + + for (j = 0; j < qnodes[i]->num_links; j++) + icc_link_create(node, qnodes[i]->links[j]); + + data->nodes[i] = node; + } + data->num_nodes = num_nodes; + + for (i = 0; i < qp->num_bcms; i++) + qcom_icc_bcm_init(qp->bcms[i], &pdev->dev); + + platform_set_drvdata(pdev, qp); + + return 0; +err: + icc_nodes_remove(provider); + icc_provider_del(provider); + return ret; +} + +static int qnoc_remove(struct platform_device *pdev) +{ + struct qcom_icc_provider *qp = platform_get_drvdata(pdev); + + icc_nodes_remove(&qp->provider); + return icc_provider_del(&qp->provider); +} + +static const struct of_device_id qnoc_of_match[] = { + { .compatible = "qcom,sc7180-aggre1-noc", + .data = &sc7180_aggre1_noc}, + { .compatible = "qcom,sc7180-aggre2-noc", + .data = &sc7180_aggre2_noc}, + { .compatible = "qcom,sc7180-camnoc-virt", + .data = &sc7180_camnoc_virt}, + { .compatible = "qcom,sc7180-compute-noc", + .data = &sc7180_compute_noc}, + { .compatible = "qcom,sc7180-config-noc", + .data = &sc7180_config_noc}, + { .compatible = "qcom,sc7180-dc-noc", + .data = &sc7180_dc_noc}, + { .compatible = "qcom,sc7180-gem-noc", + .data = &sc7180_gem_noc}, + { .compatible = "qcom,sc7180-ipa-virt", + .data = &sc7180_ipa_virt}, + { .compatible = "qcom,sc7180-mc-virt", + .data = &sc7180_mc_virt}, + { .compatible = "qcom,sc7180-mmss-noc", + .data = &sc7180_mmss_noc}, + { .compatible = "qcom,sc7180-npu-noc", + .data = &sc7180_npu_noc}, + { .compatible = "qcom,sc7180-qup-virt", + .data = &sc7180_qup_virt}, + { .compatible = "qcom,sc7180-system-noc", + .data = &sc7180_system_noc}, + { } +}; +MODULE_DEVICE_TABLE(of, qnoc_of_match); + +static struct platform_driver qnoc_driver = { + .probe = qnoc_probe, + .remove = qnoc_remove, + .driver = { + .name = "qnoc-sc7180", + .of_match_table = qnoc_of_match, + }, +}; +module_platform_driver(qnoc_driver); + +MODULE_DESCRIPTION("Qualcomm SC7180 NoC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/qcom/sc7180.h b/drivers/interconnect/qcom/sc7180.h new file mode 100644 index 000000000000..c2d8388bb880 --- /dev/null +++ b/drivers/interconnect/qcom/sc7180.h @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Qualcomm #define SC7180 interconnect IDs + * + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef __DRIVERS_INTERCONNECT_QCOM_SC7180_H +#define __DRIVERS_INTERCONNECT_QCOM_SC7180_H + +#define SC7180_MASTER_APPSS_PROC 0 +#define SC7180_MASTER_SYS_TCU 1 +#define SC7180_MASTER_NPU_SYS 2 +#define SC7180_MASTER_IPA_CORE 3 +#define SC7180_MASTER_LLCC 4 +#define SC7180_MASTER_A1NOC_CFG 5 +#define SC7180_MASTER_A2NOC_CFG 6 +#define SC7180_MASTER_CNOC_DC_NOC 7 +#define SC7180_MASTER_GEM_NOC_CFG 8 +#define SC7180_MASTER_CNOC_MNOC_CFG 9 +#define SC7180_MASTER_NPU_NOC_CFG 10 +#define SC7180_MASTER_QDSS_BAM 11 +#define SC7180_MASTER_QSPI 12 +#define SC7180_MASTER_QUP_0 13 +#define SC7180_MASTER_QUP_1 14 +#define SC7180_MASTER_SNOC_CFG 15 +#define SC7180_MASTER_A1NOC_SNOC 16 +#define SC7180_MASTER_A2NOC_SNOC 17 +#define SC7180_MASTER_COMPUTE_NOC 18 +#define SC7180_MASTER_GEM_NOC_SNOC 19 +#define SC7180_MASTER_MNOC_HF_MEM_NOC 20 +#define SC7180_MASTER_MNOC_SF_MEM_NOC 21 +#define SC7180_MASTER_NPU 22 +#define SC7180_MASTER_SNOC_CNOC 23 +#define SC7180_MASTER_SNOC_GC_MEM_NOC 24 +#define SC7180_MASTER_SNOC_SF_MEM_NOC 25 +#define SC7180_MASTER_QUP_CORE_0 26 +#define SC7180_MASTER_QUP_CORE_1 27 +#define SC7180_MASTER_CAMNOC_HF0 28 +#define SC7180_MASTER_CAMNOC_HF1 29 +#define SC7180_MASTER_CAMNOC_HF0_UNCOMP 30 +#define SC7180_MASTER_CAMNOC_HF1_UNCOMP 31 +#define SC7180_MASTER_CAMNOC_SF 32 +#define SC7180_MASTER_CAMNOC_SF_UNCOMP 33 +#define SC7180_MASTER_CRYPTO 34 +#define SC7180_MASTER_GFX3D 35 +#define SC7180_MASTER_IPA 36 +#define SC7180_MASTER_MDP0 37 +#define SC7180_MASTER_NPU_PROC 38 +#define SC7180_MASTER_PIMEM 39 +#define SC7180_MASTER_ROTATOR 40 +#define SC7180_MASTER_VIDEO_P0 41 +#define SC7180_MASTER_VIDEO_PROC 42 +#define SC7180_MASTER_QDSS_DAP 43 +#define SC7180_MASTER_QDSS_ETR 44 +#define SC7180_MASTER_SDCC_2 45 +#define SC7180_MASTER_UFS_MEM 46 +#define SC7180_MASTER_USB3 47 +#define SC7180_MASTER_EMMC 48 +#define SC7180_SLAVE_EBI1 49 +#define SC7180_SLAVE_IPA_CORE 50 +#define SC7180_SLAVE_A1NOC_CFG 51 +#define SC7180_SLAVE_A2NOC_CFG 52 +#define SC7180_SLAVE_AHB2PHY_SOUTH 53 +#define SC7180_SLAVE_AHB2PHY_CENTER 54 +#define SC7180_SLAVE_AOP 55 +#define SC7180_SLAVE_AOSS 56 +#define SC7180_SLAVE_APPSS 57 +#define SC7180_SLAVE_BOOT_ROM 58 +#define SC7180_SLAVE_NPU_CAL_DP0 59 +#define SC7180_SLAVE_CAMERA_CFG 60 +#define SC7180_SLAVE_CAMERA_NRT_THROTTLE_CFG 61 +#define SC7180_SLAVE_CAMERA_RT_THROTTLE_CFG 62 +#define SC7180_SLAVE_CLK_CTL 63 +#define SC7180_SLAVE_NPU_CP 64 +#define SC7180_SLAVE_RBCPR_CX_CFG 65 +#define SC7180_SLAVE_RBCPR_MX_CFG 66 +#define SC7180_SLAVE_CRYPTO_0_CFG 67 +#define SC7180_SLAVE_DCC_CFG 68 +#define SC7180_SLAVE_CNOC_DDRSS 69 +#define SC7180_SLAVE_DISPLAY_CFG 70 +#define SC7180_SLAVE_DISPLAY_RT_THROTTLE_CFG 71 +#define SC7180_SLAVE_DISPLAY_THROTTLE_CFG 72 +#define SC7180_SLAVE_NPU_INT_DMA_BWMON_CFG 73 +#define SC7180_SLAVE_NPU_DPM 74 +#define SC7180_SLAVE_EMMC_CFG 75 +#define SC7180_SLAVE_GEM_NOC_CFG 76 +#define SC7180_SLAVE_GLM 77 +#define SC7180_SLAVE_GFX3D_CFG 78 +#define SC7180_SLAVE_IMEM_CFG 79 +#define SC7180_SLAVE_IPA_CFG 80 +#define SC7180_SLAVE_ISENSE_CFG 81 +#define SC7180_SLAVE_LLCC_CFG 82 +#define SC7180_SLAVE_NPU_LLM_CFG 83 +#define SC7180_SLAVE_MSS_PROC_MS_MPU_CFG 84 +#define SC7180_SLAVE_CNOC_MNOC_CFG 85 +#define SC7180_SLAVE_CNOC_MSS 86 +#define SC7180_SLAVE_NPU_CFG 87 +#define SC7180_SLAVE_NPU_DMA_BWMON_CFG 88 +#define SC7180_SLAVE_NPU_PROC_BWMON_CFG 89 +#define SC7180_SLAVE_PDM 90 +#define SC7180_SLAVE_PIMEM_CFG 91 +#define SC7180_SLAVE_PRNG 92 +#define SC7180_SLAVE_QDSS_CFG 93 +#define SC7180_SLAVE_QM_CFG 94 +#define SC7180_SLAVE_QM_MPU_CFG 95 +#define SC7180_SLAVE_QSPI_0 96 +#define SC7180_SLAVE_QUP_0 97 +#define SC7180_SLAVE_QUP_1 98 +#define SC7180_SLAVE_SDCC_2 99 +#define SC7180_SLAVE_SECURITY 100 +#define SC7180_SLAVE_SNOC_CFG 101 +#define SC7180_SLAVE_NPU_TCM 102 +#define SC7180_SLAVE_TCSR 103 +#define SC7180_SLAVE_TLMM_WEST 104 +#define SC7180_SLAVE_TLMM_NORTH 105 +#define SC7180_SLAVE_TLMM_SOUTH 106 +#define SC7180_SLAVE_UFS_MEM_CFG 107 +#define SC7180_SLAVE_USB3 108 +#define SC7180_SLAVE_VENUS_CFG 109 +#define SC7180_SLAVE_VENUS_THROTTLE_CFG 110 +#define SC7180_SLAVE_VSENSE_CTRL_CFG 111 +#define SC7180_SLAVE_A1NOC_SNOC 112 +#define SC7180_SLAVE_A2NOC_SNOC 113 +#define SC7180_SLAVE_CAMNOC_UNCOMP 114 +#define SC7180_SLAVE_CDSP_GEM_NOC 115 +#define SC7180_SLAVE_SNOC_CNOC 116 +#define SC7180_SLAVE_GEM_NOC_SNOC 117 +#define SC7180_SLAVE_SNOC_GEM_NOC_GC 118 +#define SC7180_SLAVE_SNOC_GEM_NOC_SF 119 +#define SC7180_SLAVE_LLCC 120 +#define SC7180_SLAVE_MNOC_HF_MEM_NOC 121 +#define SC7180_SLAVE_MNOC_SF_MEM_NOC 122 +#define SC7180_SLAVE_NPU_COMPUTE_NOC 123 +#define SC7180_SLAVE_QUP_CORE_0 124 +#define SC7180_SLAVE_QUP_CORE_1 125 +#define SC7180_SLAVE_IMEM 126 +#define SC7180_SLAVE_PIMEM 127 +#define SC7180_SLAVE_SERVICE_A1NOC 128 +#define SC7180_SLAVE_SERVICE_A2NOC 129 +#define SC7180_SLAVE_SERVICE_CNOC 130 +#define SC7180_SLAVE_SERVICE_GEM_NOC 131 +#define SC7180_SLAVE_SERVICE_MNOC 132 +#define SC7180_SLAVE_SERVICE_NPU_NOC 133 +#define SC7180_SLAVE_SERVICE_SNOC 134 +#define SC7180_SLAVE_QDSS_STM 135 +#define SC7180_SLAVE_TCU 136 + +#endif From 78465b0d3db6ab579641cd7762c33f389ac93573 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Tue, 3 Mar 2020 19:02:52 +0200 Subject: [PATCH 1084/4444] interconnect: qcom: Allow icc node to be used across icc providers Move the icc node ids to a common header, this will allow for referencing/linking of icc nodes to multiple icc providers on SDM845 SoCs. Signed-off-by: Sibi Sankar Reviewed-by: Evan Green Link: https://lore.kernel.org/r/20200227105632.15041-2-sibis@codeaurora.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/sdm845.c | 134 +-------------------------- drivers/interconnect/qcom/sdm845.h | 140 +++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 133 deletions(-) create mode 100644 drivers/interconnect/qcom/sdm845.h diff --git a/drivers/interconnect/qcom/sdm845.c b/drivers/interconnect/qcom/sdm845.c index ab968afeee59..b013b80caa45 100644 --- a/drivers/interconnect/qcom/sdm845.c +++ b/drivers/interconnect/qcom/sdm845.c @@ -13,139 +13,7 @@ #include "bcm-voter.h" #include "icc-rpmh.h" - -enum { - SDM845_MASTER_A1NOC_CFG = 1, - SDM845_MASTER_BLSP_1, - SDM845_MASTER_TSIF, - SDM845_MASTER_SDCC_2, - SDM845_MASTER_SDCC_4, - SDM845_MASTER_UFS_CARD, - SDM845_MASTER_UFS_MEM, - SDM845_MASTER_PCIE_0, - SDM845_MASTER_A2NOC_CFG, - SDM845_MASTER_QDSS_BAM, - SDM845_MASTER_BLSP_2, - SDM845_MASTER_CNOC_A2NOC, - SDM845_MASTER_CRYPTO, - SDM845_MASTER_IPA, - SDM845_MASTER_PCIE_1, - SDM845_MASTER_QDSS_ETR, - SDM845_MASTER_USB3_0, - SDM845_MASTER_USB3_1, - SDM845_MASTER_CAMNOC_HF0_UNCOMP, - SDM845_MASTER_CAMNOC_HF1_UNCOMP, - SDM845_MASTER_CAMNOC_SF_UNCOMP, - SDM845_MASTER_SPDM, - SDM845_MASTER_TIC, - SDM845_MASTER_SNOC_CNOC, - SDM845_MASTER_QDSS_DAP, - SDM845_MASTER_CNOC_DC_NOC, - SDM845_MASTER_APPSS_PROC, - SDM845_MASTER_GNOC_CFG, - SDM845_MASTER_LLCC, - SDM845_MASTER_TCU_0, - SDM845_MASTER_MEM_NOC_CFG, - SDM845_MASTER_GNOC_MEM_NOC, - SDM845_MASTER_MNOC_HF_MEM_NOC, - SDM845_MASTER_MNOC_SF_MEM_NOC, - SDM845_MASTER_SNOC_GC_MEM_NOC, - SDM845_MASTER_SNOC_SF_MEM_NOC, - SDM845_MASTER_GFX3D, - SDM845_MASTER_CNOC_MNOC_CFG, - SDM845_MASTER_CAMNOC_HF0, - SDM845_MASTER_CAMNOC_HF1, - SDM845_MASTER_CAMNOC_SF, - SDM845_MASTER_MDP0, - SDM845_MASTER_MDP1, - SDM845_MASTER_ROTATOR, - SDM845_MASTER_VIDEO_P0, - SDM845_MASTER_VIDEO_P1, - SDM845_MASTER_VIDEO_PROC, - SDM845_MASTER_SNOC_CFG, - SDM845_MASTER_A1NOC_SNOC, - SDM845_MASTER_A2NOC_SNOC, - SDM845_MASTER_GNOC_SNOC, - SDM845_MASTER_MEM_NOC_SNOC, - SDM845_MASTER_ANOC_PCIE_SNOC, - SDM845_MASTER_PIMEM, - SDM845_MASTER_GIC, - SDM845_SLAVE_A1NOC_SNOC, - SDM845_SLAVE_SERVICE_A1NOC, - SDM845_SLAVE_ANOC_PCIE_A1NOC_SNOC, - SDM845_SLAVE_A2NOC_SNOC, - SDM845_SLAVE_ANOC_PCIE_SNOC, - SDM845_SLAVE_SERVICE_A2NOC, - SDM845_SLAVE_CAMNOC_UNCOMP, - SDM845_SLAVE_A1NOC_CFG, - SDM845_SLAVE_A2NOC_CFG, - SDM845_SLAVE_AOP, - SDM845_SLAVE_AOSS, - SDM845_SLAVE_CAMERA_CFG, - SDM845_SLAVE_CLK_CTL, - SDM845_SLAVE_CDSP_CFG, - SDM845_SLAVE_RBCPR_CX_CFG, - SDM845_SLAVE_CRYPTO_0_CFG, - SDM845_SLAVE_DCC_CFG, - SDM845_SLAVE_CNOC_DDRSS, - SDM845_SLAVE_DISPLAY_CFG, - SDM845_SLAVE_GLM, - SDM845_SLAVE_GFX3D_CFG, - SDM845_SLAVE_IMEM_CFG, - SDM845_SLAVE_IPA_CFG, - SDM845_SLAVE_CNOC_MNOC_CFG, - SDM845_SLAVE_PCIE_0_CFG, - SDM845_SLAVE_PCIE_1_CFG, - SDM845_SLAVE_PDM, - SDM845_SLAVE_SOUTH_PHY_CFG, - SDM845_SLAVE_PIMEM_CFG, - SDM845_SLAVE_PRNG, - SDM845_SLAVE_QDSS_CFG, - SDM845_SLAVE_BLSP_2, - SDM845_SLAVE_BLSP_1, - SDM845_SLAVE_SDCC_2, - SDM845_SLAVE_SDCC_4, - SDM845_SLAVE_SNOC_CFG, - SDM845_SLAVE_SPDM_WRAPPER, - SDM845_SLAVE_SPSS_CFG, - SDM845_SLAVE_TCSR, - SDM845_SLAVE_TLMM_NORTH, - SDM845_SLAVE_TLMM_SOUTH, - SDM845_SLAVE_TSIF, - SDM845_SLAVE_UFS_CARD_CFG, - SDM845_SLAVE_UFS_MEM_CFG, - SDM845_SLAVE_USB3_0, - SDM845_SLAVE_USB3_1, - SDM845_SLAVE_VENUS_CFG, - SDM845_SLAVE_VSENSE_CTRL_CFG, - SDM845_SLAVE_CNOC_A2NOC, - SDM845_SLAVE_SERVICE_CNOC, - SDM845_SLAVE_LLCC_CFG, - SDM845_SLAVE_MEM_NOC_CFG, - SDM845_SLAVE_GNOC_SNOC, - SDM845_SLAVE_GNOC_MEM_NOC, - SDM845_SLAVE_SERVICE_GNOC, - SDM845_SLAVE_EBI1, - SDM845_SLAVE_MSS_PROC_MS_MPU_CFG, - SDM845_SLAVE_MEM_NOC_GNOC, - SDM845_SLAVE_LLCC, - SDM845_SLAVE_MEM_NOC_SNOC, - SDM845_SLAVE_SERVICE_MEM_NOC, - SDM845_SLAVE_MNOC_SF_MEM_NOC, - SDM845_SLAVE_MNOC_HF_MEM_NOC, - SDM845_SLAVE_SERVICE_MNOC, - SDM845_SLAVE_APPSS, - SDM845_SLAVE_SNOC_CNOC, - SDM845_SLAVE_SNOC_MEM_NOC_GC, - SDM845_SLAVE_SNOC_MEM_NOC_SF, - SDM845_SLAVE_IMEM, - SDM845_SLAVE_PCIE_0, - SDM845_SLAVE_PCIE_1, - SDM845_SLAVE_PIMEM, - SDM845_SLAVE_SERVICE_SNOC, - SDM845_SLAVE_QDSS_STM, - SDM845_SLAVE_TCU -}; +#include "sdm845.h" DEFINE_QNODE(qhm_a1noc_cfg, SDM845_MASTER_A1NOC_CFG, 1, 4, SDM845_SLAVE_SERVICE_A1NOC); DEFINE_QNODE(qhm_qup1, SDM845_MASTER_BLSP_1, 1, 4, SDM845_SLAVE_A1NOC_SNOC); diff --git a/drivers/interconnect/qcom/sdm845.h b/drivers/interconnect/qcom/sdm845.h new file mode 100644 index 000000000000..bc7e425ce985 --- /dev/null +++ b/drivers/interconnect/qcom/sdm845.h @@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef __DRIVERS_INTERCONNECT_QCOM_SDM845_H__ +#define __DRIVERS_INTERCONNECT_QCOM_SDM845_H__ + +#define SDM845_MASTER_A1NOC_CFG 1 +#define SDM845_MASTER_BLSP_1 2 +#define SDM845_MASTER_TSIF 3 +#define SDM845_MASTER_SDCC_2 4 +#define SDM845_MASTER_SDCC_4 5 +#define SDM845_MASTER_UFS_CARD 6 +#define SDM845_MASTER_UFS_MEM 7 +#define SDM845_MASTER_PCIE_0 8 +#define SDM845_MASTER_A2NOC_CFG 9 +#define SDM845_MASTER_QDSS_BAM 10 +#define SDM845_MASTER_BLSP_2 11 +#define SDM845_MASTER_CNOC_A2NOC 12 +#define SDM845_MASTER_CRYPTO 13 +#define SDM845_MASTER_IPA 14 +#define SDM845_MASTER_PCIE_1 15 +#define SDM845_MASTER_QDSS_ETR 16 +#define SDM845_MASTER_USB3_0 17 +#define SDM845_MASTER_USB3_1 18 +#define SDM845_MASTER_CAMNOC_HF0_UNCOMP 19 +#define SDM845_MASTER_CAMNOC_HF1_UNCOMP 20 +#define SDM845_MASTER_CAMNOC_SF_UNCOMP 21 +#define SDM845_MASTER_SPDM 22 +#define SDM845_MASTER_TIC 23 +#define SDM845_MASTER_SNOC_CNOC 24 +#define SDM845_MASTER_QDSS_DAP 25 +#define SDM845_MASTER_CNOC_DC_NOC 26 +#define SDM845_MASTER_APPSS_PROC 27 +#define SDM845_MASTER_GNOC_CFG 28 +#define SDM845_MASTER_LLCC 29 +#define SDM845_MASTER_TCU_0 30 +#define SDM845_MASTER_MEM_NOC_CFG 31 +#define SDM845_MASTER_GNOC_MEM_NOC 32 +#define SDM845_MASTER_MNOC_HF_MEM_NOC 33 +#define SDM845_MASTER_MNOC_SF_MEM_NOC 34 +#define SDM845_MASTER_SNOC_GC_MEM_NOC 35 +#define SDM845_MASTER_SNOC_SF_MEM_NOC 36 +#define SDM845_MASTER_GFX3D 37 +#define SDM845_MASTER_CNOC_MNOC_CFG 38 +#define SDM845_MASTER_CAMNOC_HF0 39 +#define SDM845_MASTER_CAMNOC_HF1 40 +#define SDM845_MASTER_CAMNOC_SF 41 +#define SDM845_MASTER_MDP0 42 +#define SDM845_MASTER_MDP1 43 +#define SDM845_MASTER_ROTATOR 44 +#define SDM845_MASTER_VIDEO_P0 45 +#define SDM845_MASTER_VIDEO_P1 46 +#define SDM845_MASTER_VIDEO_PROC 47 +#define SDM845_MASTER_SNOC_CFG 48 +#define SDM845_MASTER_A1NOC_SNOC 49 +#define SDM845_MASTER_A2NOC_SNOC 50 +#define SDM845_MASTER_GNOC_SNOC 51 +#define SDM845_MASTER_MEM_NOC_SNOC 52 +#define SDM845_MASTER_ANOC_PCIE_SNOC 53 +#define SDM845_MASTER_PIMEM 54 +#define SDM845_MASTER_GIC 55 +#define SDM845_SLAVE_A1NOC_SNOC 56 +#define SDM845_SLAVE_SERVICE_A1NOC 57 +#define SDM845_SLAVE_ANOC_PCIE_A1NOC_SNOC 58 +#define SDM845_SLAVE_A2NOC_SNOC 59 +#define SDM845_SLAVE_ANOC_PCIE_SNOC 60 +#define SDM845_SLAVE_SERVICE_A2NOC 61 +#define SDM845_SLAVE_CAMNOC_UNCOMP 62 +#define SDM845_SLAVE_A1NOC_CFG 63 +#define SDM845_SLAVE_A2NOC_CFG 64 +#define SDM845_SLAVE_AOP 65 +#define SDM845_SLAVE_AOSS 66 +#define SDM845_SLAVE_CAMERA_CFG 67 +#define SDM845_SLAVE_CLK_CTL 68 +#define SDM845_SLAVE_CDSP_CFG 69 +#define SDM845_SLAVE_RBCPR_CX_CFG 70 +#define SDM845_SLAVE_CRYPTO_0_CFG 71 +#define SDM845_SLAVE_DCC_CFG 72 +#define SDM845_SLAVE_CNOC_DDRSS 73 +#define SDM845_SLAVE_DISPLAY_CFG 74 +#define SDM845_SLAVE_GLM 75 +#define SDM845_SLAVE_GFX3D_CFG 76 +#define SDM845_SLAVE_IMEM_CFG 77 +#define SDM845_SLAVE_IPA_CFG 78 +#define SDM845_SLAVE_CNOC_MNOC_CFG 79 +#define SDM845_SLAVE_PCIE_0_CFG 80 +#define SDM845_SLAVE_PCIE_1_CFG 81 +#define SDM845_SLAVE_PDM 82 +#define SDM845_SLAVE_SOUTH_PHY_CFG 83 +#define SDM845_SLAVE_PIMEM_CFG 84 +#define SDM845_SLAVE_PRNG 85 +#define SDM845_SLAVE_QDSS_CFG 86 +#define SDM845_SLAVE_BLSP_2 87 +#define SDM845_SLAVE_BLSP_1 88 +#define SDM845_SLAVE_SDCC_2 89 +#define SDM845_SLAVE_SDCC_4 90 +#define SDM845_SLAVE_SNOC_CFG 91 +#define SDM845_SLAVE_SPDM_WRAPPER 92 +#define SDM845_SLAVE_SPSS_CFG 93 +#define SDM845_SLAVE_TCSR 94 +#define SDM845_SLAVE_TLMM_NORTH 95 +#define SDM845_SLAVE_TLMM_SOUTH 96 +#define SDM845_SLAVE_TSIF 97 +#define SDM845_SLAVE_UFS_CARD_CFG 98 +#define SDM845_SLAVE_UFS_MEM_CFG 99 +#define SDM845_SLAVE_USB3_0 100 +#define SDM845_SLAVE_USB3_1 101 +#define SDM845_SLAVE_VENUS_CFG 102 +#define SDM845_SLAVE_VSENSE_CTRL_CFG 103 +#define SDM845_SLAVE_CNOC_A2NOC 104 +#define SDM845_SLAVE_SERVICE_CNOC 105 +#define SDM845_SLAVE_LLCC_CFG 106 +#define SDM845_SLAVE_MEM_NOC_CFG 107 +#define SDM845_SLAVE_GNOC_SNOC 108 +#define SDM845_SLAVE_GNOC_MEM_NOC 109 +#define SDM845_SLAVE_SERVICE_GNOC 110 +#define SDM845_SLAVE_EBI1 111 +#define SDM845_SLAVE_MSS_PROC_MS_MPU_CFG 112 +#define SDM845_SLAVE_MEM_NOC_GNOC 113 +#define SDM845_SLAVE_LLCC 114 +#define SDM845_SLAVE_MEM_NOC_SNOC 115 +#define SDM845_SLAVE_SERVICE_MEM_NOC 116 +#define SDM845_SLAVE_MNOC_SF_MEM_NOC 117 +#define SDM845_SLAVE_MNOC_HF_MEM_NOC 118 +#define SDM845_SLAVE_SERVICE_MNOC 119 +#define SDM845_SLAVE_APPSS 120 +#define SDM845_SLAVE_SNOC_CNOC 121 +#define SDM845_SLAVE_SNOC_MEM_NOC_GC 122 +#define SDM845_SLAVE_SNOC_MEM_NOC_SF 123 +#define SDM845_SLAVE_IMEM 124 +#define SDM845_SLAVE_PCIE_0 125 +#define SDM845_SLAVE_PCIE_1 126 +#define SDM845_SLAVE_PIMEM 127 +#define SDM845_SLAVE_SERVICE_SNOC 128 +#define SDM845_SLAVE_QDSS_STM 129 +#define SDM845_SLAVE_TCU 130 + +#endif /* __DRIVERS_INTERCONNECT_QCOM_SDM845_H__ */ From 7a077f7fdaa4fa641c43a554db2811c62048d7f4 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Tue, 3 Mar 2020 19:02:52 +0200 Subject: [PATCH 1085/4444] dt-bindings: interconnect: Add OSM L3 DT bindings Add bindings for Operating State Manager (OSM) L3 interconnect provider on SDM845 SoCs. Reviewed-by: Rob Herring Signed-off-by: Sibi Sankar Link: https://lore.kernel.org/r/20200227105632.15041-3-sibis@codeaurora.org Signed-off-by: Georgi Djakov --- .../bindings/interconnect/qcom,osm-l3.yaml | 61 +++++++++++++++++++ .../dt-bindings/interconnect/qcom,osm-l3.h | 12 ++++ 2 files changed, 73 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml create mode 100644 include/dt-bindings/interconnect/qcom,osm-l3.h diff --git a/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml b/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml new file mode 100644 index 000000000000..b4d46a1e9257 --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interconnect/qcom,osm-l3.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Operating State Manager (OSM) L3 Interconnect Provider + +maintainers: + - Sibi Sankar + +description: + L3 cache bandwidth requirements on Qualcomm SoCs is serviced by the OSM. + The OSM L3 interconnect provider aggregates the L3 bandwidth requests + from CPU/GPU and relays it to the OSM. + +properties: + compatible: + enum: + - qcom,sdm845-osm-l3 + + reg: + maxItems: 1 + + clocks: + items: + - description: xo clock + - description: alternate clock + + clock-names: + items: + - const: xo + - const: alternate + + '#interconnect-cells': + const: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - '#interconnect-cells' + +additionalProperties: false + +examples: + - | + + #define GPLL0 165 + #define RPMH_CXO_CLK 0 + + osm_l3: interconnect@17d41000 { + compatible = "qcom,sdm845-osm-l3"; + reg = <0x17d41000 0x1400>; + + clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>; + clock-names = "xo", "alternate"; + + #interconnect-cells = <1>; + }; diff --git a/include/dt-bindings/interconnect/qcom,osm-l3.h b/include/dt-bindings/interconnect/qcom,osm-l3.h new file mode 100644 index 000000000000..54858ff7674d --- /dev/null +++ b/include/dt-bindings/interconnect/qcom,osm-l3.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2019 The Linux Foundation. All rights reserved. + */ + +#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_OSM_L3_H +#define __DT_BINDINGS_INTERCONNECT_QCOM_OSM_L3_H + +#define MASTER_OSM_L3_APPS 0 +#define SLAVE_OSM_L3 1 + +#endif From 5bc9900addafb99163232dbb970eb07661ae4178 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Tue, 3 Mar 2020 19:02:52 +0200 Subject: [PATCH 1086/4444] interconnect: qcom: Add OSM L3 interconnect provider support On some Qualcomm SoCs, Operating State Manager (OSM) controls the resources of scaling L3 caches. Add a driver to handle bandwidth requests to OSM L3 from CPU on SDM845 SoCs. Signed-off-by: Sibi Sankar Reviewed-by: Evan Green Link: https://lore.kernel.org/r/20200227105632.15041-4-sibis@codeaurora.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/Kconfig | 7 + drivers/interconnect/qcom/Makefile | 2 + drivers/interconnect/qcom/osm-l3.c | 261 +++++++++++++++++++++++++++++ drivers/interconnect/qcom/sdm845.h | 2 + 4 files changed, 272 insertions(+) create mode 100644 drivers/interconnect/qcom/osm-l3.c diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig index c36155611434..a88f2f07bc27 100644 --- a/drivers/interconnect/qcom/Kconfig +++ b/drivers/interconnect/qcom/Kconfig @@ -26,6 +26,13 @@ config INTERCONNECT_QCOM_MSM8974 This is a driver for the Qualcomm Network-on-Chip on msm8974-based platforms. +config INTERCONNECT_QCOM_OSM_L3 + tristate "Qualcomm OSM L3 interconnect driver" + depends on INTERCONNECT_QCOM || COMPILE_TEST + help + Say y here to support the Operating State Manager (OSM) interconnect + driver which controls the scaling of L3 caches on Qualcomm SoCs. + config INTERCONNECT_QCOM_QCS404 tristate "Qualcomm QCS404 interconnect driver" depends on INTERCONNECT_QCOM diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile index 532555812ef6..3a047fe6e45a 100644 --- a/drivers/interconnect/qcom/Makefile +++ b/drivers/interconnect/qcom/Makefile @@ -3,6 +3,7 @@ icc-bcm-voter-objs := bcm-voter.o qnoc-msm8916-objs := msm8916.o qnoc-msm8974-objs := msm8974.o +icc-osm-l3-objs := osm-l3.o qnoc-qcs404-objs := qcs404.o icc-rpmh-obj := icc-rpmh.o qnoc-sc7180-objs := sc7180.o @@ -12,6 +13,7 @@ icc-smd-rpm-objs := smd-rpm.o obj-$(CONFIG_INTERCONNECT_QCOM_BCM_VOTER) += icc-bcm-voter.o obj-$(CONFIG_INTERCONNECT_QCOM_MSM8916) += qnoc-msm8916.o obj-$(CONFIG_INTERCONNECT_QCOM_MSM8974) += qnoc-msm8974.o +obj-$(CONFIG_INTERCONNECT_QCOM_OSM_L3) += icc-osm-l3.o obj-$(CONFIG_INTERCONNECT_QCOM_QCS404) += qnoc-qcs404.o obj-$(CONFIG_INTERCONNECT_QCOM_RPMH) += icc-rpmh.o obj-$(CONFIG_INTERCONNECT_QCOM_SC7180) += qnoc-sc7180.o diff --git a/drivers/interconnect/qcom/osm-l3.c b/drivers/interconnect/qcom/osm-l3.c new file mode 100644 index 000000000000..bbf813319597 --- /dev/null +++ b/drivers/interconnect/qcom/osm-l3.c @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "sdm845.h" + +#define LUT_MAX_ENTRIES 40U +#define LUT_SRC GENMASK(31, 30) +#define LUT_L_VAL GENMASK(7, 0) +#define LUT_ROW_SIZE 32 +#define CLK_HW_DIV 2 + +/* Register offsets */ +#define REG_ENABLE 0x0 +#define REG_FREQ_LUT 0x110 +#define REG_PERF_STATE 0x920 + +#define OSM_L3_MAX_LINKS 1 + +#define to_qcom_provider(_provider) \ + container_of(_provider, struct qcom_osm_l3_icc_provider, provider) + +struct qcom_osm_l3_icc_provider { + void __iomem *base; + unsigned int max_state; + unsigned long lut_tables[LUT_MAX_ENTRIES]; + struct icc_provider provider; +}; + +/** + * struct qcom_icc_node - Qualcomm specific interconnect nodes + * @name: the node name used in debugfs + * @links: an array of nodes where we can go next while traversing + * @id: a unique node identifier + * @num_links: the total number of @links + * @buswidth: width of the interconnect between a node and the bus + */ +struct qcom_icc_node { + const char *name; + u16 links[OSM_L3_MAX_LINKS]; + u16 id; + u16 num_links; + u16 buswidth; +}; + +struct qcom_icc_desc { + struct qcom_icc_node **nodes; + size_t num_nodes; +}; + +#define DEFINE_QNODE(_name, _id, _buswidth, ...) \ + static struct qcom_icc_node _name = { \ + .name = #_name, \ + .id = _id, \ + .buswidth = _buswidth, \ + .num_links = ARRAY_SIZE(((int[]){ __VA_ARGS__ })), \ + .links = { __VA_ARGS__ }, \ + } + +DEFINE_QNODE(sdm845_osm_apps_l3, SDM845_MASTER_OSM_L3_APPS, 16, SDM845_SLAVE_OSM_L3); +DEFINE_QNODE(sdm845_osm_l3, SDM845_SLAVE_OSM_L3, 16); + +static struct qcom_icc_node *sdm845_osm_l3_nodes[] = { + [MASTER_OSM_L3_APPS] = &sdm845_osm_apps_l3, + [SLAVE_OSM_L3] = &sdm845_osm_l3, +}; + +const static struct qcom_icc_desc sdm845_icc_osm_l3 = { + .nodes = sdm845_osm_l3_nodes, + .num_nodes = ARRAY_SIZE(sdm845_osm_l3_nodes), +}; + +static int qcom_icc_set(struct icc_node *src, struct icc_node *dst) +{ + struct qcom_osm_l3_icc_provider *qp; + struct icc_provider *provider; + struct qcom_icc_node *qn; + struct icc_node *n; + unsigned int index; + u32 agg_peak = 0; + u32 agg_avg = 0; + u64 rate; + + qn = src->data; + provider = src->provider; + qp = to_qcom_provider(provider); + + list_for_each_entry(n, &provider->nodes, node_list) + provider->aggregate(n, 0, n->avg_bw, n->peak_bw, + &agg_avg, &agg_peak); + + rate = max(agg_avg, agg_peak); + rate = icc_units_to_bps(rate); + do_div(rate, qn->buswidth); + + for (index = 0; index < qp->max_state - 1; index++) { + if (qp->lut_tables[index] >= rate) + break; + } + + writel_relaxed(index, qp->base + REG_PERF_STATE); + + return 0; +} + +static int qcom_osm_l3_remove(struct platform_device *pdev) +{ + struct qcom_osm_l3_icc_provider *qp = platform_get_drvdata(pdev); + + icc_nodes_remove(&qp->provider); + return icc_provider_del(&qp->provider); +} + +static int qcom_osm_l3_probe(struct platform_device *pdev) +{ + u32 info, src, lval, i, prev_freq = 0, freq; + static unsigned long hw_rate, xo_rate; + struct qcom_osm_l3_icc_provider *qp; + const struct qcom_icc_desc *desc; + struct icc_onecell_data *data; + struct icc_provider *provider; + struct qcom_icc_node **qnodes; + struct icc_node *node; + size_t num_nodes; + struct clk *clk; + int ret; + + clk = clk_get(&pdev->dev, "xo"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + xo_rate = clk_get_rate(clk); + clk_put(clk); + + clk = clk_get(&pdev->dev, "alternate"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + hw_rate = clk_get_rate(clk) / CLK_HW_DIV; + clk_put(clk); + + qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL); + if (!qp) + return -ENOMEM; + + qp->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(qp->base)) + return PTR_ERR(qp->base); + + /* HW should be in enabled state to proceed */ + if (!(readl_relaxed(qp->base + REG_ENABLE) & 0x1)) { + dev_err(&pdev->dev, "error hardware not enabled\n"); + return -ENODEV; + } + + for (i = 0; i < LUT_MAX_ENTRIES; i++) { + info = readl_relaxed(qp->base + REG_FREQ_LUT + + i * LUT_ROW_SIZE); + src = FIELD_GET(LUT_SRC, info); + lval = FIELD_GET(LUT_L_VAL, info); + if (src) + freq = xo_rate * lval; + else + freq = hw_rate; + + /* Two of the same frequencies signify end of table */ + if (i > 0 && prev_freq == freq) + break; + + dev_dbg(&pdev->dev, "index=%d freq=%d\n", i, freq); + + qp->lut_tables[i] = freq; + prev_freq = freq; + } + qp->max_state = i; + + desc = device_get_match_data(&pdev->dev); + if (!desc) + return -EINVAL; + + qnodes = desc->nodes; + num_nodes = desc->num_nodes; + + data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL); + if (!data) + return -ENOMEM; + + provider = &qp->provider; + provider->dev = &pdev->dev; + provider->set = qcom_icc_set; + provider->aggregate = icc_std_aggregate; + provider->xlate = of_icc_xlate_onecell; + INIT_LIST_HEAD(&provider->nodes); + provider->data = data; + + ret = icc_provider_add(provider); + if (ret) { + dev_err(&pdev->dev, "error adding interconnect provider\n"); + return ret; + } + + for (i = 0; i < num_nodes; i++) { + size_t j; + + node = icc_node_create(qnodes[i]->id); + if (IS_ERR(node)) { + ret = PTR_ERR(node); + goto err; + } + + node->name = qnodes[i]->name; + node->data = qnodes[i]; + icc_node_add(node, provider); + + for (j = 0; j < qnodes[i]->num_links; j++) + icc_link_create(node, qnodes[i]->links[j]); + + data->nodes[i] = node; + } + data->num_nodes = num_nodes; + + platform_set_drvdata(pdev, qp); + + return 0; +err: + icc_nodes_remove(provider); + icc_provider_del(provider); + + return ret; +} + +static const struct of_device_id osm_l3_of_match[] = { + { .compatible = "qcom,sdm845-osm-l3", .data = &sdm845_icc_osm_l3 }, + { } +}; +MODULE_DEVICE_TABLE(of, osm_l3_of_match); + +static struct platform_driver osm_l3_driver = { + .probe = qcom_osm_l3_probe, + .remove = qcom_osm_l3_remove, + .driver = { + .name = "osm-l3", + .of_match_table = osm_l3_of_match, + }, +}; +module_platform_driver(osm_l3_driver); + +MODULE_DESCRIPTION("Qualcomm OSM L3 interconnect driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/qcom/sdm845.h b/drivers/interconnect/qcom/sdm845.h index bc7e425ce985..776e9c2acb27 100644 --- a/drivers/interconnect/qcom/sdm845.h +++ b/drivers/interconnect/qcom/sdm845.h @@ -136,5 +136,7 @@ #define SDM845_SLAVE_SERVICE_SNOC 128 #define SDM845_SLAVE_QDSS_STM 129 #define SDM845_SLAVE_TCU 130 +#define SDM845_MASTER_OSM_L3_APPS 131 +#define SDM845_SLAVE_OSM_L3 132 #endif /* __DRIVERS_INTERCONNECT_QCOM_SDM845_H__ */ From ff3edec1c3fd9bec103f0055406f9732b4919ea8 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Tue, 3 Mar 2020 19:02:52 +0200 Subject: [PATCH 1087/4444] dt-bindings: interconnect: Add OSM L3 DT binding on SC7180 Add OSM L3 interconnect provider binding on SC7180 SoCs. Acked-by: Rob Herring Signed-off-by: Sibi Sankar Link: https://lore.kernel.org/r/20200227105632.15041-5-sibis@codeaurora.org Signed-off-by: Georgi Djakov --- Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml b/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml index b4d46a1e9257..91f70c9067d1 100644 --- a/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml +++ b/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml @@ -17,6 +17,7 @@ description: properties: compatible: enum: + - qcom,sc7180-osm-l3 - qcom,sdm845-osm-l3 reg: From 03c4e6186bbbe639b5277077c26786069e9e2b89 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Tue, 3 Mar 2020 19:02:52 +0200 Subject: [PATCH 1088/4444] interconnect: qcom: Add OSM L3 support on SC7180 Add Operating State Manager (OSM) L3 interconnect provider support on SC7180 SoCs. Signed-off-by: Sibi Sankar Reviewed-by: Evan Green Link: https://lore.kernel.org/r/20200227105632.15041-6-sibis@codeaurora.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/osm-l3.c | 15 +++++++++++++++ drivers/interconnect/qcom/sc7180.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/drivers/interconnect/qcom/osm-l3.c b/drivers/interconnect/qcom/osm-l3.c index bbf813319597..a03c6d6833df 100644 --- a/drivers/interconnect/qcom/osm-l3.c +++ b/drivers/interconnect/qcom/osm-l3.c @@ -14,6 +14,7 @@ #include +#include "sc7180.h" #include "sdm845.h" #define LUT_MAX_ENTRIES 40U @@ -82,6 +83,19 @@ const static struct qcom_icc_desc sdm845_icc_osm_l3 = { .num_nodes = ARRAY_SIZE(sdm845_osm_l3_nodes), }; +DEFINE_QNODE(sc7180_osm_apps_l3, SC7180_MASTER_OSM_L3_APPS, 16, SC7180_SLAVE_OSM_L3); +DEFINE_QNODE(sc7180_osm_l3, SC7180_SLAVE_OSM_L3, 16); + +static struct qcom_icc_node *sc7180_osm_l3_nodes[] = { + [MASTER_OSM_L3_APPS] = &sc7180_osm_apps_l3, + [SLAVE_OSM_L3] = &sc7180_osm_l3, +}; + +const static struct qcom_icc_desc sc7180_icc_osm_l3 = { + .nodes = sc7180_osm_l3_nodes, + .num_nodes = ARRAY_SIZE(sc7180_osm_l3_nodes), +}; + static int qcom_icc_set(struct icc_node *src, struct icc_node *dst) { struct qcom_osm_l3_icc_provider *qp; @@ -242,6 +256,7 @@ err: } static const struct of_device_id osm_l3_of_match[] = { + { .compatible = "qcom,sc7180-osm-l3", .data = &sc7180_icc_osm_l3 }, { .compatible = "qcom,sdm845-osm-l3", .data = &sdm845_icc_osm_l3 }, { } }; diff --git a/drivers/interconnect/qcom/sc7180.h b/drivers/interconnect/qcom/sc7180.h index c2d8388bb880..c6212a10c2f6 100644 --- a/drivers/interconnect/qcom/sc7180.h +++ b/drivers/interconnect/qcom/sc7180.h @@ -145,5 +145,7 @@ #define SC7180_SLAVE_SERVICE_SNOC 134 #define SC7180_SLAVE_QDSS_STM 135 #define SC7180_SLAVE_TCU 136 +#define SC7180_MASTER_OSM_L3_APPS 137 +#define SC7180_SLAVE_OSM_L3 138 #endif From ab70a73aa45beccab01cc0bb1d920361e3642393 Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Thu, 30 Jan 2020 17:04:19 +0000 Subject: [PATCH 1089/4444] riscv: Use flush_icache_mm for flush_icache_user_range The only call path is: __access_remote_vm -> copy_to_user_page -> flush_icache_user_range Seems it's ok to use flush_icache_mm instead of flush_icache_all and it could reduce flush_icache_all called on other harts. Signed-off-by: Guo Ren [Palmer: git-am wouldn't apply the patch, I did so manually] Fixes: 08f051eda33b ("RISC-V: Flush I$ when making a dirty page executable") Reviewed-by: Palmer Dabbelt Signed-off-by: Palmer Dabbelt --- arch/riscv/include/asm/cacheflush.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/include/asm/cacheflush.h b/arch/riscv/include/asm/cacheflush.h index 555b20b11dc3..c8677c75f82c 100644 --- a/arch/riscv/include/asm/cacheflush.h +++ b/arch/riscv/include/asm/cacheflush.h @@ -85,7 +85,7 @@ static inline void flush_dcache_page(struct page *page) * so instead we just flush the whole thing. */ #define flush_icache_range(start, end) flush_icache_all() -#define flush_icache_user_range(vma, pg, addr, len) flush_icache_all() +#define flush_icache_user_range(vma, pg, addr, len) flush_icache_mm(vma->vm_mm, 0) #ifndef CONFIG_SMP From 2fab7a15604cfe3605775c5d146a7dfcf97412bb Mon Sep 17 00:00:00 2001 From: Deepa Dinamani Date: Sun, 5 Jan 2020 12:10:20 -0800 Subject: [PATCH 1090/4444] riscv: Delete CONFIG_SYSFS_SYSCALL from defconfigs According to init/Kconfig: "sys_sysfs is an obsolete system call no longer supported in libc. Note that disabling this option is more secure but might break compatibility with some systems." This syscall is not required for new architectures. Since the config defaults to 'y'. Set this to 'n' exlicitly. Signed-off-by: Deepa Dinamani Signed-off-by: Palmer Dabbelt --- arch/riscv/configs/defconfig | 1 + arch/riscv/configs/rv32_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig index e2ff95cb3390..58f97b3cb24c 100644 --- a/arch/riscv/configs/defconfig +++ b/arch/riscv/configs/defconfig @@ -125,3 +125,4 @@ CONFIG_DEBUG_BLOCK_EXT_DEVT=y # CONFIG_FTRACE is not set # CONFIG_RUNTIME_TESTING_MENU is not set CONFIG_MEMTEST=y +# CONFIG_SYSFS_SYSCALL is not set diff --git a/arch/riscv/configs/rv32_defconfig b/arch/riscv/configs/rv32_defconfig index eb519407c841..f4076b6ac063 100644 --- a/arch/riscv/configs/rv32_defconfig +++ b/arch/riscv/configs/rv32_defconfig @@ -122,3 +122,4 @@ CONFIG_DEBUG_BLOCK_EXT_DEVT=y # CONFIG_FTRACE is not set # CONFIG_RUNTIME_TESTING_MENU is not set CONFIG_MEMTEST=y +# CONFIG_SYSFS_SYSCALL is not set From aff7783392e0c0152ee01653ce9c61abb4928910 Mon Sep 17 00:00:00 2001 From: Zong Li Date: Tue, 4 Feb 2020 19:19:47 +0800 Subject: [PATCH 1091/4444] riscv: force hart_lottery to put in .sdata section In PIC code model, the zero initialized data always be put in .bss section, so when building kernel as PIE, the hart_lottery won't present in small data section, and it causes more than one harts to get the lottery, because the main hart clears the content of .bss section immediately after it getting the lottery. Signed-off-by: Zong Li Reviewed-by: Anup Patel [Palmer: added a comment] Reviewed-by: Palmer Dabbelt Signed-off-by: Palmer Dabbelt --- arch/riscv/kernel/setup.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index 0a6d415b0a5a..cb836fcc6118 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -39,8 +39,12 @@ struct screen_info screen_info = { }; #endif -/* The lucky hart to first increment this variable will boot the other cores */ -atomic_t hart_lottery; +/* + * The lucky hart to first increment this variable will boot the other cores. + * This is used before the kernel initializes the BSS so it can't be in the + * BSS. + */ +atomic_t hart_lottery __section(.sdata); unsigned long boot_cpu_hartid; void __init parse_dtb(void) From 064223b947a8c3d0b35a4ac9ae6e31e3f77657fd Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Tue, 18 Feb 2020 13:17:06 -0800 Subject: [PATCH 1092/4444] RISC-V: Stop putting .sbss in .sdata I don't know why we were doing this, as it's been there since the beginning. After d841f729e655 ("riscv: force hart_lottery to put in .sdata section") my guess would be that it made the kernel boot and we forgot to fix it more cleanly. The default .bss segment already contains the .sbss section, so we don't need to do anything additional to ensure the symbols in .sbss continue to work. Tested-by: Zong Li Signed-off-by: Palmer Dabbelt --- arch/riscv/kernel/vmlinux.lds.S | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S index 1e0193ded420..a8fb52a00295 100644 --- a/arch/riscv/kernel/vmlinux.lds.S +++ b/arch/riscv/kernel/vmlinux.lds.S @@ -64,7 +64,6 @@ SECTIONS *(.sdata*) /* End of data section */ _edata = .; - *(.sbss*) } BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0) From 52e7c52d2ded5908e6a4f8a7248e5fa6e0d6809a Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Thu, 27 Feb 2020 11:07:28 -0800 Subject: [PATCH 1093/4444] RISC-V: Stop relying on GCC's register allocator's hueristics GCC allows users to hint to the register allocation that a variable should be placed in a register by using a syntax along the lines of function(...) { register long in_REG __asm__("REG"); } We've abused this a bit throughout the RISC-V port to access fixed registers directly as C variables. In practice it's never going to blow up because GCC isn't going to allocate these registers, but it's not a well defined syntax so we really shouldn't be relying upon this. Luckily there is a very similar but well defined syntax that allows us to still access these registers directly as C variables, which is to simply declare the register variables globally. For fixed variables this doesn't change the ABI. LLVM disallows this ambiguous syntax, so this isn't just strictly a formatting change. Signed-off-by: Palmer Dabbelt --- arch/riscv/include/asm/current.h | 5 +++-- arch/riscv/kernel/process.c | 5 +++-- arch/riscv/kernel/stacktrace.c | 7 ++++--- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/arch/riscv/include/asm/current.h b/arch/riscv/include/asm/current.h index dd973efe5d7c..1de233d8e8de 100644 --- a/arch/riscv/include/asm/current.h +++ b/arch/riscv/include/asm/current.h @@ -17,6 +17,8 @@ struct task_struct; +register struct task_struct *riscv_current_is_tp __asm__("tp"); + /* * This only works because "struct thread_info" is at offset 0 from "struct * task_struct". This constraint seems to be necessary on other architectures @@ -26,8 +28,7 @@ struct task_struct; */ static __always_inline struct task_struct *get_current(void) { - register struct task_struct *tp __asm__("tp"); - return tp; + return riscv_current_is_tp; } #define current get_current() diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c index 817cf7b0974c..610c11e91606 100644 --- a/arch/riscv/kernel/process.c +++ b/arch/riscv/kernel/process.c @@ -22,6 +22,8 @@ #include #include +unsigned long gp_in_global __asm__("gp"); + extern asmlinkage void ret_from_fork(void); extern asmlinkage void ret_from_kernel_thread(void); @@ -107,9 +109,8 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long usp, /* p->thread holds context to be restored by __switch_to() */ if (unlikely(p->flags & PF_KTHREAD)) { /* Kernel thread */ - const register unsigned long gp __asm__ ("gp"); memset(childregs, 0, sizeof(struct pt_regs)); - childregs->gp = gp; + childregs->gp = gp_in_global; /* Supervisor/Machine, irqs on: */ childregs->status = SR_PP | SR_PIE; diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c index 0940681d2f68..02087fe539c6 100644 --- a/arch/riscv/kernel/stacktrace.c +++ b/arch/riscv/kernel/stacktrace.c @@ -19,6 +19,8 @@ struct stackframe { unsigned long ra; }; +register unsigned long sp_in_global __asm__("sp"); + void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, bool (*fn)(unsigned long, void *), void *arg) { @@ -29,7 +31,7 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, sp = user_stack_pointer(regs); pc = instruction_pointer(regs); } else if (task == NULL || task == current) { - const register unsigned long current_sp __asm__ ("sp"); + const register unsigned long current_sp = sp_in_global; fp = (unsigned long)__builtin_frame_address(0); sp = current_sp; pc = (unsigned long)walk_stackframe; @@ -73,8 +75,7 @@ static void notrace walk_stackframe(struct task_struct *task, sp = user_stack_pointer(regs); pc = instruction_pointer(regs); } else if (task == NULL || task == current) { - const register unsigned long current_sp __asm__ ("sp"); - sp = current_sp; + sp = sp_in_global; pc = (unsigned long)walk_stackframe; } else { /* task blocked in __switch_to */ From fdff9911f266951b14b20e25557278b5b3f0d90d Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Thu, 27 Feb 2020 11:15:03 -0800 Subject: [PATCH 1094/4444] RISC-V: Inline the assembly register save/restore macros These are only used once, and when reading the code I've always found them to be more of a headache than a benefit. While they were never worth removing before, LLVM's integrated assembler doesn't support LOCAL so rather that trying to figure out how to refactor the macros it seems saner to just inline them. Reviewed-by: Nick Desaulniers Signed-off-by: Palmer Dabbelt --- arch/riscv/kernel/entry.S | 143 ++++++++++++++++---------------------- 1 file changed, 61 insertions(+), 82 deletions(-) diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S index bad4d85b5e91..f2e8e7c8089d 100644 --- a/arch/riscv/kernel/entry.S +++ b/arch/riscv/kernel/entry.S @@ -13,17 +13,11 @@ #include #include - .text - .altmacro - -/* - * Prepares to enter a system call or exception by saving all registers to the - * stack. - */ - .macro SAVE_ALL - LOCAL _restore_kernel_tpsp - LOCAL _save_context +#if !IS_ENABLED(CONFIG_PREEMPTION) +.set resume_kernel, restore_all +#endif +ENTRY(handle_exception) /* * If coming from userspace, preserve the user thread pointer and load * the kernel thread pointer. If we came from the kernel, the scratch @@ -90,77 +84,6 @@ _save_context: REG_S s3, PT_BADADDR(sp) REG_S s4, PT_CAUSE(sp) REG_S s5, PT_TP(sp) - .endm - -/* - * Prepares to return from a system call or exception by restoring all - * registers from the stack. - */ - .macro RESTORE_ALL - REG_L a0, PT_STATUS(sp) - /* - * The current load reservation is effectively part of the processor's - * state, in the sense that load reservations cannot be shared between - * different hart contexts. We can't actually save and restore a load - * reservation, so instead here we clear any existing reservation -- - * it's always legal for implementations to clear load reservations at - * any point (as long as the forward progress guarantee is kept, but - * we'll ignore that here). - * - * Dangling load reservations can be the result of taking a trap in the - * middle of an LR/SC sequence, but can also be the result of a taken - * forward branch around an SC -- which is how we implement CAS. As a - * result we need to clear reservations between the last CAS and the - * jump back to the new context. While it is unlikely the store - * completes, implementations are allowed to expand reservations to be - * arbitrarily large. - */ - REG_L a2, PT_EPC(sp) - REG_SC x0, a2, PT_EPC(sp) - - csrw CSR_STATUS, a0 - csrw CSR_EPC, a2 - - REG_L x1, PT_RA(sp) - REG_L x3, PT_GP(sp) - REG_L x4, PT_TP(sp) - REG_L x5, PT_T0(sp) - REG_L x6, PT_T1(sp) - REG_L x7, PT_T2(sp) - REG_L x8, PT_S0(sp) - REG_L x9, PT_S1(sp) - REG_L x10, PT_A0(sp) - REG_L x11, PT_A1(sp) - REG_L x12, PT_A2(sp) - REG_L x13, PT_A3(sp) - REG_L x14, PT_A4(sp) - REG_L x15, PT_A5(sp) - REG_L x16, PT_A6(sp) - REG_L x17, PT_A7(sp) - REG_L x18, PT_S2(sp) - REG_L x19, PT_S3(sp) - REG_L x20, PT_S4(sp) - REG_L x21, PT_S5(sp) - REG_L x22, PT_S6(sp) - REG_L x23, PT_S7(sp) - REG_L x24, PT_S8(sp) - REG_L x25, PT_S9(sp) - REG_L x26, PT_S10(sp) - REG_L x27, PT_S11(sp) - REG_L x28, PT_T3(sp) - REG_L x29, PT_T4(sp) - REG_L x30, PT_T5(sp) - REG_L x31, PT_T6(sp) - - REG_L x2, PT_SP(sp) - .endm - -#if !IS_ENABLED(CONFIG_PREEMPTION) -.set resume_kernel, restore_all -#endif - -ENTRY(handle_exception) - SAVE_ALL /* * Set the scratch register to 0, so that if a recursive exception @@ -298,7 +221,63 @@ resume_userspace: csrw CSR_SCRATCH, tp restore_all: - RESTORE_ALL + REG_L a0, PT_STATUS(sp) + /* + * The current load reservation is effectively part of the processor's + * state, in the sense that load reservations cannot be shared between + * different hart contexts. We can't actually save and restore a load + * reservation, so instead here we clear any existing reservation -- + * it's always legal for implementations to clear load reservations at + * any point (as long as the forward progress guarantee is kept, but + * we'll ignore that here). + * + * Dangling load reservations can be the result of taking a trap in the + * middle of an LR/SC sequence, but can also be the result of a taken + * forward branch around an SC -- which is how we implement CAS. As a + * result we need to clear reservations between the last CAS and the + * jump back to the new context. While it is unlikely the store + * completes, implementations are allowed to expand reservations to be + * arbitrarily large. + */ + REG_L a2, PT_EPC(sp) + REG_SC x0, a2, PT_EPC(sp) + + csrw CSR_STATUS, a0 + csrw CSR_EPC, a2 + + REG_L x1, PT_RA(sp) + REG_L x3, PT_GP(sp) + REG_L x4, PT_TP(sp) + REG_L x5, PT_T0(sp) + REG_L x6, PT_T1(sp) + REG_L x7, PT_T2(sp) + REG_L x8, PT_S0(sp) + REG_L x9, PT_S1(sp) + REG_L x10, PT_A0(sp) + REG_L x11, PT_A1(sp) + REG_L x12, PT_A2(sp) + REG_L x13, PT_A3(sp) + REG_L x14, PT_A4(sp) + REG_L x15, PT_A5(sp) + REG_L x16, PT_A6(sp) + REG_L x17, PT_A7(sp) + REG_L x18, PT_S2(sp) + REG_L x19, PT_S3(sp) + REG_L x20, PT_S4(sp) + REG_L x21, PT_S5(sp) + REG_L x22, PT_S6(sp) + REG_L x23, PT_S7(sp) + REG_L x24, PT_S8(sp) + REG_L x25, PT_S9(sp) + REG_L x26, PT_S10(sp) + REG_L x27, PT_S11(sp) + REG_L x28, PT_T3(sp) + REG_L x29, PT_T4(sp) + REG_L x30, PT_T5(sp) + REG_L x31, PT_T6(sp) + + REG_L x2, PT_SP(sp) + #ifdef CONFIG_RISCV_M_MODE mret #else From abc71bf0a70311ab294f97a7f16e8de03718c05a Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Thu, 27 Feb 2020 11:16:28 -0800 Subject: [PATCH 1095/4444] RISC-V: Stop using LOCAL for the uaccess fixups LLVM's integrated assembler doesn't support the LOCAL directive, which we're using when generating our uaccess fixup tables. Luckily the table fragment is small enough that there's only one internal symbol, so using a relative symbol reference doesn't really complicate anything. Signed-off-by: Palmer Dabbelt --- arch/riscv/lib/uaccess.S | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/riscv/lib/uaccess.S b/arch/riscv/lib/uaccess.S index f29d2ba2c0a6..fceaeb18cc64 100644 --- a/arch/riscv/lib/uaccess.S +++ b/arch/riscv/lib/uaccess.S @@ -3,14 +3,12 @@ #include #include - .altmacro .macro fixup op reg addr lbl - LOCAL _epc -_epc: +100: \op \reg, \addr .section __ex_table,"a" .balign RISCV_SZPTR - RISCV_PTR _epc, \lbl + RISCV_PTR 100b, \lbl .previous .endm From b396bfdebffcc05a855137775e38f4652cbca454 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 12 Feb 2020 12:21:03 -0500 Subject: [PATCH 1096/4444] tracing: Have hwlat ts be first instance and record count of instances The hwlat tracer runs a loop of width time during a given window. It then reports the max latency over a given threshold and records a timestamp. But this timestamp is the time after the width has finished, and not the time it actually triggered. Record the actual time when the latency was greater than the threshold as well as the number of times it was greater in a given width per window. Signed-off-by: Steven Rostedt (VMware) --- Documentation/trace/ftrace.rst | 32 ++++++++++++++++++++++---------- kernel/trace/trace_entries.h | 4 +++- kernel/trace/trace_hwlat.c | 24 +++++++++++++++++------- kernel/trace/trace_output.c | 4 ++-- 4 files changed, 44 insertions(+), 20 deletions(-) diff --git a/Documentation/trace/ftrace.rst b/Documentation/trace/ftrace.rst index ff658e27d25b..99a0890e20ec 100644 --- a/Documentation/trace/ftrace.rst +++ b/Documentation/trace/ftrace.rst @@ -2126,6 +2126,8 @@ periodically make a CPU constantly busy with interrupts disabled. # cat trace # tracer: hwlat # + # entries-in-buffer/entries-written: 13/13 #P:8 + # # _-----=> irqs-off # / _----=> need-resched # | / _---=> hardirq/softirq @@ -2133,12 +2135,18 @@ periodically make a CPU constantly busy with interrupts disabled. # ||| / delay # TASK-PID CPU# |||| TIMESTAMP FUNCTION # | | | |||| | | - <...>-3638 [001] d... 19452.055471: #1 inner/outer(us): 12/14 ts:1499801089.066141940 - <...>-3638 [003] d... 19454.071354: #2 inner/outer(us): 11/9 ts:1499801091.082164365 - <...>-3638 [002] dn.. 19461.126852: #3 inner/outer(us): 12/9 ts:1499801098.138150062 - <...>-3638 [001] d... 19488.340960: #4 inner/outer(us): 8/12 ts:1499801125.354139633 - <...>-3638 [003] d... 19494.388553: #5 inner/outer(us): 8/12 ts:1499801131.402150961 - <...>-3638 [003] d... 19501.283419: #6 inner/outer(us): 0/12 ts:1499801138.297435289 nmi-total:4 nmi-count:1 + <...>-1729 [001] d... 678.473449: #1 inner/outer(us): 11/12 ts:1581527483.343962693 count:6 + <...>-1729 [004] d... 689.556542: #2 inner/outer(us): 16/9 ts:1581527494.889008092 count:1 + <...>-1729 [005] d... 714.756290: #3 inner/outer(us): 16/16 ts:1581527519.678961629 count:5 + <...>-1729 [001] d... 718.788247: #4 inner/outer(us): 9/17 ts:1581527523.889012713 count:1 + <...>-1729 [002] d... 719.796341: #5 inner/outer(us): 13/9 ts:1581527524.912872606 count:1 + <...>-1729 [006] d... 844.787091: #6 inner/outer(us): 9/12 ts:1581527649.889048502 count:2 + <...>-1729 [003] d... 849.827033: #7 inner/outer(us): 18/9 ts:1581527654.889013793 count:1 + <...>-1729 [007] d... 853.859002: #8 inner/outer(us): 9/12 ts:1581527658.889065736 count:1 + <...>-1729 [001] d... 855.874978: #9 inner/outer(us): 9/11 ts:1581527660.861991877 count:1 + <...>-1729 [001] d... 863.938932: #10 inner/outer(us): 9/11 ts:1581527668.970010500 count:1 nmi-total:7 nmi-count:1 + <...>-1729 [007] d... 878.050780: #11 inner/outer(us): 9/12 ts:1581527683.385002600 count:1 nmi-total:5 nmi-count:1 + <...>-1729 [007] d... 886.114702: #12 inner/outer(us): 9/12 ts:1581527691.385001600 count:1 The above output is somewhat the same in the header. All events will have @@ -2148,7 +2156,7 @@ interrupts disabled 'd'. Under the FUNCTION title there is: This is the count of events recorded that were greater than the tracing_threshold (See below). - inner/outer(us): 12/14 + inner/outer(us): 11/11 This shows two numbers as "inner latency" and "outer latency". The test runs in a loop checking a timestamp twice. The latency detected within @@ -2156,11 +2164,15 @@ interrupts disabled 'd'. Under the FUNCTION title there is: after the previous timestamp and the next timestamp in the loop is the "outer latency". - ts:1499801089.066141940 + ts:1581527483.343962693 - The absolute timestamp that the event happened. + The absolute timestamp that the first latency was recorded in the window. - nmi-total:4 nmi-count:1 + count:6 + + The number of times a latency was detected during the window. + + nmi-total:7 nmi-count:1 On architectures that support it, if an NMI comes in during the test, the time spent in NMI is reported in "nmi-total" (in diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h index f22746f3c132..a523da0dae0a 100644 --- a/kernel/trace/trace_entries.h +++ b/kernel/trace/trace_entries.h @@ -325,14 +325,16 @@ FTRACE_ENTRY(hwlat, hwlat_entry, __field_desc( long, timestamp, tv_nsec ) __field( unsigned int, nmi_count ) __field( unsigned int, seqnum ) + __field( unsigned int, count ) ), - F_printk("cnt:%u\tts:%010llu.%010lu\tinner:%llu\touter:%llu\tnmi-ts:%llu\tnmi-count:%u\n", + F_printk("cnt:%u\tts:%010llu.%010lu\tinner:%llu\touter:%llu\tcount:%d\tnmi-ts:%llu\tnmi-count:%u\n", __entry->seqnum, __entry->tv_sec, __entry->tv_nsec, __entry->duration, __entry->outer_duration, + __entry->count, __entry->nmi_total_ts, __entry->nmi_count) ); diff --git a/kernel/trace/trace_hwlat.c b/kernel/trace/trace_hwlat.c index a48808c43249..e2be7bb7ef7e 100644 --- a/kernel/trace/trace_hwlat.c +++ b/kernel/trace/trace_hwlat.c @@ -83,6 +83,7 @@ struct hwlat_sample { u64 nmi_total_ts; /* Total time spent in NMIs */ struct timespec64 timestamp; /* wall time */ int nmi_count; /* # NMIs during this sample */ + int count; /* # of iteratons over threash */ }; /* keep the global state somewhere. */ @@ -124,6 +125,7 @@ static void trace_hwlat_sample(struct hwlat_sample *sample) entry->timestamp = sample->timestamp; entry->nmi_total_ts = sample->nmi_total_ts; entry->nmi_count = sample->nmi_count; + entry->count = sample->count; if (!call_filter_check_discard(call, entry, buffer, event)) trace_buffer_unlock_commit_nostack(buffer, event); @@ -167,12 +169,14 @@ void trace_hwlat_callback(bool enter) static int get_sample(void) { struct trace_array *tr = hwlat_trace; + struct hwlat_sample s; time_type start, t1, t2, last_t2; - s64 diff, total, last_total = 0; + s64 diff, outer_diff, total, last_total = 0; u64 sample = 0; u64 thresh = tracing_thresh; u64 outer_sample = 0; int ret = -1; + unsigned int count = 0; do_div(thresh, NSEC_PER_USEC); /* modifies interval value */ @@ -186,6 +190,7 @@ static int get_sample(void) init_time(last_t2, 0); start = time_get(); /* start timestamp */ + outer_diff = 0; do { @@ -194,14 +199,14 @@ static int get_sample(void) if (time_u64(last_t2)) { /* Check the delta from outer loop (t2 to next t1) */ - diff = time_to_us(time_sub(t1, last_t2)); + outer_diff = time_to_us(time_sub(t1, last_t2)); /* This shouldn't happen */ - if (diff < 0) { + if (outer_diff < 0) { pr_err(BANNER "time running backwards\n"); goto out; } - if (diff > outer_sample) - outer_sample = diff; + if (outer_diff > outer_sample) + outer_sample = outer_diff; } last_t2 = t2; @@ -217,6 +222,12 @@ static int get_sample(void) /* This checks the inner loop (t1 to t2) */ diff = time_to_us(time_sub(t2, t1)); /* current diff */ + if (diff > thresh || outer_diff > thresh) { + if (!count) + ktime_get_real_ts64(&s.timestamp); + count++; + } + /* This shouldn't happen */ if (diff < 0) { pr_err(BANNER "time running backwards\n"); @@ -236,7 +247,6 @@ static int get_sample(void) /* If we exceed the threshold value, we have found a hardware latency */ if (sample > thresh || outer_sample > thresh) { - struct hwlat_sample s; u64 latency; ret = 1; @@ -249,9 +259,9 @@ static int get_sample(void) s.seqnum = hwlat_data.count; s.duration = sample; s.outer_duration = outer_sample; - ktime_get_real_ts64(&s.timestamp); s.nmi_total_ts = nmi_total_ts; s.nmi_count = nmi_count; + s.count = count; trace_hwlat_sample(&s); latency = max(sample, outer_sample); diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index b4909082f6a4..e25a7da79c6b 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c @@ -1158,12 +1158,12 @@ trace_hwlat_print(struct trace_iterator *iter, int flags, trace_assign_type(field, entry); - trace_seq_printf(s, "#%-5u inner/outer(us): %4llu/%-5llu ts:%lld.%09ld", + trace_seq_printf(s, "#%-5u inner/outer(us): %4llu/%-5llu ts:%lld.%09ld count:%d", field->seqnum, field->duration, field->outer_duration, (long long)field->timestamp.tv_sec, - field->timestamp.tv_nsec); + field->timestamp.tv_nsec, field->count); if (field->nmi_count) { /* From 5412e0b763e0c46165fa353f695fa3b68a66ac91 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Fri, 14 Feb 2020 16:20:04 -0500 Subject: [PATCH 1097/4444] tracing: Remove unused TRACE_BUFFER bits Commit 567cd4da54ff ("ring-buffer: User context bit recursion checking") added the TRACE_BUFFER bits to be used in the current task's trace_recursion field. But the final submission of the logic removed the use of those bits, but never removed the bits themselves (they were never used in upstream Linux). These can be safely removed. Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 99372dd7d168..c61e1b1c85a6 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -557,12 +557,7 @@ struct tracer { * caller, and we can skip the current check. */ enum { - TRACE_BUFFER_BIT, - TRACE_BUFFER_NMI_BIT, - TRACE_BUFFER_IRQ_BIT, - TRACE_BUFFER_SIRQ_BIT, - - /* Start of function recursion bits */ + /* Function recursion bits */ TRACE_FTRACE_BIT, TRACE_FTRACE_NMI_BIT, TRACE_FTRACE_IRQ_BIT, From 306b69dce9269df116bfa94319b1b827c22d5794 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 3 Mar 2020 20:24:40 +0900 Subject: [PATCH 1098/4444] bootconfig: Support O= option Support O= option to build bootconfig tool in the other directory. As same as other tools, if you specify O=, bootconfig command is build under . Link: http://lkml.kernel.org/r/158323468033.10560.14661631369326294355.stgit@devnote2 Reported-by: Randy Dunlap Signed-off-by: Masami Hiramatsu Signed-off-by: Steven Rostedt (VMware) --- tools/bootconfig/Makefile | 27 +++++++++++++++++---------- tools/bootconfig/test-bootconfig.sh | 14 ++++++++++---- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/tools/bootconfig/Makefile b/tools/bootconfig/Makefile index a6146ac64458..da5975775337 100644 --- a/tools/bootconfig/Makefile +++ b/tools/bootconfig/Makefile @@ -1,23 +1,30 @@ # SPDX-License-Identifier: GPL-2.0 # Makefile for bootconfig command +include ../scripts/Makefile.include bindir ?= /usr/bin -HEADER = include/linux/bootconfig.h -CFLAGS = -Wall -g -I./include +ifeq ($(srctree),) +srctree := $(patsubst %/,%,$(dir $(CURDIR))) +srctree := $(patsubst %/,%,$(dir $(srctree))) +endif -PROGS = bootconfig +LIBSRC = $(srctree)/lib/bootconfig.c $(srctree)/include/linux/bootconfig.h +CFLAGS = -Wall -g -I$(CURDIR)/include -all: $(PROGS) +ALL_TARGETS := bootconfig +ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS)) -bootconfig: ../../lib/bootconfig.c main.c $(HEADER) +all: $(ALL_PROGRAMS) + +$(OUTPUT)bootconfig: main.c $(LIBSRC) $(CC) $(filter %.c,$^) $(CFLAGS) -o $@ -install: $(PROGS) - install bootconfig $(DESTDIR)$(bindir) +test: $(ALL_PROGRAMS) test-bootconfig.sh + ./test-bootconfig.sh $(OUTPUT) -test: bootconfig - ./test-bootconfig.sh +install: $(ALL_PROGRAMS) + install $(OUTPUT)bootconfig $(DESTDIR)$(bindir) clean: - $(RM) -f *.o bootconfig + $(RM) -f $(OUTPUT)*.o $(ALL_PROGRAMS) diff --git a/tools/bootconfig/test-bootconfig.sh b/tools/bootconfig/test-bootconfig.sh index 1411f4c3454f..81b350ffd03f 100755 --- a/tools/bootconfig/test-bootconfig.sh +++ b/tools/bootconfig/test-bootconfig.sh @@ -3,9 +3,16 @@ echo "Boot config test script" -BOOTCONF=./bootconfig -INITRD=`mktemp initrd-XXXX` -TEMPCONF=`mktemp temp-XXXX.bconf` +if [ -d "$1" ]; then + TESTDIR=$1 +else + TESTDIR=. +fi +BOOTCONF=${TESTDIR}/bootconfig + +INITRD=`mktemp ${TESTDIR}/initrd-XXXX` +TEMPCONF=`mktemp ${TESTDIR}/temp-XXXX.bconf` +OUTFILE=`mktemp ${TESTDIR}/tempout-XXXX` NG=0 cleanup() { @@ -65,7 +72,6 @@ new_size=$(stat -c %s $INITRD) xpass test $new_size -eq $initrd_size echo "No error messge while applying" -OUTFILE=`mktemp tempout-XXXX` dd if=/dev/zero of=$INITRD bs=4096 count=1 printf " \0\0\0 \0\0\0" >> $INITRD $BOOTCONF -a $TEMPCONF $INITRD > $OUTFILE 2>&1 From 89b74cac7834734d6b2733204c639917d3826083 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 3 Mar 2020 20:24:50 +0900 Subject: [PATCH 1099/4444] tools/bootconfig: Show line and column in parse error Show line and column when we got a parse error in bootconfig tool. Current lib/bootconfig shows the parse error with byte offset, but that is not human readable. This makes xbc_init() not showing error message itself but able to pass the error message and position to caller, so that the caller can decode it and show the error message with line number and columns. With this patch, bootconfig tool shows an error with line:column as below. $ cat samples/bad-dotword.bconf # do not start keyword with . key { .word = 1 } $ ./bootconfig -a samples/bad-dotword.bconf initrd Parse Error: Invalid keyword at 3:3 Link: http://lkml.kernel.org/r/158323469002.10560.4023923847704522760.stgit@devnote2 Signed-off-by: Masami Hiramatsu Signed-off-by: Steven Rostedt (VMware) --- include/linux/bootconfig.h | 3 ++- init/main.c | 14 ++++++++++---- lib/bootconfig.c | 35 ++++++++++++++++++++++++++--------- tools/bootconfig/main.c | 35 +++++++++++++++++++++++++++++++---- 4 files changed, 69 insertions(+), 18 deletions(-) diff --git a/include/linux/bootconfig.h b/include/linux/bootconfig.h index d11e183fcb54..9903088891fa 100644 --- a/include/linux/bootconfig.h +++ b/include/linux/bootconfig.h @@ -216,7 +216,8 @@ static inline int __init xbc_node_compose_key(struct xbc_node *node, } /* XBC node initializer */ -int __init xbc_init(char *buf); +int __init xbc_init(char *buf, const char **emsg, int *epos); + /* XBC cleanup data structures */ void __init xbc_destroy_all(void); diff --git a/init/main.c b/init/main.c index ee4947af823f..e488213857e2 100644 --- a/init/main.c +++ b/init/main.c @@ -353,6 +353,8 @@ static int __init bootconfig_params(char *param, char *val, static void __init setup_boot_config(const char *cmdline) { static char tmp_cmdline[COMMAND_LINE_SIZE] __initdata; + const char *msg; + int pos; u32 size, csum; char *data, *copy; u32 *hdr; @@ -400,10 +402,14 @@ static void __init setup_boot_config(const char *cmdline) memcpy(copy, data, size); copy[size] = '\0'; - ret = xbc_init(copy); - if (ret < 0) - pr_err("Failed to parse bootconfig\n"); - else { + ret = xbc_init(copy, &msg, &pos); + if (ret < 0) { + if (pos < 0) + pr_err("Failed to init bootconfig: %s.\n", msg); + else + pr_err("Failed to parse bootconfig: %s at %d.\n", + msg, pos); + } else { pr_info("Load bootconfig: %d bytes %d nodes\n", size, ret); /* keys starting with "kernel." are passed via cmdline */ extra_command_line = xbc_make_cmdline("kernel"); diff --git a/lib/bootconfig.c b/lib/bootconfig.c index ec3ce7fd299f..912ef4921398 100644 --- a/lib/bootconfig.c +++ b/lib/bootconfig.c @@ -29,12 +29,14 @@ static int xbc_node_num __initdata; static char *xbc_data __initdata; static size_t xbc_data_size __initdata; static struct xbc_node *last_parent __initdata; +static const char *xbc_err_msg __initdata; +static int xbc_err_pos __initdata; static int __init xbc_parse_error(const char *msg, const char *p) { - int pos = p - xbc_data; + xbc_err_msg = msg; + xbc_err_pos = (int)(p - xbc_data); - pr_err("Parse error at pos %d: %s\n", pos, msg); return -EINVAL; } @@ -738,33 +740,44 @@ void __init xbc_destroy_all(void) /** * xbc_init() - Parse given XBC file and build XBC internal tree * @buf: boot config text + * @emsg: A pointer of const char * to store the error message + * @epos: A pointer of int to store the error position * * This parses the boot config text in @buf. @buf must be a * null terminated string and smaller than XBC_DATA_MAX. * Return the number of stored nodes (>0) if succeeded, or -errno * if there is any error. + * In error cases, @emsg will be updated with an error message and + * @epos will be updated with the error position which is the byte offset + * of @buf. If the error is not a parser error, @epos will be -1. */ -int __init xbc_init(char *buf) +int __init xbc_init(char *buf, const char **emsg, int *epos) { char *p, *q; int ret, c; + if (epos) + *epos = -1; + if (xbc_data) { - pr_err("Error: bootconfig is already initialized.\n"); + if (emsg) + *emsg = "Bootconfig is already initialized"; return -EBUSY; } ret = strlen(buf); if (ret > XBC_DATA_MAX - 1 || ret == 0) { - pr_err("Error: Config data is %s.\n", - ret ? "too big" : "empty"); + if (emsg) + *emsg = ret ? "Config data is too big" : + "Config data is empty"; return -ERANGE; } xbc_nodes = memblock_alloc(sizeof(struct xbc_node) * XBC_NODE_MAX, SMP_CACHE_BYTES); if (!xbc_nodes) { - pr_err("Failed to allocate memory for bootconfig nodes.\n"); + if (emsg) + *emsg = "Failed to allocate bootconfig nodes"; return -ENOMEM; } memset(xbc_nodes, 0, sizeof(struct xbc_node) * XBC_NODE_MAX); @@ -814,9 +827,13 @@ int __init xbc_init(char *buf) if (!ret) ret = xbc_verify_tree(); - if (ret < 0) + if (ret < 0) { + if (epos) + *epos = xbc_err_pos; + if (emsg) + *emsg = xbc_err_msg; xbc_destroy_all(); - else + } else ret = xbc_node_num; return ret; diff --git a/tools/bootconfig/main.c b/tools/bootconfig/main.c index a9b97814d1a9..16b9a420e6fd 100644 --- a/tools/bootconfig/main.c +++ b/tools/bootconfig/main.c @@ -130,6 +130,7 @@ int load_xbc_from_initrd(int fd, char **buf) int ret; u32 size = 0, csum = 0, rcsum; char magic[BOOTCONFIG_MAGIC_LEN]; + const char *msg; ret = fstat(fd, &stat); if (ret < 0) @@ -182,10 +183,12 @@ int load_xbc_from_initrd(int fd, char **buf) return -EINVAL; } - ret = xbc_init(*buf); + ret = xbc_init(*buf, &msg, NULL); /* Wrong data */ - if (ret < 0) + if (ret < 0) { + pr_err("parse error: %s.\n", msg); return ret; + } return size; } @@ -244,11 +247,34 @@ int delete_xbc(const char *path) return ret; } +static void show_xbc_error(const char *data, const char *msg, int pos) +{ + int lin = 1, col, i; + + if (pos < 0) { + pr_err("Error: %s.\n", msg); + return; + } + + /* Note that pos starts from 0 but lin and col should start from 1. */ + col = pos + 1; + for (i = 0; i < pos; i++) { + if (data[i] == '\n') { + lin++; + col = pos - i; + } + } + pr_err("Parse Error: %s at %d:%d\n", msg, lin, col); + +} + int apply_xbc(const char *path, const char *xbc_path) { u32 size, csum; char *buf, *data; int ret, fd; + const char *msg; + int pos; ret = load_xbc_file(xbc_path, &buf); if (ret < 0) { @@ -267,11 +293,12 @@ int apply_xbc(const char *path, const char *xbc_path) *(u32 *)(data + size + 4) = csum; /* Check the data format */ - ret = xbc_init(buf); + ret = xbc_init(buf, &msg, &pos); if (ret < 0) { - pr_err("Failed to parse %s: %d\n", xbc_path, ret); + show_xbc_error(data, msg, pos); free(data); free(buf); + return ret; } printf("Apply %s to %s\n", xbc_path, path); From bbd9d05618a6d608c72640b1d3d651a75913456a Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Mon, 2 Mar 2020 15:50:44 -0800 Subject: [PATCH 1100/4444] gpu/trace: add a gpu total memory usage tracepoint This change adds the below gpu memory tracepoint: gpu_mem/gpu_mem_total: track global or proc gpu memory total usages Per process tracking of total gpu memory usage in the gem layer is not appropriate and hard to implement with trivial overhead. So for the gfx device driver layer to track total gpu memory usage both globally and per process in an easy and uniform way is to integrate the tracepoint in this patch to the underlying varied implementations of gpu memory tracking system from vendors. Putting this tracepoint in the common trace events can not only help wean the gfx drivers off of debugfs but also greatly help the downstream Android gpu vendors because debugfs is to be deprecated in the upcoming Android release. Then the gpu memory tracking of both Android kernel and the upstream linux kernel can stay closely, which can benefit the whole kernel eco-system in the long term. Link: http://lkml.kernel.org/r/20200302235044.59163-1-zzyiwei@google.com Acked-by: Greg Kroah-Hartman Signed-off-by: Yiwei Zhang Signed-off-by: Steven Rostedt (VMware) --- drivers/Kconfig | 2 ++ drivers/gpu/Makefile | 1 + drivers/gpu/trace/Kconfig | 4 +++ drivers/gpu/trace/Makefile | 3 ++ drivers/gpu/trace/trace_gpu_mem.c | 13 +++++++ include/trace/events/gpu_mem.h | 57 +++++++++++++++++++++++++++++++ 6 files changed, 80 insertions(+) create mode 100644 drivers/gpu/trace/Kconfig create mode 100644 drivers/gpu/trace/Makefile create mode 100644 drivers/gpu/trace/trace_gpu_mem.c create mode 100644 include/trace/events/gpu_mem.h diff --git a/drivers/Kconfig b/drivers/Kconfig index 8befa53f43be..e0eda1a5c3f9 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -200,6 +200,8 @@ source "drivers/thunderbolt/Kconfig" source "drivers/android/Kconfig" +source "drivers/gpu/trace/Kconfig" + source "drivers/nvdimm/Kconfig" source "drivers/dax/Kconfig" diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile index f17d01f076c7..835c88318cec 100644 --- a/drivers/gpu/Makefile +++ b/drivers/gpu/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_TEGRA_HOST1X) += host1x/ obj-y += drm/ vga/ obj-$(CONFIG_IMX_IPUV3_CORE) += ipu-v3/ +obj-$(CONFIG_TRACE_GPU_MEM) += trace/ diff --git a/drivers/gpu/trace/Kconfig b/drivers/gpu/trace/Kconfig new file mode 100644 index 000000000000..c24e9edd022e --- /dev/null +++ b/drivers/gpu/trace/Kconfig @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config TRACE_GPU_MEM + bool diff --git a/drivers/gpu/trace/Makefile b/drivers/gpu/trace/Makefile new file mode 100644 index 000000000000..b70fbdc5847f --- /dev/null +++ b/drivers/gpu/trace/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_TRACE_GPU_MEM) += trace_gpu_mem.o diff --git a/drivers/gpu/trace/trace_gpu_mem.c b/drivers/gpu/trace/trace_gpu_mem.c new file mode 100644 index 000000000000..01e855897b6d --- /dev/null +++ b/drivers/gpu/trace/trace_gpu_mem.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * GPU memory trace points + * + * Copyright (C) 2020 Google, Inc. + */ + +#include + +#define CREATE_TRACE_POINTS +#include + +EXPORT_TRACEPOINT_SYMBOL(gpu_mem_total); diff --git a/include/trace/events/gpu_mem.h b/include/trace/events/gpu_mem.h new file mode 100644 index 000000000000..1897822a9150 --- /dev/null +++ b/include/trace/events/gpu_mem.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * GPU memory trace points + * + * Copyright (C) 2020 Google, Inc. + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM gpu_mem + +#if !defined(_TRACE_GPU_MEM_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_GPU_MEM_H + +#include + +/* + * The gpu_memory_total event indicates that there's an update to either the + * global or process total gpu memory counters. + * + * This event should be emitted whenever the kernel device driver allocates, + * frees, imports, unimports memory in the GPU addressable space. + * + * @gpu_id: This is the gpu id. + * + * @pid: Put 0 for global total, while positive pid for process total. + * + * @size: Virtual size of the allocation in bytes. + * + */ +TRACE_EVENT(gpu_mem_total, + + TP_PROTO(uint32_t gpu_id, uint32_t pid, uint64_t size), + + TP_ARGS(gpu_id, pid, size), + + TP_STRUCT__entry( + __field(uint32_t, gpu_id) + __field(uint32_t, pid) + __field(uint64_t, size) + ), + + TP_fast_assign( + __entry->gpu_id = gpu_id; + __entry->pid = pid; + __entry->size = size; + ), + + TP_printk("gpu_id=%u pid=%u size=%llu", + __entry->gpu_id, + __entry->pid, + __entry->size) +); + +#endif /* _TRACE_GPU_MEM_H */ + +/* This part must be outside protection */ +#include From 98060484e2328a4d29b62eb42ef31219a4629587 Mon Sep 17 00:00:00 2001 From: afzal mohammed Date: Wed, 4 Mar 2020 06:11:11 +0530 Subject: [PATCH 1101/4444] xtensa: replace setup_irq() by request_irq() request_irq() is preferred over setup_irq(). Invocations of setup_irq() occur after memory allocators are ready. Per tglx[1], setup_irq() existed in olden days when allocators were not ready by the time early interrupts were initialized. Hence replace setup_irq() by request_irq(). [1] https://lkml.kernel.org/r/alpine.DEB.2.20.1710191609480.1971@nanos Signed-off-by: afzal mohammed Message-Id: <20200304004112.3848-1-afzal.mohd.ma@gmail.com> Signed-off-by: Max Filippov --- arch/xtensa/kernel/smp.c | 8 ++------ arch/xtensa/kernel/time.c | 12 +++++------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/arch/xtensa/kernel/smp.c b/arch/xtensa/kernel/smp.c index 83b244ce61ee..cd85a7a2722b 100644 --- a/arch/xtensa/kernel/smp.c +++ b/arch/xtensa/kernel/smp.c @@ -53,16 +53,12 @@ static void system_flush_invalidate_dcache_range(unsigned long start, #define IPI_IRQ 0 static irqreturn_t ipi_interrupt(int irq, void *dev_id); -static struct irqaction ipi_irqaction = { - .handler = ipi_interrupt, - .flags = IRQF_PERCPU, - .name = "ipi", -}; void ipi_init(void) { unsigned irq = irq_create_mapping(NULL, IPI_IRQ); - setup_irq(irq, &ipi_irqaction); + if (request_irq(irq, ipi_interrupt, IRQF_PERCPU, "ipi", NULL)) + pr_err("Failed to request irq %u (ipi)\n", irq); } static inline unsigned int get_core_count(void) diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 69db8c93c1f9..77971fe4cc95 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -128,12 +128,6 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static struct irqaction timer_irqaction = { - .handler = timer_interrupt, - .flags = IRQF_TIMER, - .name = "timer", -}; - void local_timer_setup(unsigned cpu) { struct ccount_timer *timer = &per_cpu(ccount_timer, cpu); @@ -184,6 +178,8 @@ static inline void calibrate_ccount(void) void __init time_init(void) { + int irq; + of_clk_init(NULL); #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT pr_info("Calibrating CPU frequency "); @@ -199,7 +195,9 @@ void __init time_init(void) __func__); clocksource_register_hz(&ccount_clocksource, ccount_freq); local_timer_setup(0); - setup_irq(this_cpu_ptr(&ccount_timer)->evt.irq, &timer_irqaction); + irq = this_cpu_ptr(&ccount_timer)->evt.irq; + if (request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL)) + pr_err("Failed to request irq %d (timer)\n", irq); sched_clock_register(ccount_sched_clock_read, 32, ccount_freq); timer_probe(); } From 226bbb937efbe903258f51feed37a8586b087f5f Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 20 Feb 2020 15:28:54 +0530 Subject: [PATCH 1102/4444] soc: qcom: Do not depend on ARCH_QCOM for QMI helpers QMI helpers are not always used by Qualcomm platforms. One of the exceptions is the external modems available in near future. Cc: Andy Gross Cc: Bjorn Andersson Cc: linux-arm-msm@vger.kernel.org Signed-off-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20200220095854.4804-17-manivannan.sadhasivam@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index d0a73e76d563..80aa8b6c56e0 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -88,7 +88,6 @@ config QCOM_PM config QCOM_QMI_HELPERS tristate - depends on ARCH_QCOM || COMPILE_TEST depends on NET config QCOM_RMTFS_MEM From 12437759602315d1eaa5ece8169cd1eedd018ff2 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 27 Feb 2020 14:42:29 +0100 Subject: [PATCH 1103/4444] s390/mm: mark private defines for vm_fault_t as such This fixes several sparse warnings for fault.c: arch/s390/mm/fault.c:336:36: warning: restricted vm_fault_t degrades to integer arch/s390/mm/fault.c:573:23: warning: incorrect type in assignment (different base types) arch/s390/mm/fault.c:573:23: expected restricted vm_fault_t [usertype] fault arch/s390/mm/fault.c:573:23: got int Signed-off-by: Christian Borntraeger Reviewed-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/mm/fault.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 7b0bb475c166..151adef0d5dd 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -44,11 +44,11 @@ #define __SUBCODE_MASK 0x0600 #define __PF_RES_FIELD 0x8000000000000000ULL -#define VM_FAULT_BADCONTEXT 0x010000 -#define VM_FAULT_BADMAP 0x020000 -#define VM_FAULT_BADACCESS 0x040000 -#define VM_FAULT_SIGNAL 0x080000 -#define VM_FAULT_PFAULT 0x100000 +#define VM_FAULT_BADCONTEXT ((__force vm_fault_t) 0x010000) +#define VM_FAULT_BADMAP ((__force vm_fault_t) 0x020000) +#define VM_FAULT_BADACCESS ((__force vm_fault_t) 0x040000) +#define VM_FAULT_SIGNAL ((__force vm_fault_t) 0x080000) +#define VM_FAULT_PFAULT ((__force vm_fault_t) 0x100000) enum fault_type { KERNEL_FAULT, From e189b172d212adcba33146348d50072bf6323121 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Mon, 2 Mar 2020 09:48:08 +0100 Subject: [PATCH 1104/4444] MAINTAINERS: Update s390/cio maintainer Update maintainer entry for s390 Common I/O Layer. Sebastian has left IBM, Vineeth takes over maintainership. Signed-off-by: Peter Oberparleiter Acked-by: Vineeth Vijayan Signed-off-by: Vasily Gorbik --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index a0d86490c2c6..e170f74e0361 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14461,7 +14461,7 @@ F: Documentation/s390/ F: Documentation/driver-api/s390-drivers.rst S390 COMMON I/O LAYER -M: Sebastian Ott +M: Vineeth Vijayan M: Peter Oberparleiter L: linux-s390@vger.kernel.org W: http://www.ibm.com/developerworks/linux/linux390/ From 5e674c308baba7b3c5912110aaff4fff2131de49 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Mon, 2 Mar 2020 09:54:26 +0100 Subject: [PATCH 1105/4444] MAINTAINERS: Update s390/pci maintainer Update maintainer entry for s390 PCI subsystem. Sebastian has left IBM, Niklas takes over maintainership. Signed-off-by: Peter Oberparleiter Acked-by: Niklas Schnelle Signed-off-by: Vasily Gorbik --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index e170f74e0361..2c73d6d0854e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14503,7 +14503,7 @@ S: Supported F: drivers/s390/net/ S390 PCI SUBSYSTEM -M: Sebastian Ott +M: Niklas Schnelle M: Gerald Schaefer L: linux-s390@vger.kernel.org W: http://www.ibm.com/developerworks/linux/linux390/ From 636a0e4b079483437c1b673eda69b7e4f12b00f9 Mon Sep 17 00:00:00 2001 From: Remi Pommarel Date: Fri, 24 Jan 2020 00:29:37 +0100 Subject: [PATCH 1106/4444] dt-bindings: Add AXG PCIE PHY bindings Add documentation for PCIE PHYs found in AXG SoCs. Signed-off-by: Remi Pommarel Signed-off-by: Lorenzo Pieralisi Reviewed-by: Rob Herring --- .../bindings/phy/amlogic,meson-axg-pcie.yaml | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/amlogic,meson-axg-pcie.yaml diff --git a/Documentation/devicetree/bindings/phy/amlogic,meson-axg-pcie.yaml b/Documentation/devicetree/bindings/phy/amlogic,meson-axg-pcie.yaml new file mode 100644 index 000000000000..086478aec946 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/amlogic,meson-axg-pcie.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/phy/amlogic,meson-axg-pcie.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Amlogic AXG PCIE PHY + +maintainers: + - Remi Pommarel + +properties: + compatible: + const: amlogic,axg-pcie-phy + + reg: + maxItems: 1 + + resets: + maxItems: 1 + + phys: + maxItems: 1 + + phy-names: + const: analog + + "#phy-cells": + const: 0 + +required: + - compatible + - reg + - phys + - phy-names + - resets + - "#phy-cells" + +additionalProperties: false + +examples: + - | + #include + #include + pcie_phy: pcie-phy@ff644000 { + compatible = "amlogic,axg-pcie-phy"; + reg = <0x0 0xff644000 0x0 0x1c>; + resets = <&reset RESET_PCIE_PHY>; + phys = <&mipi_analog_phy PHY_TYPE_PCIE>; + phy-names = "analog"; + #phy-cells = <0>; + }; From b09b48b3d09413f557d3006f5618d42e75192dd0 Mon Sep 17 00:00:00 2001 From: Remi Pommarel Date: Fri, 24 Jan 2020 00:29:38 +0100 Subject: [PATCH 1107/4444] dt-bindings: Add AXG shared MIPI/PCIE analog PHY bindings Add documentation for the shared MIPI/PCIE analog PHY found in AXG SoCs. Signed-off-by: Remi Pommarel Signed-off-by: Lorenzo Pieralisi Reviewed-by: Rob Herring --- .../amlogic,meson-axg-mipi-pcie-analog.yaml | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml diff --git a/Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml b/Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml new file mode 100644 index 000000000000..88683db6cf81 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/amlogic,meson-axg-mipi-pcie-analog.yaml @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/phy/amlogic,meson-axg-mipi-pcie-analog.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Amlogic AXG shared MIPI/PCIE analog PHY + +maintainers: + - Remi Pommarel + +properties: + compatible: + const: amlogic,axg-mipi-pcie-analog-phy + + reg: + maxItems: 1 + + "#phy-cells": + const: 1 + +required: + - compatible + - reg + - "#phy-cells" + +additionalProperties: false + +examples: + - | + mpphy: phy@0 { + compatible = "amlogic,axg-mipi-pcie-analog-phy"; + reg = <0x0 0x0 0x0 0xc>; + #phy-cells = <1>; + }; From 6e5f77031cc92397aba2d03c9f82bfc511b83467 Mon Sep 17 00:00:00 2001 From: Remi Pommarel Date: Fri, 24 Jan 2020 00:29:39 +0100 Subject: [PATCH 1108/4444] dt-bindings: PCI: meson: Update PCIE bindings documentation Now that a new PHYs has been introduced for AXG SoC family, update dt bindings documentation. Please note that this breaks backward compatibility but as not a single devicetree uses that yet that seems ok. Signed-off-by: Remi Pommarel Signed-off-by: Lorenzo Pieralisi Reviewed-by: Rob Herring --- .../bindings/pci/amlogic,meson-pcie.txt | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/Documentation/devicetree/bindings/pci/amlogic,meson-pcie.txt b/Documentation/devicetree/bindings/pci/amlogic,meson-pcie.txt index 84fdc422792e..b6acbe694ffb 100644 --- a/Documentation/devicetree/bindings/pci/amlogic,meson-pcie.txt +++ b/Documentation/devicetree/bindings/pci/amlogic,meson-pcie.txt @@ -18,7 +18,6 @@ Required properties: - reg-names: Must be - "elbi" External local bus interface registers - "cfg" Meson specific registers - - "phy" Meson PCIE PHY registers for AXG SoC Family - "config" PCIe configuration space - reset-gpios: The GPIO to generate PCIe PERST# assert and deassert signal. - clocks: Must contain an entry for each entry in clock-names. @@ -26,13 +25,13 @@ Required properties: - "pclk" PCIe GEN 100M PLL clock - "port" PCIe_x(A or B) RC clock gate - "general" PCIe Phy clock - - "mipi" PCIe_x(A or B) 100M ref clock gate for AXG SoC Family - resets: phandle to the reset lines. -- reset-names: must contain "phy" "port" and "apb" - - "phy" Share PHY reset for AXG SoC Family +- reset-names: must contain "port" and "apb" - "port" Port A or B reset - "apb" Share APB reset -- phys: should contain a phandle to the shared phy for G12A SoC Family +- phys: should contain a phandle to the PCIE phy +- phy-names: must contain "pcie" + - device_type: should be "pci". As specified in designware-pcie.txt @@ -43,9 +42,8 @@ Example configuration: compatible = "amlogic,axg-pcie", "snps,dw-pcie"; reg = <0x0 0xf9800000 0x0 0x400000 0x0 0xff646000 0x0 0x2000 - 0x0 0xff644000 0x0 0x2000 0x0 0xf9f00000 0x0 0x100000>; - reg-names = "elbi", "cfg", "phy", "config"; + reg-names = "elbi", "cfg", "config"; reset-gpios = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; interrupts = ; #interrupt-cells = <1>; @@ -58,17 +56,15 @@ Example configuration: ranges = <0x82000000 0 0 0x0 0xf9c00000 0 0x00300000>; clocks = <&clkc CLKID_USB - &clkc CLKID_MIPI_ENABLE &clkc CLKID_PCIE_A &clkc CLKID_PCIE_CML_EN0>; clock-names = "general", - "mipi", "pclk", "port"; - resets = <&reset RESET_PCIE_PHY>, - <&reset RESET_PCIE_A>, + resets = <&reset RESET_PCIE_A>, <&reset RESET_PCIE_APB>; - reset-names = "phy", - "port", + reset-names = "port", "apb"; + phys = <&pcie_phy>; + phy-names = "pcie"; }; From af3f5722d10cc345cbcfd2e1190334baa237a4ee Mon Sep 17 00:00:00 2001 From: Remi Pommarel Date: Fri, 24 Jan 2020 00:29:41 +0100 Subject: [PATCH 1109/4444] phy: amlogic: Add Amlogic AXG MIPI/PCIE analog PHY Driver This adds support for the MIPI analog PHY which is also used for PCIE found in the Amlogic AXG SoC Family. MIPI or PCIE selection is done by the #phy-cells, making the mode static and exclusive. For now only PCIE functionality is supported. This PHY will be used to replace the mipi_enable clock gating logic which was mistakenly added in the clock subsystem. This also activates a non documented band gap bit in those registers that allows reliable PCIE clock signal generation on AXG platforms. Signed-off-by: Remi Pommarel Signed-off-by: Lorenzo Pieralisi Reviewed-by: Neil Armstrong Acked-by: Jerome Brunet --- drivers/phy/amlogic/Kconfig | 11 + drivers/phy/amlogic/Makefile | 11 +- .../amlogic/phy-meson-axg-mipi-pcie-analog.c | 188 ++++++++++++++++++ 3 files changed, 205 insertions(+), 5 deletions(-) create mode 100644 drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig index af774ac2b934..8c9cf2403591 100644 --- a/drivers/phy/amlogic/Kconfig +++ b/drivers/phy/amlogic/Kconfig @@ -59,3 +59,14 @@ config PHY_MESON_G12A_USB3_PCIE Enable this to support the Meson USB3 + PCIE Combo PHY found in Meson G12A SoCs. If unsure, say N. + +config PHY_MESON_AXG_MIPI_PCIE_ANALOG + tristate "Meson AXG MIPI + PCIE analog PHY driver" + default ARCH_MESON + depends on OF && (ARCH_MESON || COMPILE_TEST) + select GENERIC_PHY + select REGMAP_MMIO + help + Enable this to support the Meson MIPI + PCIE analog PHY + found in Meson AXG SoCs. + If unsure, say N. diff --git a/drivers/phy/amlogic/Makefile b/drivers/phy/amlogic/Makefile index 11d1c42ac2be..0aecf92d796a 100644 --- a/drivers/phy/amlogic/Makefile +++ b/drivers/phy/amlogic/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o -obj-$(CONFIG_PHY_MESON_GXL_USB2) += phy-meson-gxl-usb2.o -obj-$(CONFIG_PHY_MESON_G12A_USB2) += phy-meson-g12a-usb2.o -obj-$(CONFIG_PHY_MESON_GXL_USB3) += phy-meson-gxl-usb3.o -obj-$(CONFIG_PHY_MESON_G12A_USB3_PCIE) += phy-meson-g12a-usb3-pcie.o +obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o +obj-$(CONFIG_PHY_MESON_GXL_USB2) += phy-meson-gxl-usb2.o +obj-$(CONFIG_PHY_MESON_G12A_USB2) += phy-meson-g12a-usb2.o +obj-$(CONFIG_PHY_MESON_GXL_USB3) += phy-meson-gxl-usb3.o +obj-$(CONFIG_PHY_MESON_G12A_USB3_PCIE) += phy-meson-g12a-usb3-pcie.o +obj-$(CONFIG_PHY_MESON_AXG_MIPI_PCIE_ANALOG) += phy-meson-axg-mipi-pcie-analog.o diff --git a/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c new file mode 100644 index 000000000000..1431cbf885e1 --- /dev/null +++ b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Amlogic AXG MIPI + PCIE analog PHY driver + * + * Copyright (C) 2019 Remi Pommarel + */ +#include +#include +#include +#include +#include + +#define HHI_MIPI_CNTL0 0x00 +#define HHI_MIPI_CNTL0_COMMON_BLOCK GENMASK(31, 28) +#define HHI_MIPI_CNTL0_ENABLE BIT(29) +#define HHI_MIPI_CNTL0_BANDGAP BIT(26) +#define HHI_MIPI_CNTL0_DECODE_TO_RTERM GENMASK(15, 12) +#define HHI_MIPI_CNTL0_OUTPUT_EN BIT(3) + +#define HHI_MIPI_CNTL1 0x01 +#define HHI_MIPI_CNTL1_CH0_CML_PDR_EN BIT(12) +#define HHI_MIPI_CNTL1_LP_ABILITY GENMASK(5, 4) +#define HHI_MIPI_CNTL1_LP_RESISTER BIT(3) +#define HHI_MIPI_CNTL1_INPUT_SETTING BIT(2) +#define HHI_MIPI_CNTL1_INPUT_SEL BIT(1) +#define HHI_MIPI_CNTL1_PRBS7_EN BIT(0) + +#define HHI_MIPI_CNTL2 0x02 +#define HHI_MIPI_CNTL2_CH_PU GENMASK(31, 25) +#define HHI_MIPI_CNTL2_CH_CTL GENMASK(24, 19) +#define HHI_MIPI_CNTL2_CH0_DIGDR_EN BIT(18) +#define HHI_MIPI_CNTL2_CH_DIGDR_EN BIT(17) +#define HHI_MIPI_CNTL2_LPULPS_EN BIT(16) +#define HHI_MIPI_CNTL2_CH_EN(n) BIT(15 - (n)) +#define HHI_MIPI_CNTL2_CH0_LP_CTL GENMASK(10, 1) + +struct phy_axg_mipi_pcie_analog_priv { + struct phy *phy; + unsigned int mode; + struct regmap *regmap; +}; + +static const struct regmap_config phy_axg_mipi_pcie_analog_regmap_conf = { + .reg_bits = 8, + .val_bits = 32, + .reg_stride = 4, + .max_register = HHI_MIPI_CNTL2, +}; + +static int phy_axg_mipi_pcie_analog_power_on(struct phy *phy) +{ + struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy); + + /* MIPI not supported yet */ + if (priv->mode != PHY_TYPE_PCIE) + return -EINVAL; + + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, + HHI_MIPI_CNTL0_BANDGAP, HHI_MIPI_CNTL0_BANDGAP); + + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, + HHI_MIPI_CNTL0_ENABLE, HHI_MIPI_CNTL0_ENABLE); + return 0; +} + +static int phy_axg_mipi_pcie_analog_power_off(struct phy *phy) +{ + struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy); + + /* MIPI not supported yet */ + if (priv->mode != PHY_TYPE_PCIE) + return -EINVAL; + + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, + HHI_MIPI_CNTL0_BANDGAP, 0); + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, + HHI_MIPI_CNTL0_ENABLE, 0); + return 0; +} + +static int phy_axg_mipi_pcie_analog_init(struct phy *phy) +{ + return 0; +} + +static int phy_axg_mipi_pcie_analog_exit(struct phy *phy) +{ + return 0; +} + +static const struct phy_ops phy_axg_mipi_pcie_analog_ops = { + .init = phy_axg_mipi_pcie_analog_init, + .exit = phy_axg_mipi_pcie_analog_exit, + .power_on = phy_axg_mipi_pcie_analog_power_on, + .power_off = phy_axg_mipi_pcie_analog_power_off, + .owner = THIS_MODULE, +}; + +static struct phy *phy_axg_mipi_pcie_analog_xlate(struct device *dev, + struct of_phandle_args *args) +{ + struct phy_axg_mipi_pcie_analog_priv *priv = dev_get_drvdata(dev); + unsigned int mode; + + if (args->args_count != 1) { + dev_err(dev, "invalid number of arguments\n"); + return ERR_PTR(-EINVAL); + } + + mode = args->args[0]; + + /* MIPI mode is not supported yet */ + if (mode != PHY_TYPE_PCIE) { + dev_err(dev, "invalid phy mode select argument\n"); + return ERR_PTR(-EINVAL); + } + + priv->mode = mode; + return priv->phy; +} + +static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev) +{ + struct phy_provider *phy; + struct device *dev = &pdev->dev; + struct phy_axg_mipi_pcie_analog_priv *priv; + struct device_node *np = dev->of_node; + struct regmap *map; + struct resource *res; + void __iomem *base; + int ret; + + priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) { + dev_err(dev, "failed to get regmap base\n"); + return PTR_ERR(base); + } + + map = devm_regmap_init_mmio(dev, base, + &phy_axg_mipi_pcie_analog_regmap_conf); + if (IS_ERR(map)) { + dev_err(dev, "failed to get HHI regmap\n"); + return PTR_ERR(map); + } + priv->regmap = map; + + priv->phy = devm_phy_create(dev, np, &phy_axg_mipi_pcie_analog_ops); + if (IS_ERR(priv->phy)) { + ret = PTR_ERR(priv->phy); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to create PHY\n"); + return ret; + } + + phy_set_drvdata(priv->phy, priv); + dev_set_drvdata(dev, priv); + + phy = devm_of_phy_provider_register(dev, + phy_axg_mipi_pcie_analog_xlate); + + return PTR_ERR_OR_ZERO(phy); +} + +static const struct of_device_id phy_axg_mipi_pcie_analog_of_match[] = { + { + .compatible = "amlogic,axg-mipi-pcie-analog-phy", + }, + { }, +}; +MODULE_DEVICE_TABLE(of, phy_axg_mipi_pcie_analog_of_match); + +static struct platform_driver phy_axg_mipi_pcie_analog_driver = { + .probe = phy_axg_mipi_pcie_analog_probe, + .driver = { + .name = "phy-axg-mipi-pcie-analog", + .of_match_table = phy_axg_mipi_pcie_analog_of_match, + }, +}; +module_platform_driver(phy_axg_mipi_pcie_analog_driver); + +MODULE_AUTHOR("Remi Pommarel "); +MODULE_DESCRIPTION("Amlogic AXG MIPI + PCIE analog PHY driver"); +MODULE_LICENSE("GPL v2"); From e2463559ff1d5a76e708a26ec91e4950e702b25c Mon Sep 17 00:00:00 2001 From: Remi Pommarel Date: Fri, 24 Jan 2020 00:29:42 +0100 Subject: [PATCH 1110/4444] phy: amlogic: Add Amlogic AXG PCIE PHY Driver This adds support for the PCI PHY found in the Amlogic AXG SoC Family. This will allow to mutualize code in pci-meson.c between AXG and G12A SoC. This PHY also uses and chains an analog PHY, which on AXG platform is needed to have reliable PCIe communication. Signed-off-by: Remi Pommarel Signed-off-by: Lorenzo Pieralisi Reviewed-by: Neil Armstrong --- drivers/phy/amlogic/Kconfig | 11 ++ drivers/phy/amlogic/Makefile | 1 + drivers/phy/amlogic/phy-meson-axg-pcie.c | 192 +++++++++++++++++++++++ 3 files changed, 204 insertions(+) create mode 100644 drivers/phy/amlogic/phy-meson-axg-pcie.c diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig index 8c9cf2403591..71801e30d601 100644 --- a/drivers/phy/amlogic/Kconfig +++ b/drivers/phy/amlogic/Kconfig @@ -60,6 +60,17 @@ config PHY_MESON_G12A_USB3_PCIE in Meson G12A SoCs. If unsure, say N. +config PHY_MESON_AXG_PCIE + tristate "Meson AXG PCIE PHY driver" + default ARCH_MESON + depends on OF && (ARCH_MESON || COMPILE_TEST) + select GENERIC_PHY + select REGMAP_MMIO + help + Enable this to support the Meson MIPI + PCIE PHY found + in Meson AXG SoCs. + If unsure, say N. + config PHY_MESON_AXG_MIPI_PCIE_ANALOG tristate "Meson AXG MIPI + PCIE analog PHY driver" default ARCH_MESON diff --git a/drivers/phy/amlogic/Makefile b/drivers/phy/amlogic/Makefile index 0aecf92d796a..e2baa133f7af 100644 --- a/drivers/phy/amlogic/Makefile +++ b/drivers/phy/amlogic/Makefile @@ -4,4 +4,5 @@ obj-$(CONFIG_PHY_MESON_GXL_USB2) += phy-meson-gxl-usb2.o obj-$(CONFIG_PHY_MESON_G12A_USB2) += phy-meson-g12a-usb2.o obj-$(CONFIG_PHY_MESON_GXL_USB3) += phy-meson-gxl-usb3.o obj-$(CONFIG_PHY_MESON_G12A_USB3_PCIE) += phy-meson-g12a-usb3-pcie.o +obj-$(CONFIG_PHY_MESON_AXG_PCIE) += phy-meson-axg-pcie.o obj-$(CONFIG_PHY_MESON_AXG_MIPI_PCIE_ANALOG) += phy-meson-axg-mipi-pcie-analog.o diff --git a/drivers/phy/amlogic/phy-meson-axg-pcie.c b/drivers/phy/amlogic/phy-meson-axg-pcie.c new file mode 100644 index 000000000000..377ed0dcd0d9 --- /dev/null +++ b/drivers/phy/amlogic/phy-meson-axg-pcie.c @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Amlogic AXG PCIE PHY driver + * + * Copyright (C) 2020 Remi Pommarel + */ +#include +#include +#include +#include +#include +#include +#include + +#define MESON_PCIE_REG0 0x00 +#define MESON_PCIE_COMMON_CLK BIT(4) +#define MESON_PCIE_PORT_SEL GENMASK(3, 2) +#define MESON_PCIE_CLK BIT(1) +#define MESON_PCIE_POWERDOWN BIT(0) + +#define MESON_PCIE_TWO_X1 FIELD_PREP(MESON_PCIE_PORT_SEL, 0x3) +#define MESON_PCIE_COMMON_REF_CLK FIELD_PREP(MESON_PCIE_COMMON_CLK, 0x1) +#define MESON_PCIE_PHY_INIT (MESON_PCIE_TWO_X1 | \ + MESON_PCIE_COMMON_REF_CLK) +#define MESON_PCIE_RESET_DELAY 500 + +struct phy_axg_pcie_priv { + struct phy *phy; + struct phy *analog; + struct regmap *regmap; + struct reset_control *reset; +}; + +static const struct regmap_config phy_axg_pcie_regmap_conf = { + .reg_bits = 8, + .val_bits = 32, + .reg_stride = 4, + .max_register = MESON_PCIE_REG0, +}; + +static int phy_axg_pcie_power_on(struct phy *phy) +{ + struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy); + int ret; + + ret = phy_power_on(priv->analog); + if (ret != 0) + return ret; + + regmap_update_bits(priv->regmap, MESON_PCIE_REG0, + MESON_PCIE_POWERDOWN, 0); + return 0; +} + +static int phy_axg_pcie_power_off(struct phy *phy) +{ + struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy); + int ret; + + ret = phy_power_off(priv->analog); + if (ret != 0) + return ret; + + regmap_update_bits(priv->regmap, MESON_PCIE_REG0, + MESON_PCIE_POWERDOWN, 1); + return 0; +} + +static int phy_axg_pcie_init(struct phy *phy) +{ + struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy); + int ret; + + ret = phy_init(priv->analog); + if (ret != 0) + return ret; + + regmap_write(priv->regmap, MESON_PCIE_REG0, MESON_PCIE_PHY_INIT); + return reset_control_reset(priv->reset); +} + +static int phy_axg_pcie_exit(struct phy *phy) +{ + struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy); + int ret; + + ret = phy_exit(priv->analog); + if (ret != 0) + return ret; + + return reset_control_reset(priv->reset); +} + +static int phy_axg_pcie_reset(struct phy *phy) +{ + struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy); + int ret = 0; + + ret = phy_reset(priv->analog); + if (ret != 0) + goto out; + + ret = reset_control_assert(priv->reset); + if (ret != 0) + goto out; + udelay(MESON_PCIE_RESET_DELAY); + + ret = reset_control_deassert(priv->reset); + if (ret != 0) + goto out; + udelay(MESON_PCIE_RESET_DELAY); + +out: + return ret; +} + +static const struct phy_ops phy_axg_pcie_ops = { + .init = phy_axg_pcie_init, + .exit = phy_axg_pcie_exit, + .power_on = phy_axg_pcie_power_on, + .power_off = phy_axg_pcie_power_off, + .reset = phy_axg_pcie_reset, + .owner = THIS_MODULE, +}; + +static int phy_axg_pcie_probe(struct platform_device *pdev) +{ + struct phy_provider *pphy; + struct device *dev = &pdev->dev; + struct phy_axg_pcie_priv *priv; + struct device_node *np = dev->of_node; + struct resource *res; + void __iomem *base; + int ret; + + priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->phy = devm_phy_create(dev, np, &phy_axg_pcie_ops); + if (IS_ERR(priv->phy)) { + ret = PTR_ERR(priv->phy); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to create PHY\n"); + return ret; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + priv->regmap = devm_regmap_init_mmio(dev, base, + &phy_axg_pcie_regmap_conf); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + priv->reset = devm_reset_control_array_get(dev, false, false); + if (IS_ERR(priv->reset)) + return PTR_ERR(priv->reset); + + priv->analog = devm_phy_get(dev, "analog"); + if (IS_ERR(priv->analog)) + return PTR_ERR(priv->analog); + + phy_set_drvdata(priv->phy, priv); + dev_set_drvdata(dev, priv); + pphy = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + + return PTR_ERR_OR_ZERO(pphy); +} + +static const struct of_device_id phy_axg_pcie_of_match[] = { + { + .compatible = "amlogic,axg-pcie-phy", + }, + { }, +}; +MODULE_DEVICE_TABLE(of, phy_axg_pcie_of_match); + +static struct platform_driver phy_axg_pcie_driver = { + .probe = phy_axg_pcie_probe, + .driver = { + .name = "phy-axg-pcie", + .of_match_table = phy_axg_pcie_of_match, + }, +}; +module_platform_driver(phy_axg_pcie_driver); + +MODULE_AUTHOR("Remi Pommarel "); +MODULE_DESCRIPTION("Amlogic AXG PCIE PHY driver"); +MODULE_LICENSE("GPL v2"); From 1e6bbc468893f2b3cdff4b9c6e7ee04d799c8e84 Mon Sep 17 00:00:00 2001 From: Remi Pommarel Date: Fri, 24 Jan 2020 00:29:43 +0100 Subject: [PATCH 1111/4444] PCI: amlogic: Use AXG PCIE Now that PCIE PHY has been introduced for AXG, the whole has_shared_phy logic can be mutualized between AXG and G12A platforms. This new PHY makes use of the shared MIPI/PCIE analog PHY found on AXG platforms, which need to be used in order to have reliable PCIE communications. Signed-off-by: Remi Pommarel Signed-off-by: Lorenzo Pieralisi Reviewed-by: Neil Armstrong Acked-by: Kishon Vijay Abraham I --- drivers/pci/controller/dwc/pci-meson.c | 116 +++++-------------------- 1 file changed, 22 insertions(+), 94 deletions(-) diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c index 3772b02a5c55..3715dceca1bf 100644 --- a/drivers/pci/controller/dwc/pci-meson.c +++ b/drivers/pci/controller/dwc/pci-meson.c @@ -66,7 +66,6 @@ #define PORT_CLK_RATE 100000000UL #define MAX_PAYLOAD_SIZE 256 #define MAX_READ_REQ_SIZE 256 -#define MESON_PCIE_PHY_POWERUP 0x1c #define PCIE_RESET_DELAY 500 #define PCIE_SHARED_RESET 1 #define PCIE_NORMAL_RESET 0 @@ -81,26 +80,19 @@ enum pcie_data_rate { struct meson_pcie_mem_res { void __iomem *elbi_base; void __iomem *cfg_base; - void __iomem *phy_base; }; struct meson_pcie_clk_res { struct clk *clk; - struct clk *mipi_gate; struct clk *port_clk; struct clk *general_clk; }; struct meson_pcie_rc_reset { - struct reset_control *phy; struct reset_control *port; struct reset_control *apb; }; -struct meson_pcie_param { - bool has_shared_phy; -}; - struct meson_pcie { struct dw_pcie pci; struct meson_pcie_mem_res mem_res; @@ -108,7 +100,6 @@ struct meson_pcie { struct meson_pcie_rc_reset mrst; struct gpio_desc *reset_gpio; struct phy *phy; - const struct meson_pcie_param *param; }; static struct reset_control *meson_pcie_get_reset(struct meson_pcie *mp, @@ -130,13 +121,6 @@ static int meson_pcie_get_resets(struct meson_pcie *mp) { struct meson_pcie_rc_reset *mrst = &mp->mrst; - if (!mp->param->has_shared_phy) { - mrst->phy = meson_pcie_get_reset(mp, "phy", PCIE_SHARED_RESET); - if (IS_ERR(mrst->phy)) - return PTR_ERR(mrst->phy); - reset_control_deassert(mrst->phy); - } - mrst->port = meson_pcie_get_reset(mp, "port", PCIE_NORMAL_RESET); if (IS_ERR(mrst->port)) return PTR_ERR(mrst->port); @@ -162,22 +146,6 @@ static void __iomem *meson_pcie_get_mem(struct platform_device *pdev, return devm_ioremap_resource(dev, res); } -static void __iomem *meson_pcie_get_mem_shared(struct platform_device *pdev, - struct meson_pcie *mp, - const char *id) -{ - struct device *dev = mp->pci.dev; - struct resource *res; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, id); - if (!res) { - dev_err(dev, "No REG resource %s\n", id); - return ERR_PTR(-ENXIO); - } - - return devm_ioremap(dev, res->start, resource_size(res)); -} - static int meson_pcie_get_mems(struct platform_device *pdev, struct meson_pcie *mp) { @@ -189,14 +157,6 @@ static int meson_pcie_get_mems(struct platform_device *pdev, if (IS_ERR(mp->mem_res.cfg_base)) return PTR_ERR(mp->mem_res.cfg_base); - /* Meson AXG SoC has two PCI controllers use same phy register */ - if (!mp->param->has_shared_phy) { - mp->mem_res.phy_base = - meson_pcie_get_mem_shared(pdev, mp, "phy"); - if (IS_ERR(mp->mem_res.phy_base)) - return PTR_ERR(mp->mem_res.phy_base); - } - return 0; } @@ -204,37 +164,33 @@ static int meson_pcie_power_on(struct meson_pcie *mp) { int ret = 0; - if (mp->param->has_shared_phy) { - ret = phy_init(mp->phy); - if (ret) - return ret; + ret = phy_init(mp->phy); + if (ret) + return ret; - ret = phy_power_on(mp->phy); - if (ret) { - phy_exit(mp->phy); - return ret; - } - } else - writel(MESON_PCIE_PHY_POWERUP, mp->mem_res.phy_base); + ret = phy_power_on(mp->phy); + if (ret) { + phy_exit(mp->phy); + return ret; + } return 0; } +static void meson_pcie_power_off(struct meson_pcie *mp) +{ + phy_power_off(mp->phy); + phy_exit(mp->phy); +} + static int meson_pcie_reset(struct meson_pcie *mp) { struct meson_pcie_rc_reset *mrst = &mp->mrst; int ret = 0; - if (mp->param->has_shared_phy) { - ret = phy_reset(mp->phy); - if (ret) - return ret; - } else { - reset_control_assert(mrst->phy); - udelay(PCIE_RESET_DELAY); - reset_control_deassert(mrst->phy); - udelay(PCIE_RESET_DELAY); - } + ret = phy_reset(mp->phy); + if (ret) + return ret; reset_control_assert(mrst->port); reset_control_assert(mrst->apb); @@ -286,12 +242,6 @@ static int meson_pcie_probe_clocks(struct meson_pcie *mp) if (IS_ERR(res->port_clk)) return PTR_ERR(res->port_clk); - if (!mp->param->has_shared_phy) { - res->mipi_gate = meson_pcie_probe_clock(dev, "mipi", 0); - if (IS_ERR(res->mipi_gate)) - return PTR_ERR(res->mipi_gate); - } - res->general_clk = meson_pcie_probe_clock(dev, "general", 0); if (IS_ERR(res->general_clk)) return PTR_ERR(res->general_clk); @@ -562,7 +512,6 @@ static const struct dw_pcie_ops dw_pcie_ops = { static int meson_pcie_probe(struct platform_device *pdev) { - const struct meson_pcie_param *match_data; struct device *dev = &pdev->dev; struct dw_pcie *pci; struct meson_pcie *mp; @@ -576,17 +525,10 @@ static int meson_pcie_probe(struct platform_device *pdev) pci->dev = dev; pci->ops = &dw_pcie_ops; - match_data = of_device_get_match_data(dev); - if (!match_data) { - dev_err(dev, "failed to get match data\n"); - return -ENODEV; - } - mp->param = match_data; - - if (mp->param->has_shared_phy) { - mp->phy = devm_phy_get(dev, "pcie"); - if (IS_ERR(mp->phy)) - return PTR_ERR(mp->phy); + mp->phy = devm_phy_get(dev, "pcie"); + if (IS_ERR(mp->phy)) { + dev_err(dev, "get phy failed, %ld\n", PTR_ERR(mp->phy)); + return PTR_ERR(mp->phy); } mp->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); @@ -636,30 +578,16 @@ static int meson_pcie_probe(struct platform_device *pdev) return 0; err_phy: - if (mp->param->has_shared_phy) { - phy_power_off(mp->phy); - phy_exit(mp->phy); - } - + meson_pcie_power_off(mp); return ret; } -static struct meson_pcie_param meson_pcie_axg_param = { - .has_shared_phy = false, -}; - -static struct meson_pcie_param meson_pcie_g12a_param = { - .has_shared_phy = true, -}; - static const struct of_device_id meson_pcie_of_match[] = { { .compatible = "amlogic,axg-pcie", - .data = &meson_pcie_axg_param, }, { .compatible = "amlogic,g12a-pcie", - .data = &meson_pcie_g12a_param, }, {}, }; From 365ad0b60d944050d61252e123e6a8b2c3950398 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 8 Feb 2020 15:09:04 +0100 Subject: [PATCH 1112/4444] powerpc/83xx: Fix some typo in some warning message "couldn;t" should be "couldn't". Signed-off-by: Christophe JAILLET Acked-by: Scott Wood Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200208140904.7521-1-christophe.jaillet@wanadoo.fr --- arch/powerpc/platforms/83xx/km83xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/platforms/83xx/km83xx.c b/arch/powerpc/platforms/83xx/km83xx.c index ada42f03915a..306be75faec7 100644 --- a/arch/powerpc/platforms/83xx/km83xx.c +++ b/arch/powerpc/platforms/83xx/km83xx.c @@ -53,13 +53,13 @@ static void quirk_mpc8360e_qe_enet10(void) np_par = of_find_node_by_name(NULL, "par_io"); if (np_par == NULL) { - pr_warn("%s couldn;t find par_io node\n", __func__); + pr_warn("%s couldn't find par_io node\n", __func__); return; } /* Map Parallel I/O ports registers */ ret = of_address_to_resource(np_par, 0, &res); if (ret) { - pr_warn("%s couldn;t map par_io registers\n", __func__); + pr_warn("%s couldn't map par_io registers\n", __func__); return; } From 88654d5b4476a438bd86b257dc4d70bb32266f1b Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 8 Feb 2020 15:09:20 +0100 Subject: [PATCH 1113/4444] powerpc/83xx: Add some error handling in 'quirk_mpc8360e_qe_enet10()' In some error handling path, we should call "of_node_put(np_par)" or some resource may be leaking in case of error. Fixes: 8159df72d43e ("83xx: add support for the kmeter1 board.") Signed-off-by: Christophe JAILLET Acked-by: Scott Wood Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200208140920.7652-1-christophe.jaillet@wanadoo.fr --- arch/powerpc/platforms/83xx/km83xx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/83xx/km83xx.c b/arch/powerpc/platforms/83xx/km83xx.c index 306be75faec7..bcdc2c203ec9 100644 --- a/arch/powerpc/platforms/83xx/km83xx.c +++ b/arch/powerpc/platforms/83xx/km83xx.c @@ -60,10 +60,12 @@ static void quirk_mpc8360e_qe_enet10(void) ret = of_address_to_resource(np_par, 0, &res); if (ret) { pr_warn("%s couldn't map par_io registers\n", __func__); - return; + goto out; } base = ioremap(res.start, resource_size(&res)); + if (!base) + goto out; /* * set output delay adjustments to default values according @@ -111,6 +113,7 @@ static void quirk_mpc8360e_qe_enet10(void) setbits32((base + 0xac), 0x0000c000); } iounmap(base); +out: of_node_put(np_par); } From 860286cf33963fa8a0fe542995bdec2df5cb3abb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 9 Feb 2020 11:58:56 +0100 Subject: [PATCH 1114/4444] powerpc/kernel: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200209105901.1620958-1-gregkh@linuxfoundation.org --- arch/powerpc/kernel/fadump.c | 10 +++------- arch/powerpc/kernel/setup-common.c | 3 +-- arch/powerpc/kernel/traps.c | 25 +++++-------------------- 3 files changed, 9 insertions(+), 29 deletions(-) diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index 265b4aa72252..59e60a9a9f5c 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -1455,7 +1455,6 @@ DEFINE_SHOW_ATTRIBUTE(fadump_region); static void fadump_init_files(void) { - struct dentry *debugfs_file; int rc = 0; fadump_kobj = kobject_create_and_add("fadump", kernel_kobj); @@ -1463,12 +1462,9 @@ static void fadump_init_files(void) pr_err("failed to create fadump kobject\n"); return; } - debugfs_file = debugfs_create_file("fadump_region", 0444, - powerpc_debugfs_root, NULL, - &fadump_region_fops); - if (!debugfs_file) - printk(KERN_ERR "fadump: unable to create debugfs file" - " fadump_region\n"); + + debugfs_create_file("fadump_region", 0444, powerpc_debugfs_root, NULL, + &fadump_region_fops); if (fw_dump.dump_active) { rc = sysfs_create_file(fadump_kobj, &release_attr.attr); diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 7f8c890360fe..f9c0d888ce8a 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -787,8 +787,7 @@ EXPORT_SYMBOL(powerpc_debugfs_root); static int powerpc_debugfs_init(void) { powerpc_debugfs_root = debugfs_create_dir("powerpc", NULL); - - return powerpc_debugfs_root == NULL; + return 0; } arch_initcall(powerpc_debugfs_init); #endif diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 82a3438300fd..3fca22276bb1 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -2278,35 +2278,20 @@ void ppc_warn_emulated_print(const char *type) static int __init ppc_warn_emulated_init(void) { - struct dentry *dir, *d; + struct dentry *dir; unsigned int i; struct ppc_emulated_entry *entries = (void *)&ppc_emulated; - if (!powerpc_debugfs_root) - return -ENODEV; - dir = debugfs_create_dir("emulated_instructions", powerpc_debugfs_root); - if (!dir) - return -ENOMEM; - d = debugfs_create_u32("do_warn", 0644, dir, - &ppc_warn_emulated); - if (!d) - goto fail; + debugfs_create_u32("do_warn", 0644, dir, &ppc_warn_emulated); - for (i = 0; i < sizeof(ppc_emulated)/sizeof(*entries); i++) { - d = debugfs_create_u32(entries[i].name, 0644, dir, - (u32 *)&entries[i].val.counter); - if (!d) - goto fail; - } + for (i = 0; i < sizeof(ppc_emulated)/sizeof(*entries); i++) + debugfs_create_u32(entries[i].name, 0644, dir, + (u32 *)&entries[i].val.counter); return 0; - -fail: - debugfs_remove_recursive(dir); - return -ENOMEM; } device_initcall(ppc_warn_emulated_init); From c4fd527f52ecb135018655c7f56f87800872c5bc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 9 Feb 2020 11:58:57 +0100 Subject: [PATCH 1115/4444] powerpc/kvm: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Because of this cleanup, we get to remove a few fields in struct kvm_arch that are now unused. Signed-off-by: Greg Kroah-Hartman [mpe: Fix build error in kvm/timing.c, adapt kvmppc_remove_cpu_debugfs()] Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200209105901.1620958-2-gregkh@linuxfoundation.org --- arch/powerpc/include/asm/kvm_host.h | 3 --- arch/powerpc/kvm/book3s_64_mmu_hv.c | 5 ++--- arch/powerpc/kvm/book3s_64_mmu_radix.c | 5 ++--- arch/powerpc/kvm/book3s_hv.c | 9 ++------- arch/powerpc/kvm/timing.c | 17 ++++------------- 5 files changed, 10 insertions(+), 29 deletions(-) diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 6e8b8ffd06ad..877f8aa2bc1e 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -308,8 +308,6 @@ struct kvm_arch { pgd_t *pgtable; u64 process_table; struct dentry *debugfs_dir; - struct dentry *htab_dentry; - struct dentry *radix_dentry; struct kvm_resize_hpt *resize_hpt; /* protected by kvm->lock */ #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE @@ -830,7 +828,6 @@ struct kvm_vcpu_arch { struct kvmhv_tb_accumulator cede_time; /* time napping inside guest */ struct dentry *debugfs_dir; - struct dentry *debugfs_timings; #endif /* CONFIG_KVM_BOOK3S_HV_EXIT_TIMING */ }; diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index 6c372f5c61b6..8b4eac0c9dcd 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c @@ -2138,9 +2138,8 @@ static const struct file_operations debugfs_htab_fops = { void kvmppc_mmu_debugfs_init(struct kvm *kvm) { - kvm->arch.htab_dentry = debugfs_create_file("htab", 0400, - kvm->arch.debugfs_dir, kvm, - &debugfs_htab_fops); + debugfs_create_file("htab", 0400, kvm->arch.debugfs_dir, kvm, + &debugfs_htab_fops); } void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu) diff --git a/arch/powerpc/kvm/book3s_64_mmu_radix.c b/arch/powerpc/kvm/book3s_64_mmu_radix.c index 803940d79b73..1d75ed684b53 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_radix.c +++ b/arch/powerpc/kvm/book3s_64_mmu_radix.c @@ -1376,9 +1376,8 @@ static const struct file_operations debugfs_radix_fops = { void kvmhv_radix_debugfs_init(struct kvm *kvm) { - kvm->arch.radix_dentry = debugfs_create_file("radix", 0400, - kvm->arch.debugfs_dir, kvm, - &debugfs_radix_fops); + debugfs_create_file("radix", 0400, kvm->arch.debugfs_dir, kvm, + &debugfs_radix_fops); } int kvmppc_radix_init(void) diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 2cefd071b848..33be4d93248a 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -2258,14 +2258,9 @@ static void debugfs_vcpu_init(struct kvm_vcpu *vcpu, unsigned int id) struct kvm *kvm = vcpu->kvm; snprintf(buf, sizeof(buf), "vcpu%u", id); - if (IS_ERR_OR_NULL(kvm->arch.debugfs_dir)) - return; vcpu->arch.debugfs_dir = debugfs_create_dir(buf, kvm->arch.debugfs_dir); - if (IS_ERR_OR_NULL(vcpu->arch.debugfs_dir)) - return; - vcpu->arch.debugfs_timings = - debugfs_create_file("timings", 0444, vcpu->arch.debugfs_dir, - vcpu, &debugfs_timings_ops); + debugfs_create_file("timings", 0444, vcpu->arch.debugfs_dir, vcpu, + &debugfs_timings_ops); } #else /* CONFIG_KVM_BOOK3S_HV_EXIT_TIMING */ diff --git a/arch/powerpc/kvm/timing.c b/arch/powerpc/kvm/timing.c index bfe4f106cffc..ba56a5cbba97 100644 --- a/arch/powerpc/kvm/timing.c +++ b/arch/powerpc/kvm/timing.c @@ -211,23 +211,14 @@ void kvmppc_create_vcpu_debugfs(struct kvm_vcpu *vcpu, unsigned int id) snprintf(dbg_fname, sizeof(dbg_fname), "vm%u_vcpu%u_timing", current->pid, id); - debugfs_file = debugfs_create_file(dbg_fname, 0666, - kvm_debugfs_dir, vcpu, - &kvmppc_exit_timing_fops); - - if (!debugfs_file) { - printk(KERN_ERR"%s: error creating debugfs file %s\n", - __func__, dbg_fname); - return; - } + debugfs_file = debugfs_create_file(dbg_fname, 0666, kvm_debugfs_dir, + vcpu, &kvmppc_exit_timing_fops); vcpu->arch.debugfs_exit_timing = debugfs_file; } void kvmppc_remove_vcpu_debugfs(struct kvm_vcpu *vcpu) { - if (vcpu->arch.debugfs_exit_timing) { - debugfs_remove(vcpu->arch.debugfs_exit_timing); - vcpu->arch.debugfs_exit_timing = NULL; - } + debugfs_remove(vcpu->arch.debugfs_exit_timing); + vcpu->arch.debugfs_exit_timing = NULL; } From 08f6a7974ab949d43c2584f966db458d255b2b0a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 9 Feb 2020 11:58:58 +0100 Subject: [PATCH 1116/4444] powerpc/mm: book3s64: hash_utils: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200209105901.1620958-3-gregkh@linuxfoundation.org --- arch/powerpc/mm/book3s64/hash_utils.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c index 523d4d39d11e..7e5714a69a58 100644 --- a/arch/powerpc/mm/book3s64/hash_utils.c +++ b/arch/powerpc/mm/book3s64/hash_utils.c @@ -2018,11 +2018,8 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_hpt_order, hpt_order_get, hpt_order_set, "%llu\n") static int __init hash64_debugfs(void) { - if (!debugfs_create_file_unsafe("hpt_order", 0600, powerpc_debugfs_root, - NULL, &fops_hpt_order)) { - pr_err("lpar: unable to create hpt_order debugsfs file\n"); - } - + debugfs_create_file("hpt_order", 0600, powerpc_debugfs_root, NULL, + &fops_hpt_order); return 0; } machine_device_initcall(pseries, hash64_debugfs); From f3c05201950a71c1b8b4f11828303f76c5dd0944 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 9 Feb 2020 11:58:59 +0100 Subject: [PATCH 1117/4444] powerpc/mm: ptdump: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200209105901.1620958-4-gregkh@linuxfoundation.org --- arch/powerpc/mm/ptdump/bats.c | 8 +++----- arch/powerpc/mm/ptdump/hashpagetable.c | 7 ++----- arch/powerpc/mm/ptdump/ptdump.c | 8 +++----- arch/powerpc/mm/ptdump/segment_regs.c | 8 +++----- 4 files changed, 11 insertions(+), 20 deletions(-) diff --git a/arch/powerpc/mm/ptdump/bats.c b/arch/powerpc/mm/ptdump/bats.c index 4154feac1da3..d3a5d6b318d1 100644 --- a/arch/powerpc/mm/ptdump/bats.c +++ b/arch/powerpc/mm/ptdump/bats.c @@ -164,10 +164,8 @@ static const struct file_operations bats_fops = { static int __init bats_init(void) { - struct dentry *debugfs_file; - - debugfs_file = debugfs_create_file("block_address_translation", 0400, - powerpc_debugfs_root, NULL, &bats_fops); - return debugfs_file ? 0 : -ENOMEM; + debugfs_create_file("block_address_translation", 0400, + powerpc_debugfs_root, NULL, &bats_fops); + return 0; } device_initcall(bats_init); diff --git a/arch/powerpc/mm/ptdump/hashpagetable.c b/arch/powerpc/mm/ptdump/hashpagetable.c index a07278027c6f..b6ed9578382f 100644 --- a/arch/powerpc/mm/ptdump/hashpagetable.c +++ b/arch/powerpc/mm/ptdump/hashpagetable.c @@ -527,13 +527,10 @@ static const struct file_operations ptdump_fops = { static int ptdump_init(void) { - struct dentry *debugfs_file; - if (!radix_enabled()) { populate_markers(); - debugfs_file = debugfs_create_file("kernel_hash_pagetable", - 0400, NULL, NULL, &ptdump_fops); - return debugfs_file ? 0 : -ENOMEM; + debugfs_create_file("kernel_hash_pagetable", 0400, NULL, NULL, + &ptdump_fops); } return 0; } diff --git a/arch/powerpc/mm/ptdump/ptdump.c b/arch/powerpc/mm/ptdump/ptdump.c index 206156255247..d92bb8ea229c 100644 --- a/arch/powerpc/mm/ptdump/ptdump.c +++ b/arch/powerpc/mm/ptdump/ptdump.c @@ -417,12 +417,10 @@ void ptdump_check_wx(void) static int ptdump_init(void) { - struct dentry *debugfs_file; - populate_markers(); build_pgtable_complete_mask(); - debugfs_file = debugfs_create_file("kernel_page_tables", 0400, NULL, - NULL, &ptdump_fops); - return debugfs_file ? 0 : -ENOMEM; + debugfs_create_file("kernel_page_tables", 0400, NULL, NULL, + &ptdump_fops); + return 0; } device_initcall(ptdump_init); diff --git a/arch/powerpc/mm/ptdump/segment_regs.c b/arch/powerpc/mm/ptdump/segment_regs.c index 501843664bb9..dde2fe8de4b2 100644 --- a/arch/powerpc/mm/ptdump/segment_regs.c +++ b/arch/powerpc/mm/ptdump/segment_regs.c @@ -55,10 +55,8 @@ static const struct file_operations sr_fops = { static int __init sr_init(void) { - struct dentry *debugfs_file; - - debugfs_file = debugfs_create_file("segment_registers", 0400, - powerpc_debugfs_root, NULL, &sr_fops); - return debugfs_file ? 0 : -ENOMEM; + debugfs_create_file("segment_registers", 0400, powerpc_debugfs_root, + NULL, &sr_fops); + return 0; } device_initcall(sr_init); From e04906aa1fbaf435b9a1f2ec6bbe7971a3ef8e42 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 9 Feb 2020 11:59:00 +0100 Subject: [PATCH 1118/4444] powerpc/cell/axon_msi: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200209105901.1620958-5-gregkh@linuxfoundation.org --- arch/powerpc/platforms/cell/axon_msi.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index 57c4e0e86c88..ca2555b8a0c2 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c @@ -480,10 +480,6 @@ void axon_msi_debug_setup(struct device_node *dn, struct axon_msic *msic) snprintf(name, sizeof(name), "msic_%d", of_node_to_nid(dn)); - if (!debugfs_create_file(name, 0600, powerpc_debugfs_root, - msic, &fops_msic)) { - pr_devel("axon_msi: debugfs_create_file failed!\n"); - return; - } + debugfs_create_file(name, 0600, powerpc_debugfs_root, msic, &fops_msic); } #endif /* DEBUG */ From f344f0ab993987ae29cb39cc52054d7346db082f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 9 Feb 2020 11:59:01 +0100 Subject: [PATCH 1119/4444] powerpc/powernv: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Oliver O'Halloran Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200209105901.1620958-6-gregkh@linuxfoundation.org --- arch/powerpc/platforms/powernv/memtrace.c | 7 ---- arch/powerpc/platforms/powernv/opal-imc.c | 24 ++++---------- arch/powerpc/platforms/powernv/pci-ioda.c | 5 --- arch/powerpc/platforms/powernv/vas-debug.c | 37 ++-------------------- 4 files changed, 10 insertions(+), 63 deletions(-) diff --git a/arch/powerpc/platforms/powernv/memtrace.c b/arch/powerpc/platforms/powernv/memtrace.c index eb2e75dac369..d6d64f8718e6 100644 --- a/arch/powerpc/platforms/powernv/memtrace.c +++ b/arch/powerpc/platforms/powernv/memtrace.c @@ -187,11 +187,6 @@ static int memtrace_init_debugfs(void) snprintf(ent->name, 16, "%08x", ent->nid); dir = debugfs_create_dir(ent->name, memtrace_debugfs_dir); - if (!dir) { - pr_err("Failed to create debugfs directory for node %d\n", - ent->nid); - return -1; - } ent->dir = dir; debugfs_create_file("trace", 0400, dir, ent, &memtrace_fops); @@ -314,8 +309,6 @@ static int memtrace_init(void) { memtrace_debugfs_dir = debugfs_create_dir("memtrace", powerpc_debugfs_root); - if (!memtrace_debugfs_dir) - return -1; debugfs_create_file("enable", 0600, memtrace_debugfs_dir, NULL, &memtrace_init_fops); diff --git a/arch/powerpc/platforms/powernv/opal-imc.c b/arch/powerpc/platforms/powernv/opal-imc.c index 000b350d4060..968b9a4d1cd9 100644 --- a/arch/powerpc/platforms/powernv/opal-imc.c +++ b/arch/powerpc/platforms/powernv/opal-imc.c @@ -35,11 +35,10 @@ static int imc_mem_set(void *data, u64 val) } DEFINE_DEBUGFS_ATTRIBUTE(fops_imc_x64, imc_mem_get, imc_mem_set, "0x%016llx\n"); -static struct dentry *imc_debugfs_create_x64(const char *name, umode_t mode, - struct dentry *parent, u64 *value) +static void imc_debugfs_create_x64(const char *name, umode_t mode, + struct dentry *parent, u64 *value) { - return debugfs_create_file_unsafe(name, mode, parent, - value, &fops_imc_x64); + debugfs_create_file_unsafe(name, mode, parent, value, &fops_imc_x64); } /* @@ -59,9 +58,6 @@ static void export_imc_mode_and_cmd(struct device_node *node, imc_debugfs_parent = debugfs_create_dir("imc", powerpc_debugfs_root); - if (!imc_debugfs_parent) - return; - if (of_property_read_u32(node, "cb_offset", &cb_offset)) cb_offset = IMC_CNTL_BLK_OFFSET; @@ -69,21 +65,15 @@ static void export_imc_mode_and_cmd(struct device_node *node, loc = (u64)(ptr->vbase) + cb_offset; imc_mode_addr = (u64 *)(loc + IMC_CNTL_BLK_MODE_OFFSET); sprintf(mode, "imc_mode_%d", (u32)(ptr->id)); - if (!imc_debugfs_create_x64(mode, 0600, imc_debugfs_parent, - imc_mode_addr)) - goto err; + imc_debugfs_create_x64(mode, 0600, imc_debugfs_parent, + imc_mode_addr); imc_cmd_addr = (u64 *)(loc + IMC_CNTL_BLK_CMD_OFFSET); sprintf(cmd, "imc_cmd_%d", (u32)(ptr->id)); - if (!imc_debugfs_create_x64(cmd, 0600, imc_debugfs_parent, - imc_cmd_addr)) - goto err; + imc_debugfs_create_x64(cmd, 0600, imc_debugfs_parent, + imc_cmd_addr); ptr++; } - return; - -err: - debugfs_remove_recursive(imc_debugfs_parent); } /* diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 22c22cd7bd82..57d3a6af1d52 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -3174,11 +3174,6 @@ static void pnv_pci_ioda_create_dbgfs(void) sprintf(name, "PCI%04x", hose->global_number); phb->dbgfs = debugfs_create_dir(name, powerpc_debugfs_root); - if (!phb->dbgfs) { - pr_warn("%s: Error on creating debugfs on PHB#%x\n", - __func__, hose->global_number); - continue; - } debugfs_create_file_unsafe("dump_diag_regs", 0200, phb->dbgfs, phb, &pnv_pci_diag_data_fops); diff --git a/arch/powerpc/platforms/powernv/vas-debug.c b/arch/powerpc/platforms/powernv/vas-debug.c index 09e63df53c30..44035a3d6414 100644 --- a/arch/powerpc/platforms/powernv/vas-debug.c +++ b/arch/powerpc/platforms/powernv/vas-debug.c @@ -115,7 +115,7 @@ void vas_window_free_dbgdir(struct vas_window *window) void vas_window_init_dbgdir(struct vas_window *window) { - struct dentry *f, *d; + struct dentry *d; if (!window->vinst->dbgdir) return; @@ -127,28 +127,10 @@ void vas_window_init_dbgdir(struct vas_window *window) snprintf(window->dbgname, 16, "w%d", window->winid); d = debugfs_create_dir(window->dbgname, window->vinst->dbgdir); - if (IS_ERR(d)) - goto free_name; - window->dbgdir = d; - f = debugfs_create_file("info", 0444, d, window, &info_fops); - if (IS_ERR(f)) - goto remove_dir; - - f = debugfs_create_file("hvwc", 0444, d, window, &hvwc_fops); - if (IS_ERR(f)) - goto remove_dir; - - return; - -remove_dir: - debugfs_remove_recursive(window->dbgdir); - window->dbgdir = NULL; - -free_name: - kfree(window->dbgname); - window->dbgname = NULL; + debugfs_create_file("info", 0444, d, window, &info_fops); + debugfs_create_file("hvwc", 0444, d, window, &hvwc_fops); } void vas_instance_init_dbgdir(struct vas_instance *vinst) @@ -156,8 +138,6 @@ void vas_instance_init_dbgdir(struct vas_instance *vinst) struct dentry *d; vas_init_dbgdir(); - if (!vas_debugfs) - return; vinst->dbgname = kzalloc(16, GFP_KERNEL); if (!vinst->dbgname) @@ -166,16 +146,7 @@ void vas_instance_init_dbgdir(struct vas_instance *vinst) snprintf(vinst->dbgname, 16, "v%d", vinst->vas_id); d = debugfs_create_dir(vinst->dbgname, vas_debugfs); - if (IS_ERR(d)) - goto free_name; - vinst->dbgdir = d; - return; - -free_name: - kfree(vinst->dbgname); - vinst->dbgname = NULL; - vinst->dbgdir = NULL; } /* @@ -191,6 +162,4 @@ void vas_init_dbgdir(void) first_time = false; vas_debugfs = debugfs_create_dir("vas", NULL); - if (IS_ERR(vas_debugfs)) - vas_debugfs = NULL; } From c4b78169e3667413184c9a20e11b5832288a109f Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Mon, 23 Dec 2019 17:03:51 +1100 Subject: [PATCH 1120/4444] powerpc/book3s64: Fix error handling in mm_iommu_do_alloc() The last jump to free_exit in mm_iommu_do_alloc() happens after page pointers in struct mm_iommu_table_group_mem_t were already converted to physical addresses. Thus calling put_page() on these physical addresses will likely crash. This moves the loop which calculates the pageshift and converts page struct pointers to physical addresses later after the point when we cannot fail; thus eliminating the need to convert pointers back. Fixes: eb9d7a62c386 ("powerpc/mm_iommu: Fix potential deadlock") Reported-by: Jan Kara Signed-off-by: Alexey Kardashevskiy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20191223060351.26359-1-aik@ozlabs.ru --- arch/powerpc/mm/book3s64/iommu_api.c | 39 +++++++++++++++------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/arch/powerpc/mm/book3s64/iommu_api.c b/arch/powerpc/mm/book3s64/iommu_api.c index eba73ebd8ae5..fa05bbd1f682 100644 --- a/arch/powerpc/mm/book3s64/iommu_api.c +++ b/arch/powerpc/mm/book3s64/iommu_api.c @@ -121,24 +121,6 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, unsigned long ua, goto free_exit; } - pageshift = PAGE_SHIFT; - for (i = 0; i < entries; ++i) { - struct page *page = mem->hpages[i]; - - /* - * Allow to use larger than 64k IOMMU pages. Only do that - * if we are backed by hugetlb. - */ - if ((mem->pageshift > PAGE_SHIFT) && PageHuge(page)) - pageshift = page_shift(compound_head(page)); - mem->pageshift = min(mem->pageshift, pageshift); - /* - * We don't need struct page reference any more, switch - * to physical address. - */ - mem->hpas[i] = page_to_pfn(page) << PAGE_SHIFT; - } - good_exit: atomic64_set(&mem->mapped, 1); mem->used = 1; @@ -158,6 +140,27 @@ good_exit: } } + if (mem->dev_hpa == MM_IOMMU_TABLE_INVALID_HPA) { + /* + * Allow to use larger than 64k IOMMU pages. Only do that + * if we are backed by hugetlb. Skip device memory as it is not + * backed with page structs. + */ + pageshift = PAGE_SHIFT; + for (i = 0; i < entries; ++i) { + struct page *page = mem->hpages[i]; + + if ((mem->pageshift > PAGE_SHIFT) && PageHuge(page)) + pageshift = page_shift(compound_head(page)); + mem->pageshift = min(mem->pageshift, pageshift); + /* + * We don't need struct page reference any more, switch + * to physical address. + */ + mem->hpas[i] = page_to_pfn(page) << PAGE_SHIFT; + } + } + list_add_rcu(&mem->next, &mm->context.iommu_group_mem_list); mutex_unlock(&mem_list_mutex); From 6453f9ed9d4e4b4cdf201bf34bf460c436bf50ea Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Mon, 17 Feb 2020 09:41:35 +0000 Subject: [PATCH 1121/4444] powerpc/mm: Don't kmap_atomic() in pte_offset_map() on PPC32 On PPC32, pte_offset_map() does a kmap_atomic() in order to support page tables allocated in high memory, just like ARM and x86/32. But since at least 2008 and commit 8054a3428fbe ("powerpc: Remove dead CONFIG_HIGHPTE"), page tables are never allocated in high memory. When the page is in low mem, kmap_atomic() just returns the page address but still disable preemption and pagefault. And it is not an inlined function, so we suffer function call for no reason. Make pte_offset_map() the same as pte_offset_kernel() and make pte_unmap() void, in the same way as PPC64 which doesn't have HIGHMEM. Signed-off-by: Christophe Leroy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/03c97f0f6b3790d164822563be80f2fd4713a955.1581932480.git.christophe.leroy@c-s.fr --- arch/powerpc/include/asm/book3s/32/pgtable.h | 6 ++---- arch/powerpc/include/asm/nohash/32/pgtable.h | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h index 5b39c11e884a..7549393c4c43 100644 --- a/arch/powerpc/include/asm/book3s/32/pgtable.h +++ b/arch/powerpc/include/asm/book3s/32/pgtable.h @@ -366,10 +366,8 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma, (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) #define pte_offset_kernel(dir, addr) \ ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(addr)) -#define pte_offset_map(dir, addr) \ - ((pte_t *)(kmap_atomic(pmd_page(*(dir))) + \ - (pmd_page_vaddr(*(dir)) & ~PAGE_MASK)) + pte_index(addr)) -#define pte_unmap(pte) kunmap_atomic(pte) +#define pte_offset_map(dir, addr) pte_offset_kernel((dir), (addr)) +static inline void pte_unmap(pte_t *pte) { } /* * Encode and decode a swap entry. diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h index 60c4d829152e..b04ba257fddb 100644 --- a/arch/powerpc/include/asm/nohash/32/pgtable.h +++ b/arch/powerpc/include/asm/nohash/32/pgtable.h @@ -372,10 +372,8 @@ static inline int pte_young(pte_t pte) #define pte_offset_kernel(dir, addr) \ (pmd_bad(*(dir)) ? NULL : (pte_t *)pmd_page_vaddr(*(dir)) + \ pte_index(addr)) -#define pte_offset_map(dir, addr) \ - ((pte_t *)(kmap_atomic(pmd_page(*(dir))) + \ - (pmd_page_vaddr(*(dir)) & ~PAGE_MASK)) + pte_index(addr)) -#define pte_unmap(pte) kunmap_atomic(pte) +#define pte_offset_map(dir, addr) pte_offset_kernel((dir), (addr)) +static inline void pte_unmap(pte_t *pte) { } /* * Encode and decode a swap entry. From d42c6d0f8d004c3661dde3c376ed637e9f292c22 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 19 Feb 2020 11:04:34 +1100 Subject: [PATCH 1122/4444] powerpc/Makefile: Mark phony targets as PHONY Some of our phony targets are not marked as such. This can lead to confusing errors, eg: $ make clean $ touch install $ make install make: 'install' is up to date. $ Fix it by adding them to the PHONY variable which is marked phony in the top-level Makefile, or in scripts/Makefile.build for the boot Makefile. Suggested-by: Masahiro Yamada Signed-off-by: Michael Ellerman Reviewed-by: Masahiro Yamada Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200219000434.15872-1-mpe@ellerman.id.au --- arch/powerpc/Makefile | 6 ++++++ arch/powerpc/boot/Makefile | 2 ++ 2 files changed, 8 insertions(+) diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index f35730548e42..cbe5ca4f0ee5 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -298,6 +298,7 @@ $(BOOT_TARGETS2): vmlinux $(Q)$(MAKE) $(build)=$(boot) $(patsubst %,$(boot)/%,$@) +PHONY += bootwrapper_install bootwrapper_install: $(Q)$(MAKE) $(build)=$(boot) $(patsubst %,$(boot)/%,$@) @@ -403,9 +404,11 @@ define archhelp @echo ' (minus the .dts extension).' endef +PHONY += install install: $(Q)$(MAKE) $(build)=$(boot) install +PHONY += vdso_install vdso_install: ifdef CONFIG_PPC64 $(Q)$(MAKE) $(build)=arch/$(ARCH)/kernel/vdso64 $@ @@ -425,6 +428,7 @@ archheaders: ifdef CONFIG_STACKPROTECTOR prepare: stack_protector_prepare +PHONY += stack_protector_prepare stack_protector_prepare: prepare0 ifdef CONFIG_PPC64 $(eval KBUILD_CFLAGS += -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "PACA_CANARY") print $$3;}' include/generated/asm-offsets.h)) @@ -436,10 +440,12 @@ endif ifdef CONFIG_SMP prepare: task_cpu_prepare +PHONY += task_cpu_prepare task_cpu_prepare: prepare0 $(eval KBUILD_CFLAGS += -D_TASK_CPU=$(shell awk '{if ($$2 == "TASK_CPU") print $$3;}' include/generated/asm-offsets.h)) endif +PHONY += checkbin # Check toolchain versions: # - gcc-4.6 is the minimum kernel-wide version so nothing required. checkbin: diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 0556bf4fc9e9..c53a1b8bba8b 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -445,6 +445,8 @@ install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y)) zInstall: $(CONFIGURE) $(addprefix $(obj)/, $(image-y)) sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $^ +PHONY += install zInstall + # anything not in $(targets) clean-files += $(image-) $(initrd-) cuImage.* dtbImage.* treeImage.* \ zImage zImage.initrd zImage.chrp zImage.coff zImage.holly \ From 16985f2d25095899685952296f128a71f0aff05c Mon Sep 17 00:00:00 2001 From: Oliver O'Halloran Date: Mon, 17 Feb 2020 13:48:32 +1100 Subject: [PATCH 1123/4444] powerpc/powernv: Treat an empty reboot string as default Treat an empty reboot cmd string the same as a NULL string. This squashes a spurious unsupported reboot message that sometimes gets out when using xmon. Signed-off-by: Oliver O'Halloran Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200217024833.30580-1-oohall@gmail.com --- arch/powerpc/platforms/powernv/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index 11fdae81b5dd..a8fe630cf7cc 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c @@ -229,7 +229,7 @@ static void __noreturn pnv_restart(char *cmd) pnv_prepare_going_down(); do { - if (!cmd) + if (!cmd || !strlen(cmd)) rc = opal_cec_reboot(); else if (strcmp(cmd, "full") == 0) rc = opal_cec_reboot2(OPAL_REBOOT_FULL_IPL, NULL); From 672e480aa21023fc8e4b6ab8635d8898822b97e7 Mon Sep 17 00:00:00 2001 From: Oliver O'Halloran Date: Mon, 17 Feb 2020 13:48:33 +1100 Subject: [PATCH 1124/4444] powerpc/powernv: Add explicit fast-reboot support Add a way to manually invoke a fast-reboot rather than setting the NVRAM flag. The idea is to allow userspace to invoke a fast-reboot using the optional string argument to the reboot() system call, or using the xmon zr command so we don't need to leave around a persistent changes on a system to use the feature. Signed-off-by: Oliver O'Halloran Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200217024833.30580-2-oohall@gmail.com --- arch/powerpc/include/asm/opal-api.h | 1 + arch/powerpc/platforms/powernv/setup.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index c1f25a760eb1..1dffa3cb16ba 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h @@ -1067,6 +1067,7 @@ enum { OPAL_REBOOT_PLATFORM_ERROR = 1, OPAL_REBOOT_FULL_IPL = 2, OPAL_REBOOT_MPIPL = 3, + OPAL_REBOOT_FAST = 4, }; /* Argument to OPAL_PCI_TCE_KILL */ diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index a8fe630cf7cc..3bc188da82ba 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c @@ -237,6 +237,8 @@ static void __noreturn pnv_restart(char *cmd) rc = opal_cec_reboot2(OPAL_REBOOT_MPIPL, NULL); else if (strcmp(cmd, "error") == 0) rc = opal_cec_reboot2(OPAL_REBOOT_PLATFORM_ERROR, NULL); + else if (strcmp(cmd, "fast") == 0) + rc = opal_cec_reboot2(OPAL_REBOOT_FAST, NULL); else rc = OPAL_UNSUPPORTED; From fcdb524d440d6326c286006e16f252b40ba4fd6a Mon Sep 17 00:00:00 2001 From: Madhavan Srinivasan Date: Fri, 14 Feb 2020 13:36:05 +0530 Subject: [PATCH 1125/4444] powerpc/kernel/sysfs: Refactor current sysfs.c An attempt to refactor the current sysfs.c file. To start with a big chuck of macro #defines and dscr functions are moved to start of the file. Secondly, HAS_ #define macros are cleanup based on CONFIG_ options Finally new HAS_ macro added: 1. HAS_PPC_PA6T (for PA6T) to separate out non-PMU SPRs. 2. HAS_PPC_PMC56 to separate out PMC SPR's from HAS_PPC_PMC_CLASSIC which come under CONFIG_PPC64. Signed-off-by: Madhavan Srinivasan Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200214080606.26872-1-kjain@linux.ibm.com --- arch/powerpc/kernel/sysfs.c | 393 +++++++++++++++++++----------------- 1 file changed, 209 insertions(+), 184 deletions(-) diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 80a676da11cb..74da5ebf088e 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -87,6 +87,155 @@ __setup("smt-snooze-delay=", setup_smt_snooze_delay); #endif /* CONFIG_PPC64 */ +#define __SYSFS_SPRSETUP_READ_WRITE(NAME, ADDRESS, EXTRA) \ +static void read_##NAME(void *val) \ +{ \ + *(unsigned long *)val = mfspr(ADDRESS); \ +} \ +static void write_##NAME(void *val) \ +{ \ + EXTRA; \ + mtspr(ADDRESS, *(unsigned long *)val); \ +} + +#define __SYSFS_SPRSETUP_SHOW_STORE(NAME) \ +static ssize_t show_##NAME(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct cpu *cpu = container_of(dev, struct cpu, dev); \ + unsigned long val; \ + smp_call_function_single(cpu->dev.id, read_##NAME, &val, 1); \ + return sprintf(buf, "%lx\n", val); \ +} \ +static ssize_t __used \ + store_##NAME(struct device *dev, struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + struct cpu *cpu = container_of(dev, struct cpu, dev); \ + unsigned long val; \ + int ret = sscanf(buf, "%lx", &val); \ + if (ret != 1) \ + return -EINVAL; \ + smp_call_function_single(cpu->dev.id, write_##NAME, &val, 1); \ + return count; \ +} + +#define SYSFS_PMCSETUP(NAME, ADDRESS) \ + __SYSFS_SPRSETUP_READ_WRITE(NAME, ADDRESS, ppc_enable_pmcs()) \ + __SYSFS_SPRSETUP_SHOW_STORE(NAME) +#define SYSFS_SPRSETUP(NAME, ADDRESS) \ + __SYSFS_SPRSETUP_READ_WRITE(NAME, ADDRESS, ) \ + __SYSFS_SPRSETUP_SHOW_STORE(NAME) + +#define SYSFS_SPRSETUP_SHOW_STORE(NAME) \ + __SYSFS_SPRSETUP_SHOW_STORE(NAME) + +#ifdef CONFIG_PPC64 + +/* + * This is the system wide DSCR register default value. Any + * change to this default value through the sysfs interface + * will update all per cpu DSCR default values across the + * system stored in their respective PACA structures. + */ +static unsigned long dscr_default; + +/** + * read_dscr() - Fetch the cpu specific DSCR default + * @val: Returned cpu specific DSCR default value + * + * This function returns the per cpu DSCR default value + * for any cpu which is contained in it's PACA structure. + */ +static void read_dscr(void *val) +{ + *(unsigned long *)val = get_paca()->dscr_default; +} + + +/** + * write_dscr() - Update the cpu specific DSCR default + * @val: New cpu specific DSCR default value to update + * + * This function updates the per cpu DSCR default value + * for any cpu which is contained in it's PACA structure. + */ +static void write_dscr(void *val) +{ + get_paca()->dscr_default = *(unsigned long *)val; + if (!current->thread.dscr_inherit) { + current->thread.dscr = *(unsigned long *)val; + mtspr(SPRN_DSCR, *(unsigned long *)val); + } +} + +SYSFS_SPRSETUP_SHOW_STORE(dscr); +static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr); + +static void add_write_permission_dev_attr(struct device_attribute *attr) +{ + attr->attr.mode |= 0200; +} + +/** + * show_dscr_default() - Fetch the system wide DSCR default + * @dev: Device structure + * @attr: Device attribute structure + * @buf: Interface buffer + * + * This function returns the system wide DSCR default value. + */ +static ssize_t show_dscr_default(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%lx\n", dscr_default); +} + +/** + * store_dscr_default() - Update the system wide DSCR default + * @dev: Device structure + * @attr: Device attribute structure + * @buf: Interface buffer + * @count: Size of the update + * + * This function updates the system wide DSCR default value. + */ +static ssize_t __used store_dscr_default(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + unsigned long val; + int ret = 0; + + ret = sscanf(buf, "%lx", &val); + if (ret != 1) + return -EINVAL; + dscr_default = val; + + on_each_cpu(write_dscr, &val, 1); + + return count; +} + +static DEVICE_ATTR(dscr_default, 0600, + show_dscr_default, store_dscr_default); + +static void sysfs_create_dscr_default(void) +{ + if (cpu_has_feature(CPU_FTR_DSCR)) { + int err = 0; + int cpu; + + dscr_default = spr_default_dscr; + for_each_possible_cpu(cpu) + paca_ptrs[cpu]->dscr_default = dscr_default; + + err = device_create_file(cpu_subsys.dev_root, &dev_attr_dscr_default); + } +} +#endif /* CONFIG_PPC64 */ + #ifdef CONFIG_PPC_FSL_BOOK3E #define MAX_BIT 63 @@ -407,84 +556,33 @@ void ppc_enable_pmcs(void) } EXPORT_SYMBOL(ppc_enable_pmcs); -#define __SYSFS_SPRSETUP_READ_WRITE(NAME, ADDRESS, EXTRA) \ -static void read_##NAME(void *val) \ -{ \ - *(unsigned long *)val = mfspr(ADDRESS); \ -} \ -static void write_##NAME(void *val) \ -{ \ - EXTRA; \ - mtspr(ADDRESS, *(unsigned long *)val); \ -} -#define __SYSFS_SPRSETUP_SHOW_STORE(NAME) \ -static ssize_t show_##NAME(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct cpu *cpu = container_of(dev, struct cpu, dev); \ - unsigned long val; \ - smp_call_function_single(cpu->dev.id, read_##NAME, &val, 1); \ - return sprintf(buf, "%lx\n", val); \ -} \ -static ssize_t __used \ - store_##NAME(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct cpu *cpu = container_of(dev, struct cpu, dev); \ - unsigned long val; \ - int ret = sscanf(buf, "%lx", &val); \ - if (ret != 1) \ - return -EINVAL; \ - smp_call_function_single(cpu->dev.id, write_##NAME, &val, 1); \ - return count; \ -} - -#define SYSFS_PMCSETUP(NAME, ADDRESS) \ - __SYSFS_SPRSETUP_READ_WRITE(NAME, ADDRESS, ppc_enable_pmcs()) \ - __SYSFS_SPRSETUP_SHOW_STORE(NAME) -#define SYSFS_SPRSETUP(NAME, ADDRESS) \ - __SYSFS_SPRSETUP_READ_WRITE(NAME, ADDRESS, ) \ - __SYSFS_SPRSETUP_SHOW_STORE(NAME) - -#define SYSFS_SPRSETUP_SHOW_STORE(NAME) \ - __SYSFS_SPRSETUP_SHOW_STORE(NAME) /* Let's define all possible registers, we'll only hook up the ones * that are implemented on the current processor */ -#if defined(CONFIG_PPC64) +#if defined(CONFIG_PPC64) || defined(CONFIG_PPC_BOOK3S_32) #define HAS_PPC_PMC_CLASSIC 1 #define HAS_PPC_PMC_IBM 1 -#define HAS_PPC_PMC_PA6T 1 -#elif defined(CONFIG_PPC_BOOK3S_32) -#define HAS_PPC_PMC_CLASSIC 1 -#define HAS_PPC_PMC_IBM 1 -#define HAS_PPC_PMC_G4 1 -#endif - - -#ifdef HAS_PPC_PMC_CLASSIC -SYSFS_PMCSETUP(mmcr0, SPRN_MMCR0); -SYSFS_PMCSETUP(mmcr1, SPRN_MMCR1); -SYSFS_PMCSETUP(pmc1, SPRN_PMC1); -SYSFS_PMCSETUP(pmc2, SPRN_PMC2); -SYSFS_PMCSETUP(pmc3, SPRN_PMC3); -SYSFS_PMCSETUP(pmc4, SPRN_PMC4); -SYSFS_PMCSETUP(pmc5, SPRN_PMC5); -SYSFS_PMCSETUP(pmc6, SPRN_PMC6); - -#ifdef HAS_PPC_PMC_G4 -SYSFS_PMCSETUP(mmcr2, SPRN_MMCR2); #endif #ifdef CONFIG_PPC64 -SYSFS_PMCSETUP(pmc7, SPRN_PMC7); -SYSFS_PMCSETUP(pmc8, SPRN_PMC8); +#define HAS_PPC_PMC_PA6T 1 +#define HAS_PPC_PMC56 1 +#endif -SYSFS_PMCSETUP(mmcra, SPRN_MMCRA); +#ifdef CONFIG_PPC_BOOK3S_32 +#define HAS_PPC_PMC_G4 1 +#endif + +#if defined(CONFIG_PPC64) && defined(CONFIG_DEBUG_MISC) +#define HAS_PPC_PA6T +#endif +/* + * SPRs which are not related to PMU. + */ +#ifdef CONFIG_PPC64 SYSFS_SPRSETUP(purr, SPRN_PURR); SYSFS_SPRSETUP(spurr, SPRN_SPURR); SYSFS_SPRSETUP(pir, SPRN_PIR); @@ -495,116 +593,39 @@ SYSFS_SPRSETUP(tscr, SPRN_TSCR); enable write when needed with a separate function. Lets be conservative and default to pseries. */ -static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra); static DEVICE_ATTR(spurr, 0400, show_spurr, NULL); static DEVICE_ATTR(purr, 0400, show_purr, store_purr); static DEVICE_ATTR(pir, 0400, show_pir, NULL); static DEVICE_ATTR(tscr, 0600, show_tscr, store_tscr); - -/* - * This is the system wide DSCR register default value. Any - * change to this default value through the sysfs interface - * will update all per cpu DSCR default values across the - * system stored in their respective PACA structures. - */ -static unsigned long dscr_default; - -/** - * read_dscr() - Fetch the cpu specific DSCR default - * @val: Returned cpu specific DSCR default value - * - * This function returns the per cpu DSCR default value - * for any cpu which is contained in it's PACA structure. - */ -static void read_dscr(void *val) -{ - *(unsigned long *)val = get_paca()->dscr_default; -} - - -/** - * write_dscr() - Update the cpu specific DSCR default - * @val: New cpu specific DSCR default value to update - * - * This function updates the per cpu DSCR default value - * for any cpu which is contained in it's PACA structure. - */ -static void write_dscr(void *val) -{ - get_paca()->dscr_default = *(unsigned long *)val; - if (!current->thread.dscr_inherit) { - current->thread.dscr = *(unsigned long *)val; - mtspr(SPRN_DSCR, *(unsigned long *)val); - } -} - -SYSFS_SPRSETUP_SHOW_STORE(dscr); -static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr); - -static void add_write_permission_dev_attr(struct device_attribute *attr) -{ - attr->attr.mode |= 0200; -} - -/** - * show_dscr_default() - Fetch the system wide DSCR default - * @dev: Device structure - * @attr: Device attribute structure - * @buf: Interface buffer - * - * This function returns the system wide DSCR default value. - */ -static ssize_t show_dscr_default(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%lx\n", dscr_default); -} - -/** - * store_dscr_default() - Update the system wide DSCR default - * @dev: Device structure - * @attr: Device attribute structure - * @buf: Interface buffer - * @count: Size of the update - * - * This function updates the system wide DSCR default value. - */ -static ssize_t __used store_dscr_default(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - unsigned long val; - int ret = 0; - - ret = sscanf(buf, "%lx", &val); - if (ret != 1) - return -EINVAL; - dscr_default = val; - - on_each_cpu(write_dscr, &val, 1); - - return count; -} - -static DEVICE_ATTR(dscr_default, 0600, - show_dscr_default, store_dscr_default); - -static void sysfs_create_dscr_default(void) -{ - if (cpu_has_feature(CPU_FTR_DSCR)) { - int err = 0; - int cpu; - - dscr_default = spr_default_dscr; - for_each_possible_cpu(cpu) - paca_ptrs[cpu]->dscr_default = dscr_default; - - err = device_create_file(cpu_subsys.dev_root, &dev_attr_dscr_default); - } -} - #endif /* CONFIG_PPC64 */ +#ifdef HAS_PPC_PMC_CLASSIC +SYSFS_PMCSETUP(mmcr0, SPRN_MMCR0); +SYSFS_PMCSETUP(mmcr1, SPRN_MMCR1); +SYSFS_PMCSETUP(pmc1, SPRN_PMC1); +SYSFS_PMCSETUP(pmc2, SPRN_PMC2); +SYSFS_PMCSETUP(pmc3, SPRN_PMC3); +SYSFS_PMCSETUP(pmc4, SPRN_PMC4); +SYSFS_PMCSETUP(pmc5, SPRN_PMC5); +SYSFS_PMCSETUP(pmc6, SPRN_PMC6); +#endif + +#ifdef HAS_PPC_PMC_G4 +SYSFS_PMCSETUP(mmcr2, SPRN_MMCR2); +#endif + +#ifdef HAS_PPC_PMC56 +SYSFS_PMCSETUP(pmc7, SPRN_PMC7); +SYSFS_PMCSETUP(pmc8, SPRN_PMC8); + +SYSFS_PMCSETUP(mmcra, SPRN_MMCRA); + +static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra); +#endif /* HAS_PPC_PMC56 */ + + + + #ifdef HAS_PPC_PMC_PA6T SYSFS_PMCSETUP(pa6t_pmc0, SPRN_PA6T_PMC0); SYSFS_PMCSETUP(pa6t_pmc1, SPRN_PA6T_PMC1); @@ -612,7 +633,9 @@ SYSFS_PMCSETUP(pa6t_pmc2, SPRN_PA6T_PMC2); SYSFS_PMCSETUP(pa6t_pmc3, SPRN_PA6T_PMC3); SYSFS_PMCSETUP(pa6t_pmc4, SPRN_PA6T_PMC4); SYSFS_PMCSETUP(pa6t_pmc5, SPRN_PA6T_PMC5); -#ifdef CONFIG_DEBUG_MISC +#endif + +#ifdef HAS_PPC_PA6T SYSFS_SPRSETUP(hid0, SPRN_HID0); SYSFS_SPRSETUP(hid1, SPRN_HID1); SYSFS_SPRSETUP(hid4, SPRN_HID4); @@ -641,15 +664,14 @@ SYSFS_SPRSETUP(tsr0, SPRN_PA6T_TSR0); SYSFS_SPRSETUP(tsr1, SPRN_PA6T_TSR1); SYSFS_SPRSETUP(tsr2, SPRN_PA6T_TSR2); SYSFS_SPRSETUP(tsr3, SPRN_PA6T_TSR3); -#endif /* CONFIG_DEBUG_MISC */ -#endif /* HAS_PPC_PMC_PA6T */ +#endif /* HAS_PPC_PA6T */ #ifdef HAS_PPC_PMC_IBM static struct device_attribute ibm_common_attrs[] = { __ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0), __ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1), }; -#endif /* HAS_PPC_PMC_G4 */ +#endif /* HAS_PPC_PMC_IBM */ #ifdef HAS_PPC_PMC_G4 static struct device_attribute g4_common_attrs[] = { @@ -659,6 +681,7 @@ static struct device_attribute g4_common_attrs[] = { }; #endif /* HAS_PPC_PMC_G4 */ +#ifdef HAS_PPC_PMC_CLASSIC static struct device_attribute classic_pmc_attrs[] = { __ATTR(pmc1, 0600, show_pmc1, store_pmc1), __ATTR(pmc2, 0600, show_pmc2, store_pmc2), @@ -666,14 +689,16 @@ static struct device_attribute classic_pmc_attrs[] = { __ATTR(pmc4, 0600, show_pmc4, store_pmc4), __ATTR(pmc5, 0600, show_pmc5, store_pmc5), __ATTR(pmc6, 0600, show_pmc6, store_pmc6), -#ifdef CONFIG_PPC64 +#ifdef HAS_PPC_PMC56 __ATTR(pmc7, 0600, show_pmc7, store_pmc7), __ATTR(pmc8, 0600, show_pmc8, store_pmc8), #endif }; +#endif -#ifdef HAS_PPC_PMC_PA6T +#if defined(HAS_PPC_PMC_PA6T) || defined(HAS_PPC_PA6T) static struct device_attribute pa6t_attrs[] = { +#ifdef HAS_PPC_PMC_PA6T __ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0), __ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1), __ATTR(pmc0, 0600, show_pa6t_pmc0, store_pa6t_pmc0), @@ -682,7 +707,8 @@ static struct device_attribute pa6t_attrs[] = { __ATTR(pmc3, 0600, show_pa6t_pmc3, store_pa6t_pmc3), __ATTR(pmc4, 0600, show_pa6t_pmc4, store_pa6t_pmc4), __ATTR(pmc5, 0600, show_pa6t_pmc5, store_pa6t_pmc5), -#ifdef CONFIG_DEBUG_MISC +#endif +#ifdef HAS_PPC_PA6T __ATTR(hid0, 0600, show_hid0, store_hid0), __ATTR(hid1, 0600, show_hid1, store_hid1), __ATTR(hid4, 0600, show_hid4, store_hid4), @@ -711,10 +737,9 @@ static struct device_attribute pa6t_attrs[] = { __ATTR(tsr1, 0600, show_tsr1, store_tsr1), __ATTR(tsr2, 0600, show_tsr2, store_tsr2), __ATTR(tsr3, 0600, show_tsr3, store_tsr3), -#endif /* CONFIG_DEBUG_MISC */ +#endif /* HAS_PPC_PA6T */ }; -#endif /* HAS_PPC_PMC_PA6T */ -#endif /* HAS_PPC_PMC_CLASSIC */ +#endif #ifdef CONFIG_PPC_SVM static ssize_t show_svm(struct device *dev, struct device_attribute *attr, char *buf) @@ -765,14 +790,14 @@ static int register_cpu_online(unsigned int cpu) pmc_attrs = classic_pmc_attrs; break; #endif /* HAS_PPC_PMC_G4 */ -#ifdef HAS_PPC_PMC_PA6T +#if defined(HAS_PPC_PMC_PA6T) || defined(HAS_PPC_PA6T) case PPC_PMC_PA6T: /* PA Semi starts counting at PMC0 */ attrs = pa6t_attrs; nattrs = sizeof(pa6t_attrs) / sizeof(struct device_attribute); pmc_attrs = NULL; break; -#endif /* HAS_PPC_PMC_PA6T */ +#endif default: attrs = NULL; nattrs = 0; @@ -854,14 +879,14 @@ static int unregister_cpu_online(unsigned int cpu) pmc_attrs = classic_pmc_attrs; break; #endif /* HAS_PPC_PMC_G4 */ -#ifdef HAS_PPC_PMC_PA6T +#if defined(HAS_PPC_PMC_PA6T) || defined(HAS_PPC_PA6T) case PPC_PMC_PA6T: /* PA Semi starts counting at PMC0 */ attrs = pa6t_attrs; nattrs = sizeof(pa6t_attrs) / sizeof(struct device_attribute); pmc_attrs = NULL; break; -#endif /* HAS_PPC_PMC_PA6T */ +#endif default: attrs = NULL; nattrs = 0; From 22697da36d0cee57c2a5750ef7d84e4d88da17e7 Mon Sep 17 00:00:00 2001 From: Kajol Jain Date: Fri, 14 Feb 2020 13:36:06 +0530 Subject: [PATCH 1126/4444] powerpc/kernel/sysfs: Add new config option PMU_SYSFS to enable PMU SPRs sysfs file creation Many of the performance monitoring unit (PMU) SPRs are exposed in the sysfs. This may not be a desirable since "perf" API is the primary interface to program PMU and collect counter data in the system. But that said, we cant remove these sysfs files since we dont whether anyone/anything is using them. So the patch adds a new CONFIG option 'CONFIG_PMU_SYSFS' (user selectable) to be used in sysfs file creation for PMU SPRs. New option by default is disabled, but can be enabled if user needs it. Tested this patch behaviour in powernv and pseries machines. Patch is also tested for pmac32_defconfig. Signed-off-by: Kajol Jain Tested-by: Nageswara R Sastry Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200214080606.26872-2-kjain@linux.ibm.com --- arch/powerpc/kernel/sysfs.c | 6 ++++++ arch/powerpc/platforms/Kconfig.cputype | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 74da5ebf088e..479c70680b76 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -562,6 +562,7 @@ EXPORT_SYMBOL(ppc_enable_pmcs); * that are implemented on the current processor */ +#ifdef CONFIG_PMU_SYSFS #if defined(CONFIG_PPC64) || defined(CONFIG_PPC_BOOK3S_32) #define HAS_PPC_PMC_CLASSIC 1 #define HAS_PPC_PMC_IBM 1 @@ -575,6 +576,7 @@ EXPORT_SYMBOL(ppc_enable_pmcs); #ifdef CONFIG_PPC_BOOK3S_32 #define HAS_PPC_PMC_G4 1 #endif +#endif /* CONFIG_PMU_SYSFS */ #if defined(CONFIG_PPC64) && defined(CONFIG_DEBUG_MISC) #define HAS_PPC_PA6T @@ -812,8 +814,10 @@ static int register_cpu_online(unsigned int cpu) device_create_file(s, &pmc_attrs[i]); #ifdef CONFIG_PPC64 +#ifdef CONFIG_PMU_SYSFS if (cpu_has_feature(CPU_FTR_MMCRA)) device_create_file(s, &dev_attr_mmcra); +#endif /* CONFIG_PMU_SYSFS */ if (cpu_has_feature(CPU_FTR_PURR)) { if (!firmware_has_feature(FW_FEATURE_LPAR)) @@ -901,8 +905,10 @@ static int unregister_cpu_online(unsigned int cpu) device_remove_file(s, &pmc_attrs[i]); #ifdef CONFIG_PPC64 +#ifdef CONFIG_PMU_SYSFS if (cpu_has_feature(CPU_FTR_MMCRA)) device_remove_file(s, &dev_attr_mmcra); +#endif /* CONFIG_PMU_SYSFS */ if (cpu_has_feature(CPU_FTR_PURR)) device_remove_file(s, &dev_attr_purr); diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 6caedc88474f..4208724e9f28 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype @@ -425,6 +425,12 @@ config PPC_MM_SLICES config PPC_HAVE_PMU_SUPPORT bool +config PMU_SYSFS + bool "Create PMU SPRs sysfs file" + default n + help + This option enables sysfs file creation for PMU SPRs like MMCR* and PMC*. + config PPC_PERF_CTRS def_bool y depends on PERF_EVENTS && PPC_HAVE_PMU_SUPPORT From 3d13e839e801e081bdece0127c2affa33d0f77cf Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 20 Feb 2020 22:51:37 +1100 Subject: [PATCH 1127/4444] powerpc: Rename current_stack_pointer() to current_stack_frame() current_stack_pointer(), which was called __get_SP(), used to just return the value in r1. But that caused problems in some cases, so it was turned into a function in commit bfe9a2cfe91a ("powerpc: Reimplement __get_SP() as a function not a define"). Because it's a function in a separate compilation unit to all its callers, it has the effect of causing a stack frame to be created, and then returns the address of that frame. This is good in some cases like those described in the above commit, but in other cases it's overkill, we just need to know what stack page we're on. On some other arches current_stack_pointer is just a register global giving the stack pointer, and we'd like to do that too. So rename our current_stack_pointer() to current_stack_frame() to make that possible. Signed-off-by: Michael Ellerman Reviewed-by: Christophe Leroy Link: https://lore.kernel.org/r/20200220115141.2707-1-mpe@ellerman.id.au --- arch/powerpc/include/asm/perf_event.h | 2 +- arch/powerpc/include/asm/reg.h | 2 +- arch/powerpc/kernel/irq.c | 4 ++-- arch/powerpc/kernel/misc.S | 4 ++-- arch/powerpc/kernel/process.c | 2 +- arch/powerpc/kernel/stacktrace.c | 6 +++--- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/include/asm/perf_event.h b/arch/powerpc/include/asm/perf_event.h index 7426d7a90e1e..eed3954082fa 100644 --- a/arch/powerpc/include/asm/perf_event.h +++ b/arch/powerpc/include/asm/perf_event.h @@ -32,7 +32,7 @@ do { \ (regs)->result = 0; \ (regs)->nip = __ip; \ - (regs)->gpr[1] = current_stack_pointer(); \ + (regs)->gpr[1] = current_stack_frame(); \ asm volatile("mfmsr %0" : "=r" ((regs)->msr)); \ } while (0) diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 1aa46dff0957..1b1ffdba6097 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -1448,7 +1448,7 @@ static inline void mtsrin(u32 val, u32 idx) #define proc_trap() asm volatile("trap") -extern unsigned long current_stack_pointer(void); +extern unsigned long current_stack_frame(void); extern unsigned long scom970_read(unsigned int address); extern void scom970_write(unsigned int address, unsigned long value); diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 5c9b11878555..02118c18434d 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -602,7 +602,7 @@ static inline void check_stack_overflow(void) #ifdef CONFIG_DEBUG_STACKOVERFLOW long sp; - sp = current_stack_pointer() & (THREAD_SIZE-1); + sp = current_stack_frame() & (THREAD_SIZE-1); /* check for stack overflow: is there less than 2KB free? */ if (unlikely(sp < 2048)) { @@ -647,7 +647,7 @@ void do_IRQ(struct pt_regs *regs) void *cursp, *irqsp, *sirqsp; /* Switch to the irq stack to handle this */ - cursp = (void *)(current_stack_pointer() & ~(THREAD_SIZE - 1)); + cursp = (void *)(current_stack_frame() & ~(THREAD_SIZE - 1)); irqsp = hardirq_ctx[raw_smp_processor_id()]; sirqsp = softirq_ctx[raw_smp_processor_id()]; diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S index 974f65f79a8e..65f9f731c229 100644 --- a/arch/powerpc/kernel/misc.S +++ b/arch/powerpc/kernel/misc.S @@ -110,7 +110,7 @@ _GLOBAL(longjmp) li r3, 1 blr -_GLOBAL(current_stack_pointer) +_GLOBAL(current_stack_frame) PPC_LL r3,0(r1) blr -EXPORT_SYMBOL(current_stack_pointer) +EXPORT_SYMBOL(current_stack_frame) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index e730b8e522b0..110db94cdf3c 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -2051,7 +2051,7 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) sp = (unsigned long) stack; if (sp == 0) { if (tsk == current) - sp = current_stack_pointer(); + sp = current_stack_frame(); else sp = tsk->thread.ksp; } diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c index e2a46cfed5fd..c477b8585a29 100644 --- a/arch/powerpc/kernel/stacktrace.c +++ b/arch/powerpc/kernel/stacktrace.c @@ -57,7 +57,7 @@ void save_stack_trace(struct stack_trace *trace) { unsigned long sp; - sp = current_stack_pointer(); + sp = current_stack_frame(); save_context_stack(trace, sp, current, 1); } @@ -71,7 +71,7 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) return; if (tsk == current) - sp = current_stack_pointer(); + sp = current_stack_frame(); else sp = tsk->thread.ksp; @@ -131,7 +131,7 @@ static int __save_stack_trace_tsk_reliable(struct task_struct *tsk, } if (tsk == current) - sp = current_stack_pointer(); + sp = current_stack_frame(); else sp = tsk->thread.ksp; From 0e63f0151719ee4cb90d85e60c98045099c995e2 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Thu, 20 Feb 2020 22:51:38 +1100 Subject: [PATCH 1128/4444] powerpc: Add current_stack_pointer as a register global current_stack_frame() doesn't return the stack pointer, but the caller's stack frame. See commit bfe9a2cfe91a ("powerpc: Reimplement __get_SP() as a function not a define") and commit acf620ecf56c ("powerpc: Rename __get_SP() to current_stack_pointer()") for details. In some cases this is overkill or incorrect, as it doesn't return the current value of r1. So add a current_stack_pointer register global to get the value of r1 directly. Signed-off-by: Christophe Leroy [mpe: Split out of other patch, tweak change log] Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200220115141.2707-2-mpe@ellerman.id.au --- arch/powerpc/include/asm/reg.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 1b1ffdba6097..da5cab038e25 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -1450,6 +1450,8 @@ static inline void mtsrin(u32 val, u32 idx) extern unsigned long current_stack_frame(void); +register unsigned long current_stack_pointer asm("r1"); + extern unsigned long scom970_read(unsigned int address); extern void scom970_write(unsigned int address, unsigned long value); From 84ab14893054751a2b3adba725834183b872a17f Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Thu, 20 Feb 2020 22:51:39 +1100 Subject: [PATCH 1129/4444] powerpc/irq: Use current_stack_pointer in check_stack_overflow() The purpose of check_stack_overflow() is to verify that the stack has not overflowed. To really know whether the stack pointer is still within boundaries, the check must be done directly on the value of r1. So use current_stack_pointer, which returns the current value of r1, rather than current_stack_frame() which causes a frame to be created and then returns that value. Signed-off-by: Christophe Leroy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200220115141.2707-3-mpe@ellerman.id.au --- arch/powerpc/kernel/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 02118c18434d..c7d6f5cdffdb 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -602,7 +602,7 @@ static inline void check_stack_overflow(void) #ifdef CONFIG_DEBUG_STACKOVERFLOW long sp; - sp = current_stack_frame() & (THREAD_SIZE-1); + sp = current_stack_pointer & (THREAD_SIZE - 1); /* check for stack overflow: is there less than 2KB free? */ if (unlikely(sp < 2048)) { From 0dec6e1cca7eee6d5616f982efab2ff3b3ea1f9f Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Thu, 20 Feb 2020 22:51:40 +1100 Subject: [PATCH 1130/4444] powerpc/irq: use IS_ENABLED() in check_stack_overflow() Instead of #ifdef, use IS_ENABLED(CONFIG_DEBUG_STACKOVERFLOW). This enable GCC to check for code validity even when the option is not selected. Signed-off-by: Christophe Leroy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200220115141.2707-4-mpe@ellerman.id.au --- arch/powerpc/kernel/irq.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index c7d6f5cdffdb..46d5852fb00a 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -599,9 +599,11 @@ u64 arch_irq_stat_cpu(unsigned int cpu) static inline void check_stack_overflow(void) { -#ifdef CONFIG_DEBUG_STACKOVERFLOW long sp; + if (!IS_ENABLED(CONFIG_DEBUG_STACKOVERFLOW)) + return; + sp = current_stack_pointer & (THREAD_SIZE - 1); /* check for stack overflow: is there less than 2KB free? */ @@ -609,7 +611,6 @@ static inline void check_stack_overflow(void) pr_err("do_IRQ: stack overflow: %ld\n", sp); dump_stack(); } -#endif } void __do_irq(struct pt_regs *regs) From 532d43a73cf191cf951d27e49d8d0a03e8cf2297 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Thu, 20 Feb 2020 22:51:41 +1100 Subject: [PATCH 1131/4444] powerpc/irq: Use current_stack_pointer in do_IRQ() Until commit 7306e83ccf5c ("powerpc: Don't use CURRENT_THREAD_INFO to find the stack"), the current stack base address was obtained by calling current_thread_info(). That inline function was simply masking out the value of r1. In that commit, it was changed to using current_stack_pointer() (since renamed current_stack_frame()), which is a heavier function as it is an outline assembly function which cannot be inlined and which reads the content of the stack at 0(r1). Convert to using current_stack_pointer for geting r1 and masking out its value to obtain the base address of the stack pointer as before. Fixes: 7306e83ccf5c ("powerpc: Don't use CURRENT_THREAD_INFO to find the stack") Signed-off-by: Christophe Leroy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200220115141.2707-5-mpe@ellerman.id.au --- arch/powerpc/kernel/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 46d5852fb00a..1bed18b7229e 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -648,7 +648,7 @@ void do_IRQ(struct pt_regs *regs) void *cursp, *irqsp, *sirqsp; /* Switch to the irq stack to handle this */ - cursp = (void *)(current_stack_frame() & ~(THREAD_SIZE - 1)); + cursp = (void *)(current_stack_pointer & ~(THREAD_SIZE - 1)); irqsp = hardirq_ctx[raw_smp_processor_id()]; sirqsp = softirq_ctx[raw_smp_processor_id()]; From a05f0e5be4e81e4977d3f92aaf7688ee0cb7d5db Mon Sep 17 00:00:00 2001 From: Srikar Dronamraju Date: Wed, 29 Jan 2020 19:21:21 +0530 Subject: [PATCH 1132/4444] powerpc/smp: Use nid as fallback for package_id package_id is to match cores that are part of the same chip. On PowerNV machines, package_id defaults to chip_id. However ibm,chip_id property is not present in device-tree of PowerVM LPARs. Hence lscpu output shows one core per socket and multiple cores. To overcome this, use nid as the package_id on PowerVM LPARs. Before the patch: Architecture: ppc64le Byte Order: Little Endian CPU(s): 128 On-line CPU(s) list: 0-127 Thread(s) per core: 8 Core(s) per socket: 1 <---------------------- Socket(s): 16 <---------------------- NUMA node(s): 2 Model: 2.2 (pvr 004e 0202) Model name: POWER9 (architected), altivec supported Hypervisor vendor: pHyp Virtualization type: para L1d cache: 32K L1i cache: 32K L2 cache: 512K L3 cache: 10240K NUMA node0 CPU(s): 0-63 NUMA node1 CPU(s): 64-127 # # cat /sys/devices/system/cpu/cpu0/topology/physical_package_id -1 After the patch: Architecture: ppc64le Byte Order: Little Endian CPU(s): 128 On-line CPU(s) list: 0-127 Thread(s) per core: 8 <--------------------- Core(s) per socket: 8 <--------------------- Socket(s): 2 NUMA node(s): 2 Model: 2.2 (pvr 004e 0202) Model name: POWER9 (architected), altivec supported Hypervisor vendor: pHyp Virtualization type: para L1d cache: 32K L1i cache: 32K L2 cache: 512K L3 cache: 10240K NUMA node0 CPU(s): 0-63 NUMA node1 CPU(s): 64-127 # # cat /sys/devices/system/cpu/cpu0/topology/physical_package_id 0 Now lscpu output is more in line with the system configuration. Signed-off-by: Srikar Dronamraju [mpe: Use pkg_id instead of ppid, tweak change log and comment] Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200129135121.24617-1-srikar@linux.vnet.ibm.com --- arch/powerpc/include/asm/topology.h | 6 ++++++ arch/powerpc/kernel/smp.c | 30 ++++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h index 2f7e1ea5089e..e2e1ccd4a18d 100644 --- a/arch/powerpc/include/asm/topology.h +++ b/arch/powerpc/include/asm/topology.h @@ -134,7 +134,13 @@ static inline void shared_proc_topology_init(void) {} #ifdef CONFIG_PPC64 #include +#ifdef CONFIG_PPC_SPLPAR +int get_physical_package_id(int cpu); +#define topology_physical_package_id(cpu) (get_physical_package_id(cpu)) +#else #define topology_physical_package_id(cpu) (cpu_to_chip_id(cpu)) +#endif + #define topology_sibling_cpumask(cpu) (per_cpu(cpu_sibling_map, cpu)) #define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu)) #define topology_core_id(cpu) (cpu_to_core_id(cpu)) diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index ea6adbf6a221..f68cde82bdf3 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -1185,10 +1185,34 @@ static inline void add_cpu_to_smallcore_masks(int cpu) } } +int get_physical_package_id(int cpu) +{ + int pkg_id = cpu_to_chip_id(cpu); + +#ifdef CONFIG_PPC_SPLPAR + /* + * If the platform is PowerNV or Guest on KVM, ibm,chip-id is + * defined. Hence we would return the chip-id as the result of + * get_physical_package_id. + */ + if (pkg_id == -1 && firmware_has_feature(FW_FEATURE_LPAR)) { + struct device_node *np = of_get_cpu_node(cpu, NULL); + + if (np) { + pkg_id = of_node_to_nid(np); + of_node_put(np); + } + } +#endif /* CONFIG_PPC_SPLPAR */ + + return pkg_id; +} +EXPORT_SYMBOL_GPL(get_physical_package_id); + static void add_cpu_to_masks(int cpu) { int first_thread = cpu_first_thread_sibling(cpu); - int chipid = cpu_to_chip_id(cpu); + int pkg_id = get_physical_package_id(cpu); int i; /* @@ -1217,11 +1241,11 @@ static void add_cpu_to_masks(int cpu) for_each_cpu(i, cpu_l2_cache_mask(cpu)) set_cpus_related(cpu, i, cpu_core_mask); - if (chipid == -1) + if (pkg_id == -1) return; for_each_cpu(i, cpu_online_mask) - if (cpu_to_chip_id(i) == chipid) + if (get_physical_package_id(i) == pkg_id) set_cpus_related(cpu, i, cpu_core_mask); } From e7214ae9d85aa325c9f3cb34bf4fad7f112861d7 Mon Sep 17 00:00:00 2001 From: Srikar Dronamraju Date: Wed, 29 Jan 2020 19:22:57 +0530 Subject: [PATCH 1133/4444] powerpc/vphn: Check for error from hcall_vphn There is no value in unpacking associativity, if H_HOME_NODE_ASSOCIATIVITY hcall has returned an error. Signed-off-by: Srikar Dronamraju Reported-by: Abdul Haleem Reviewed-by: Nathan Lynch Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200129135301.24739-2-srikar@linux.vnet.ibm.com --- arch/powerpc/platforms/pseries/vphn.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/pseries/vphn.c b/arch/powerpc/platforms/pseries/vphn.c index 3f07bf6c670e..cca474a2c396 100644 --- a/arch/powerpc/platforms/pseries/vphn.c +++ b/arch/powerpc/platforms/pseries/vphn.c @@ -82,7 +82,8 @@ long hcall_vphn(unsigned long cpu, u64 flags, __be32 *associativity) long retbuf[PLPAR_HCALL9_BUFSIZE] = {0}; rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, retbuf, flags, cpu); - vphn_unpack_associativity(retbuf, associativity); + if (rc == H_SUCCESS) + vphn_unpack_associativity(retbuf, associativity); return rc; } From 76b7bfb1732d139dc20a2f0c19ec32e09c8891cf Mon Sep 17 00:00:00 2001 From: Srikar Dronamraju Date: Wed, 29 Jan 2020 19:22:58 +0530 Subject: [PATCH 1134/4444] powerpc/numa: Handle extra hcall_vphn error cases Currently code handles H_FUNCTION, H_SUCCESS, H_HARDWARE return codes. However hcall_vphn can return other return codes. Now it also handles H_PARAMETER return code. Also the rest return codes are handled under the default case. Signed-off-by: Srikar Dronamraju Reported-by: Abdul Haleem Reviewed-by: Nathan Lynch Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200129135301.24739-3-srikar@linux.vnet.ibm.com --- arch/powerpc/mm/numa.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 3c7dec70cda0..2cb87c9a0544 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -1191,23 +1191,30 @@ static long vphn_get_associativity(unsigned long cpu, VPHN_FLAG_VCPU, associativity); switch (rc) { - case H_FUNCTION: - printk_once(KERN_INFO - "VPHN is not supported. Disabling polling...\n"); - stop_topology_update(); - break; - case H_HARDWARE: - printk(KERN_ERR - "hcall_vphn() experienced a hardware fault " - "preventing VPHN. Disabling polling...\n"); - stop_topology_update(); - break; case H_SUCCESS: dbg("VPHN hcall succeeded. Reset polling...\n"); timed_topology_update(0); + goto out; + + case H_FUNCTION: + pr_err_ratelimited("VPHN unsupported. Disabling polling...\n"); + break; + case H_HARDWARE: + pr_err_ratelimited("hcall_vphn() experienced a hardware fault " + "preventing VPHN. Disabling polling...\n"); + break; + case H_PARAMETER: + pr_err_ratelimited("hcall_vphn() was passed an invalid parameter. " + "Disabling polling...\n"); + break; + default: + pr_err_ratelimited("hcall_vphn() returned %ld. Disabling polling...\n" + , rc); break; } + stop_topology_update(); +out: return rc; } From 413e40550c5cfdba7e062aa6350a0d2448014519 Mon Sep 17 00:00:00 2001 From: Srikar Dronamraju Date: Wed, 29 Jan 2020 19:22:59 +0530 Subject: [PATCH 1135/4444] powerpc/numa: Use cpu node map of first sibling thread All the sibling threads of a core have to be part of the same node. To ensure that all the sibling threads map to the same node, always lookup/update the cpu-to-node map of the first thread in the core. Signed-off-by: Srikar Dronamraju Reported-by: Abdul Haleem Reviewed-by: Nathan Lynch Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200129135301.24739-4-srikar@linux.vnet.ibm.com --- arch/powerpc/mm/numa.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 2cb87c9a0544..518c6dbbccbe 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -467,15 +467,20 @@ static int of_drconf_to_nid_single(struct drmem_lmb *lmb) */ static int numa_setup_cpu(unsigned long lcpu) { - int nid = NUMA_NO_NODE; struct device_node *cpu; + int fcpu = cpu_first_thread_sibling(lcpu); + int nid = NUMA_NO_NODE; /* * If a valid cpu-to-node mapping is already available, use it * directly instead of querying the firmware, since it represents * the most recent mapping notified to us by the platform (eg: VPHN). + * Since cpu_to_node binding remains the same for all threads in the + * core. If a valid cpu-to-node mapping is already available, for + * the first thread in the core, use it. */ - if ((nid = numa_cpu_lookup_table[lcpu]) >= 0) { + nid = numa_cpu_lookup_table[fcpu]; + if (nid >= 0) { map_cpu_to_node(lcpu, nid); return nid; } @@ -496,6 +501,19 @@ out_present: if (nid < 0 || !node_possible(nid)) nid = first_online_node; + /* + * Update for the first thread of the core. All threads of a core + * have to be part of the same node. This not only avoids querying + * for every other thread in the core, but always avoids a case + * where virtual node associativity change causes subsequent threads + * of a core to be associated with different nid. However if first + * thread is already online, expect it to have a valid mapping. + */ + if (fcpu != lcpu) { + WARN_ON(cpu_online(fcpu)); + map_cpu_to_node(fcpu, nid); + } + map_cpu_to_node(lcpu, nid); of_node_put(cpu); out: From dc909d8b0c9c0d2c42dc1cf34216c4830f639f7b Mon Sep 17 00:00:00 2001 From: Srikar Dronamraju Date: Wed, 29 Jan 2020 19:23:00 +0530 Subject: [PATCH 1136/4444] powerpc/numa: Early request for home node associativity Currently the kernel detects if its running on a shared lpar platform and requests home node associativity before the scheduler sched_domains are setup. However between the time NUMA setup is initialized and the request for home node associativity, workqueue initializes its per node cpumask. The per node workqueue possible cpumask may turn invalid after home node associativity resulting in weird situations like workqueue possible cpumask being a subset of workqueue online cpumask. This can be fixed by requesting home node associativity earlier just before NUMA setup. However at the NUMA setup time, kernel may not be in a position to detect if its running on a shared lpar platform. So request for home node associativity and if the request fails, fallback on the device tree property. Signed-off-by: Srikar Dronamraju Reported-by: Abdul Haleem Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200129135301.24739-5-srikar@linux.vnet.ibm.com --- arch/powerpc/mm/numa.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 518c6dbbccbe..5a8abf0165d7 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -461,6 +461,41 @@ static int of_drconf_to_nid_single(struct drmem_lmb *lmb) return nid; } +#ifdef CONFIG_PPC_SPLPAR +static int vphn_get_nid(long lcpu) +{ + __be32 associativity[VPHN_ASSOC_BUFSIZE] = {0}; + long rc, hwid; + + /* + * On a shared lpar, device tree will not have node associativity. + * At this time lppaca, or its __old_status field may not be + * updated. Hence kernel cannot detect if its on a shared lpar. So + * request an explicit associativity irrespective of whether the + * lpar is shared or dedicated. Use the device tree property as a + * fallback. cpu_to_phys_id is only valid between + * smp_setup_cpu_maps() and smp_setup_pacas(). + */ + if (firmware_has_feature(FW_FEATURE_VPHN)) { + if (cpu_to_phys_id) + hwid = cpu_to_phys_id[lcpu]; + else + hwid = get_hard_smp_processor_id(lcpu); + + rc = hcall_vphn(hwid, VPHN_FLAG_VCPU, associativity); + if (rc == H_SUCCESS) + return associativity_to_nid(associativity); + } + + return NUMA_NO_NODE; +} +#else +static int vphn_get_nid(long unused) +{ + return NUMA_NO_NODE; +} +#endif /* CONFIG_PPC_SPLPAR */ + /* * Figure out to which domain a cpu belongs and stick it there. * Return the id of the domain used. @@ -485,6 +520,10 @@ static int numa_setup_cpu(unsigned long lcpu) return nid; } + nid = vphn_get_nid(lcpu); + if (nid != NUMA_NO_NODE) + goto out_present; + cpu = of_get_cpu_node(lcpu, NULL); if (!cpu) { @@ -496,6 +535,7 @@ static int numa_setup_cpu(unsigned long lcpu) } nid = of_node_to_nid_single(cpu); + of_node_put(cpu); out_present: if (nid < 0 || !node_possible(nid)) @@ -515,7 +555,6 @@ out_present: } map_cpu_to_node(lcpu, nid); - of_node_put(cpu); out: return nid; } From 247257b03b04398ca07da4bce3d17bee25d623cb Mon Sep 17 00:00:00 2001 From: Srikar Dronamraju Date: Wed, 29 Jan 2020 19:23:01 +0530 Subject: [PATCH 1137/4444] powerpc/numa: Remove late request for home node associativity With commit ("powerpc/numa: Early request for home node associativity"), commit 2ea626306810 ("powerpc/topology: Get topology for shared processors at boot") which was requesting home node associativity becomes redundant. Hence remove the late request for home node associativity. Signed-off-by: Srikar Dronamraju Reported-by: Abdul Haleem Reviewed-by: Nathan Lynch Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200129135301.24739-6-srikar@linux.vnet.ibm.com --- arch/powerpc/include/asm/topology.h | 4 ---- arch/powerpc/kernel/smp.c | 5 ----- arch/powerpc/mm/numa.c | 9 --------- 3 files changed, 18 deletions(-) diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h index e2e1ccd4a18d..2db7ba789720 100644 --- a/arch/powerpc/include/asm/topology.h +++ b/arch/powerpc/include/asm/topology.h @@ -98,7 +98,6 @@ extern int stop_topology_update(void); extern int prrn_is_enabled(void); extern int find_and_online_cpu_nid(int cpu); extern int timed_topology_update(int nsecs); -extern void __init shared_proc_topology_init(void); #else static inline int start_topology_update(void) { @@ -121,9 +120,6 @@ static inline int timed_topology_update(int nsecs) return 0; } -#ifdef CONFIG_SMP -static inline void shared_proc_topology_init(void) {} -#endif #endif /* CONFIG_NUMA && CONFIG_PPC_SPLPAR */ #include diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index f68cde82bdf3..37c12e3bab9e 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -1383,11 +1383,6 @@ void __init smp_cpus_done(unsigned int max_cpus) if (smp_ops && smp_ops->bringup_done) smp_ops->bringup_done(); - /* - * On a shared LPAR, associativity needs to be requested. - * Hence, get numa topology before dumping cpu topology - */ - shared_proc_topology_init(); dump_numa_cpu_topology(); #ifdef CONFIG_SCHED_SMT diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 5a8abf0165d7..9fcf2d195830 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -1632,15 +1632,6 @@ int prrn_is_enabled(void) return prrn_enabled; } -void __init shared_proc_topology_init(void) -{ - if (lppaca_shared_proc(get_lppaca())) { - bitmap_fill(cpumask_bits(&cpu_associativity_changes_mask), - nr_cpumask_bits); - numa_update_cpu_topology(false); - } -} - static int topology_read(struct seq_file *file, void *v) { if (vphn_enabled || prrn_enabled) From 14beaccc36dc9c1afbe6da627b873bf1d6849234 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 4 Mar 2020 16:40:57 +0800 Subject: [PATCH 1138/4444] ASoc: amd: acp3x: Add missing include gcc 7.4.0 build fails: In file included from sound/soc/amd/acp3x-rt5682-max9836.c:20:0: sound/soc/amd/raven/acp3x.h: In function rv_readl: sound/soc/amd/raven/acp3x.h:113:9: error: implicit declaration of function readl; did you mean rv_readl? [-Werror=implicit-function-declaration] return readl(base_addr - ACP3x_PHY_BASE_ADDRESS); ^~~~~ rv_readl sound/soc/amd/raven/acp3x.h: In function rv_writel: sound/soc/amd/raven/acp3x.h:118:2: error: implicit declaration of function writel; did you mean rv_writel? [-Werror=implicit-function-declaration] writel(val, base_addr - ACP3x_PHY_BASE_ADDRESS); ^~~~~~ rv_writel Add to fix this. Fixes: 6b8e4e7db3cd ("ASoC: amd: Add machine driver for Raven based platform") Reported-by: Hulk Robot Signed-off-by: YueHaibing Message-Id: <20200304084057.44764-1-yuehaibing@huawei.com> Signed-off-by: Mark Brown --- sound/soc/amd/acp3x-rt5682-max9836.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c index 521c9ab4c29c..8f71c3f7ef79 100644 --- a/sound/soc/amd/acp3x-rt5682-max9836.c +++ b/sound/soc/amd/acp3x-rt5682-max9836.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "raven/acp3x.h" From 40d39c1a7cacd8db29f298f14e4e0617e8ca65bd Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 20 Sep 2019 10:36:22 -0500 Subject: [PATCH 1139/4444] ARM: dts: integratorap: Remove top level dma-ranges 'dma-ranges' at the top level doesn't make sense. 'dma-ranges' implies there is a parent bus node with '#address-cells' and '#size-cells' which is impossible here. Likely this translation needs to be moved down to sub-nodes that need it. Cc: Linus Walleij Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Rob Herring Signed-off-by: Linus Walleij --- arch/arm/boot/dts/integratorap.dts | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/integratorap.dts b/arch/arm/boot/dts/integratorap.dts index 94d2ff9836d0..198d66181c50 100644 --- a/arch/arm/boot/dts/integratorap.dts +++ b/arch/arm/boot/dts/integratorap.dts @@ -9,7 +9,6 @@ / { model = "ARM Integrator/AP"; compatible = "arm,integrator-ap"; - dma-ranges = <0x80000000 0x0 0x80000000>; cpus { #address-cells = <1>; From 53a5927b6514328a0109a0f6a4b5bde55918480b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 6 Feb 2020 16:33:43 +0100 Subject: [PATCH 1140/4444] ARM: dts: Versatile: Use syscon as node name for IB2 The IB2 syscon should not have any funny names, just call it syscon@ as per the convention so the schema will apply properly. Signed-off-by: Linus Walleij --- arch/arm/boot/dts/versatile-ab-ib2.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/versatile-ab-ib2.dts b/arch/arm/boot/dts/versatile-ab-ib2.dts index 5890cb974f78..c577ff4bb4be 100644 --- a/arch/arm/boot/dts/versatile-ab-ib2.dts +++ b/arch/arm/boot/dts/versatile-ab-ib2.dts @@ -10,7 +10,7 @@ model = "ARM Versatile AB + IB2 board"; /* Special IB2 control register */ - ib2_syscon@27000000 { + syscon@27000000 { compatible = "arm,versatile-ib2-syscon", "syscon", "simple-mfd"; reg = <0x27000000 0x4>; From b92d5a7d71ab7436d52a5b964181968f2c5a47a9 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 6 Feb 2020 22:04:29 +0100 Subject: [PATCH 1141/4444] ARM: dts: RealView: Fix the name of the SoC node Drop the surplus @0 on the soc node making the devicetree conform strictly to the schema. Signed-off-by: Linus Walleij --- arch/arm/boot/dts/arm-realview-pbx.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/arm-realview-pbx.dtsi b/arch/arm/boot/dts/arm-realview-pbx.dtsi index 09f3f544f3a7..f61bd59ae5ba 100644 --- a/arch/arm/boot/dts/arm-realview-pbx.dtsi +++ b/arch/arm/boot/dts/arm-realview-pbx.dtsi @@ -210,7 +210,7 @@ }; }; - soc: soc@0 { + soc: soc { compatible = "arm,realview-pbx-soc", "simple-bus"; #address-cells = <1>; #size-cells = <1>; From 33fbfb3eaf4eff553bcf82b2c2821324293f577a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 6 Feb 2020 16:02:43 +0100 Subject: [PATCH 1142/4444] dt-bindings: arm: Add Integrator YAML schema This implements the top-level schema for the ARM Integrator platforms. Cc: Sudeep Holla Reviewed-by: Rob Herring Signed-off-by: Linus Walleij --- .../bindings/arm/arm,integrator.yaml | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/arm,integrator.yaml diff --git a/Documentation/devicetree/bindings/arm/arm,integrator.yaml b/Documentation/devicetree/bindings/arm/arm,integrator.yaml new file mode 100644 index 000000000000..192ded470e32 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/arm,integrator.yaml @@ -0,0 +1,86 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/arm,integrator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ARM Integrator Boards Device Tree Bindings + +maintainers: + - Linus Walleij + +description: |+ + These were the first ARM platforms officially supported by ARM Ltd. + They are ARMv4, ARMv5 and ARMv6-capable using different core tiles, + so the system is modular and can host a variety of CPU tiles called + "core tiles" and referred to in the device tree as "core modules". + +properties: + $nodename: + const: '/' + compatible: + oneOf: + - description: ARM Integrator Application Platform, this board has a PCI + host and several PCI slots, as well as a number of slots for logical + expansion modules, it is referred to as an "ASIC Development + Motherboard" and is extended with custom FPGA and is intended for + rapid prototyping. See ARM DUI 0098B. This board can physically come + pre-packaged in a PC Tower form factor called Integrator/PP1 or a + special metal fixture called Integrator/PP2, see ARM DUI 0169A. + items: + - const: arm,integrator-ap + - description: ARM Integrator Compact Platform (HBI-0086), this board has + a compact form factor and mainly consists of the bare minimum + peripherals to make use of the core module. See ARM DUI 0159B. + items: + - const: arm,integrator-cp + - description: ARM Integrator Standard Development Board (SDB) Platform, + this board is a PCI-based board conforming to the Microsoft SDB + (HARP) specification. See ARM DUI 0099A. + items: + - const: arm,integrator-sp + + core-module@10000000: + type: object + description: the root node in the Integrator platforms must contain + a core module child node. They are always at physical address + 0x10000000 in all the Integrator variants. + properties: + compatible: + items: + - const: arm,core-module-integrator + - const: syscon + - const: simple-mfd + reg: + maxItems: 1 + + required: + - compatible + - reg + +patternProperties: + "^syscon@[0-9a-f]+$": + description: All Integrator boards must provide a system controller as a + node in the root of the device tree. + type: object + properties: + compatible: + items: + - enum: + - arm,integrator-ap-syscon + - arm,integrator-cp-syscon + - arm,integrator-sp-syscon + - const: syscon + reg: + maxItems: 1 + + required: + - compatible + - reg + + +required: + - compatible + - core-module@10000000 + +... From 4b900070d50d3ba167a169f7699cde3ef9c3f067 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 6 Feb 2020 16:36:25 +0100 Subject: [PATCH 1143/4444] dt-bindings: arm: Add Versatile YAML schema This implements the top-level schema for the ARM Versatile platforms. Cc: Sudeep Holla Reviewed-by: Rob Herring Signed-off-by: Linus Walleij --- .../bindings/arm/arm,versatile.yaml | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/arm,versatile.yaml diff --git a/Documentation/devicetree/bindings/arm/arm,versatile.yaml b/Documentation/devicetree/bindings/arm/arm,versatile.yaml new file mode 100644 index 000000000000..06efd2a075c9 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/arm,versatile.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/arm,versatile.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ARM Versatile Boards Device Tree Bindings + +maintainers: + - Linus Walleij + +description: |+ + The ARM Versatile boards are two variants of ARM926EJ-S evaluation boards + with various pluggable interface boards, in essence the Versatile PB version + is a superset of the Versatile AB version. + +properties: + $nodename: + const: '/' + compatible: + oneOf: + - description: The ARM Versatile Application Baseboard (HBI-0118) is an + evaluation board specifically for the ARM926EJ-S. It can be connected + to an IB1 interface board for a touchscreen-type use case or an IB2 + for a candybar phone-type use case. See ARM DUI 0225D. + items: + - const: arm,versatile-ab + - description: The ARM Versatile Platform Baseboard (HBI-0117) is an + extension of the Versatile Application Baseboard that includes a + PCI host controller. Like the sibling board, it is done specifically + for ARM926EJ-S. See ARM DUI 0224B. + items: + - const: arm,versatile-pb + + core-module@10000000: + type: object + description: the root node in the Versatile platforms must contain + a core module child node. They are always at physical address + 0x10000000 in all the Versatile variants. + properties: + compatible: + items: + - const: arm,core-module-versatile + - const: syscon + - const: simple-mfd + reg: + maxItems: 1 + + required: + - compatible + - reg + +patternProperties: + "^syscon@[0-9a-f]+$": + type: object + description: When fitted with the IB2 Interface Board, the Versatile + AB will present an optional system controller node which controls the + extra peripherals on the interface board. + properties: + compatible: + contains: + const: arm,versatile-ib2-syscon + required: + - compatible + - reg + +required: + - compatible + - core-module@10000000 + +... From 7db625b9fa758f6b00c5b63ad16f8b2caaa8d1b7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 6 Feb 2020 22:03:11 +0100 Subject: [PATCH 1144/4444] dt-bindings: arm: Add RealView YAML schema This implements the top-level schema for the ARM RealView platforms. Cc: Sudeep Holla Reviewed-by: Rob Herring Signed-off-by: Linus Walleij --- .../devicetree/bindings/arm/arm,realview.yaml | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/arm,realview.yaml diff --git a/Documentation/devicetree/bindings/arm/arm,realview.yaml b/Documentation/devicetree/bindings/arm/arm,realview.yaml new file mode 100644 index 000000000000..d6e85d198afe --- /dev/null +++ b/Documentation/devicetree/bindings/arm/arm,realview.yaml @@ -0,0 +1,123 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/arm,realview.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ARM RealView Boards Device Tree Bindings + +maintainers: + - Linus Walleij + +description: |+ + The ARM RealView series of reference designs were built to explore the ARM + 11, Cortex A-8 and Cortex A-9 CPUs. This included new features compared to + the earlier CPUs such as TrustZone and multicore (MPCore). + +properties: + $nodename: + const: '/' + compatible: + oneOf: + - description: ARM RealView Emulation Baseboard (HBI-0140) was created + as a generic platform to test different FPGA designs, and has + pluggable CPU modules, see ARM DUI 0303E. + items: + - const: arm,realview-eb + - description: ARM RealView Platform Baseboard for ARM1176JZF-S + (HBI-0147) was created as a development board to test ARM TrustZone, + CoreSight and Intelligent Energy Management (IEM) see ARM DUI 0425F. + items: + - const: arm,realview-pb1176 + - description: ARM RealView Platform Baseboard for ARM 11 MPCore + (HBI-0159, HBI-0175 and HBI-0176) was created to showcase + multiprocessing with ARM11 using MPCore using symmetric + multiprocessing (SMP). See ARM DUI 0351E. + items: + - const: arm,realview-pb11mp + - description: ARM RealView Platform Baseboard for Cortex-A8 (HBI-0178, + HBI-0176 and HBI-0175) was the first reference platform for the + Cortex CPU family, including a Cortex-A8 test chip. + items: + - const: arm,realview-pba8 + - description: ARM RealView Platform Baseboard Explore for Cortex-A9 + (HBI-0182 and HBI-0183) was the reference platform for the Cortex-A9 + CPU. + items: + - const: arm,realview-pbx + + soc: + description: All RealView boards must provide a soc node in the root of the + device tree, representing the System-on-Chip since these test chips are + rather complex. + type: object + properties: + compatible: + oneOf: + - items: + - const: arm,realview-eb-soc + - const: simple-bus + - items: + - const: arm,realview-pb1176-soc + - const: simple-bus + - items: + - const: arm,realview-pb11mp-soc + - const: simple-bus + - items: + - const: arm,realview-pba8-soc + - const: simple-bus + - items: + - const: arm,realview-pbx-soc + - const: simple-bus + + patternProperties: + "^.*syscon@[0-9a-f]+$": + type: object + description: All RealView boards must provide a syscon system controller + node inside the soc node. + properties: + compatible: + oneOf: + - items: + - const: arm,realview-eb11mp-revb-syscon + - const: arm,realview-eb-syscon + - const: syscon + - const: simple-mfd + - items: + - const: arm,realview-eb11mp-revc-syscon + - const: arm,realview-eb-syscon + - const: syscon + - const: simple-mfd + - items: + - const: arm,realview-eb-syscon + - const: syscon + - const: simple-mfd + - items: + - const: arm,realview-pb1176-syscon + - const: syscon + - const: simple-mfd + - items: + - const: arm,realview-pb11mp-syscon + - const: syscon + - const: simple-mfd + - items: + - const: arm,realview-pba8-syscon + - const: syscon + - const: simple-mfd + - items: + - const: arm,realview-pbx-syscon + - const: syscon + - const: simple-mfd + + required: + - compatible + - reg + + required: + - compatible + +required: + - compatible + - soc + +... From 4fb00d9066c13a3cb755d9b05e8de007024ed1a4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 10 Feb 2020 10:17:09 +0100 Subject: [PATCH 1145/4444] dt-bindings: arm: Add Versatile Express and Juno YAML schema This implements the top-level schema for the ARM Versatile Express and Juno platforms. Acked-by: Sudeep Holla Reviewed-by: Rob Herring Signed-off-by: Linus Walleij --- .../bindings/arm/arm,vexpress-juno.yaml | 223 ++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml diff --git a/Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml b/Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml new file mode 100644 index 000000000000..8c06a73f716c --- /dev/null +++ b/Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml @@ -0,0 +1,223 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/arm,vexpress-juno.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ARM Versatile Express and Juno Boards Device Tree Bindings + +maintainers: + - Sudeep Holla + - Linus Walleij + +description: |+ + ARM's Versatile Express platform were built as reference designs for exploring + multicore Cortex-A class systems. The Versatile Express family contains both + 32 bit (Aarch32) and 64 bit (Aarch64) systems. + + The board consist of a motherboard and one or more daughterboards (tiles). The + motherboard provides a set of peripherals. Processor and RAM "live" on the + tiles. + + The motherboard and each core tile should be described by a separate Device + Tree source file, with the tile's description including the motherboard file + using an include directive. As the motherboard can be initialized in one of + two different configurations ("memory maps"), care must be taken to include + the correct one. + + When a new generation of boards were introduced under the name "Juno", these + shared to many common characteristics with the Versatile Express that the + "arm,vexpress" compatible was retained in the root node, and these are + included in this binding schema as well. + + The root node indicates the CPU SoC on the core tile, and this + is a daughterboard to the main motherboard. The name used in the compatible + string shall match the name given in the core tile's technical reference + manual, followed by "arm,vexpress" as an additional compatible value. If + further subvariants are released of the core tile, even more fine-granular + compatible strings with up to three compatible strings are used. + +properties: + $nodename: + const: '/' + compatible: + oneOf: + - description: CoreTile Express A9x4 (V2P-CA9) has 4 Cortex A9 CPU cores + in MPCore configuration in a test chip on the core tile. See ARM + DUI 0448I. This was the first Versatile Express platform. + items: + - const: arm,vexpress,v2p-ca9 + - const: arm,vexpress + - description: CoreTile Express A5x2 (V2P-CA5s) has 2 Cortex A5 CPU cores + in a test chip on the core tile. It is intended to evaluate NEON, FPU + and Jazelle support in the Cortex A5 family. See ARM DUI 0541C. + items: + - const: arm,vexpress,v2p-ca5s + - const: arm,vexpress + - description: Coretile Express A15x2 (V2P-CA15) has 2 Cortex A15 CPU + cores in a MPCore configuration in a test chip on the core tile. See + ARM DUI 0604F. + items: + - const: arm,vexpress,v2p-ca15 + - const: arm,vexpress + - description: CoreTile Express A15x4 (V2P-CA15, HBI-0237A) has 4 Cortex + A15 CPU cores in a test chip on the core tile. This is the first test + chip called "TC1". + items: + - const: arm,vexpress,v2p-ca15,tc1 + - const: arm,vexpress,v2p-ca15 + - const: arm,vexpress + - description: Coretile Express A15x2 A7x3 (V2P-CA15_A7) has 2 Cortex A15 + CPU cores and 3 Cortex A7 cores in a big.LITTLE MPCore configuration + in a test chip on the core tile. See ARM DDI 0503I. + items: + - const: arm,vexpress,v2p-ca15_a7 + - const: arm,vexpress + - description: LogicTile Express 20MG (V2F-1XV7) has 2 Cortex A53 CPU + cores in a test chip on the core tile. See ARM DDI 0498D. + items: + - const: arm,vexpress,v2f-1xv7,ca53x2 + - const: arm,vexpress,v2f-1xv7 + - const: arm,vexpress + - description: Arm Versatile Express Juno "r0" (the first Juno board, + V2M-Juno) was introduced as a vehicle for evaluating big.LITTLE on + AArch64 CPU cores. It has 2 Cortex A57 CPU cores and 4 Cortex A53 + cores in a big.LITTLE configuration. It also features the MALI T624 + GPU. See ARM document 100113_0000_07_en. + items: + - const: arm,juno + - const: arm,vexpress + - description: Arm Versatile Express Juno r1 Development Platform + (V2M-Juno r1) was introduced mainly aimed at development of PCIe + based systems. Juno r1 also has support for AXI masters placed on + the TLX connectors to join the coherency domain. Otherwise it is the + same configuration as Juno r0. See ARM document 100122_0100_06_en. + items: + - const: arm,juno-r1 + - const: arm,juno + - const: arm,vexpress + - description: Arm Versatile Express Juno r2 Development Platform + (V2M-Juno r2). It has the same feature set as Juno r0 and r1. See + ARM document 100114_0200_04_en. + items: + - const: arm,juno-r2 + - const: arm,juno + - const: arm,vexpress + - description: Arm AEMv8a Versatile Express Real-Time System Model + (VE RTSM) is a programmers view of the Versatile Express with Arm + v8A hardware. See ARM DUI 0575D. + items: + - const: arm,rtsm_ve,aemv8a + - const: arm,vexpress + - description: Arm FVP (Fixed Virtual Platform) base model revision C + See ARM Document 100964_1190_00_en. + items: + - const: arm,fvp-base-revc + - const: arm,vexpress + - description: Arm Foundation model for Aarch64 + items: + - const: arm,foundation-aarch64 + - const: arm,vexpress + + arm,hbi: + $ref: '/schemas/types.yaml#/definitions/uint32' + description: This indicates the ARM HBI (Hardware Board ID), this is + ARM's unique board model ID, visible on the PCB's silkscreen. + + arm,vexpress,site: + description: As Versatile Express can be configured in number of physically + different setups, the device tree should describe platform topology. + For this reason the root node and main motherboard node must define this + property, describing the physical location of the children nodes. + 0 means motherboard site, while 1 and 2 are daughterboard sites, and + 0xf means "sisterboard" which is the site containing the main CPU tile. + allOf: + - $ref: '/schemas/types.yaml#/definitions/uint32' + - minimum: 0 + maximum: 15 + + arm,vexpress,position: + description: When daughterboards are stacked on one site, their position + in the stack be be described this attribute. + allOf: + - $ref: '/schemas/types.yaml#/definitions/uint32' + - minimum: 0 + maximum: 3 + + arm,vexpress,dcc: + description: When describing tiles consisting of more than one DCC, its + number can be specified with this attribute. + allOf: + - $ref: '/schemas/types.yaml#/definitions/uint32' + - minimum: 0 + maximum: 3 + +patternProperties: + "^bus@[0-9a-f]+$": + description: Static Memory Bus (SMB) node, if this exists it describes + the connection between the motherboard and any tiles. Sometimes the + compatible is placed directly under this node, sometimes it is placed + in a subnode named "motherboard". Sometimes the compatible includes + "arm,vexpress,v2?-p1" sometimes (on software models) is is just + "simple-bus". If the compatible is placed in the "motherboard" node, + it is stricter and always has two compatibles. + type: object + allOf: + - $ref: '/schemas/simple-bus.yaml' + + properties: + compatible: + oneOf: + - items: + - enum: + - arm,vexpress,v2m-p1 + - arm,vexpress,v2p-p1 + - const: simple-bus + - const: simple-bus + motherboard: + type: object + description: The motherboard description provides a single "motherboard" + node using 2 address cells corresponding to the Static Memory Bus + used between the motherboard and the tile. The first cell defines the + Chip Select (CS) line number, the second cell address offset within + the CS. All interrupt lines between the motherboard and the tile + are active high and are described using single cell. + properties: + "#address-cells": + const: 2 + "#size-cells": + const: 1 + compatible: + items: + - enum: + - arm,vexpress,v2m-p1 + - arm,vexpress,v2p-p1 + - const: simple-bus + arm,v2m-memory-map: + description: This describes the memory map type. + allOf: + - $ref: '/schemas/types.yaml#/definitions/string' + - enum: + - rs1 + - rs2 + required: + - compatible + required: + - compatible + +allOf: + - if: + properties: + compatible: + contains: + enum: + - arm,vexpress,v2p-ca9 + - arm,vexpress,v2p-ca5s + - arm,vexpress,v2p-ca15 + - arm,vexpress,v2p-ca15_a7 + - arm,vexpress,v2f-1xv7,ca53x2 + then: + required: + - arm,hbi + +... From 2d483550b6d21de8af60e67e728fa118a537b07d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 10 Feb 2020 10:21:31 +0100 Subject: [PATCH 1146/4444] dt-bindings: arm: Drop the non-YAML bindings We created new bindings for the ARM Board using YAML so delete the old human-parseable-only bindings. Cc: Sudeep Holla Reviewed-by: Rob Herring Signed-off-by: Linus Walleij --- .../devicetree/bindings/arm/arm-boards | 237 ------------------ .../devicetree/bindings/arm/vexpress.txt | 229 ----------------- 2 files changed, 466 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/arm-boards delete mode 100644 Documentation/devicetree/bindings/arm/vexpress.txt diff --git a/Documentation/devicetree/bindings/arm/arm-boards b/Documentation/devicetree/bindings/arm/arm-boards deleted file mode 100644 index 96b1dad58253..000000000000 --- a/Documentation/devicetree/bindings/arm/arm-boards +++ /dev/null @@ -1,237 +0,0 @@ -ARM Integrator/AP (Application Platform) and Integrator/CP (Compact Platform) ------------------------------------------------------------------------------ -ARM's oldest Linux-supported platform with connectors for different core -tiles of ARMv4, ARMv5 and ARMv6 type. - -Required properties (in root node): - compatible = "arm,integrator-ap"; /* Application Platform */ - compatible = "arm,integrator-cp"; /* Compact Platform */ - -FPGA type interrupt controllers, see the versatile-fpga-irq binding doc. - -Required nodes: - -- core-module: the root node to the Integrator platforms must have - a core-module with regs and the compatible string - "arm,core-module-integrator" -- external-bus-interface: the root node to the Integrator platforms - must have an external bus interface with regs and the - compatible-string "arm,external-bus-interface" - - Required properties for the core module: - - regs: the location and size of the core module registers, one - range of 0x200 bytes. - -- syscon: the root node of the Integrator platforms must have a - system controller node pointing to the control registers, - with the compatible string - "arm,integrator-ap-syscon" - "arm,integrator-cp-syscon" - respectively. - - Required properties for the system controller: - - regs: the location and size of the system controller registers, - one range of 0x100 bytes. - - Required properties for the AP system controller: - - interrupts: the AP syscon node must include the logical module - interrupts, stated in order of module instance , - , ... for the CP system controller this - is not required not of any use. - -/dts-v1/; -/include/ "integrator.dtsi" - -/ { - model = "ARM Integrator/AP"; - compatible = "arm,integrator-ap"; - - core-module@10000000 { - compatible = "arm,core-module-integrator"; - reg = <0x10000000 0x200>; - }; - - ebi@12000000 { - compatible = "arm,external-bus-interface"; - reg = <0x12000000 0x100>; - }; - - syscon { - compatible = "arm,integrator-ap-syscon"; - reg = <0x11000000 0x100>; - interrupt-parent = <&pic>; - /* These are the logic module IRQs */ - interrupts = <9>, <10>, <11>, <12>; - }; -}; - - -ARM Versatile Application and Platform Baseboards -------------------------------------------------- -ARM's development hardware platform with connectors for customizable -core tiles. The hardware configuration of the Versatile boards is -highly customizable. - -Required properties (in root node): - compatible = "arm,versatile-ab"; /* Application baseboard */ - compatible = "arm,versatile-pb"; /* Platform baseboard */ - -Interrupt controllers: -- VIC required properties: - compatible = "arm,versatile-vic"; - interrupt-controller; - #interrupt-cells = <1>; - -- SIC required properties: - compatible = "arm,versatile-sic"; - interrupt-controller; - #interrupt-cells = <1>; - -Required nodes: - -- core-module: the root node to the Versatile platforms must have - a core-module with regs and the compatible strings - "arm,core-module-versatile", "syscon" - -Optional nodes: - -- arm,versatile-ib2-syscon : if the Versatile has an IB2 interface - board mounted, this has a separate system controller that is - defined in this node. - Required properties: - compatible = "arm,versatile-ib2-syscon", "syscon" - -ARM RealView Boards -------------------- -The RealView boards cover tailored evaluation boards that are used to explore -the ARM11 and Cortex A-8 and Cortex A-9 processors. - -Required properties (in root node): - /* RealView Emulation Baseboard */ - compatible = "arm,realview-eb"; - /* RealView Platform Baseboard for ARM1176JZF-S */ - compatible = "arm,realview-pb1176"; - /* RealView Platform Baseboard for ARM11 MPCore */ - compatible = "arm,realview-pb11mp"; - /* RealView Platform Baseboard for Cortex A-8 */ - compatible = "arm,realview-pba8"; - /* RealView Platform Baseboard Explore for Cortex A-9 */ - compatible = "arm,realview-pbx"; - -Required nodes: - -- soc: some node of the RealView platforms must be the SoC - node that contain the SoC-specific devices, with the compatible - string set to one of these tuples: - "arm,realview-eb-soc", "simple-bus" - "arm,realview-pb1176-soc", "simple-bus" - "arm,realview-pb11mp-soc", "simple-bus" - "arm,realview-pba8-soc", "simple-bus" - "arm,realview-pbx-soc", "simple-bus" - -- syscon: some subnode of the RealView SoC node must be a - system controller node pointing to the control registers, - with the compatible string set to one of these: - "arm,realview-eb11mp-revb-syscon", "arm,realview-eb-syscon", "syscon" - "arm,realview-eb11mp-revc-syscon", "arm,realview-eb-syscon", "syscon" - "arm,realview-eb-syscon", "syscon" - "arm,realview-pb1176-syscon", "syscon" - "arm,realview-pb11mp-syscon", "syscon" - "arm,realview-pba8-syscon", "syscon" - "arm,realview-pbx-syscon", "syscon" - - Required properties for the system controller: - - regs: the location and size of the system controller registers, - one range of 0x1000 bytes. - -Example: - -/dts-v1/; -#include - -/ { - model = "ARM RealView PB1176 with device tree"; - compatible = "arm,realview-pb1176"; - #address-cells = <1>; - #size-cells = <1>; - - soc { - #address-cells = <1>; - #size-cells = <1>; - compatible = "arm,realview-pb1176-soc", "simple-bus"; - ranges; - - syscon: syscon@10000000 { - compatible = "arm,realview-syscon", "syscon"; - reg = <0x10000000 0x1000>; - }; - - }; -}; - -ARM Versatile Express Boards ------------------------------ -For details on the device tree bindings for ARM Versatile Express boards -please consult the vexpress.txt file in the same directory as this file. - -ARM Juno Boards ----------------- -The Juno boards are targeting development for AArch64 systems. The first -iteration, Juno r0, is a vehicle for evaluating big.LITTLE on AArch64, -with the second iteration, Juno r1, mainly aimed at development of PCIe -based systems. Juno r1 also has support for AXI masters placed on the TLX -connectors to join the coherency domain. - -Juno boards are described in a similar way to ARM Versatile Express boards, -with the motherboard part of the hardware being described in a separate file -to highlight the fact that is part of the support infrastructure for the SoC. -Juno device tree bindings also share the Versatile Express bindings as -described under the RS1 memory mapping. - -Required properties (in root node): - compatible = "arm,juno"; /* For Juno r0 board */ - compatible = "arm,juno-r1"; /* For Juno r1 board */ - compatible = "arm,juno-r2"; /* For Juno r2 board */ - -Required nodes: -The description for the board must include: - - a "psci" node describing the boot method used for the secondary CPUs. - A detailed description of the bindings used for "psci" nodes is present - in the psci.yaml file. - - a "cpus" node describing the available cores and their associated - "enable-method"s. For more details see cpus.yaml file. - -Example: - -/dts-v1/; -/ { - model = "ARM Juno development board (r0)"; - compatible = "arm,juno", "arm,vexpress"; - interrupt-parent = <&gic>; - #address-cells = <2>; - #size-cells = <2>; - - cpus { - #address-cells = <2>; - #size-cells = <0>; - - A57_0: cpu@0 { - compatible = "arm,cortex-a57"; - reg = <0x0 0x0>; - device_type = "cpu"; - enable-method = "psci"; - }; - - ..... - - A53_0: cpu@100 { - compatible = "arm,cortex-a53"; - reg = <0x0 0x100>; - device_type = "cpu"; - enable-method = "psci"; - }; - - ..... - }; - -}; diff --git a/Documentation/devicetree/bindings/arm/vexpress.txt b/Documentation/devicetree/bindings/arm/vexpress.txt deleted file mode 100644 index 39844cd0bcce..000000000000 --- a/Documentation/devicetree/bindings/arm/vexpress.txt +++ /dev/null @@ -1,229 +0,0 @@ -ARM Versatile Express boards family ------------------------------------ - -ARM's Versatile Express platform consists of a motherboard and one -or more daughterboards (tiles). The motherboard provides a set of -peripherals. Processor and RAM "live" on the tiles. - -The motherboard and each core tile should be described by a separate -Device Tree source file, with the tile's description including -the motherboard file using a /include/ directive. As the motherboard -can be initialized in one of two different configurations ("memory -maps"), care must be taken to include the correct one. - - -Root node ---------- - -Required properties in the root node: -- compatible value: - compatible = "arm,vexpress,", "arm,vexpress"; - where is the full tile model name (as used in the tile's - Technical Reference Manual), eg.: - - for Coretile Express A5x2 (V2P-CA5s): - compatible = "arm,vexpress,v2p-ca5s", "arm,vexpress"; - - for Coretile Express A9x4 (V2P-CA9): - compatible = "arm,vexpress,v2p-ca9", "arm,vexpress"; - If a tile comes in several variants or can be used in more then one - configuration, the compatible value should be: - compatible = "arm,vexpress,,", \ - "arm,vexpress,", "arm,vexpress"; - eg: - - Coretile Express A15x2 (V2P-CA15) with Tech Chip 1: - compatible = "arm,vexpress,v2p-ca15,tc1", \ - "arm,vexpress,v2p-ca15", "arm,vexpress"; - - LogicTile Express 13MG (V2F-2XV6) running Cortex-A7 (3 cores) SMM: - compatible = "arm,vexpress,v2f-2xv6,ca7x3", \ - "arm,vexpress,v2f-2xv6", "arm,vexpress"; - -Optional properties in the root node: -- tile model name (use name from the tile's Technical Reference - Manual, eg. "V2P-CA5s") - model = ""; -- tile's HBI number (unique ARM's board model ID, visible on the - PCB's silkscreen) in hexadecimal transcription: - arm,hbi = <0xhbi> - eg: - - for Coretile Express A5x2 (V2P-CA5s) HBI-0191: - arm,hbi = <0x191>; - - Coretile Express A9x4 (V2P-CA9) HBI-0225: - arm,hbi = <0x225>; - - -CPU nodes ---------- - -Top-level standard "cpus" node is required. It must contain a node -with device_type = "cpu" property for every available core, eg.: - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a5"; - reg = <0>; - }; - }; - - -Configuration infrastructure ----------------------------- - -The platform has an elaborated configuration system, consisting of -microcontrollers residing on the mother- and daughterboards known -as Motherboard/Daughterboard Configuration Controller (MCC and DCC). -The controllers are responsible for the platform initialization -(reset generation, flash programming, FPGA bitfiles loading etc.) -but also control clock generators, voltage regulators, gather -environmental data like temperature, power consumption etc. Even -the video output switch (FPGA) is controlled that way. - -The controllers are not mapped into normal memory address space -and must be accessed through bridges - other devices capable -of generating transactions on the configuration bus. - -The nodes describing configuration controllers must define -the following properties: -- compatible value: - compatible = "arm,vexpress,config-bus"; -- bridge phandle: - arm,vexpress,config-bridge = ; -and children describing available functions. - - -Platform topology ------------------ - -As Versatile Express can be configured in number of physically -different setups, the device tree should describe platform topology. -Root node and main motherboard node must define the following -property, describing physical location of the children nodes: -- site number: - arm,vexpress,site = ; - where 0 means motherboard, 1 or 2 are daugtherboard sites, - 0xf means "master" site (site containing main CPU tile) -- when daughterboards are stacked on one site, their position - in the stack be be described with: - arm,vexpress,position = ; -- when describing tiles consisting more than one DCC, its number - can be described with: - arm,vexpress,dcc = ; - -Any of the numbers above defaults to zero if not defined in -the node or any of its parent. - - -Motherboard ------------ - -The motherboard description file provides a single "motherboard" node -using 2 address cells corresponding to the Static Memory Bus used -between the motherboard and the tile. The first cell defines the Chip -Select (CS) line number, the second cell address offset within the CS. -All interrupt lines between the motherboard and the tile are active -high and are described using single cell. - -Optional properties of the "motherboard" node: -- motherboard's memory map variant: - arm,v2m-memory-map = ""; - where name is one of: - - "rs1" - for RS1 map (i.a. peripherals on CS3); this map is also - referred to as "ARM Cortex-A Series memory map": - arm,v2m-memory-map = "rs1"; - When this property is missing, the motherboard is using the original - memory map (also known as the "Legacy memory map", primarily used - with the original CoreTile Express A9x4) with peripherals on CS7. - -Motherboard .dtsi files provide a set of labelled peripherals that -can be used to obtain required phandle in the tile's "aliases" node: -- UARTs, note that the numbers correspond to the physical connectors - on the motherboard's back panel: - v2m_serial0, v2m_serial1, v2m_serial2 and v2m_serial3 -- I2C controllers: - v2m_i2c_dvi and v2m_i2c_pcie -- SP804 timers: - v2m_timer01 and v2m_timer23 - -The tile description should define a "smb" node, describing the -Static Memory Bus between the tile and motherboard. It must define -the following properties: -- "simple-bus" compatible value (to ensure creation of the children) - compatible = "simple-bus"; -- mapping of the SMB CS/offset addresses into main address space: - #address-cells = <2>; - #size-cells = <1>; - ranges = <...>; -- interrupts mapping: - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 63>; - interrupt-map = <...>; - - -Example of a VE tile description (simplified) ---------------------------------------------- - -/dts-v1/; - -/ { - model = "V2P-CA5s"; - arm,hbi = <0x225>; - arm,vexpress,site = <0xf>; - compatible = "arm,vexpress-v2p-ca5s", "arm,vexpress"; - interrupt-parent = <&gic>; - #address-cells = <1>; - #size-cells = <1>; - - chosen { }; - - aliases { - serial0 = &v2m_serial0; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a5"; - reg = <0>; - }; - }; - - gic: interrupt-controller@2c001000 { - compatible = "arm,cortex-a9-gic"; - #interrupt-cells = <3>; - #address-cells = <0>; - interrupt-controller; - reg = <0x2c001000 0x1000>, - <0x2c000100 0x100>; - }; - - dcc { - compatible = "arm,vexpress,config-bus"; - arm,vexpress,config-bridge = <&v2m_sysreg>; - - osc@0 { - compatible = "arm,vexpress-osc"; - }; - }; - - smb { - compatible = "simple-bus"; - - #address-cells = <2>; - #size-cells = <1>; - /* CS0 is visible at 0x08000000 */ - ranges = <0 0 0x08000000 0x04000000>; - - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 63>; - /* Active high IRQ 0 is connected to GIC's SPI0 */ - interrupt-map = <0 0 0 &gic 0 0 4>; - - /include/ "vexpress-v2m-rs1.dtsi" - }; -}; - From bee7ff37ecf17317ef9295a6ab6e607db034f8a3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 26 Feb 2020 10:19:43 +0100 Subject: [PATCH 1147/4444] ARM/arm64: dts: Rename SMB bus to just bus Discussing the YAML validation schema with the DT maintainers it came out that a bus named "smb@80000000" is not really accepted, and the schema was written to name the static memory bus just "bus@80000000". This change is necessary for the schema to kick in and validate these device trees, else the schema gets ignored. Cc: Rob Herring Acked-by: Sudeep Holla Signed-off-by: Linus Walleij --- arch/arm/boot/dts/vexpress-v2m-rs1.dtsi | 2 +- arch/arm/boot/dts/vexpress-v2m.dtsi | 2 +- arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts | 2 +- arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts | 2 +- arch/arm/boot/dts/vexpress-v2p-ca5s.dts | 2 +- arch/arm/boot/dts/vexpress-v2p-ca9.dts | 2 +- arch/arm64/boot/dts/arm/foundation-v8.dtsi | 2 +- arch/arm64/boot/dts/arm/fvp-base-revc.dts | 2 +- arch/arm64/boot/dts/arm/juno-base.dtsi | 2 +- arch/arm64/boot/dts/arm/juno-motherboard.dtsi | 2 +- arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts | 2 +- arch/arm64/boot/dts/arm/rtsm_ve-motherboard-rs2.dtsi | 2 +- arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi | 2 +- arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi index dfae90adbb7c..5c183483ec3b 100644 --- a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi +++ b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi @@ -19,7 +19,7 @@ */ / { - smb@8000000 { + bus@8000000 { motherboard { model = "V2M-P1"; arm,hbi = <0x190>; diff --git a/arch/arm/boot/dts/vexpress-v2m.dtsi b/arch/arm/boot/dts/vexpress-v2m.dtsi index 2e29d7790497..5e48b641068a 100644 --- a/arch/arm/boot/dts/vexpress-v2m.dtsi +++ b/arch/arm/boot/dts/vexpress-v2m.dtsi @@ -19,7 +19,7 @@ */ / { - smb@4000000 { + bus@4000000 { motherboard { model = "V2M-P1"; arm,hbi = <0x190>; diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts index 0dc4277d5f8b..f82fa34c90be 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts @@ -236,7 +236,7 @@ }; }; - smb@8000000 { + bus@8000000 { compatible = "simple-bus"; #address-cells = <2>; diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts index 1de0a658adf1..3ac95a179452 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts @@ -608,7 +608,7 @@ }; }; - smb: smb@8000000 { + smb: bus@8000000 { compatible = "simple-bus"; #address-cells = <2>; diff --git a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts index d5b47d526f9e..7aa64ae25779 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts @@ -206,7 +206,7 @@ }; }; - smb: smb@8000000 { + smb: bus@8000000 { compatible = "simple-bus"; #address-cells = <2>; diff --git a/arch/arm/boot/dts/vexpress-v2p-ca9.dts b/arch/arm/boot/dts/vexpress-v2p-ca9.dts index d796efaadbe3..623246f37448 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca9.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca9.dts @@ -295,7 +295,7 @@ }; }; - smb: smb@4000000 { + smb: bus@4000000 { compatible = "simple-bus"; #address-cells = <2>; diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dtsi b/arch/arm64/boot/dts/arm/foundation-v8.dtsi index 3f78373f708a..12f039fa3dad 100644 --- a/arch/arm64/boot/dts/arm/foundation-v8.dtsi +++ b/arch/arm64/boot/dts/arm/foundation-v8.dtsi @@ -92,7 +92,7 @@ timeout-sec = <30>; }; - smb@8000000 { + bus@8000000 { compatible = "arm,vexpress,v2m-p1", "simple-bus"; arm,v2m-memory-map = "rs1"; #address-cells = <2>; /* SMB chipselect number and offset */ diff --git a/arch/arm64/boot/dts/arm/fvp-base-revc.dts b/arch/arm64/boot/dts/arm/fvp-base-revc.dts index 62ab0d54ff71..c8ba328ed3fe 100644 --- a/arch/arm64/boot/dts/arm/fvp-base-revc.dts +++ b/arch/arm64/boot/dts/arm/fvp-base-revc.dts @@ -206,7 +206,7 @@ }; }; - smb@8000000 { + bus@8000000 { compatible = "simple-bus"; #address-cells = <2>; diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi index 1f3c80aafbd7..f5889281545f 100644 --- a/arch/arm64/boot/dts/arm/juno-base.dtsi +++ b/arch/arm64/boot/dts/arm/juno-base.dtsi @@ -800,7 +800,7 @@ <0x00000008 0x80000000 0x1 0x80000000>; }; - smb@8000000 { + bus@8000000 { compatible = "simple-bus"; #address-cells = <2>; #size-cells = <1>; diff --git a/arch/arm64/boot/dts/arm/juno-motherboard.dtsi b/arch/arm64/boot/dts/arm/juno-motherboard.dtsi index 9f60dacb4f80..e3983ded3c3c 100644 --- a/arch/arm64/boot/dts/arm/juno-motherboard.dtsi +++ b/arch/arm64/boot/dts/arm/juno-motherboard.dtsi @@ -8,7 +8,7 @@ */ / { - smb@8000000 { + bus@8000000 { mb_clk24mhz: clk24mhz { compatible = "fixed-clock"; #clock-cells = <0>; diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts index 6e685d883303..c5d15cbd8cf6 100644 --- a/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts +++ b/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts @@ -132,7 +132,7 @@ }; }; - smb@8000000 { + bus@8000000 { compatible = "simple-bus"; #address-cells = <2>; diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard-rs2.dtsi b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard-rs2.dtsi index 57b0b9d7f3fa..60703b5763c6 100644 --- a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard-rs2.dtsi +++ b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard-rs2.dtsi @@ -5,7 +5,7 @@ * "rs2" extension for the v2m motherboard */ / { - smb@8000000 { + bus@8000000 { motherboard { arm,v2m-memory-map = "rs2"; diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi index 03a7bf079c8f..e333c8d2d0e4 100644 --- a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi +++ b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi @@ -8,7 +8,7 @@ * VEMotherBoard.lisa */ / { - smb@8000000 { + bus@8000000 { motherboard { arm,v2m-memory-map = "rs1"; compatible = "arm,vexpress,v2m-p1", "simple-bus"; diff --git a/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts index 22383c26bb03..d859914500a7 100644 --- a/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts +++ b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts @@ -144,7 +144,7 @@ }; }; - smb: smb@8000000 { + smb: bus@8000000 { compatible = "simple-bus"; #address-cells = <2>; From 25bfaaa73c7d26a6e897559c510d7daff5e9d22d Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 3 Mar 2020 09:31:00 -0800 Subject: [PATCH 1148/4444] bus: ti-sysc: Detect EDMA and set quirk flags for tptc In order to probe EDMA with ti-sysc interconnect target module and with device tree data, we need to properly detect EDMA and set the flags for SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY for tptc. We have these flags currently set for am4 and dra7, but not for am335x. Let's set them for all the SoCs as the tptc module should behave the same for all of them. It's likely that am335x was never tested to idle EDMA tptc. Cc: Peter Ujfalusi Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 46b25fa4237f..bc1c52f87046 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1331,6 +1331,10 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_MODULE_QUIRK_SGX), SYSC_QUIRK("rtc", 0, 0x74, 0x78, -ENODEV, 0x4eb01908, 0xffff00f0, SYSC_MODULE_QUIRK_RTC_UNLOCK), + SYSC_QUIRK("tptc", 0, 0, 0x10, -ENODEV, 0x40006c00, 0xffffefff, + SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY), + SYSC_QUIRK("tptc", 0, 0, -ENODEV, -ENODEV, 0x40007c00, 0xffffffff, + SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY), SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050, 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY), SYSC_QUIRK("usb_otg_hs", 0, 0, 0x10, -ENODEV, 0x4ea2080d, 0xffffffff, @@ -1397,6 +1401,7 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("spinlock", 0, 0, 0x10, -ENODEV, 0x50020000, 0xffffffff, 0), SYSC_QUIRK("rng", 0, 0x1fe0, 0x1fe4, -ENODEV, 0x00000020, 0xffffffff, 0), SYSC_QUIRK("timer32k", 0, 0, 0x4, -ENODEV, 0x00000060, 0xffffffff, 0), + SYSC_QUIRK("tpcc", 0, 0, -ENODEV, -ENODEV, 0x40014c00, 0xffffffff, 0), SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000004, 0xffffffff, 0), SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000008, 0xffffffff, 0), SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, 0x14, 0x50700100, 0xffffffff, 0), From f2ce16c3c15e90f8279ccda8deeb24682a4a3706 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 3 Mar 2020 21:27:48 +0100 Subject: [PATCH 1149/4444] iommu/omap: Fix pointer cast -Wpointer-to-int-cast warnings on 64 bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pointers should be casted to unsigned long to avoid -Wpointer-to-int-cast warnings when compiling on 64-bit platform (e.g. with COMPILE_TEST): drivers/iommu/omap-iommu.c: In function ‘omap2_iommu_enable’: drivers/iommu/omap-iommu.c:170:25: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K)) ^ Signed-off-by: Krzysztof Kozlowski Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index be551cc34be4..50e8acf88ec4 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -167,7 +167,7 @@ static int omap2_iommu_enable(struct omap_iommu *obj) { u32 l, pa; - if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K)) + if (!obj->iopgd || !IS_ALIGNED((unsigned long)obj->iopgd, SZ_16K)) return -EINVAL; pa = virt_to_phys(obj->iopgd); From 6135a891dc0bc43265cd583614419e04f3fd42b4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 3 Mar 2020 21:27:49 +0100 Subject: [PATCH 1150/4444] iommu/omap: Fix printing format for size_t on 64-bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Print size_t as %zu or %zx to fix -Wformat warnings when compiling on 64-bit platform (e.g. with COMPILE_TEST): drivers/iommu/omap-iommu.c: In function ‘flush_iotlb_page’: drivers/iommu/omap-iommu.c:437:47: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 7 has type ‘size_t {aka long unsigned int}’ [-Wformat=] Acked-by: Suman Anna Signed-off-by: Krzysztof Kozlowski Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iommu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index 50e8acf88ec4..887fefcb03b4 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -434,7 +434,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da) bytes = iopgsz_to_bytes(cr.cam & 3); if ((start <= da) && (da < start + bytes)) { - dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n", + dev_dbg(obj->dev, "%s: %08x<=%08x(%zx)\n", __func__, start, da, bytes); iotlb_load_cr(obj, &cr); iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY); @@ -1352,11 +1352,11 @@ static int omap_iommu_map(struct iommu_domain *domain, unsigned long da, omap_pgsz = bytes_to_iopgsz(bytes); if (omap_pgsz < 0) { - dev_err(dev, "invalid size to map: %d\n", bytes); + dev_err(dev, "invalid size to map: %zu\n", bytes); return -EINVAL; } - dev_dbg(dev, "mapping da 0x%lx to pa %pa size 0x%x\n", da, &pa, bytes); + dev_dbg(dev, "mapping da 0x%lx to pa %pa size 0x%zx\n", da, &pa, bytes); iotlb_init_entry(&e, da, pa, omap_pgsz); @@ -1393,7 +1393,7 @@ static size_t omap_iommu_unmap(struct iommu_domain *domain, unsigned long da, size_t bytes = 0; int i; - dev_dbg(dev, "unmapping da 0x%lx size %u\n", da, size); + dev_dbg(dev, "unmapping da 0x%lx size %zu\n", da, size); iommu = omap_domain->iommus; for (i = 0; i < omap_domain->num_iommus; i++, iommu++) { From d84edddc447df2d87e6ce9fbf94d95225504ab32 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 3 Mar 2020 21:27:50 +0100 Subject: [PATCH 1151/4444] iommu/omap: Fix -Woverflow warnings when compiling on 64-bit architectures Although the OMAP IOMMU driver supports only ARMv7 (32-bit) platforms, it can be compile tested for other architectures, including 64-bit ones. In such case the warning appears: In file included from drivers/iommu/omap-iommu.c:33:0: drivers/iommu/omap-iommu.c: In function 'omap_iommu_iova_to_phys': >> drivers/iommu/omap-iopgtable.h:44:21: warning: large integer implicitly truncated to unsigned type [-Woverflow] #define IOPTE_MASK (~(IOPTE_SIZE - 1)) ^ >> drivers/iommu/omap-iommu.c:1641:41: note: in expansion of macro 'IOPTE_MASK' ret = omap_iommu_translate(*pte, da, IOPTE_MASK); ^~~~~~~~~~ Fix this by using architecture-depending types in omap_iommu_translate(): 1. Pointer should be cast to unsigned long, 2. Virtual addresses should be cast to dma_addr_t. On 32-bit this will be the same as original code (using u32). On 64-bit it should produce meaningful result, although it does not really matter. Reported-by: kbuild test robot Signed-off-by: Krzysztof Kozlowski Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iopgtable.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/omap-iopgtable.h b/drivers/iommu/omap-iopgtable.h index 1a4adb59a859..51d74002cc30 100644 --- a/drivers/iommu/omap-iopgtable.h +++ b/drivers/iommu/omap-iopgtable.h @@ -63,7 +63,8 @@ * * va to pa translation */ -static inline phys_addr_t omap_iommu_translate(u32 d, u32 va, u32 mask) +static inline phys_addr_t omap_iommu_translate(unsigned long d, dma_addr_t va, + dma_addr_t mask) { return (d & mask) | (va & (~mask)); } From e93a1695d7fb551376b1c1220a267d032b6ad159 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 3 Mar 2020 21:27:51 +0100 Subject: [PATCH 1152/4444] iommu: Enable compile testing for some of drivers Some of the IOMMU drivers can be compile tested to increase build coverage. The OMAP, Rockchip and Exynos drivers use device.dev_archdata.iommu field which does not exist on all platforms. The sPAPR TCE and ARM SMMU have also restrictions where they can be built. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Joerg Roedel --- drivers/iommu/Kconfig | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index d2fade984999..ff41c3d9e11f 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -273,7 +273,7 @@ config IRQ_REMAP # OMAP IOMMU support config OMAP_IOMMU bool "OMAP IOMMU Support" - depends on ARM && MMU + depends on ARM && MMU || (COMPILE_TEST && (ARM || ARM64 || IA64 || SPARC)) depends on ARCH_OMAP2PLUS || COMPILE_TEST select IOMMU_API ---help--- @@ -291,7 +291,7 @@ config OMAP_IOMMU_DEBUG config ROCKCHIP_IOMMU bool "Rockchip IOMMU Support" - depends on ARM || ARM64 + depends on ARM || ARM64 || (COMPILE_TEST && (ARM64 || IA64 || SPARC)) depends on ARCH_ROCKCHIP || COMPILE_TEST select IOMMU_API select ARM_DMA_USE_IOMMU @@ -325,7 +325,7 @@ config TEGRA_IOMMU_SMMU config EXYNOS_IOMMU bool "Exynos IOMMU Support" - depends on ARCH_EXYNOS && MMU + depends on ARCH_EXYNOS && MMU || (COMPILE_TEST && (ARM || ARM64 || IA64 || SPARC)) depends on !CPU_BIG_ENDIAN # revisit driver if we can enable big-endian ptes select IOMMU_API select ARM_DMA_USE_IOMMU @@ -361,7 +361,7 @@ config IPMMU_VMSA config SPAPR_TCE_IOMMU bool "sPAPR TCE IOMMU Support" - depends on PPC_POWERNV || PPC_PSERIES + depends on PPC_POWERNV || PPC_PSERIES || (PPC && COMPILE_TEST) select IOMMU_API help Enables bits of IOMMU API required by VFIO. The iommu_ops @@ -370,7 +370,7 @@ config SPAPR_TCE_IOMMU # ARM IOMMU support config ARM_SMMU tristate "ARM Ltd. System MMU (SMMU) Support" - depends on (ARM64 || ARM) && MMU + depends on (ARM64 || ARM || (COMPILE_TEST && !GENERIC_ATOMIC64)) && MMU select IOMMU_API select IOMMU_IO_PGTABLE_LPAE select ARM_DMA_USE_IOMMU if ARM @@ -440,7 +440,7 @@ config S390_IOMMU config S390_CCW_IOMMU bool "S390 CCW IOMMU Support" - depends on S390 && CCW + depends on S390 && CCW || COMPILE_TEST select IOMMU_API help Enables bits of IOMMU API required by VFIO. The iommu_ops @@ -448,7 +448,7 @@ config S390_CCW_IOMMU config S390_AP_IOMMU bool "S390 AP IOMMU Support" - depends on S390 && ZCRYPT + depends on S390 && ZCRYPT || COMPILE_TEST select IOMMU_API help Enables bits of IOMMU API required by VFIO. The iommu_ops @@ -456,7 +456,7 @@ config S390_AP_IOMMU config MTK_IOMMU bool "MTK IOMMU Support" - depends on ARM || ARM64 + depends on ARM || ARM64 || COMPILE_TEST depends on ARCH_MEDIATEK || COMPILE_TEST select ARM_DMA_USE_IOMMU select IOMMU_API From 4d0dd3802ee1b6b14b7c46621cd581eb7c1ade79 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 27 Feb 2020 16:28:33 -0600 Subject: [PATCH 1153/4444] dt-bindings: bus: ti-sysc: Add support for PRUSS SYSC type The PRUSS module has a SYSCFG which is unique. The SYSCFG has two additional unique fields called STANDBY_INIT and SUB_MWAIT in addition to regular IDLE_MODE and STANDBY_MODE fields. Add the bindings for this new sysc type. Cc: Rob Herring Signed-off-by: Roger Quadros Signed-off-by: Suman Anna Acked-by: Rob Herring Signed-off-by: Tony Lindgren --- Documentation/devicetree/bindings/bus/ti-sysc.txt | 1 + include/dt-bindings/bus/ti-sysc.h | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/bus/ti-sysc.txt b/Documentation/devicetree/bindings/bus/ti-sysc.txt index 233eb8294204..c984143d08d2 100644 --- a/Documentation/devicetree/bindings/bus/ti-sysc.txt +++ b/Documentation/devicetree/bindings/bus/ti-sysc.txt @@ -38,6 +38,7 @@ Required standard properties: "ti,sysc-dra7-mcasp" "ti,sysc-usb-host-fs" "ti,sysc-dra7-mcan" + "ti,sysc-pruss" - reg shall have register areas implemented for the interconnect target module in question such as revision, sysc and syss diff --git a/include/dt-bindings/bus/ti-sysc.h b/include/dt-bindings/bus/ti-sysc.h index babd08a1d226..76b07826ed05 100644 --- a/include/dt-bindings/bus/ti-sysc.h +++ b/include/dt-bindings/bus/ti-sysc.h @@ -18,6 +18,10 @@ #define SYSC_DRA7_MCAN_ENAWAKEUP (1 << 4) +/* PRUSS sysc found on AM33xx/AM43xx/AM57xx */ +#define SYSC_PRUSS_SUB_MWAIT (1 << 5) +#define SYSC_PRUSS_STANDBY_INIT (1 << 4) + /* SYSCONFIG STANDBYMODE/MIDLEMODE/SIDLEMODE supported by hardware */ #define SYSC_IDLE_FORCE 0 #define SYSC_IDLE_NO 1 From b2745d92bb015cc4454d4195c4ce6e2852db397e Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Thu, 27 Feb 2020 16:28:34 -0600 Subject: [PATCH 1154/4444] bus: ti-sysc: Add support for PRUSS SYSC type The PRU-ICSS present on AM33xx/AM43xx/AM57xx has a very unique SYSCFG register. The register follows the OMAP4-style SYSC_TYPE3 for Master Standby and Slave Idle, but also has two additional unique fields - STANDBY_INIT and SUB_MWAIT. The STANDBY_INIT is a control bit that is used to initiate a Standby sequence (when set) and trigger a MStandby request to the SoC's PRCM module. This same bit is also used to enable the OCP master ports (when cleared) to allow the PRU cores to access any peripherals or memory beyond the PRU subsystem. The SUB_MWAIT is a ready status field for the external access. Add support for this SYSC type. The STANDBY_INIT has to be set during suspend, without which it results in a hang in the resume sequence on AM33xx/AM43xx boards and requires a board reset to come out of the hang. Any PRU applications requiring external access are supposed to clear the STANDBY_INIT bit. Note that the PRUSS context is lost during a suspend sequence because the PRUSS module is reset and/or disabled. Signed-off-by: Suman Anna Signed-off-by: Roger Quadros [tony@atomide.com: updated quirk define number and to use -ENODEV] Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 27 +++++++++++++++++++++++++++ include/linux/platform_data/ti-sysc.h | 2 ++ 2 files changed, 29 insertions(+) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index bc1c52f87046..86ac61fa5bc6 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1341,6 +1341,9 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY), SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, SYSC_MODULE_QUIRK_WDT), + /* PRUSS on am3, am4 and am5 */ + SYSC_QUIRK("pruss", 0, 0x26000, 0x26004, -ENODEV, 0x47000000, 0xff000000, + SYSC_MODULE_QUIRK_PRUSS), /* Watchdog on am3 and am4 */ SYSC_QUIRK("wdt", 0x44e35000, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, SYSC_MODULE_QUIRK_WDT | SYSC_QUIRK_SWSUP_SIDLE), @@ -1712,6 +1715,16 @@ static void sysc_reset_done_quirk_wdt(struct sysc *ddata) dev_warn(ddata->dev, "wdt disable step2 failed\n"); } +/* PRUSS needs to set MSTANDBY_INIT inorder to idle properly */ +static void sysc_module_disable_quirk_pruss(struct sysc *ddata) +{ + u32 reg; + + reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]); + reg |= SYSC_PRUSS_STANDBY_INIT; + sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg); +} + static void sysc_init_module_quirks(struct sysc *ddata) { if (ddata->legacy_mode || !ddata->name) @@ -1750,6 +1763,9 @@ static void sysc_init_module_quirks(struct sysc *ddata) ddata->reset_done_quirk = sysc_reset_done_quirk_wdt; ddata->module_disable_quirk = sysc_reset_done_quirk_wdt; } + + if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_PRUSS) + ddata->module_disable_quirk = sysc_module_disable_quirk_pruss; } static int sysc_clockdomain_init(struct sysc *ddata) @@ -2555,6 +2571,16 @@ static const struct sysc_capabilities sysc_dra7_mcan = { .mod_quirks = SYSS_QUIRK_RESETDONE_INVERTED, }; +/* + * PRUSS found on some AM33xx, AM437x and AM57xx SoCs + */ +static const struct sysc_capabilities sysc_pruss = { + .type = TI_SYSC_PRUSS, + .sysc_mask = SYSC_PRUSS_STANDBY_INIT | SYSC_PRUSS_SUB_MWAIT, + .regbits = &sysc_regbits_omap4_simple, + .mod_quirks = SYSC_MODULE_QUIRK_PRUSS, +}; + static int sysc_init_pdata(struct sysc *ddata) { struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev); @@ -2936,6 +2962,7 @@ static const struct of_device_id sysc_match[] = { { .compatible = "ti,sysc-usb-host-fs", .data = &sysc_omap4_usb_host_fs, }, { .compatible = "ti,sysc-dra7-mcan", .data = &sysc_dra7_mcan, }, + { .compatible = "ti,sysc-pruss", .data = &sysc_pruss, }, { }, }; MODULE_DEVICE_TABLE(of, sysc_match); diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index ecd3a979a14d..c59999ce044e 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -17,6 +17,7 @@ enum ti_sysc_module_type { TI_SYSC_OMAP4_MCASP, TI_SYSC_OMAP4_USB_HOST_FS, TI_SYSC_DRA7_MCAN, + TI_SYSC_PRUSS, }; struct ti_sysc_cookie { @@ -49,6 +50,7 @@ struct sysc_regbits { s8 emufree_shift; }; +#define SYSC_MODULE_QUIRK_PRUSS BIT(24) #define SYSC_MODULE_QUIRK_DSS_RESET BIT(23) #define SYSC_MODULE_QUIRK_RTC_UNLOCK BIT(22) #define SYSC_QUIRK_CLKDM_NOAUTO BIT(21) From 63b34416aa7eed35f1d472700bf5de6a74b3a0df Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:37 -0800 Subject: [PATCH 1155/4444] ARM: dts: Configure interconnect target module for omap4 dss We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty until the child devices are probing with ti-sysc interconnect driver. The display subsystem (DSS) is in a 16MB interconnect target module mapped to l4 and l3 buses. We are only using the l3 port as recommended by the TRM. So there is no need to configure l4 ranges like we've done for l4 ABE instance for example. Initially let's just update the top level dss node to probe with ti-sysc interconnect target module driver. The child nodes are still children of dispc, only the node indentation changes for them now along with using the reg range provided by top level dss. Let's also add add a note about using only the l3 access without l4 as noted in the TRM. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Sebastian Reichel Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap4-l4.dtsi | 1 + arch/arm/boot/dts/omap4.dtsi | 160 ++++++++++++++++++-------------- 2 files changed, 91 insertions(+), 70 deletions(-) diff --git a/arch/arm/boot/dts/omap4-l4.dtsi b/arch/arm/boot/dts/omap4-l4.dtsi index 459fd7027591..ef59e4e97d7c 100644 --- a/arch/arm/boot/dts/omap4-l4.dtsi +++ b/arch/arm/boot/dts/omap4-l4.dtsi @@ -1529,6 +1529,7 @@ }; }; + /* Unused DSS L4 access, see L3 instead */ target-module@40000 { /* 0x48040000, ap 13 0a.0 */ compatible = "ti,sysc"; status = "disabled"; diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 9a87440d0b9d..6d8edb51a897 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -415,87 +415,107 @@ */ }; - dss: dss@58000000 { - compatible = "ti,omap4-dss"; - reg = <0x58000000 0x80>; - status = "disabled"; + /* + * DSS is only using l3 mapping without l4 as noted in the TRM + * "10.1.3 DSS Register Manual" for omap4460. + */ + target-module@58000000 { + compatible = "ti,sysc-omap2", "ti,sysc"; ti,hwmods = "dss_core"; - clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>; - clock-names = "fck"; + reg = <0x58000000 4>, + <0x58000014 4>; + reg-names = "rev", "syss"; + ti,syss-mask = <1>; + clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 0>, + <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 9>, + <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 10>, + <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 11>; + clock-names = "fck", "hdmi_clk", "sys_clk", "tv_clk"; #address-cells = <1>; #size-cells = <1>; - ranges; + ranges = <0 0x58000000 0x1000000>; - dispc@58001000 { - compatible = "ti,omap4-dispc"; - reg = <0x58001000 0x1000>; - interrupts = ; - ti,hwmods = "dss_dispc"; + dss: dss@0 { + compatible = "ti,omap4-dss"; + reg = <0 0x80>; + status = "disabled"; clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>; clock-names = "fck"; - }; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0x1000000>; - rfbi: encoder@58002000 { - compatible = "ti,omap4-rfbi"; - reg = <0x58002000 0x1000>; - status = "disabled"; - ti,hwmods = "dss_rfbi"; - clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>, <&l3_div_ck>; - clock-names = "fck", "ick"; - }; + dispc@1000 { + compatible = "ti,omap4-dispc"; + reg = <0x1000 0x1000>; + interrupts = ; + ti,hwmods = "dss_dispc"; + clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>; + clock-names = "fck"; + }; - venc: encoder@58003000 { - compatible = "ti,omap4-venc"; - reg = <0x58003000 0x1000>; - status = "disabled"; - ti,hwmods = "dss_venc"; - clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 11>; - clock-names = "fck"; - }; + rfbi: encoder@2000 { + compatible = "ti,omap4-rfbi"; + reg = <0x2000 0x1000>; + status = "disabled"; + ti,hwmods = "dss_rfbi"; + clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>, <&l3_div_ck>; + clock-names = "fck", "ick"; + }; - dsi1: encoder@58004000 { - compatible = "ti,omap4-dsi"; - reg = <0x58004000 0x200>, - <0x58004200 0x40>, - <0x58004300 0x20>; - reg-names = "proto", "phy", "pll"; - interrupts = ; - status = "disabled"; - ti,hwmods = "dss_dsi1"; - clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>, - <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 10>; - clock-names = "fck", "sys_clk"; - }; + venc: encoder@3000 { + compatible = "ti,omap4-venc"; + reg = <0x3000 0x1000>; + status = "disabled"; + ti,hwmods = "dss_venc"; + clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 11>; + clock-names = "fck"; + }; - dsi2: encoder@58005000 { - compatible = "ti,omap4-dsi"; - reg = <0x58005000 0x200>, - <0x58005200 0x40>, - <0x58005300 0x20>; - reg-names = "proto", "phy", "pll"; - interrupts = ; - status = "disabled"; - ti,hwmods = "dss_dsi2"; - clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>, - <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 10>; - clock-names = "fck", "sys_clk"; - }; + dsi1: encoder@4000 { + compatible = "ti,omap4-dsi"; + reg = <0x4000 0x200>, + <0x4200 0x40>, + <0x4300 0x20>; + reg-names = "proto", "phy", "pll"; + interrupts = ; + status = "disabled"; + ti,hwmods = "dss_dsi1"; + clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>, + <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 10>; + clock-names = "fck", "sys_clk"; + }; - hdmi: encoder@58006000 { - compatible = "ti,omap4-hdmi"; - reg = <0x58006000 0x200>, - <0x58006200 0x100>, - <0x58006300 0x100>, - <0x58006400 0x1000>; - reg-names = "wp", "pll", "phy", "core"; - interrupts = ; - status = "disabled"; - ti,hwmods = "dss_hdmi"; - clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 9>, - <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 10>; - clock-names = "fck", "sys_clk"; - dmas = <&sdma 76>; - dma-names = "audio_tx"; + dsi2: encoder@5000 { + compatible = "ti,omap4-dsi"; + reg = <0x5000 0x200>, + <0x5200 0x40>, + <0x5300 0x20>; + reg-names = "proto", "phy", "pll"; + interrupts = ; + status = "disabled"; + ti,hwmods = "dss_dsi2"; + clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>, + <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 10>; + clock-names = "fck", "sys_clk"; + }; + + hdmi: encoder@6000 { + compatible = "ti,omap4-hdmi"; + reg = <0x6000 0x200>, + <0x6200 0x100>, + <0x6300 0x100>, + <0x6400 0x1000>; + reg-names = "wp", "pll", "phy", "core"; + interrupts = ; + status = "disabled"; + ti,hwmods = "dss_hdmi"; + clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 9>, + <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 10>; + clock-names = "fck", "sys_clk"; + dmas = <&sdma 76>; + dma-names = "audio_tx"; + }; }; }; }; From 4c8d1c8d62cdcc8357f41313c655542e0a7a0cce Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:37 -0800 Subject: [PATCH 1156/4444] ARM: dts: Configure interconnect target module for omap4 dispc We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty until the child devices are probing with ti-sysc interconnect driver. We must now also configure sys_clk for reset to complete, the top level module only keeps optional clocks enabled for it's own reset. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Sebastian Reichel Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap4.dtsi | 37 ++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 6d8edb51a897..60bb7b9c9aed 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -445,13 +445,38 @@ #size-cells = <1>; ranges = <0 0 0x1000000>; - dispc@1000 { - compatible = "ti,omap4-dispc"; - reg = <0x1000 0x1000>; - interrupts = ; + target-module@1000 { + compatible = "ti,sysc-omap2", "ti,sysc"; ti,hwmods = "dss_dispc"; - clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>; - clock-names = "fck"; + reg = <0x1000 0x4>, + <0x1010 0x4>, + <0x1014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-sidle = , + , + ; + ti,sysc-midle = , + , + ; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,syss-mask = <1>; + clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>, + <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 10>; + clock-names = "fck", "sys_clk"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x1000 0x1000>; + + dispc@0 { + compatible = "ti,omap4-dispc"; + reg = <0 0x1000>; + interrupts = ; + clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>; + clock-names = "fck"; + }; }; rfbi: encoder@2000 { From 3a97c4b9a1602bad42cc3c7e56105ad0ffd346c7 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:37 -0800 Subject: [PATCH 1157/4444] ARM: dts: Configure interconnect target module for omap4 rfbi We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module and drop "ti,hwmods" peroperty as this module is a child node of dispc and has no dependencies to to legacy platform data. We must now also configure sys_clk for reset to complete, the top level module only keeps optional clocks enabled for it's own reset. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Sebastian Reichel Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap4.dtsi | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 60bb7b9c9aed..f63ed8fcdf88 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -479,13 +479,31 @@ }; }; - rfbi: encoder@2000 { - compatible = "ti,omap4-rfbi"; - reg = <0x2000 0x1000>; - status = "disabled"; - ti,hwmods = "dss_rfbi"; - clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>, <&l3_div_ck>; - clock-names = "fck", "ick"; + target-module@2000 { + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x2000 0x4>, + <0x2010 0x4>, + <0x2014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-sidle = , + , + ; + ti,sysc-mask = <(SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,syss-mask = <1>; + clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>, + <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 10>; + clock-names = "fck", "sys_clk"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x2000 0x1000>; + + rfbi: encoder@0 { + reg = <0 0x1000>; + status = "disabled"; + clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>, <&l3_div_ck>; + clock-names = "fck", "ick"; + }; }; venc: encoder@3000 { From 663de788d4e224d88d48a49c5850e0dbb2183f38 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:38 -0800 Subject: [PATCH 1158/4444] ARM: dts: Configure interconnect target module for omap4 venc We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module and drop "ti,hwmods" peroperty as this module is a child node of dispc and has no dependencies to to legacy platform data. We must now also configure sys_clk for reset to complete, the top level module only keeps optional clocks enabled for it's own reset. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Sebastian Reichel Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap4.dtsi | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index f63ed8fcdf88..fe1ca68bcd65 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -506,13 +506,23 @@ }; }; - venc: encoder@3000 { - compatible = "ti,omap4-venc"; - reg = <0x3000 0x1000>; - status = "disabled"; - ti,hwmods = "dss_venc"; - clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 11>; - clock-names = "fck"; + target-module@3000 { + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x3000 0x4>; + reg-names = "rev"; + clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 10>; + clock-names = "sys_clk"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x3000 0x1000>; + + venc: encoder@0 { + compatible = "ti,omap4-venc"; + reg = <0 0x1000>; + status = "disabled"; + clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 11>; + clock-names = "fck"; + }; }; dsi1: encoder@4000 { From 0b98d518347265c9bbe3b3ba522e0493570bd2fe Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:38 -0800 Subject: [PATCH 1159/4444] ARM: dts: Configure interconnect target module for omap4 dsi1 We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module and drop "ti,hwmods" peroperty as this module is a child node of dispc and has no dependencies to to legacy platform data. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Sebastian Reichel Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap4.dtsi | 42 +++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index fe1ca68bcd65..03b365761687 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -525,18 +525,36 @@ }; }; - dsi1: encoder@4000 { - compatible = "ti,omap4-dsi"; - reg = <0x4000 0x200>, - <0x4200 0x40>, - <0x4300 0x20>; - reg-names = "proto", "phy", "pll"; - interrupts = ; - status = "disabled"; - ti,hwmods = "dss_dsi1"; - clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>, - <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 10>; - clock-names = "fck", "sys_clk"; + target-module@4000 { + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x4000 0x4>, + <0x4010 0x4>, + <0x4014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-sidle = , + , + ; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,syss-mask = <1>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x4000 0x1000>; + + dsi1: encoder@0 { + compatible = "ti,omap4-dsi"; + reg = <0 0x200>, + <0x200 0x40>, + <0x300 0x20>; + reg-names = "proto", "phy", "pll"; + interrupts = ; + status = "disabled"; + clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>, + <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 10>; + clock-names = "fck", "sys_clk"; + }; }; dsi2: encoder@5000 { From dc7578e99d42ea7ece26112c1b69c19c40cf61f8 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:39 -0800 Subject: [PATCH 1160/4444] ARM: dts: Configure interconnect target module for omap4 dsi2 We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module and drop "ti,hwmods" peroperty as this module is a child node of dispc and has no dependencies to to legacy platform data. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Sebastian Reichel Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap4.dtsi | 42 +++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 03b365761687..2aeab8f94960 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -557,18 +557,36 @@ }; }; - dsi2: encoder@5000 { - compatible = "ti,omap4-dsi"; - reg = <0x5000 0x200>, - <0x5200 0x40>, - <0x5300 0x20>; - reg-names = "proto", "phy", "pll"; - interrupts = ; - status = "disabled"; - ti,hwmods = "dss_dsi2"; - clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>, - <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 10>; - clock-names = "fck", "sys_clk"; + target-module@5000 { + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x5000 0x4>, + <0x5010 0x4>, + <0x5014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-sidle = , + , + ; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,syss-mask = <1>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x5000 0x1000>; + + dsi2: encoder@0 { + compatible = "ti,omap4-dsi"; + reg = <0 0x200>, + <0x200 0x40>, + <0x300 0x20>; + reg-names = "proto", "phy", "pll"; + interrupts = ; + status = "disabled"; + clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>, + <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 10>; + clock-names = "fck", "sys_clk"; + }; }; hdmi: encoder@6000 { From 8f66156341507ab7977ec53684df3aa7244c88eb Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:39 -0800 Subject: [PATCH 1161/4444] ARM: dts: Configure interconnect target module for omap4 hdmi We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module and drop "ti,hwmods" peroperty as this module is a child node of dispc and has no dependencies to to legacy platform data. Note that we must disable smart idle modes for HDMI audio like we've done with the legacy platform data. And HDMI needs both hdmi clock and dss clock to operate. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Sebastian Reichel Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap4.dtsi | 47 +++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 2aeab8f94960..e5b647120b4d 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -589,21 +589,40 @@ }; }; - hdmi: encoder@6000 { - compatible = "ti,omap4-hdmi"; - reg = <0x6000 0x200>, - <0x6200 0x100>, - <0x6300 0x100>, - <0x6400 0x1000>; - reg-names = "wp", "pll", "phy", "core"; - interrupts = ; - status = "disabled"; - ti,hwmods = "dss_hdmi"; + target-module@6000 { + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0x6000 0x4>, + <0x6010 0x4>; + reg-names = "rev", "sysc"; + /* + * Has SYSC_IDLE_SMART and SYSC_IDLE_SMART_WKUP + * but HDMI audio will fail with them. + */ + ti,sysc-sidle = , + ; + ti,sysc-mask = <(SYSC_OMAP4_SOFTRESET)>; clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 9>, - <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 10>; - clock-names = "fck", "sys_clk"; - dmas = <&sdma 76>; - dma-names = "audio_tx"; + <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 8>; + clock-names = "fck", "dss_clk"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x6000 0x2000>; + + hdmi: encoder@0 { + compatible = "ti,omap4-hdmi"; + reg = <0 0x200>, + <0x200 0x100>, + <0x300 0x100>, + <0x400 0x1000>; + reg-names = "wp", "pll", "phy", "core"; + interrupts = ; + status = "disabled"; + clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 9>, + <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 10>; + clock-names = "fck", "sys_clk"; + dmas = <&sdma 76>; + dma-names = "audio_tx"; + }; }; }; }; From 715a5a978733f08f55fe50e8e0281d106e9a8c4a Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:39 -0800 Subject: [PATCH 1162/4444] ARM: dts: Configure interconnect target module for omap5 dss We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty until the child devices are probing with ti-sysc interconnect driver. Initially let's just update the top level dss node to probe with ti-sysc interconnect target module driver. The child nodes are still children of dispc, only the node indentation changes for them now along with using the reg range provided by top level dss. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap5.dtsi | 140 +++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 62 deletions(-) diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index d0ecf54d5a23..13798be8ae79 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi @@ -292,78 +292,94 @@ */ }; - dss: dss@58000000 { - compatible = "ti,omap5-dss"; - reg = <0x58000000 0x80>; - status = "disabled"; + target-module@58000000 { + compatible = "ti,sysc-omap2", "ti,sysc"; ti,hwmods = "dss_core"; - clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>; - clock-names = "fck"; + reg = <0x58000000 4>, + <0x58000014 4>; + reg-names = "rev", "syss"; + ti,syss-mask = <1>; + clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 0>, + <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 9>, + <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>, + <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 11>; + clock-names = "fck", "hdmi_clk", "sys_clk", "tv_clk"; #address-cells = <1>; #size-cells = <1>; - ranges; + ranges = <0 0x58000000 0x1000000>; - dispc@58001000 { - compatible = "ti,omap5-dispc"; - reg = <0x58001000 0x1000>; - interrupts = ; - ti,hwmods = "dss_dispc"; + dss: dss@0 { + compatible = "ti,omap5-dss"; + reg = <0 0x80>; + status = "disabled"; clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>; clock-names = "fck"; - }; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0x1000000>; - rfbi: encoder@58002000 { - compatible = "ti,omap5-rfbi"; - reg = <0x58002000 0x100>; - status = "disabled"; - ti,hwmods = "dss_rfbi"; - clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>, <&l3_iclk_div>; - clock-names = "fck", "ick"; - }; + dispc@1000 { + compatible = "ti,omap5-dispc"; + reg = <0x1000 0x1000>; + interrupts = ; + ti,hwmods = "dss_dispc"; + clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>; + clock-names = "fck"; + }; - dsi1: encoder@58004000 { - compatible = "ti,omap5-dsi"; - reg = <0x58004000 0x200>, - <0x58004200 0x40>, - <0x58004300 0x40>; - reg-names = "proto", "phy", "pll"; - interrupts = ; - status = "disabled"; - ti,hwmods = "dss_dsi1"; - clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>, - <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>; - clock-names = "fck", "sys_clk"; - }; + rfbi: encoder@2000 { + compatible = "ti,omap5-rfbi"; + reg = <0x2000 0x100>; + status = "disabled"; + ti,hwmods = "dss_rfbi"; + clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>, <&l3_iclk_div>; + clock-names = "fck", "ick"; + }; - dsi2: encoder@58005000 { - compatible = "ti,omap5-dsi"; - reg = <0x58009000 0x200>, - <0x58009200 0x40>, - <0x58009300 0x40>; - reg-names = "proto", "phy", "pll"; - interrupts = ; - status = "disabled"; - ti,hwmods = "dss_dsi2"; - clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>, - <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>; - clock-names = "fck", "sys_clk"; - }; + dsi1: encoder@4000 { + compatible = "ti,omap5-dsi"; + reg = <0x4000 0x200>, + <0x4200 0x40>, + <0x4300 0x40>; + reg-names = "proto", "phy", "pll"; + interrupts = ; + status = "disabled"; + ti,hwmods = "dss_dsi1"; + clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>, + <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>; + clock-names = "fck", "sys_clk"; + }; - hdmi: encoder@58060000 { - compatible = "ti,omap5-hdmi"; - reg = <0x58040000 0x200>, - <0x58040200 0x80>, - <0x58040300 0x80>, - <0x58060000 0x19000>; - reg-names = "wp", "pll", "phy", "core"; - interrupts = ; - status = "disabled"; - ti,hwmods = "dss_hdmi"; - clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 9>, - <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>; - clock-names = "fck", "sys_clk"; - dmas = <&sdma 76>; - dma-names = "audio_tx"; + dsi2: encoder@9000 { + compatible = "ti,omap5-dsi"; + reg = <0x9000 0x200>, + <0x9200 0x40>, + <0x9300 0x40>; + reg-names = "proto", "phy", "pll"; + interrupts = ; + status = "disabled"; + ti,hwmods = "dss_dsi2"; + clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>, + <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>; + clock-names = "fck", "sys_clk"; + }; + + hdmi: encoder@40000 { + compatible = "ti,omap5-hdmi"; + reg = <0x40000 0x200>, + <0x40200 0x80>, + <0x40300 0x80>, + <0x60000 0x19000>; + reg-names = "wp", "pll", "phy", "core"; + interrupts = ; + status = "disabled"; + ti,hwmods = "dss_hdmi"; + clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 9>, + <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>; + clock-names = "fck", "sys_clk"; + dmas = <&sdma 76>; + dma-names = "audio_tx"; + }; }; }; From 2472a4e00a2993360e2675e6e873b1efe6015710 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:40 -0800 Subject: [PATCH 1163/4444] ARM: dts: Configure interconnect target module for omap5 dispc We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty until the child devices are probing with ti-sysc interconnect driver. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap5.dtsi | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index 13798be8ae79..0085befb289e 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi @@ -318,13 +318,37 @@ #size-cells = <1>; ranges = <0 0 0x1000000>; - dispc@1000 { - compatible = "ti,omap5-dispc"; - reg = <0x1000 0x1000>; - interrupts = ; + target-module@1000 { + compatible = "ti,sysc-omap2", "ti,sysc"; ti,hwmods = "dss_dispc"; + reg = <0x1000 0x4>, + <0x1010 0x4>, + <0x1014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-sidle = , + , + ; + ti,sysc-midle = , + , + ; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,syss-mask = <1>; clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>; clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x1000 0x1000>; + + dispc@0 { + compatible = "ti,omap5-dispc"; + reg = <0 0x1000>; + interrupts = ; + clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>; + clock-names = "fck"; + }; }; rfbi: encoder@2000 { From b9a4e149533bce526dd3a20eca94f95ba7165c40 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:40 -0800 Subject: [PATCH 1164/4444] ARM: dts: Configure interconnect target module for omap5 rfbi We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module and drop "ti,hwmods" peroperty as this module is a child node of dispc and has no dependencies to to legacy platform data. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap5.dtsi | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index 0085befb289e..e1bcbd6c7d4c 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi @@ -351,13 +351,31 @@ }; }; - rfbi: encoder@2000 { - compatible = "ti,omap5-rfbi"; - reg = <0x2000 0x100>; - status = "disabled"; - ti,hwmods = "dss_rfbi"; - clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>, <&l3_iclk_div>; - clock-names = "fck", "ick"; + target-module@2000 { + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x2000 0x4>, + <0x2010 0x4>, + <0x2014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-sidle = , + , + ; + ti,sysc-mask = <(SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,syss-mask = <1>; + clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x2000 0x1000>; + + rfbi: encoder@0 { + compatible = "ti,omap5-rfbi"; + reg = <0 0x100>; + status = "disabled"; + clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>, <&l3_iclk_div>; + clock-names = "fck", "ick"; + }; }; dsi1: encoder@4000 { From 5a507162f096b5411cbd6e19d03fef101f83d53f Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:40 -0800 Subject: [PATCH 1165/4444] ARM: dts: Configure interconnect target module for omap5 dsi1 We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module and drop "ti,hwmods" peroperty as this module is a child node of dispc and has no dependencies to to legacy platform data. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap5.dtsi | 41 +++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index e1bcbd6c7d4c..8b6f2a076e91 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi @@ -378,18 +378,35 @@ }; }; - dsi1: encoder@4000 { - compatible = "ti,omap5-dsi"; - reg = <0x4000 0x200>, - <0x4200 0x40>, - <0x4300 0x40>; - reg-names = "proto", "phy", "pll"; - interrupts = ; - status = "disabled"; - ti,hwmods = "dss_dsi1"; - clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>, - <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>; - clock-names = "fck", "sys_clk"; + target-module@5000 { + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x5000 0x4>, + <0x5010 0x4>, + <0x5014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-sidle = , + , + ; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,syss-mask = <1>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x5000 0x1000>; + + dsi1: encoder@0 { + compatible = "ti,omap5-dsi"; + reg = <0 0x200>, + <0x200 0x40>, + <0x300 0x40>; + reg-names = "proto", "phy", "pll"; + interrupts = ; + status = "disabled"; + clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>; + clock-names = "fck"; + }; }; dsi2: encoder@9000 { From 98e1a6a86a22d62aef465da083eb6879b0a80d34 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:41 -0800 Subject: [PATCH 1166/4444] ARM: dts: Configure interconnect target module for omap5 dsi2 We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module and drop "ti,hwmods" peroperty as this module is a child node of dispc and has no dependencies to to legacy platform data. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap5.dtsi | 41 +++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index 8b6f2a076e91..51fd1e2725ff 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi @@ -409,18 +409,35 @@ }; }; - dsi2: encoder@9000 { - compatible = "ti,omap5-dsi"; - reg = <0x9000 0x200>, - <0x9200 0x40>, - <0x9300 0x40>; - reg-names = "proto", "phy", "pll"; - interrupts = ; - status = "disabled"; - ti,hwmods = "dss_dsi2"; - clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>, - <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>; - clock-names = "fck", "sys_clk"; + target-module@9000 { + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x9000 0x4>, + <0x9010 0x4>, + <0x9014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-sidle = , + , + ; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,syss-mask = <1>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x9000 0x1000>; + + dsi2: encoder@0 { + compatible = "ti,omap5-dsi"; + reg = <0 0x200>, + <0x200 0x40>, + <0x300 0x40>; + reg-names = "proto", "phy", "pll"; + interrupts = ; + status = "disabled"; + clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>; + clock-names = "fck"; + }; }; hdmi: encoder@40000 { From 671ab615bd507f7108d72d77903f0e20dc03011e Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:41 -0800 Subject: [PATCH 1167/4444] ARM: dts: Configure interconnect target module for omap5 hdmi We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module and drop "ti,hwmods" peroperty as this module is a child node of dispc and has no dependencies to to legacy platform data. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap5.dtsi | 45 +++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index 51fd1e2725ff..86a8f08094a5 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi @@ -440,21 +440,38 @@ }; }; - hdmi: encoder@40000 { - compatible = "ti,omap5-hdmi"; - reg = <0x40000 0x200>, - <0x40200 0x80>, - <0x40300 0x80>, - <0x60000 0x19000>; - reg-names = "wp", "pll", "phy", "core"; - interrupts = ; - status = "disabled"; - ti,hwmods = "dss_hdmi"; + target-module@40000 { + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0x40000 0x4>, + <0x40010 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-sidle = , + , + , + ; + ti,sysc-mask = <(SYSC_OMAP4_SOFTRESET)>; clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 9>, - <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>; - clock-names = "fck", "sys_clk"; - dmas = <&sdma 76>; - dma-names = "audio_tx"; + <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>; + clock-names = "fck", "dss_clk"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x40000 0x40000>; + + hdmi: encoder@0 { + compatible = "ti,omap5-hdmi"; + reg = <0 0x200>, + <0x200 0x80>, + <0x300 0x80>, + <0x20000 0x19000>; + reg-names = "wp", "pll", "phy", "core"; + interrupts = ; + status = "disabled"; + clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 9>, + <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>; + clock-names = "fck", "sys_clk"; + dmas = <&sdma 76>; + dma-names = "audio_tx"; + }; }; }; }; From a50371f2efe830f5fbc9d52801f8d40227b8b522 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:41 -0800 Subject: [PATCH 1168/4444] ARM: dts: Configure interconnect target module for dra7 dss We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty until the child devices are probing with ti-sysc interconnect driver. Initially let's just update the top level dss node to probe with ti-sysc interconnect target module driver. The child nodes are still children of dispc, only the node indentation changes for them now along with using the reg range provided by top level dss. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7.dtsi | 82 +++++++++++++++++++++-------------- arch/arm/boot/dts/dra72x.dtsi | 6 +-- arch/arm/boot/dts/dra74x.dtsi | 10 ++--- 3 files changed, 57 insertions(+), 41 deletions(-) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index d78b684e7fca..cf90a0e7528c 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -705,44 +705,60 @@ ti,irqs-safe-map = <0>; }; - dss: dss@58000000 { - compatible = "ti,dra7-dss"; - /* 'reg' defined in dra72x.dtsi and dra74x.dtsi */ - /* 'clocks' defined in dra72x.dtsi and dra74x.dtsi */ - status = "disabled"; + target-module@58000000 { + compatible = "ti,sysc-omap2", "ti,sysc"; ti,hwmods = "dss_core"; - /* CTRL_CORE_DSS_PLL_CONTROL */ - syscon-pll-ctrl = <&scm_conf 0x538>; + reg = <0x58000000 4>, + <0x58000014 4>; + reg-names = "rev", "syss"; + ti,syss-mask = <1>; + clocks = <&dss_clkctrl DRA7_DSS_CORE_CLKCTRL 0>, + <&dss_clkctrl DRA7_DSS_CORE_CLKCTRL 9>, + <&dss_clkctrl DRA7_DSS_CORE_CLKCTRL 10>, + <&dss_clkctrl DRA7_DSS_CORE_CLKCTRL 11>; + clock-names = "fck", "hdmi_clk", "sys_clk", "tv_clk"; #address-cells = <1>; #size-cells = <1>; - ranges; + ranges = <0 0x58000000 0x800000>; - dispc@58001000 { - compatible = "ti,dra7-dispc"; - reg = <0x58001000 0x1000>; - interrupts = ; - ti,hwmods = "dss_dispc"; - clocks = <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 8>; - clock-names = "fck"; - /* CTRL_CORE_SMA_SW_1 */ - syscon-pol = <&scm_conf 0x534>; - }; - - hdmi: encoder@58060000 { - compatible = "ti,dra7-hdmi"; - reg = <0x58040000 0x200>, - <0x58040200 0x80>, - <0x58040300 0x80>, - <0x58060000 0x19000>; - reg-names = "wp", "pll", "phy", "core"; - interrupts = ; + dss: dss@0 { + compatible = "ti,dra7-dss"; + /* 'reg' defined in dra72x.dtsi and dra74x.dtsi */ + /* 'clocks' defined in dra72x.dtsi and dra74x.dtsi */ status = "disabled"; - ti,hwmods = "dss_hdmi"; - clocks = <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 9>, - <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 10>; - clock-names = "fck", "sys_clk"; - dmas = <&sdma_xbar 76>; - dma-names = "audio_tx"; + /* CTRL_CORE_DSS_PLL_CONTROL */ + syscon-pll-ctrl = <&scm_conf 0x538>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0x800000>; + + dispc@1000 { + compatible = "ti,dra7-dispc"; + reg = <0x1000 0x1000>; + interrupts = ; + ti,hwmods = "dss_dispc"; + clocks = <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 8>; + clock-names = "fck"; + /* CTRL_CORE_SMA_SW_1 */ + syscon-pol = <&scm_conf 0x534>; + }; + + hdmi: encoder@40000 { + compatible = "ti,dra7-hdmi"; + reg = <0x40000 0x200>, + <0x40200 0x80>, + <0x40300 0x80>, + <0x60000 0x19000>; + reg-names = "wp", "pll", "phy", "core"; + interrupts = ; + status = "disabled"; + ti,hwmods = "dss_hdmi"; + clocks = <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 9>, + <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 10>; + clock-names = "fck", "sys_clk"; + dmas = <&sdma_xbar 76>; + dma-names = "audio_tx"; + }; }; }; diff --git a/arch/arm/boot/dts/dra72x.dtsi b/arch/arm/boot/dts/dra72x.dtsi index 82b57a35abc0..da334489b18f 100644 --- a/arch/arm/boot/dts/dra72x.dtsi +++ b/arch/arm/boot/dts/dra72x.dtsi @@ -60,9 +60,9 @@ }; &dss { - reg = <0x58000000 0x80>, - <0x58004054 0x4>, - <0x58004300 0x20>; + reg = <0 0x80>, + <0x4054 0x4>, + <0x4300 0x20>; reg-names = "dss", "pll1_clkctrl", "pll1"; clocks = <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 8>, diff --git a/arch/arm/boot/dts/dra74x.dtsi b/arch/arm/boot/dts/dra74x.dtsi index c5abc436ca1f..7b1c61298253 100644 --- a/arch/arm/boot/dts/dra74x.dtsi +++ b/arch/arm/boot/dts/dra74x.dtsi @@ -132,11 +132,11 @@ }; &dss { - reg = <0x58000000 0x80>, - <0x58004054 0x4>, - <0x58004300 0x20>, - <0x58009054 0x4>, - <0x58009300 0x20>; + reg = <0 0x80>, + <0x4054 0x4>, + <0x4300 0x20>, + <0x9054 0x4>, + <0x9300 0x20>; reg-names = "dss", "pll1_clkctrl", "pll1", "pll2_clkctrl", "pll2"; From 9a95196c43ab1b6388c4b8a72e1a64d1f20d6046 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:42 -0800 Subject: [PATCH 1169/4444] ARM: dts: Configure interconnect target module for dra7 dispc We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty until the child devices are probing with ti-sysc interconnect driver. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7.dtsi | 40 +++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index cf90a0e7528c..594b53a79f16 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -732,15 +732,39 @@ #size-cells = <1>; ranges = <0 0 0x800000>; - dispc@1000 { - compatible = "ti,dra7-dispc"; - reg = <0x1000 0x1000>; - interrupts = ; - ti,hwmods = "dss_dispc"; - clocks = <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 8>; + target-module@1000 { + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x1000 0x4>, + <0x1010 0x4>, + <0x1014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-sidle = , + , + ; + ti,sysc-midle = , + , + ; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,syss-mask = <1>; + clocks = <&dss_clkctrl DRA7_DSS_CORE_CLKCTRL 8>; clock-names = "fck"; - /* CTRL_CORE_SMA_SW_1 */ - syscon-pol = <&scm_conf 0x534>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x1000 0x1000>; + + dispc@0 { + compatible = "ti,dra7-dispc"; + reg = <0 0x1000>; + interrupts = ; + ti,hwmods = "dss_dispc"; + clocks = <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 8>; + clock-names = "fck"; + /* CTRL_CORE_SMA_SW_1 */ + syscon-pol = <&scm_conf 0x534>; + }; }; hdmi: encoder@40000 { From c4f4728b03f61b967f4fba023b8aaec6ddaedb46 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:42 -0800 Subject: [PATCH 1170/4444] ARM: dts: Configure interconnect target module for dra7 hdmi We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module and drop "ti,hwmods" peroperty as this module is a child node of dispc and has no dependencies to to legacy platform data. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7.dtsi | 47 +++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 594b53a79f16..2849bed0614c 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -767,21 +767,38 @@ }; }; - hdmi: encoder@40000 { - compatible = "ti,dra7-hdmi"; - reg = <0x40000 0x200>, - <0x40200 0x80>, - <0x40300 0x80>, - <0x60000 0x19000>; - reg-names = "wp", "pll", "phy", "core"; - interrupts = ; - status = "disabled"; - ti,hwmods = "dss_hdmi"; - clocks = <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 9>, - <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 10>; - clock-names = "fck", "sys_clk"; - dmas = <&sdma_xbar 76>; - dma-names = "audio_tx"; + target-module@40000 { + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0x40000 0x4>, + <0x40010 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-sidle = , + , + , + ; + ti,sysc-mask = <(SYSC_OMAP4_SOFTRESET)>; + clocks = <&dss_clkctrl DRA7_DSS_CORE_CLKCTRL 9>, + <&dss_clkctrl DRA7_DSS_CORE_CLKCTRL 8>; + clock-names = "fck", "dss_clk"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x40000 0x40000>; + + hdmi: encoder@0 { + compatible = "ti,dra7-hdmi"; + reg = <0 0x200>, + <0x200 0x80>, + <0x300 0x80>, + <0x20000 0x19000>; + reg-names = "wp", "pll", "phy", "core"; + interrupts = ; + status = "disabled"; + clocks = <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 9>, + <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 10>; + clock-names = "fck", "sys_clk"; + dmas = <&sdma_xbar 76>; + dma-names = "audio_tx"; + }; }; }; }; From 3b6ff6bb5a8a53cf0c29fb51c5f7a14942cff90c Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:43 -0800 Subject: [PATCH 1171/4444] ARM: dts: Move am437x dss to the interconnect target module in l4 On am437x, the display subsystem (DSS) is on l4. We already have the interconnect target module for it, so let's just move dss there. To do that, we need to adjust the module addresses for the ranges, and use the ranges already added earlier based on reading the l4 interconnect instance AP registers. Cc: Jyri Sarha Cc: Keerthy Cc: Laurent Pinchart Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am4372.dtsi | 32 ----------------------------- arch/arm/boot/dts/am437x-l4.dtsi | 35 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index faa14dc0faff..830cce2bda2b 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -394,38 +394,6 @@ }; }; - dss: dss@4832a000 { - compatible = "ti,omap3-dss"; - reg = <0x4832a000 0x200>; - status = "disabled"; - ti,hwmods = "dss_core"; - clocks = <&disp_clk>; - clock-names = "fck"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - dispc: dispc@4832a400 { - compatible = "ti,omap3-dispc"; - reg = <0x4832a400 0x400>; - interrupts = ; - ti,hwmods = "dss_dispc"; - clocks = <&disp_clk>; - clock-names = "fck"; - - max-memory-bandwidth = <230000000>; - }; - - rfbi: rfbi@4832a800 { - compatible = "ti,omap3-rfbi"; - reg = <0x4832a800 0x100>; - ti,hwmods = "dss_rfbi"; - clocks = <&disp_clk>; - clock-names = "fck"; - status = "disabled"; - }; - }; - ocmcram: sram@40300000 { compatible = "mmio-sram"; reg = <0x40300000 0x40000>; /* 256k */ diff --git a/arch/arm/boot/dts/am437x-l4.dtsi b/arch/arm/boot/dts/am437x-l4.dtsi index e18e17d31272..fdcd792d023c 100644 --- a/arch/arm/boot/dts/am437x-l4.dtsi +++ b/arch/arm/boot/dts/am437x-l4.dtsi @@ -2135,6 +2135,41 @@ <0x00000800 0x0002a800 0x00000400>, <0x00000c00 0x0002ac00 0x00000400>, <0x00001000 0x0002b000 0x00001000>; + + dss: dss@0 { + compatible = "ti,omap3-dss"; + reg = <0 0x200>; + status = "disabled"; + clocks = <&disp_clk>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x00000000 0x00000400>, + <0x00000400 0x00000400 0x00000400>, + <0x00000800 0x00000800 0x00000400>, + <0x00000c00 0x00000c00 0x00000400>, + <0x00001000 0x00001000 0x00001000>; + + dispc: dispc@4000 { + compatible = "ti,omap3-dispc"; + reg = <0x400 0x400>; + interrupts = ; + ti,hwmods = "dss_dispc"; + clocks = <&disp_clk>; + clock-names = "fck"; + + max-memory-bandwidth = <230000000>; + }; + + rfbi: rfbi@800 { + compatible = "ti,omap3-rfbi"; + reg = <0x800 0x100>; + ti,hwmods = "dss_rfbi"; + clocks = <&disp_clk>; + clock-names = "fck"; + status = "disabled"; + }; + }; }; target-module@3d000 { /* 0x4833d000, ap 102 6e.0 */ From 9fd8a854d14ed88500e5488eeef368c603273e36 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:43 -0800 Subject: [PATCH 1172/4444] ARM: dts: Configure interconnect target module for am437x dispc We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty until the child devices are probing with ti-sysc interconnect driver. Note that we also fix a harmless typo for the node name, it's dispc@400, not dispc@4000. Cc: Jyri Sarha Cc: Keerthy Cc: Laurent Pinchart Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am437x-l4.dtsi | 36 ++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/am437x-l4.dtsi b/arch/arm/boot/dts/am437x-l4.dtsi index fdcd792d023c..87702517d964 100644 --- a/arch/arm/boot/dts/am437x-l4.dtsi +++ b/arch/arm/boot/dts/am437x-l4.dtsi @@ -2150,15 +2150,39 @@ <0x00000c00 0x00000c00 0x00000400>, <0x00001000 0x00001000 0x00001000>; - dispc: dispc@4000 { - compatible = "ti,omap3-dispc"; - reg = <0x400 0x400>; - interrupts = ; + target-module@400 { + compatible = "ti,sysc-omap2", "ti,sysc"; ti,hwmods = "dss_dispc"; - clocks = <&disp_clk>; + reg = <0x400 0x4>, + <0x410 0x4>, + <0x414 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-sidle = , + , + ; + ti,sysc-midle = , + , + ; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,syss-mask = <1>; + clocks = <&dss_clkctrl AM4_DSS_DSS_CORE_CLKCTRL 0>; clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x400 0x400>; - max-memory-bandwidth = <230000000>; + dispc: dispc@0 { + compatible = "ti,omap3-dispc"; + reg = <0 0x400>; + interrupts = ; + clocks = <&disp_clk>; + clock-names = "fck"; + + max-memory-bandwidth = <230000000>; + }; }; rfbi: rfbi@800 { From 11ef2bfc60add5514a8cee22adad513d8f954ad1 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:43 -0800 Subject: [PATCH 1173/4444] ARM: dts: Configure interconnect target module for am437x rfbi We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module and drop "ti,hwmods" peroperty as this module is a child node of dispc and has no dependencies to to legacy platform data. Cc: Jyri Sarha Cc: Keerthy Cc: Laurent Pinchart Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am437x-l4.dtsi | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/am437x-l4.dtsi b/arch/arm/boot/dts/am437x-l4.dtsi index 87702517d964..a0fba8c86224 100644 --- a/arch/arm/boot/dts/am437x-l4.dtsi +++ b/arch/arm/boot/dts/am437x-l4.dtsi @@ -2185,13 +2185,31 @@ }; }; - rfbi: rfbi@800 { - compatible = "ti,omap3-rfbi"; - reg = <0x800 0x100>; - ti,hwmods = "dss_rfbi"; - clocks = <&disp_clk>; + target-module@800 { + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x800 0x4>, + <0x810 0x4>, + <0x814 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-sidle = , + , + ; + ti,sysc-mask = <(SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,syss-mask = <1>; + clocks = <&dss_clkctrl AM4_DSS_DSS_CORE_CLKCTRL 0>; clock-names = "fck"; - status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x800 0x400>; + + rfbi: rfbi@0 { + compatible = "ti,omap3-rfbi"; + reg = <0 0x100>; + clocks = <&dss_clkctrl AM4_DSS_DSS_CORE_CLKCTRL 0>; + clock-names = "fck"; + status = "disabled"; + }; }; }; }; From a2ebc75fa9e05ba3d78221ed0f15ad3c554b6efd Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:44 -0800 Subject: [PATCH 1174/4444] ARM: OMAP2+: Drop legacy platform data for omap4 dss We can now probe devices with ti-sysc interconnect driver and dts data. Let's drop the related platform data and custom ti,hwmods dts property. As we're just dropping data, and the early platform data init is based on the custom ti,hwmods property, we want to drop both the platform data and ti,hwmods property in a single patch. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Sebastian Reichel Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap4.dtsi | 2 - arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 404 --------------------- 2 files changed, 406 deletions(-) diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index e5b647120b4d..650ca819cebf 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -421,7 +421,6 @@ */ target-module@58000000 { compatible = "ti,sysc-omap2", "ti,sysc"; - ti,hwmods = "dss_core"; reg = <0x58000000 4>, <0x58000014 4>; reg-names = "rev", "syss"; @@ -447,7 +446,6 @@ target-module@1000 { compatible = "ti,sysc-omap2", "ti,sysc"; - ti,hwmods = "dss_dispc"; reg = <0x1000 0x4>, <0x1010 0x4>, <0x1014 0x4>; diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index b7c51ea8c9a6..5de7c9581555 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -386,275 +386,6 @@ static struct omap_hwmod omap44xx_dsp_hwmod = { }, }; -/* - * 'dss' class - * display sub-system - */ - -static struct omap_hwmod_class_sysconfig omap44xx_dss_sysc = { - .rev_offs = 0x0000, - .syss_offs = 0x0014, - .sysc_flags = SYSS_HAS_RESET_STATUS, -}; - -static struct omap_hwmod_class omap44xx_dss_hwmod_class = { - .name = "dss", - .sysc = &omap44xx_dss_sysc, - .reset = omap_dss_reset, -}; - -/* dss */ -static struct omap_hwmod_opt_clk dss_opt_clks[] = { - { .role = "sys_clk", .clk = "dss_sys_clk" }, - { .role = "tv_clk", .clk = "dss_tv_clk" }, - { .role = "hdmi_clk", .clk = "dss_48mhz_clk" }, -}; - -static struct omap_hwmod omap44xx_dss_hwmod = { - .name = "dss_core", - .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, - .class = &omap44xx_dss_hwmod_class, - .clkdm_name = "l3_dss_clkdm", - .main_clk = "dss_dss_clk", - .prcm = { - .omap4 = { - .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET, - .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET, - .modulemode = MODULEMODE_SWCTRL, - }, - }, - .opt_clks = dss_opt_clks, - .opt_clks_cnt = ARRAY_SIZE(dss_opt_clks), -}; - -/* - * 'dispc' class - * display controller - */ - -static struct omap_hwmod_class_sysconfig omap44xx_dispc_sysc = { - .rev_offs = 0x0000, - .sysc_offs = 0x0010, - .syss_offs = 0x0014, - .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | - SYSC_HAS_ENAWAKEUP | SYSC_HAS_MIDLEMODE | - SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | - SYSS_HAS_RESET_STATUS), - .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | - MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), - .sysc_fields = &omap_hwmod_sysc_type1, -}; - -static struct omap_hwmod_class omap44xx_dispc_hwmod_class = { - .name = "dispc", - .sysc = &omap44xx_dispc_sysc, -}; - -/* dss_dispc */ -static struct omap_dss_dispc_dev_attr omap44xx_dss_dispc_dev_attr = { - .manager_count = 3, - .has_framedonetv_irq = 1 -}; - -static struct omap_hwmod omap44xx_dss_dispc_hwmod = { - .name = "dss_dispc", - .class = &omap44xx_dispc_hwmod_class, - .clkdm_name = "l3_dss_clkdm", - .main_clk = "dss_dss_clk", - .prcm = { - .omap4 = { - .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET, - .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET, - }, - }, - .dev_attr = &omap44xx_dss_dispc_dev_attr, - .parent_hwmod = &omap44xx_dss_hwmod, -}; - -/* - * 'dsi' class - * display serial interface controller - */ - -static struct omap_hwmod_class_sysconfig omap44xx_dsi_sysc = { - .rev_offs = 0x0000, - .sysc_offs = 0x0010, - .syss_offs = 0x0014, - .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | - SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE | - SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), - .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), - .sysc_fields = &omap_hwmod_sysc_type1, -}; - -static struct omap_hwmod_class omap44xx_dsi_hwmod_class = { - .name = "dsi", - .sysc = &omap44xx_dsi_sysc, -}; - -/* dss_dsi1 */ -static struct omap_hwmod_opt_clk dss_dsi1_opt_clks[] = { - { .role = "sys_clk", .clk = "dss_sys_clk" }, -}; - -static struct omap_hwmod omap44xx_dss_dsi1_hwmod = { - .name = "dss_dsi1", - .class = &omap44xx_dsi_hwmod_class, - .clkdm_name = "l3_dss_clkdm", - .main_clk = "dss_dss_clk", - .prcm = { - .omap4 = { - .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET, - .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET, - }, - }, - .opt_clks = dss_dsi1_opt_clks, - .opt_clks_cnt = ARRAY_SIZE(dss_dsi1_opt_clks), - .parent_hwmod = &omap44xx_dss_hwmod, -}; - -/* dss_dsi2 */ -static struct omap_hwmod_opt_clk dss_dsi2_opt_clks[] = { - { .role = "sys_clk", .clk = "dss_sys_clk" }, -}; - -static struct omap_hwmod omap44xx_dss_dsi2_hwmod = { - .name = "dss_dsi2", - .class = &omap44xx_dsi_hwmod_class, - .clkdm_name = "l3_dss_clkdm", - .main_clk = "dss_dss_clk", - .prcm = { - .omap4 = { - .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET, - .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET, - }, - }, - .opt_clks = dss_dsi2_opt_clks, - .opt_clks_cnt = ARRAY_SIZE(dss_dsi2_opt_clks), - .parent_hwmod = &omap44xx_dss_hwmod, -}; - -/* - * 'hdmi' class - * hdmi controller - */ - -static struct omap_hwmod_class_sysconfig omap44xx_hdmi_sysc = { - .rev_offs = 0x0000, - .sysc_offs = 0x0010, - .sysc_flags = (SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE | - SYSC_HAS_SOFTRESET), - .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | - SIDLE_SMART_WKUP), - .sysc_fields = &omap_hwmod_sysc_type2, -}; - -static struct omap_hwmod_class omap44xx_hdmi_hwmod_class = { - .name = "hdmi", - .sysc = &omap44xx_hdmi_sysc, -}; - -/* dss_hdmi */ -static struct omap_hwmod_opt_clk dss_hdmi_opt_clks[] = { - { .role = "sys_clk", .clk = "dss_sys_clk" }, - { .role = "hdmi_clk", .clk = "dss_48mhz_clk" }, -}; - -static struct omap_hwmod omap44xx_dss_hdmi_hwmod = { - .name = "dss_hdmi", - .class = &omap44xx_hdmi_hwmod_class, - .clkdm_name = "l3_dss_clkdm", - /* - * HDMI audio requires to use no-idle mode. Hence, - * set idle mode by software. - */ - .flags = HWMOD_SWSUP_SIDLE | HWMOD_OPT_CLKS_NEEDED, - .main_clk = "dss_48mhz_clk", - .prcm = { - .omap4 = { - .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET, - .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET, - }, - }, - .opt_clks = dss_hdmi_opt_clks, - .opt_clks_cnt = ARRAY_SIZE(dss_hdmi_opt_clks), - .parent_hwmod = &omap44xx_dss_hwmod, -}; - -/* - * 'rfbi' class - * remote frame buffer interface - */ - -static struct omap_hwmod_class_sysconfig omap44xx_rfbi_sysc = { - .rev_offs = 0x0000, - .sysc_offs = 0x0010, - .syss_offs = 0x0014, - .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE | - SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), - .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), - .sysc_fields = &omap_hwmod_sysc_type1, -}; - -static struct omap_hwmod_class omap44xx_rfbi_hwmod_class = { - .name = "rfbi", - .sysc = &omap44xx_rfbi_sysc, -}; - -/* dss_rfbi */ -static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = { - { .role = "ick", .clk = "l3_div_ck" }, -}; - -static struct omap_hwmod omap44xx_dss_rfbi_hwmod = { - .name = "dss_rfbi", - .class = &omap44xx_rfbi_hwmod_class, - .clkdm_name = "l3_dss_clkdm", - .main_clk = "dss_dss_clk", - .prcm = { - .omap4 = { - .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET, - .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET, - }, - }, - .opt_clks = dss_rfbi_opt_clks, - .opt_clks_cnt = ARRAY_SIZE(dss_rfbi_opt_clks), - .parent_hwmod = &omap44xx_dss_hwmod, -}; - -/* - * 'venc' class - * video encoder - */ - -static struct omap_hwmod_class omap44xx_venc_hwmod_class = { - .name = "venc", -}; - -/* dss_venc */ -static struct omap_hwmod_opt_clk dss_venc_opt_clks[] = { - { .role = "tv_clk", .clk = "dss_tv_clk" }, -}; - -static struct omap_hwmod omap44xx_dss_venc_hwmod = { - .name = "dss_venc", - .class = &omap44xx_venc_hwmod_class, - .clkdm_name = "l3_dss_clkdm", - .main_clk = "dss_tv_clk", - .flags = HWMOD_OPT_CLKS_NEEDED, - .prcm = { - .omap4 = { - .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET, - .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET, - }, - }, - .parent_hwmod = &omap44xx_dss_hwmod, - .opt_clks = dss_venc_opt_clks, - .opt_clks_cnt = ARRAY_SIZE(dss_venc_opt_clks), -}; - - - /* * 'emif' class * external memory interface no1 @@ -1244,14 +975,6 @@ static struct omap_hwmod_ocp_if omap44xx_dsp__l3_main_1 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; -/* dss -> l3_main_1 */ -static struct omap_hwmod_ocp_if omap44xx_dss__l3_main_1 = { - .master = &omap44xx_dss_hwmod, - .slave = &omap44xx_l3_main_1_hwmod, - .clk = "l3_div_ck", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - /* l3_main_2 -> l3_main_1 */ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l3_main_1 = { .master = &omap44xx_l3_main_2_hwmod, @@ -1500,118 +1223,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__dsp = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; -/* l3_main_2 -> dss */ -static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = { - .master = &omap44xx_l3_main_2_hwmod, - .slave = &omap44xx_dss_hwmod, - .clk = "l3_div_ck", - .user = OCP_USER_SDMA, -}; - -/* l4_per -> dss */ -static struct omap_hwmod_ocp_if omap44xx_l4_per__dss = { - .master = &omap44xx_l4_per_hwmod, - .slave = &omap44xx_dss_hwmod, - .clk = "l4_div_ck", - .user = OCP_USER_MPU, -}; - -/* l3_main_2 -> dss_dispc */ -static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dispc = { - .master = &omap44xx_l3_main_2_hwmod, - .slave = &omap44xx_dss_dispc_hwmod, - .clk = "l3_div_ck", - .user = OCP_USER_SDMA, -}; - -/* l4_per -> dss_dispc */ -static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dispc = { - .master = &omap44xx_l4_per_hwmod, - .slave = &omap44xx_dss_dispc_hwmod, - .clk = "l4_div_ck", - .user = OCP_USER_MPU, -}; - -/* l3_main_2 -> dss_dsi1 */ -static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi1 = { - .master = &omap44xx_l3_main_2_hwmod, - .slave = &omap44xx_dss_dsi1_hwmod, - .clk = "l3_div_ck", - .user = OCP_USER_SDMA, -}; - -/* l4_per -> dss_dsi1 */ -static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dsi1 = { - .master = &omap44xx_l4_per_hwmod, - .slave = &omap44xx_dss_dsi1_hwmod, - .clk = "l4_div_ck", - .user = OCP_USER_MPU, -}; - -/* l3_main_2 -> dss_dsi2 */ -static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi2 = { - .master = &omap44xx_l3_main_2_hwmod, - .slave = &omap44xx_dss_dsi2_hwmod, - .clk = "l3_div_ck", - .user = OCP_USER_SDMA, -}; - -/* l4_per -> dss_dsi2 */ -static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dsi2 = { - .master = &omap44xx_l4_per_hwmod, - .slave = &omap44xx_dss_dsi2_hwmod, - .clk = "l4_div_ck", - .user = OCP_USER_MPU, -}; - -/* l3_main_2 -> dss_hdmi */ -static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_hdmi = { - .master = &omap44xx_l3_main_2_hwmod, - .slave = &omap44xx_dss_hdmi_hwmod, - .clk = "l3_div_ck", - .user = OCP_USER_SDMA, -}; - -/* l4_per -> dss_hdmi */ -static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_hdmi = { - .master = &omap44xx_l4_per_hwmod, - .slave = &omap44xx_dss_hdmi_hwmod, - .clk = "l4_div_ck", - .user = OCP_USER_MPU, -}; - -/* l3_main_2 -> dss_rfbi */ -static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_rfbi = { - .master = &omap44xx_l3_main_2_hwmod, - .slave = &omap44xx_dss_rfbi_hwmod, - .clk = "l3_div_ck", - .user = OCP_USER_SDMA, -}; - -/* l4_per -> dss_rfbi */ -static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_rfbi = { - .master = &omap44xx_l4_per_hwmod, - .slave = &omap44xx_dss_rfbi_hwmod, - .clk = "l4_div_ck", - .user = OCP_USER_MPU, -}; - -/* l3_main_2 -> dss_venc */ -static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_venc = { - .master = &omap44xx_l3_main_2_hwmod, - .slave = &omap44xx_dss_venc_hwmod, - .clk = "l3_div_ck", - .user = OCP_USER_SDMA, -}; - -/* l4_per -> dss_venc */ -static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_venc = { - .master = &omap44xx_l4_per_hwmod, - .slave = &omap44xx_dss_venc_hwmod, - .clk = "l4_div_ck", - .user = OCP_USER_MPU, -}; - /* l3_main_2 -> gpmc */ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__gpmc = { .master = &omap44xx_l3_main_2_hwmod, @@ -1763,7 +1374,6 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { &omap44xx_l3_main_3__l3_instr, &omap44xx_ocp_wp_noc__l3_instr, &omap44xx_dsp__l3_main_1, - &omap44xx_dss__l3_main_1, &omap44xx_l3_main_2__l3_main_1, &omap44xx_l4_cfg__l3_main_1, &omap44xx_mpu__l3_main_1, @@ -1795,20 +1405,6 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { &omap44xx_dsp__iva, /* &omap44xx_dsp__sl2if, */ &omap44xx_l4_cfg__dsp, - &omap44xx_l3_main_2__dss, - &omap44xx_l4_per__dss, - &omap44xx_l3_main_2__dss_dispc, - &omap44xx_l4_per__dss_dispc, - &omap44xx_l3_main_2__dss_dsi1, - &omap44xx_l4_per__dss_dsi1, - &omap44xx_l3_main_2__dss_dsi2, - &omap44xx_l4_per__dss_dsi2, - &omap44xx_l3_main_2__dss_hdmi, - &omap44xx_l4_per__dss_hdmi, - &omap44xx_l3_main_2__dss_rfbi, - &omap44xx_l4_per__dss_rfbi, - &omap44xx_l3_main_2__dss_venc, - &omap44xx_l4_per__dss_venc, &omap44xx_l3_main_2__gpmc, &omap44xx_l3_main_2__ipu, &omap44xx_l3_main_2__iss, From 19da9c0ece415b069fe686ab1bc72a7255f8ba56 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:44 -0800 Subject: [PATCH 1175/4444] ARM: OMAP2+: Drop legacy platform data for omap5 DSS We can now probe devices with ti-sysc interconnect driver and dts data. Let's drop the related platform data and custom ti,hwmods dts property. As we're just dropping data, and the early platform data init is based on the custom ti,hwmods property, we want to drop both the platform data and ti,hwmods property in a single patch. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap5.dtsi | 2 - arch/arm/mach-omap2/omap_hwmod_54xx_data.c | 288 --------------------- 2 files changed, 290 deletions(-) diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index 86a8f08094a5..cdcbb297c233 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi @@ -294,7 +294,6 @@ target-module@58000000 { compatible = "ti,sysc-omap2", "ti,sysc"; - ti,hwmods = "dss_core"; reg = <0x58000000 4>, <0x58000014 4>; reg-names = "rev", "syss"; @@ -320,7 +319,6 @@ target-module@1000 { compatible = "ti,sysc-omap2", "ti,sysc"; - ti,hwmods = "dss_dispc"; reg = <0x1000 0x4>, <0x1010 0x4>, <0x1014 0x4>; diff --git a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c index ad398f6bc011..08f34f4732fd 100644 --- a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c @@ -226,240 +226,6 @@ static struct omap_hwmod omap54xx_counter_32k_hwmod = { }, }; -/* - * 'dss' class - * display sub-system - */ -static struct omap_hwmod_class_sysconfig omap54xx_dss_sysc = { - .rev_offs = 0x0000, - .syss_offs = 0x0014, - .sysc_flags = SYSS_HAS_RESET_STATUS, -}; - -static struct omap_hwmod_class omap54xx_dss_hwmod_class = { - .name = "dss", - .sysc = &omap54xx_dss_sysc, - .reset = omap_dss_reset, -}; - -/* dss */ -static struct omap_hwmod_opt_clk dss_opt_clks[] = { - { .role = "32khz_clk", .clk = "dss_32khz_clk" }, - { .role = "sys_clk", .clk = "dss_sys_clk" }, - { .role = "hdmi_clk", .clk = "dss_48mhz_clk" }, -}; - -static struct omap_hwmod omap54xx_dss_hwmod = { - .name = "dss_core", - .class = &omap54xx_dss_hwmod_class, - .clkdm_name = "dss_clkdm", - .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, - .main_clk = "dss_dss_clk", - .prcm = { - .omap4 = { - .clkctrl_offs = OMAP54XX_CM_DSS_DSS_CLKCTRL_OFFSET, - .context_offs = OMAP54XX_RM_DSS_DSS_CONTEXT_OFFSET, - .modulemode = MODULEMODE_SWCTRL, - }, - }, - .opt_clks = dss_opt_clks, - .opt_clks_cnt = ARRAY_SIZE(dss_opt_clks), -}; - -/* - * 'dispc' class - * display controller - */ - -static struct omap_hwmod_class_sysconfig omap54xx_dispc_sysc = { - .rev_offs = 0x0000, - .sysc_offs = 0x0010, - .syss_offs = 0x0014, - .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | - SYSC_HAS_ENAWAKEUP | SYSC_HAS_MIDLEMODE | - SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | - SYSS_HAS_RESET_STATUS), - .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | - MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), - .sysc_fields = &omap_hwmod_sysc_type1, -}; - -static struct omap_hwmod_class omap54xx_dispc_hwmod_class = { - .name = "dispc", - .sysc = &omap54xx_dispc_sysc, -}; - -/* dss_dispc */ -static struct omap_hwmod_opt_clk dss_dispc_opt_clks[] = { - { .role = "sys_clk", .clk = "dss_sys_clk" }, -}; - -/* dss_dispc dev_attr */ -static struct omap_dss_dispc_dev_attr dss_dispc_dev_attr = { - .has_framedonetv_irq = 1, - .manager_count = 4, -}; - -static struct omap_hwmod omap54xx_dss_dispc_hwmod = { - .name = "dss_dispc", - .class = &omap54xx_dispc_hwmod_class, - .clkdm_name = "dss_clkdm", - .main_clk = "dss_dss_clk", - .prcm = { - .omap4 = { - .clkctrl_offs = OMAP54XX_CM_DSS_DSS_CLKCTRL_OFFSET, - .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, - }, - }, - .opt_clks = dss_dispc_opt_clks, - .opt_clks_cnt = ARRAY_SIZE(dss_dispc_opt_clks), - .dev_attr = &dss_dispc_dev_attr, - .parent_hwmod = &omap54xx_dss_hwmod, -}; - -/* - * 'dsi1' class - * display serial interface controller - */ - -static struct omap_hwmod_class_sysconfig omap54xx_dsi1_sysc = { - .rev_offs = 0x0000, - .sysc_offs = 0x0010, - .syss_offs = 0x0014, - .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | - SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE | - SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), - .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), - .sysc_fields = &omap_hwmod_sysc_type1, -}; - -static struct omap_hwmod_class omap54xx_dsi1_hwmod_class = { - .name = "dsi1", - .sysc = &omap54xx_dsi1_sysc, -}; - -/* dss_dsi1_a */ -static struct omap_hwmod_opt_clk dss_dsi1_a_opt_clks[] = { - { .role = "sys_clk", .clk = "dss_sys_clk" }, -}; - -static struct omap_hwmod omap54xx_dss_dsi1_a_hwmod = { - .name = "dss_dsi1", - .class = &omap54xx_dsi1_hwmod_class, - .clkdm_name = "dss_clkdm", - .main_clk = "dss_dss_clk", - .prcm = { - .omap4 = { - .clkctrl_offs = OMAP54XX_CM_DSS_DSS_CLKCTRL_OFFSET, - .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, - }, - }, - .opt_clks = dss_dsi1_a_opt_clks, - .opt_clks_cnt = ARRAY_SIZE(dss_dsi1_a_opt_clks), - .parent_hwmod = &omap54xx_dss_hwmod, -}; - -/* dss_dsi1_c */ -static struct omap_hwmod_opt_clk dss_dsi1_c_opt_clks[] = { - { .role = "sys_clk", .clk = "dss_sys_clk" }, -}; - -static struct omap_hwmod omap54xx_dss_dsi1_c_hwmod = { - .name = "dss_dsi2", - .class = &omap54xx_dsi1_hwmod_class, - .clkdm_name = "dss_clkdm", - .main_clk = "dss_dss_clk", - .prcm = { - .omap4 = { - .clkctrl_offs = OMAP54XX_CM_DSS_DSS_CLKCTRL_OFFSET, - .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, - }, - }, - .opt_clks = dss_dsi1_c_opt_clks, - .opt_clks_cnt = ARRAY_SIZE(dss_dsi1_c_opt_clks), - .parent_hwmod = &omap54xx_dss_hwmod, -}; - -/* - * 'hdmi' class - * hdmi controller - */ - -static struct omap_hwmod_class_sysconfig omap54xx_hdmi_sysc = { - .rev_offs = 0x0000, - .sysc_offs = 0x0010, - .sysc_flags = (SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE | - SYSC_HAS_SOFTRESET), - .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | - SIDLE_SMART_WKUP), - .sysc_fields = &omap_hwmod_sysc_type2, -}; - -static struct omap_hwmod_class omap54xx_hdmi_hwmod_class = { - .name = "hdmi", - .sysc = &omap54xx_hdmi_sysc, -}; - -static struct omap_hwmod_opt_clk dss_hdmi_opt_clks[] = { - { .role = "sys_clk", .clk = "dss_sys_clk" }, -}; - -static struct omap_hwmod omap54xx_dss_hdmi_hwmod = { - .name = "dss_hdmi", - .class = &omap54xx_hdmi_hwmod_class, - .clkdm_name = "dss_clkdm", - .main_clk = "dss_48mhz_clk", - .prcm = { - .omap4 = { - .clkctrl_offs = OMAP54XX_CM_DSS_DSS_CLKCTRL_OFFSET, - .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, - }, - }, - .opt_clks = dss_hdmi_opt_clks, - .opt_clks_cnt = ARRAY_SIZE(dss_hdmi_opt_clks), - .parent_hwmod = &omap54xx_dss_hwmod, -}; - -/* - * 'rfbi' class - * remote frame buffer interface - */ - -static struct omap_hwmod_class_sysconfig omap54xx_rfbi_sysc = { - .rev_offs = 0x0000, - .sysc_offs = 0x0010, - .syss_offs = 0x0014, - .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE | - SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), - .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), - .sysc_fields = &omap_hwmod_sysc_type1, -}; - -static struct omap_hwmod_class omap54xx_rfbi_hwmod_class = { - .name = "rfbi", - .sysc = &omap54xx_rfbi_sysc, -}; - -/* dss_rfbi */ -static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = { - { .role = "ick", .clk = "l3_iclk_div" }, -}; - -static struct omap_hwmod omap54xx_dss_rfbi_hwmod = { - .name = "dss_rfbi", - .class = &omap54xx_rfbi_hwmod_class, - .clkdm_name = "dss_clkdm", - .prcm = { - .omap4 = { - .clkctrl_offs = OMAP54XX_CM_DSS_DSS_CLKCTRL_OFFSET, - .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, - }, - }, - .opt_clks = dss_rfbi_opt_clks, - .opt_clks_cnt = ARRAY_SIZE(dss_rfbi_opt_clks), - .parent_hwmod = &omap54xx_dss_hwmod, -}; - /* * 'emif' class * external memory interface no1 (wrapper) @@ -908,54 +674,6 @@ static struct omap_hwmod_ocp_if omap54xx_l4_wkup__counter_32k = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; -/* l3_main_2 -> dss */ -static struct omap_hwmod_ocp_if omap54xx_l3_main_2__dss = { - .master = &omap54xx_l3_main_2_hwmod, - .slave = &omap54xx_dss_hwmod, - .clk = "l3_iclk_div", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - -/* l3_main_2 -> dss_dispc */ -static struct omap_hwmod_ocp_if omap54xx_l3_main_2__dss_dispc = { - .master = &omap54xx_l3_main_2_hwmod, - .slave = &omap54xx_dss_dispc_hwmod, - .clk = "l3_iclk_div", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - -/* l3_main_2 -> dss_dsi1_a */ -static struct omap_hwmod_ocp_if omap54xx_l3_main_2__dss_dsi1_a = { - .master = &omap54xx_l3_main_2_hwmod, - .slave = &omap54xx_dss_dsi1_a_hwmod, - .clk = "l3_iclk_div", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - -/* l3_main_2 -> dss_dsi1_c */ -static struct omap_hwmod_ocp_if omap54xx_l3_main_2__dss_dsi1_c = { - .master = &omap54xx_l3_main_2_hwmod, - .slave = &omap54xx_dss_dsi1_c_hwmod, - .clk = "l3_iclk_div", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - -/* l3_main_2 -> dss_hdmi */ -static struct omap_hwmod_ocp_if omap54xx_l3_main_2__dss_hdmi = { - .master = &omap54xx_l3_main_2_hwmod, - .slave = &omap54xx_dss_hdmi_hwmod, - .clk = "l3_iclk_div", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - -/* l3_main_2 -> dss_rfbi */ -static struct omap_hwmod_ocp_if omap54xx_l3_main_2__dss_rfbi = { - .master = &omap54xx_l3_main_2_hwmod, - .slave = &omap54xx_dss_rfbi_hwmod, - .clk = "l3_iclk_div", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - /* mpu -> emif1 */ static struct omap_hwmod_ocp_if omap54xx_mpu__emif1 = { .master = &omap54xx_mpu_hwmod, @@ -1030,12 +748,6 @@ static struct omap_hwmod_ocp_if *omap54xx_hwmod_ocp_ifs[] __initdata = { &omap54xx_l3_main_1__l4_wkup, &omap54xx_mpu__mpu_private, &omap54xx_l4_wkup__counter_32k, - &omap54xx_l3_main_2__dss, - &omap54xx_l3_main_2__dss_dispc, - &omap54xx_l3_main_2__dss_dsi1_a, - &omap54xx_l3_main_2__dss_dsi1_c, - &omap54xx_l3_main_2__dss_hdmi, - &omap54xx_l3_main_2__dss_rfbi, &omap54xx_mpu__emif1, &omap54xx_mpu__emif2, &omap54xx_l4_cfg__mpu, From 6fa1a9863c3c020f87ffe4fb7904a61897a22b1c Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:44 -0800 Subject: [PATCH 1176/4444] ARM: OMAP2+: Drop legacy platform data for dra7 DSS We can now probe devices with ti-sysc interconnect driver and dts data. Let's drop the related platform data and custom ti,hwmods dts property. As we're just dropping data, and the early platform data init is based on the custom ti,hwmods property, we want to drop both the platform data and ti,hwmods property in a single patch. Cc: Jyri Sarha Cc: Laurent Pinchart Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7.dtsi | 2 - arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 163 ---------------------- 2 files changed, 165 deletions(-) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 2849bed0614c..4be7f22113f6 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -707,7 +707,6 @@ target-module@58000000 { compatible = "ti,sysc-omap2", "ti,sysc"; - ti,hwmods = "dss_core"; reg = <0x58000000 4>, <0x58000014 4>; reg-names = "rev", "syss"; @@ -759,7 +758,6 @@ compatible = "ti,dra7-dispc"; reg = <0 0x1000>; interrupts = ; - ti,hwmods = "dss_dispc"; clocks = <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 8>; clock-names = "fck"; /* CTRL_CORE_SMA_SW_1 */ diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c index acef3733db4c..2f60333caaf1 100644 --- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c @@ -337,142 +337,6 @@ static struct omap_hwmod dra7xx_tptc1_hwmod = { }, }; -/* - * 'dss' class - * - */ - -static struct omap_hwmod_class_sysconfig dra7xx_dss_sysc = { - .rev_offs = 0x0000, - .syss_offs = 0x0014, - .sysc_flags = SYSS_HAS_RESET_STATUS, -}; - -static struct omap_hwmod_class dra7xx_dss_hwmod_class = { - .name = "dss", - .sysc = &dra7xx_dss_sysc, - .reset = omap_dss_reset, -}; - -/* dss */ -static struct omap_hwmod_opt_clk dss_opt_clks[] = { - { .role = "dss_clk", .clk = "dss_dss_clk" }, - { .role = "hdmi_phy_clk", .clk = "dss_48mhz_clk" }, - { .role = "32khz_clk", .clk = "dss_32khz_clk" }, - { .role = "video2_clk", .clk = "dss_video2_clk" }, - { .role = "video1_clk", .clk = "dss_video1_clk" }, - { .role = "hdmi_clk", .clk = "dss_hdmi_clk" }, - { .role = "hdcp_clk", .clk = "dss_deshdcp_clk" }, -}; - -static struct omap_hwmod dra7xx_dss_hwmod = { - .name = "dss_core", - .class = &dra7xx_dss_hwmod_class, - .clkdm_name = "dss_clkdm", - .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, - .main_clk = "dss_dss_clk", - .prcm = { - .omap4 = { - .clkctrl_offs = DRA7XX_CM_DSS_DSS_CLKCTRL_OFFSET, - .context_offs = DRA7XX_RM_DSS_DSS_CONTEXT_OFFSET, - .modulemode = MODULEMODE_SWCTRL, - }, - }, - .opt_clks = dss_opt_clks, - .opt_clks_cnt = ARRAY_SIZE(dss_opt_clks), -}; - -/* - * 'dispc' class - * display controller - */ - -static struct omap_hwmod_class_sysconfig dra7xx_dispc_sysc = { - .rev_offs = 0x0000, - .sysc_offs = 0x0010, - .syss_offs = 0x0014, - .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | - SYSC_HAS_ENAWAKEUP | SYSC_HAS_MIDLEMODE | - SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | - SYSS_HAS_RESET_STATUS), - .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | - MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), - .sysc_fields = &omap_hwmod_sysc_type1, -}; - -static struct omap_hwmod_class dra7xx_dispc_hwmod_class = { - .name = "dispc", - .sysc = &dra7xx_dispc_sysc, -}; - -/* dss_dispc */ -/* dss_dispc dev_attr */ -static struct omap_dss_dispc_dev_attr dss_dispc_dev_attr = { - .has_framedonetv_irq = 1, - .manager_count = 4, -}; - -static struct omap_hwmod dra7xx_dss_dispc_hwmod = { - .name = "dss_dispc", - .class = &dra7xx_dispc_hwmod_class, - .clkdm_name = "dss_clkdm", - .main_clk = "dss_dss_clk", - .prcm = { - .omap4 = { - .clkctrl_offs = DRA7XX_CM_DSS_DSS_CLKCTRL_OFFSET, - .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, - }, - }, - .dev_attr = &dss_dispc_dev_attr, - .parent_hwmod = &dra7xx_dss_hwmod, -}; - -/* - * 'hdmi' class - * hdmi controller - */ - -static struct omap_hwmod_class_sysconfig dra7xx_hdmi_sysc = { - .rev_offs = 0x0000, - .sysc_offs = 0x0010, - .sysc_flags = (SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE | - SYSC_HAS_SOFTRESET), - .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | - SIDLE_SMART_WKUP), - .sysc_fields = &omap_hwmod_sysc_type2, -}; - -static struct omap_hwmod_class dra7xx_hdmi_hwmod_class = { - .name = "hdmi", - .sysc = &dra7xx_hdmi_sysc, -}; - -/* dss_hdmi */ - -static struct omap_hwmod_opt_clk dss_hdmi_opt_clks[] = { - { .role = "sys_clk", .clk = "dss_hdmi_clk" }, -}; - -static struct omap_hwmod dra7xx_dss_hdmi_hwmod = { - .name = "dss_hdmi", - .class = &dra7xx_hdmi_hwmod_class, - .clkdm_name = "dss_clkdm", - .main_clk = "dss_48mhz_clk", - .prcm = { - .omap4 = { - .clkctrl_offs = DRA7XX_CM_DSS_DSS_CLKCTRL_OFFSET, - .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, - }, - }, - .opt_clks = dss_hdmi_opt_clks, - .opt_clks_cnt = ARRAY_SIZE(dss_hdmi_opt_clks), - .parent_hwmod = &dra7xx_dss_hwmod, -}; - - - - - /* * 'gpmc' class * @@ -1101,30 +965,6 @@ static struct omap_hwmod_ocp_if dra7xx_l3_main_1__tptc1 = { .user = OCP_USER_MPU, }; -/* l3_main_1 -> dss */ -static struct omap_hwmod_ocp_if dra7xx_l3_main_1__dss = { - .master = &dra7xx_l3_main_1_hwmod, - .slave = &dra7xx_dss_hwmod, - .clk = "l3_iclk_div", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - -/* l3_main_1 -> dispc */ -static struct omap_hwmod_ocp_if dra7xx_l3_main_1__dispc = { - .master = &dra7xx_l3_main_1_hwmod, - .slave = &dra7xx_dss_dispc_hwmod, - .clk = "l3_iclk_div", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - -/* l3_main_1 -> dispc */ -static struct omap_hwmod_ocp_if dra7xx_l3_main_1__hdmi = { - .master = &dra7xx_l3_main_1_hwmod, - .slave = &dra7xx_dss_hdmi_hwmod, - .clk = "l3_iclk_div", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - /* l3_main_1 -> gpmc */ static struct omap_hwmod_ocp_if dra7xx_l3_main_1__gpmc = { .master = &dra7xx_l3_main_1_hwmod, @@ -1312,9 +1152,6 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = { &dra7xx_l3_main_1__tpcc, &dra7xx_l3_main_1__tptc0, &dra7xx_l3_main_1__tptc1, - &dra7xx_l3_main_1__dss, - &dra7xx_l3_main_1__dispc, - &dra7xx_l3_main_1__hdmi, &dra7xx_l3_main_1__gpmc, &dra7xx_l4_cfg__mpu, &dra7xx_l3_main_1__pciess1, From c760f610c96628623dd5355ef01551e7d191b598 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 08:10:45 -0800 Subject: [PATCH 1177/4444] ARM: OMAP2+: Drop legacy platform data for am437x DSS We can now probe devices with ti-sysc interconnect driver and dts data. Let's drop the related platform data and custom ti,hwmods dts property. As we're just dropping data, and the early platform data init is based on the custom ti,hwmods property, we want to drop both the platform data and ti,hwmods property in a single patch. Cc: Jyri Sarha Cc: Keerthy Cc: Laurent Pinchart Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am437x-l4.dtsi | 2 - arch/arm/mach-omap2/omap_hwmod_43xx_data.c | 101 --------------------- 2 files changed, 103 deletions(-) diff --git a/arch/arm/boot/dts/am437x-l4.dtsi b/arch/arm/boot/dts/am437x-l4.dtsi index a0fba8c86224..49c6a872052e 100644 --- a/arch/arm/boot/dts/am437x-l4.dtsi +++ b/arch/arm/boot/dts/am437x-l4.dtsi @@ -2117,7 +2117,6 @@ target-module@2a000 { /* 0x4832a000, ap 88 3c.0 */ compatible = "ti,sysc-omap2", "ti,sysc"; - ti,hwmods = "dss_core"; reg = <0x2a000 0x4>, <0x2a010 0x4>, <0x2a014 0x4>; @@ -2152,7 +2151,6 @@ target-module@400 { compatible = "ti,sysc-omap2", "ti,sysc"; - ti,hwmods = "dss_dispc"; reg = <0x400 0x4>, <0x410 0x4>, <0x414 0x4>; diff --git a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c index d0867dbd788e..b2b9753ca483 100644 --- a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c @@ -156,75 +156,6 @@ static struct omap_hwmod am43xx_usb_otg_ss1_hwmod = { }, }; -/* dss */ - -static struct omap_hwmod am43xx_dss_core_hwmod = { - .name = "dss_core", - .class = &omap2_dss_hwmod_class, - .clkdm_name = "dss_clkdm", - .main_clk = "disp_clk", - .prcm = { - .omap4 = { - .clkctrl_offs = AM43XX_CM_PER_DSS_CLKCTRL_OFFSET, - .modulemode = MODULEMODE_SWCTRL, - }, - }, -}; - -/* dispc */ - -static struct omap_dss_dispc_dev_attr am43xx_dss_dispc_dev_attr = { - .manager_count = 1, - .has_framedonetv_irq = 0 -}; - -static struct omap_hwmod_class_sysconfig am43xx_dispc_sysc = { - .rev_offs = 0x0000, - .sysc_offs = 0x0010, - .syss_offs = 0x0014, - .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SOFTRESET | - SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE | - SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_MIDLEMODE), - .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | - MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), - .sysc_fields = &omap_hwmod_sysc_type1, -}; - -static struct omap_hwmod_class am43xx_dispc_hwmod_class = { - .name = "dispc", - .sysc = &am43xx_dispc_sysc, -}; - -static struct omap_hwmod am43xx_dss_dispc_hwmod = { - .name = "dss_dispc", - .class = &am43xx_dispc_hwmod_class, - .clkdm_name = "dss_clkdm", - .main_clk = "disp_clk", - .prcm = { - .omap4 = { - .clkctrl_offs = AM43XX_CM_PER_DSS_CLKCTRL_OFFSET, - }, - }, - .dev_attr = &am43xx_dss_dispc_dev_attr, - .parent_hwmod = &am43xx_dss_core_hwmod, -}; - -/* rfbi */ - -static struct omap_hwmod am43xx_dss_rfbi_hwmod = { - .name = "dss_rfbi", - .class = &omap2_rfbi_hwmod_class, - .clkdm_name = "dss_clkdm", - .main_clk = "disp_clk", - .prcm = { - .omap4 = { - .clkctrl_offs = AM43XX_CM_PER_DSS_CLKCTRL_OFFSET, - }, - }, - .parent_hwmod = &am43xx_dss_core_hwmod, -}; - - /* Interfaces */ static struct omap_hwmod_ocp_if am43xx_l3_main__emif = { .master = &am33xx_l3_main_hwmod, @@ -310,34 +241,6 @@ static struct omap_hwmod_ocp_if am43xx_l3_s__usbotgss1 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; -static struct omap_hwmod_ocp_if am43xx_dss__l3_main = { - .master = &am43xx_dss_core_hwmod, - .slave = &am33xx_l3_main_hwmod, - .clk = "l3_gclk", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - -static struct omap_hwmod_ocp_if am43xx_l4_ls__dss = { - .master = &am33xx_l4_ls_hwmod, - .slave = &am43xx_dss_core_hwmod, - .clk = "l4ls_gclk", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - -static struct omap_hwmod_ocp_if am43xx_l4_ls__dss_dispc = { - .master = &am33xx_l4_ls_hwmod, - .slave = &am43xx_dss_dispc_hwmod, - .clk = "l4ls_gclk", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - -static struct omap_hwmod_ocp_if am43xx_l4_ls__dss_rfbi = { - .master = &am33xx_l4_ls_hwmod, - .slave = &am43xx_dss_rfbi_hwmod, - .clk = "l4ls_gclk", - .user = OCP_USER_MPU | OCP_USER_SDMA, -}; - static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = { &am33xx_l4_wkup__synctimer, &am43xx_l3_main__pruss, @@ -368,10 +271,6 @@ static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = { &am33xx_l3_main__ocmc, &am43xx_l3_s__usbotgss0, &am43xx_l3_s__usbotgss1, - &am43xx_dss__l3_main, - &am43xx_l4_ls__dss, - &am43xx_l4_ls__dss_dispc, - &am43xx_l4_ls__dss_rfbi, NULL, }; From ce5ca149a6dcccee6060e08a162e837f5ebaaaa8 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Thu, 27 Feb 2020 16:28:35 -0600 Subject: [PATCH 1178/4444] ARM: dts: AM33xx-l4: Update PRUSS interconnect target-module node The PRU-ICSS present on some AM33xx SoCs has a very unique SYSC register. The IP also uses a hard-reset line, and requires this PRCM reset to be deasserted to be able to access any registers. Update the existing PRUSS interconnect target-module with all the required properties. The PRUSS device itself shall be added as a child node to this interconnect node in the future. PRU-ICSS is not supported on AM3351/AM3352/AM3354 SoCs though in the AM33xx family, so the target module node should be disabled in derivative board files that use any of these SoCs. Signed-off-by: Suman Anna Reviewed-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am33xx-l4.dtsi | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/am33xx-l4.dtsi b/arch/arm/boot/dts/am33xx-l4.dtsi index 4e2986f0c604..5ed7f3c58c0f 100644 --- a/arch/arm/boot/dts/am33xx-l4.dtsi +++ b/arch/arm/boot/dts/am33xx-l4.dtsi @@ -759,12 +759,27 @@ ranges = <0x0 0x200000 0x80000>; }; - target-module@300000 { /* 0x4a300000, ap 9 04.0 */ - compatible = "ti,sysc"; - status = "disabled"; + pruss_tm: target-module@300000 { /* 0x4a300000, ap 9 04.0 */ + compatible = "ti,sysc-pruss", "ti,sysc"; + reg = <0x326000 0x4>, + <0x326004 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-mask = <(SYSC_PRUSS_STANDBY_INIT | + SYSC_PRUSS_SUB_MWAIT)>; + ti,sysc-midle = , + , + ; + ti,sysc-sidle = , + , + ; + clocks = <&pruss_ocp_clkctrl AM3_PRUSS_OCP_PRUSS_CLKCTRL 0>; + clock-names = "fck"; + resets = <&prm_per 1>; + reset-names = "rstctrl"; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0x300000 0x80000>; + status = "disabled"; }; }; }; From 44e66a5d9d8fc2bb706458ffa3e0560dded7ccf5 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Thu, 27 Feb 2020 16:28:36 -0600 Subject: [PATCH 1179/4444] ARM: dts: AM4372: Add the PRU-ICSS interconnect target-module node The AM437x family of SoCs contains two dissimilar PRU-ICSS instances, but leverage a common reset line and SYSCFG from the larger PRU-ICSS1 instance. This SYSC register has also very unique bit-fields. Both the IPs require the PRCM reset to be deasserted to be able to access any registers. Add a common PRUSS interconnect target-module with all the required properties. The PRUSS devices themselves shall be added as child nodes to this interconnect node in the future. The PRU-ICSS instances are not supported on AM4372 SoC though in the AM437x family, so the target module node should be disabled in any derivative board files that use this SoC. Signed-off-by: Suman Anna Reviewed-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am4372.dtsi | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index 830cce2bda2b..3caddfe1e3e1 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -344,6 +344,28 @@ }; }; + pruss_tm: target-module@54400000 { + compatible = "ti,sysc-pruss", "ti,sysc"; + reg = <0x54426000 0x4>, + <0x54426004 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-mask = <(SYSC_PRUSS_STANDBY_INIT | + SYSC_PRUSS_SUB_MWAIT)>; + ti,sysc-midle = , + , + ; + ti,sysc-sidle = , + , + ; + clocks = <&pruss_ocp_clkctrl AM4_PRUSS_OCP_PRUSS_CLKCTRL 0>; + clock-names = "fck"; + resets = <&prm_per 1>; + reset-names = "rstctrl"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x54400000 0x80000>; + }; + gpmc: gpmc@50000000 { compatible = "ti,am3352-gpmc"; ti,hwmods = "gpmc"; From ecdeca6d961c647dac33c300806c051bba4762ce Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Thu, 27 Feb 2020 16:28:37 -0600 Subject: [PATCH 1180/4444] ARM: dts: dra7: Add PRU-ICSS interconnect target-module nodes The AM57xx family of SoCs contains two identical PRU-ICSS instances that have a very unique SYSC register. The IPs do not have any PRCM reset lines unlike those on AM33xx/AM437x SoCs. Add the PRUSS interconnect target-module nodes with all the required properties. Each of the PRUSS devices themselves shall be added as child nodes to the corresponding interconnect node in the future. The PRU-ICSS instances are only available on AM57xx family of SoCs and are not supported on DRA7xx family of SoCs in general, so the target module nodes are added in a separate dtsi file. This new dtsi file is included in all the AM57xx SoC dtsi files, so the nodes are automatically inherited and enabled on all AM57xx boards. Signed-off-by: Suman Anna Signed-off-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am57-pruss.dtsi | 50 +++++++++++++++++++++++++++++++ arch/arm/boot/dts/am5718.dtsi | 1 + arch/arm/boot/dts/am5728.dtsi | 1 + arch/arm/boot/dts/am5748.dtsi | 1 + arch/arm/boot/dts/dra7.dtsi | 2 +- 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/am57-pruss.dtsi diff --git a/arch/arm/boot/dts/am57-pruss.dtsi b/arch/arm/boot/dts/am57-pruss.dtsi new file mode 100644 index 000000000000..b1c583dee10b --- /dev/null +++ b/arch/arm/boot/dts/am57-pruss.dtsi @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ + * + * Common PRUSS data for TI AM57xx platforms + */ + +&ocp { + pruss1_tm: target-module@4b226000 { + compatible = "ti,sysc-pruss", "ti,sysc"; + reg = <0x4b226000 0x4>, + <0x4b226004 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-mask = <(SYSC_PRUSS_STANDBY_INIT | + SYSC_PRUSS_SUB_MWAIT)>; + ti,sysc-midle = , + , + ; + ti,sysc-sidle = , + , + ; + /* Domains (P, C): coreaon_pwrdm, l4per2_clkdm */ + clocks = <&l4per2_clkctrl DRA7_L4PER2_PRUSS1_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x4b200000 0x80000>; + }; + + pruss2_tm: target-module@4b2a6000 { + compatible = "ti,sysc-pruss", "ti,sysc"; + reg = <0x4b2a6000 0x4>, + <0x4b2a6004 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-mask = <(SYSC_PRUSS_STANDBY_INIT | + SYSC_PRUSS_SUB_MWAIT)>; + ti,sysc-midle = , + , + ; + ti,sysc-sidle = , + , + ; + /* Domains (P, C): coreaon_pwrdm, l4per2_clkdm */ + clocks = <&l4per2_clkctrl DRA7_L4PER2_PRUSS2_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x4b280000 0x80000>; + }; +}; diff --git a/arch/arm/boot/dts/am5718.dtsi b/arch/arm/boot/dts/am5718.dtsi index d51007c3e8c4..a80c2e3eee2e 100644 --- a/arch/arm/boot/dts/am5718.dtsi +++ b/arch/arm/boot/dts/am5718.dtsi @@ -4,6 +4,7 @@ */ #include "dra72x.dtsi" +#include "am57-pruss.dtsi" / { compatible = "ti,am5718", "ti,dra7"; diff --git a/arch/arm/boot/dts/am5728.dtsi b/arch/arm/boot/dts/am5728.dtsi index 82e5427ef6a9..9a3810f5adcc 100644 --- a/arch/arm/boot/dts/am5728.dtsi +++ b/arch/arm/boot/dts/am5728.dtsi @@ -4,6 +4,7 @@ */ #include "dra74x.dtsi" +#include "am57-pruss.dtsi" / { compatible = "ti,am5728", "ti,dra7"; diff --git a/arch/arm/boot/dts/am5748.dtsi b/arch/arm/boot/dts/am5748.dtsi index 5e129759d04a..2b65317b1513 100644 --- a/arch/arm/boot/dts/am5748.dtsi +++ b/arch/arm/boot/dts/am5748.dtsi @@ -4,6 +4,7 @@ */ #include "dra76x.dtsi" +#include "am57-pruss.dtsi" / { compatible = "ti,am5748", "ti,dra762", "ti,dra7"; diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 4be7f22113f6..9f8758052053 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -143,7 +143,7 @@ * the moment, just use a fake OCP bus entry to represent the whole bus * hierarchy. */ - ocp { + ocp: ocp { compatible = "ti,dra7-l3-noc", "simple-bus"; #address-cells = <1>; #size-cells = <1>; From 2333e829952fb437db915bbb17f4d8c43127d438 Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Sun, 23 Feb 2020 15:28:52 +0800 Subject: [PATCH 1181/4444] workqueue: Make workqueue_init*() return void The return values of workqueue_init() and workqueue_early_int() are always 0, and there is no usage of their return value. So just make them return void. Signed-off-by: Yu Chen Signed-off-by: Tejun Heo --- include/linux/workqueue.h | 4 ++-- kernel/workqueue.c | 8 ++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 4261d1c6e87b..c86a7691e13c 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -649,7 +649,7 @@ int workqueue_online_cpu(unsigned int cpu); int workqueue_offline_cpu(unsigned int cpu); #endif -int __init workqueue_init_early(void); -int __init workqueue_init(void); +void __init workqueue_init_early(void); +void __init workqueue_init(void); #endif diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 301db4406bc3..5afa9ad45eba 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -5896,7 +5896,7 @@ static void __init wq_numa_init(void) * items. Actual work item execution starts only after kthreads can be * created and scheduled right before early initcalls. */ -int __init workqueue_init_early(void) +void __init workqueue_init_early(void) { int std_nice[NR_STD_WORKER_POOLS] = { 0, HIGHPRI_NICE_LEVEL }; int hk_flags = HK_FLAG_DOMAIN | HK_FLAG_WQ; @@ -5963,8 +5963,6 @@ int __init workqueue_init_early(void) !system_unbound_wq || !system_freezable_wq || !system_power_efficient_wq || !system_freezable_power_efficient_wq); - - return 0; } /** @@ -5976,7 +5974,7 @@ int __init workqueue_init_early(void) * are no kworkers executing the work items yet. Populate the worker pools * with the initial workers and enable future kworker creations. */ -int __init workqueue_init(void) +void __init workqueue_init(void) { struct workqueue_struct *wq; struct worker_pool *pool; @@ -6023,6 +6021,4 @@ int __init workqueue_init(void) wq_online = true; wq_watchdog_init(); - - return 0; } From b75ca5217743e4d7076cf65e044e88389e44318d Mon Sep 17 00:00:00 2001 From: afzal mohammed Date: Sun, 1 Mar 2020 17:49:44 +0530 Subject: [PATCH 1182/4444] ARM: OMAP: replace setup_irq() by request_irq() request_irq() is preferred over setup_irq(). Invocations of setup_irq() occur after memory allocators are ready. Per tglx[1], setup_irq() existed in olden days when allocators were not ready by the time early interrupts were initialized. Hence replace setup_irq() by request_irq(). [1] https://lkml.kernel.org/r/alpine.DEB.2.20.1710191609480.1971@nanos Signed-off-by: afzal mohammed Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/pm.c | 13 ++++++------- arch/arm/mach-omap1/time.c | 10 +++------- arch/arm/mach-omap1/timer32k.c | 10 +++------- arch/arm/mach-omap2/timer.c | 11 +++-------- 4 files changed, 15 insertions(+), 29 deletions(-) diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c index d068958d6f8a..2c1e2b32b9b3 100644 --- a/arch/arm/mach-omap1/pm.c +++ b/arch/arm/mach-omap1/pm.c @@ -596,11 +596,6 @@ static irqreturn_t omap_wakeup_interrupt(int irq, void *dev) return IRQ_HANDLED; } -static struct irqaction omap_wakeup_irq = { - .name = "peripheral wakeup", - .handler = omap_wakeup_interrupt -}; - static const struct platform_suspend_ops omap_pm_ops = { @@ -613,6 +608,7 @@ static const struct platform_suspend_ops omap_pm_ops = { static int __init omap_pm_init(void) { int error = 0; + int irq; if (!cpu_class_is_omap1()) return -ENODEV; @@ -656,9 +652,12 @@ static int __init omap_pm_init(void) arm_pm_idle = omap1_pm_idle; if (cpu_is_omap7xx()) - setup_irq(INT_7XX_WAKE_UP_REQ, &omap_wakeup_irq); + irq = INT_7XX_WAKE_UP_REQ; else if (cpu_is_omap16xx()) - setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq); + irq = INT_1610_WAKE_UP_REQ; + if (request_irq(irq, omap_wakeup_interrupt, 0, "peripheral wakeup", + NULL)) + pr_err("Failed to request irq %d (peripheral wakeup)\n", irq); /* Program new power ramp-up time * (0 for most boards since we don't lower voltage when in deep sleep) diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index 524977a31a49..de590a85a42b 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c @@ -155,15 +155,11 @@ static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static struct irqaction omap_mpu_timer1_irq = { - .name = "mpu_timer1", - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = omap_mpu_timer1_interrupt, -}; - static __init void omap_init_mpu_timer(unsigned long rate) { - setup_irq(INT_TIMER1, &omap_mpu_timer1_irq); + if (request_irq(INT_TIMER1, omap_mpu_timer1_interrupt, + IRQF_TIMER | IRQF_IRQPOLL, "mpu_timer1", NULL)) + pr_err("Failed to request irq %d (mpu_timer1)\n", INT_TIMER1); omap_mpu_timer_start(0, (rate / HZ) - 1, 1); clockevent_mpu_timer1.cpumask = cpumask_of(0); diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c index 0ae6c52a7d70..780fdf03c3ce 100644 --- a/arch/arm/mach-omap1/timer32k.c +++ b/arch/arm/mach-omap1/timer32k.c @@ -148,15 +148,11 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static struct irqaction omap_32k_timer_irq = { - .name = "32KHz timer", - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = omap_32k_timer_interrupt, -}; - static __init void omap_init_32k_timer(void) { - setup_irq(INT_OS_TIMER, &omap_32k_timer_irq); + if (request_irq(INT_OS_TIMER, omap_32k_timer_interrupt, + IRQF_TIMER | IRQF_IRQPOLL, "32KHz timer", NULL)) + pr_err("Failed to request irq %d(32KHz timer)\n", INT_OS_TIMER); clockevent_32k_timer.cpumask = cpumask_of(0); clockevents_config_and_register(&clockevent_32k_timer, diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 0d0a731cb476..8b09cdacc30d 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -91,12 +91,6 @@ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static struct irqaction omap2_gp_timer_irq = { - .name = "gp_timer", - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = omap2_gp_timer_interrupt, -}; - static int omap2_gp_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { @@ -382,8 +376,9 @@ static void __init omap2_gp_clockevent_init(int gptimer_id, &clockevent_gpt.name, OMAP_TIMER_POSTED); BUG_ON(res); - omap2_gp_timer_irq.dev_id = &clkev; - setup_irq(clkev.irq, &omap2_gp_timer_irq); + if (request_irq(clkev.irq, omap2_gp_timer_interrupt, + IRQF_TIMER | IRQF_IRQPOLL, "gp_timer", &clkev)) + pr_err("Failed to request irq %d (gp_timer)\n", clkev.irq); __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW); From 5afc2b83ac2811ee931f5c1e6a606950ecdb4c46 Mon Sep 17 00:00:00 2001 From: Sam Shih Date: Wed, 4 Mar 2020 19:06:13 +0800 Subject: [PATCH 1183/4444] ARM: dts: mediatek: add mt7629 pwm support This adds pwm support for MT7629. Signed-off-by: Sam Shih Signed-off-by: Matthias Brugger --- arch/arm/boot/dts/mt7629.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm/boot/dts/mt7629.dtsi b/arch/arm/boot/dts/mt7629.dtsi index 60787632e4a1..5cbb3d244c75 100644 --- a/arch/arm/boot/dts/mt7629.dtsi +++ b/arch/arm/boot/dts/mt7629.dtsi @@ -241,6 +241,20 @@ status = "disabled"; }; + pwm: pwm@11006000 { + compatible = "mediatek,mt7629-pwm"; + reg = <0x11006000 0x1000>; + #pwm-cells = <2>; + clocks = <&topckgen CLK_TOP_PWM_SEL>, + <&pericfg CLK_PERI_PWM_PD>, + <&pericfg CLK_PERI_PWM1_PD>; + clock-names = "top", "main", "pwm1"; + assigned-clocks = <&topckgen CLK_TOP_PWM_SEL>; + assigned-clock-parents = + <&topckgen CLK_TOP_UNIVPLL2_D4>; + status = "disabled"; + }; + i2c: i2c@11007000 { compatible = "mediatek,mt7629-i2c", "mediatek,mt2712-i2c"; From c5f3f6ab5bc13da4432a11c6013e6b911a53c925 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 27 Feb 2020 21:36:48 +0900 Subject: [PATCH 1184/4444] dt-bindings: arm: Convert UniPhier System Cache to json-schema Convert the UniPhier System Cache binding to DT schema format. This is a full-custom outer cache (L2 and L3) used on UniPhier ARM 32-bit SoCs. While I was here, I added the interrupts property. This is not used in Linux, but the hardware has interrupt lines at least. Signed-off-by: Masahiro Yamada Signed-off-by: Rob Herring --- .../bindings/arm/socionext/cache-uniphier.txt | 60 ----------- .../socionext,uniphier-system-cache.yaml | 102 ++++++++++++++++++ 2 files changed, 102 insertions(+), 60 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/socionext/cache-uniphier.txt create mode 100644 Documentation/devicetree/bindings/arm/socionext/socionext,uniphier-system-cache.yaml diff --git a/Documentation/devicetree/bindings/arm/socionext/cache-uniphier.txt b/Documentation/devicetree/bindings/arm/socionext/cache-uniphier.txt deleted file mode 100644 index d27a646f48a9..000000000000 --- a/Documentation/devicetree/bindings/arm/socionext/cache-uniphier.txt +++ /dev/null @@ -1,60 +0,0 @@ -UniPhier outer cache controller - -UniPhier SoCs are integrated with a full-custom outer cache controller system. -All of them have a level 2 cache controller, and some have a level 3 cache -controller as well. - -Required properties: -- compatible: should be "socionext,uniphier-system-cache" -- reg: offsets and lengths of the register sets for the device. It should - contain 3 regions: control register, revision register, operation register, - in this order. -- cache-unified: specifies the cache is a unified cache. -- cache-size: specifies the size in bytes of the cache -- cache-sets: specifies the number of associativity sets of the cache -- cache-line-size: specifies the line size in bytes -- cache-level: specifies the level in the cache hierarchy. The value should - be 2 for L2 cache, 3 for L3 cache, etc. - -Optional properties: -- next-level-cache: phandle to the next level cache if present. The next level - cache should be also compatible with "socionext,uniphier-system-cache". - -The L2 cache must exist to use the L3 cache; the cache hierarchy must be -indicated correctly with "next-level-cache" properties. - -Example 1 (system with L2): - l2: l2-cache@500c0000 { - compatible = "socionext,uniphier-system-cache"; - reg = <0x500c0000 0x2000>, <0x503c0100 0x4>, - <0x506c0000 0x400>; - cache-unified; - cache-size = <0x80000>; - cache-sets = <256>; - cache-line-size = <128>; - cache-level = <2>; - }; - -Example 2 (system with L2 and L3): - l2: l2-cache@500c0000 { - compatible = "socionext,uniphier-system-cache"; - reg = <0x500c0000 0x2000>, <0x503c0100 0x8>, - <0x506c0000 0x400>; - cache-unified; - cache-size = <0x200000>; - cache-sets = <512>; - cache-line-size = <128>; - cache-level = <2>; - next-level-cache = <&l3>; - }; - - l3: l3-cache@500c8000 { - compatible = "socionext,uniphier-system-cache"; - reg = <0x500c8000 0x2000>, <0x503c8100 0x8>, - <0x506c8000 0x400>; - cache-unified; - cache-size = <0x400000>; - cache-sets = <512>; - cache-line-size = <256>; - cache-level = <3>; - }; diff --git a/Documentation/devicetree/bindings/arm/socionext/socionext,uniphier-system-cache.yaml b/Documentation/devicetree/bindings/arm/socionext/socionext,uniphier-system-cache.yaml new file mode 100644 index 000000000000..2e765bb3e6f6 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/socionext/socionext,uniphier-system-cache.yaml @@ -0,0 +1,102 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/socionext/socionext,uniphier-system-cache.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: UniPhier outer cache controller + +description: | + UniPhier ARM 32-bit SoCs are integrated with a full-custom outer cache + controller system. All of them have a level 2 cache controller, and some + have a level 3 cache controller as well. + +maintainers: + - Masahiro Yamada + +properties: + compatible: + const: socionext,uniphier-system-cache + + reg: + description: | + should contain 3 regions: control register, revision register, + operation register, in this order. + minItems: 3 + maxItems: 3 + + interrupts: + description: | + Interrupts can be used to notify the completion of cache operations. + The number of interrupts should match to the number of CPU cores. + The specified interrupts correspond to CPU0, CPU1, ... in this order. + minItems: 1 + maxItems: 4 + + cache-unified: true + + cache-size: true + + cache-sets: true + + cache-line-size: true + + cache-level: + minimum: 2 + maximum: 3 + + next-level-cache: true + +allOf: + - $ref: /schemas/cache-controller.yaml# + +additionalProperties: false + +required: + - compatible + - reg + - interrupts + - cache-unified + - cache-size + - cache-sets + - cache-line-size + - cache-level + +examples: + - | + // System with L2. + cache-controller@500c0000 { + compatible = "socionext,uniphier-system-cache"; + reg = <0x500c0000 0x2000>, <0x503c0100 0x4>, <0x506c0000 0x400>; + interrupts = <0 174 4>, <0 175 4>, <0 190 4>, <0 191 4>; + cache-unified; + cache-size = <0x140000>; + cache-sets = <512>; + cache-line-size = <128>; + cache-level = <2>; + }; + - | + // System with L2 and L3. + // L2 should specify the next level cache by 'next-level-cache'. + l2: cache-controller@500c0000 { + compatible = "socionext,uniphier-system-cache"; + reg = <0x500c0000 0x2000>, <0x503c0100 0x8>, <0x506c0000 0x400>; + interrupts = <0 190 4>, <0 191 4>; + cache-unified; + cache-size = <0x200000>; + cache-sets = <512>; + cache-line-size = <128>; + cache-level = <2>; + next-level-cache = <&l3>; + }; + + l3: cache-controller@500c8000 { + compatible = "socionext,uniphier-system-cache"; + reg = <0x500c8000 0x2000>, <0x503c8100 0x8>, <0x506c8000 0x400>; + interrupts = <0 174 4>, <0 175 4>; + cache-unified; + cache-size = <0x200000>; + cache-sets = <512>; + cache-line-size = <256>; + cache-level = <3>; + }; From f206c0eeb476f6eaa966f6e21a8831bb766f8659 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Sat, 29 Feb 2020 16:15:04 +0100 Subject: [PATCH 1185/4444] dt-bindings: Add vendor prefix for Elida Shenzen Elida Technology Co. Ltd. is a Chinese TFT manufacturer. Signed-off-by: Heiko Stuebner Acked-by: Sam Ravnborg Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index fcdda587def5..d035e38d6ba3 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -285,6 +285,8 @@ patternProperties: description: Elan Microelectronic Corp. "^elgin,.*": description: Elgin S/A. + "^elida,.*": + description: Shenzhen Elida Technology Co., Ltd. "^embest,.*": description: Shenzhen Embest Technology Co., Ltd. "^emlid,.*": From f15652859cbe34ec4f3667169facd86309f438d2 Mon Sep 17 00:00:00 2001 From: Sam Shih Date: Wed, 4 Mar 2020 19:06:12 +0800 Subject: [PATCH 1186/4444] dt-bindings: pwm: Update bindings for MT7629 SoC This updates bindings for MT7629 pwm controller. Signed-off-by: Sam Shih Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/pwm/pwm-mediatek.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/pwm/pwm-mediatek.txt b/Documentation/devicetree/bindings/pwm/pwm-mediatek.txt index 95536d83c5f2..29adff59c479 100644 --- a/Documentation/devicetree/bindings/pwm/pwm-mediatek.txt +++ b/Documentation/devicetree/bindings/pwm/pwm-mediatek.txt @@ -19,10 +19,15 @@ Required properties: - "pwm1-8": the eight per PWM clocks for mt2712 - "pwm1-6": the six per PWM clocks for mt7622 - "pwm1-5": the five per PWM clocks for mt7623 + - "pwm1" : the PWM1 clock for mt7629 - pinctrl-names: Must contain a "default" entry. - pinctrl-0: One property must exist for each entry in pinctrl-names. See pinctrl/pinctrl-bindings.txt for details of the property values. +Optional properties: +- assigned-clocks: Reference to the PWM clock entries. +- assigned-clock-parents: The phandle of the parent clock of PWM clock. + Example: pwm0: pwm@11006000 { compatible = "mediatek,mt7623-pwm"; From 30162dce8beb1107afab3d8ec2969efa79a769c5 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Wed, 4 Mar 2020 10:56:56 -0800 Subject: [PATCH 1187/4444] arm64: dts: sc7180: Add unit name to soc node This is just like commit a1875bf98290 ("arm64: dts: qcom: sdm845: Add unit name to soc node") but for sc7180. For reference, the warning being fixed was: Warning (unit_address_vs_reg): /soc: node has a reg or ranges property, but no unit name Reviewed-by: Stephen Boyd Fixes: 90db71e48070 ("arm64: dts: sc7180: Add minimal dts/dtsi files for SC7180 soc") Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20200304105638.1.I9ea0d337fcb927f52a28b20613b2377b6249c222@changeid Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sc7180.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index 31bf210f2e0b..b0092a0fb1e4 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -359,7 +359,7 @@ method = "smc"; }; - soc: soc { + soc: soc@0 { #address-cells = <2>; #size-cells = <2>; ranges = <0 0 0 0 0x10 0>; From b303f9f0050be2e1b4e19de09dd1898753cfc4d7 Mon Sep 17 00:00:00 2001 From: David Dai Date: Mon, 10 Feb 2020 00:04:11 +0530 Subject: [PATCH 1188/4444] arm64: dts: sdm845: Redefine interconnect provider DT nodes Add the DT nodes for each of the Network-On-Chip interconnect buses found on SDM845 based platform and redefine the rsc_hlos child node as a bcm-voter device to better represent the hardware. Reviewed-by: Evan Green Acked-by: Georgi Djakov Signed-off-by: David Dai Signed-off-by: Odelu Kukatla Signed-off-by: Sibi Sankar Link: https://lore.kernel.org/r/20200209183411.17195-7-sibis@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 65 +++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index ed882e086ba7..3da382b502e9 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -1576,6 +1576,55 @@ }; }; + mem_noc: interconnect@1380000 { + compatible = "qcom,sdm845-mem-noc"; + reg = <0 0x01380000 0 0x27200>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + dc_noc: interconnect@14e0000 { + compatible = "qcom,sdm845-dc-noc"; + reg = <0 0x014e0000 0 0x400>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + config_noc: interconnect@1500000 { + compatible = "qcom,sdm845-config-noc"; + reg = <0 0x01500000 0 0x5080>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + system_noc: interconnect@1620000 { + compatible = "qcom,sdm845-system-noc"; + reg = <0 0x01620000 0 0x18080>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + aggre1_noc: interconnect@16e0000 { + compatible = "qcom,sdm845-aggre1-noc"; + reg = <0 0x016e0000 0 0x15080>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + aggre2_noc: interconnect@1700000 { + compatible = "qcom,sdm845-aggre2-noc"; + reg = <0 0x01700000 0 0x1f300>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + mmss_noc: interconnect@1740000 { + compatible = "qcom,sdm845-mmss-noc"; + reg = <0 0x01740000 0 0x1c100>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + ufs_mem_hc: ufshc@1d84000 { compatible = "qcom,sdm845-ufshc", "qcom,ufshc", "jedec,ufs-2.0"; @@ -3335,6 +3384,13 @@ status = "disabled"; }; + gladiator_noc: interconnect@17900000 { + compatible = "qcom,sdm845-gladiator-noc"; + reg = <0 0x17900000 0 0xd080>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + watchdog@17980000 { compatible = "qcom,apss-wdt-sdm845", "qcom,kpss-wdt"; reg = <0 0x17980000 0 0x1000>; @@ -3364,6 +3420,10 @@ , ; + apps_bcm_voter: bcm-voter { + compatible = "qcom,bcm-voter"; + }; + rpmhcc: clock-controller { compatible = "qcom,sdm845-rpmh-clk"; #clock-cells = <1>; @@ -3420,11 +3480,6 @@ }; }; }; - - rsc_hlos: interconnect { - compatible = "qcom,sdm845-rsc-hlos"; - #interconnect-cells = <1>; - }; }; intc: interrupt-controller@17a00000 { From 2e4249f58074ec93746df3a902d1835b7edfef49 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Wed, 4 Mar 2020 13:34:27 -0600 Subject: [PATCH 1189/4444] ASoC: tlv320adcx140: Fix mic_bias and vref device tree verification Fix the range verification check for the mic_bias and vref device tree entries. Fixes 37bde5acf040 ("ASoC: tlv320adcx140: Add the tlv320adcx140 codec driver family") Signed-off-by: Dan Murphy Link: https://lore.kernel.org/r/20200304193427.16886-1-dmurphy@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320adcx140.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c index 93a0cb8e662c..38897568ee96 100644 --- a/sound/soc/codecs/tlv320adcx140.c +++ b/sound/soc/codecs/tlv320adcx140.c @@ -748,9 +748,8 @@ static int adcx140_codec_probe(struct snd_soc_component *component) if (ret) bias_source = ADCX140_MIC_BIAS_VAL_VREF; - if (bias_source != ADCX140_MIC_BIAS_VAL_VREF && - bias_source != ADCX140_MIC_BIAS_VAL_VREF_1096 && - bias_source != ADCX140_MIC_BIAS_VAL_AVDD) { + if (bias_source < ADCX140_MIC_BIAS_VAL_VREF || + bias_source > ADCX140_MIC_BIAS_VAL_AVDD) { dev_err(adcx140->dev, "Mic Bias source value is invalid\n"); return -EINVAL; } @@ -760,9 +759,8 @@ static int adcx140_codec_probe(struct snd_soc_component *component) if (ret) vref_source = ADCX140_MIC_BIAS_VREF_275V; - if (vref_source != ADCX140_MIC_BIAS_VREF_275V && - vref_source != ADCX140_MIC_BIAS_VREF_25V && - vref_source != ADCX140_MIC_BIAS_VREF_1375V) { + if (vref_source < ADCX140_MIC_BIAS_VREF_275V || + vref_source > ADCX140_MIC_BIAS_VREF_1375V) { dev_err(adcx140->dev, "Mic Bias source value is invalid\n"); return -EINVAL; } From fd357ec595d36676c239d8d16706a270a961ac32 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 5 Mar 2020 14:00:53 +0800 Subject: [PATCH 1190/4444] ASoC: sprd: Allow the MCDT driver to build into modules Change the config to 'tristate' for MCDT driver to allow it to build into modules, as well as changing to use IS_ENABLED() to validate if need supply dummy functions when building the MCDT driver as a module. Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/9306f2b99641136653ae4fe6cf9e859b7f698f77.1583387748.git.baolin.wang7@gmail.com Signed-off-by: Mark Brown --- sound/soc/sprd/Kconfig | 2 +- sound/soc/sprd/sprd-mcdt.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sprd/Kconfig b/sound/soc/sprd/Kconfig index 5474fd3de8c0..5e0ac8278572 100644 --- a/sound/soc/sprd/Kconfig +++ b/sound/soc/sprd/Kconfig @@ -8,7 +8,7 @@ config SND_SOC_SPRD the Spreadtrum SoCs' Audio interfaces. config SND_SOC_SPRD_MCDT - bool "Spreadtrum multi-channel data transfer support" + tristate "Spreadtrum multi-channel data transfer support" depends on SND_SOC_SPRD help Say y here to enable multi-channel data transfer support. It diff --git a/sound/soc/sprd/sprd-mcdt.h b/sound/soc/sprd/sprd-mcdt.h index 9cc7e207ac76..679e3af3baad 100644 --- a/sound/soc/sprd/sprd-mcdt.h +++ b/sound/soc/sprd/sprd-mcdt.h @@ -48,7 +48,7 @@ struct sprd_mcdt_chan { struct list_head list; }; -#ifdef CONFIG_SND_SOC_SPRD_MCDT +#if IS_ENABLED(CONFIG_SND_SOC_SPRD_MCDT) struct sprd_mcdt_chan *sprd_mcdt_request_chan(u8 channel, enum sprd_mcdt_channel_type type); void sprd_mcdt_free_chan(struct sprd_mcdt_chan *chan); From 25c2f5156dd57f03aee2de079248c23a56222c92 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 27 Feb 2020 10:54:38 +0900 Subject: [PATCH 1191/4444] ASoC: soc-pcm: use defined stream Many functions defines "stream = substream->stream", but some of them is using "substream->stream" instead of "stream". It is pointless. This patch uses defined stream. Signed-off-by: Kuninori Morimoto Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87mu947q1t.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 90857138c823..8c27eb4d5e4c 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -644,8 +644,7 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) * bailed out on a higher level, since there would be no * CODEC to support the transfer direction in that case. */ - if (!snd_soc_dai_stream_valid(codec_dai, - substream->stream)) + if (!snd_soc_dai_stream_valid(codec_dai, stream)) continue; codec_stream = snd_soc_dai_get_pcm_stream(codec_dai, stream); @@ -2149,7 +2148,7 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); - ret = dpcm_be_dai_startup(fe, fe_substream->stream); + ret = dpcm_be_dai_startup(fe, stream); if (ret < 0) { dev_err(fe->dev,"ASoC: failed to start some BEs %d\n", ret); goto be_err; @@ -2180,7 +2179,7 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) return 0; unwind: - dpcm_be_dai_startup_unwind(fe, fe_substream->stream); + dpcm_be_dai_startup_unwind(fe, stream); be_err: dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); return ret; @@ -2234,7 +2233,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream) dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); /* shutdown the BEs */ - dpcm_be_dai_shutdown(fe, substream->stream); + dpcm_be_dai_shutdown(fe, stream); dev_dbg(fe->dev, "ASoC: close FE %s\n", fe->dai_link->name); @@ -2412,9 +2411,9 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream, mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); - memcpy(&fe->dpcm[substream->stream].hw_params, params, + memcpy(&fe->dpcm[stream].hw_params, params, sizeof(struct snd_pcm_hw_params)); - ret = dpcm_be_dai_hw_params(fe, substream->stream); + ret = dpcm_be_dai_hw_params(fe, stream); if (ret < 0) { dev_err(fe->dev,"ASoC: hw_params BE failed %d\n", ret); goto out; @@ -2736,7 +2735,7 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream) goto out; } - ret = dpcm_be_dai_prepare(fe, substream->stream); + ret = dpcm_be_dai_prepare(fe, stream); if (ret < 0) goto out; From 6e02feb0d2663c1b7caa5e271c2a60e219f0ca07 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 27 Feb 2020 10:54:48 +0900 Subject: [PATCH 1192/4444] ASoC: soc-pcm: remove duplicate be check from dpcm_add_paths() dpcm_add_paths() checks returned be from dpcm_get_be() static int dpcm_add_paths(...) { ... for_each_dapm_widgets(list, i, widget) { ... be = dpcm_get_be(...); ... /* make sure BE is a real BE */ => if (!be->dai_link->no_pcm) continue; ... } ... } But, dpcm_get_be() itself is checking it already. dpcm_get_be(...) { ... for_each_card_rtds(card, be) { => if (!be->dai_link->no_pcm) continue; ... if (...) => return be; } return NULL } This patch removes duplicate check Signed-off-by: Kuninori Morimoto Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87lfoo7q1j.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 8c27eb4d5e4c..e3a2c4f7757b 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1690,10 +1690,6 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, continue; } - /* make sure BE is a real BE */ - if (!be->dai_link->no_pcm) - continue; - /* don't connect if FE is not running */ if (!fe->dpcm[stream].runtime && !fe->fe_compr) continue; From f2eeca099bbda45029da35abecb428a9084a5463 Mon Sep 17 00:00:00 2001 From: Harshad Shirwadkar Date: Tue, 24 Dec 2019 11:09:40 -0800 Subject: [PATCH 1193/4444] ext4: force buffer up-to-date while marking it dirty Writeback errors can leave buffer in not up-to-date state when there are errors during background writes. Force buffer up-to-date while marking it dirty. Signed-off-by: Harshad Shirwadkar Link: https://lore.kernel.org/r/20191224190940.157952-1-harshadshirwadkar@gmail.com Signed-off-by: Theodore Ts'o --- fs/ext4/ext4_jbd2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c index 1f53d64e42a5..ee3755c3110a 100644 --- a/fs/ext4/ext4_jbd2.c +++ b/fs/ext4/ext4_jbd2.c @@ -332,6 +332,7 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line, err); } } else { + set_buffer_uptodate(bh); if (inode) mark_buffer_dirty_inode(bh, inode); else From 72f9da1d5c8d03d6fb242d01aae66928b2b2e7a8 Mon Sep 17 00:00:00 2001 From: Xiaoguang Wang Date: Fri, 7 Feb 2020 20:07:58 +0800 Subject: [PATCH 1194/4444] ext4: start to support iopoll method Since commit "b1b4705d54ab ext4: introduce direct I/O read using iomap infrastructure", we can easily make ext4 support iopoll method, just use iomap_dio_iopoll(). Reviewed-by: Jan Kara Signed-off-by: Xiaoguang Wang Link: https://lore.kernel.org/r/20200207120758.2411-1-xiaoguang.wang@linux.alibaba.com Signed-off-by: Theodore Ts'o --- fs/ext4/file.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 5f225881176b..0d624250a62b 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -872,6 +872,7 @@ const struct file_operations ext4_file_operations = { .llseek = ext4_llseek, .read_iter = ext4_file_read_iter, .write_iter = ext4_file_write_iter, + .iopoll = iomap_dio_iopoll, .unlocked_ioctl = ext4_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = ext4_compat_ioctl, From a08fe66e4a0e12a3df982b28059f3a90e0f1b31e Mon Sep 17 00:00:00 2001 From: Chengguang Xu Date: Mon, 10 Feb 2020 16:24:45 +0800 Subject: [PATCH 1195/4444] ext4: code cleanup for ext4_statfs_project() Calling min_not_zero() to simplify complicated prjquota limit comparison in ext4_statfs_project(). Signed-off-by: Chengguang Xu Link: https://lore.kernel.org/r/20200210082445.2379-1-cgxu519@mykernel.net Signed-off-by: Theodore Ts'o --- fs/ext4/super.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 0c7c4adb664e..de5398c07161 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -5622,10 +5622,8 @@ static int ext4_statfs_project(struct super_block *sb, return PTR_ERR(dquot); spin_lock(&dquot->dq_dqb_lock); - limit = dquot->dq_dqb.dqb_bsoftlimit; - if (dquot->dq_dqb.dqb_bhardlimit && - (!limit || dquot->dq_dqb.dqb_bhardlimit < limit)) - limit = dquot->dq_dqb.dqb_bhardlimit; + limit = min_not_zero(dquot->dq_dqb.dqb_bsoftlimit, + dquot->dq_dqb.dqb_bhardlimit); limit >>= sb->s_blocksize_bits; if (limit && buf->f_blocks > limit) { @@ -5637,11 +5635,8 @@ static int ext4_statfs_project(struct super_block *sb, (buf->f_blocks - curblock) : 0; } - limit = dquot->dq_dqb.dqb_isoftlimit; - if (dquot->dq_dqb.dqb_ihardlimit && - (!limit || dquot->dq_dqb.dqb_ihardlimit < limit)) - limit = dquot->dq_dqb.dqb_ihardlimit; - + limit = min_not_zero(dquot->dq_dqb.dqb_isoftlimit, + dquot->dq_dqb.dqb_ihardlimit); if (limit && buf->f_files > limit) { buf->f_files = limit; buf->f_ffree = From 4337ecd1fe997d2b2135b4434caaccdb47c10c06 Mon Sep 17 00:00:00 2001 From: Eric Whitney Date: Tue, 11 Feb 2020 16:02:16 -0500 Subject: [PATCH 1196/4444] ext4: remove EXT4_EOFBLOCKS_FL and associated code The EXT4_EOFBLOCKS_FL inode flag is used to indicate whether a file contains unwritten blocks past i_size. It's set when ext4_fallocate is called with the KEEP_SIZE flag to extend a file with an unwritten extent. However, this flag hasn't been useful functionally since March, 2012, when a decision was made to remove it from ext4. All traces of EXT4_EOFBLOCKS_FL were removed from e2fsprogs version 1.42.2 by commit 010dc7b90d97 ("e2fsck: remove EXT4_EOFBLOCKS_FL flag handling") at that time. Now that enough time has passed to make e2fsprogs versions containing this modification common, this patch now removes the code associated with EXT4_EOFBLOCKS_FL from the kernel as well. This change has two implications. First, because pre-1.42.2 e2fsck versions only look for a problem if EXT4_EOFBLOCKS_FL is set, and because that bit will never be set by newer kernels containing this patch, old versions of e2fsck won't have a compatibility problem with files created by newer kernels. Second, newer kernels will not clear EXT4_EOFBLOCKS_FL inode flag bits belonging to a file written by an older kernel. If set, it will remain in that state until the file is deleted. Because e2fsck versions since 1.42.2 don't check the flag at all, no adverse effect is expected. However, pre-1.42.2 e2fsck versions that do check the flag may report that it is set when it ought not to be after a file has been truncated or had its unwritten blocks written. In this case, the old version of e2fsck will offer to clear the flag. No adverse effect would then occur whether the user chooses to clear the flag or not. Signed-off-by: Eric Whitney Link: https://lore.kernel.org/r/20200211210216.24960-1-enwlinux@gmail.com Signed-off-by: Theodore Ts'o --- fs/ext4/ext4.h | 5 ++- fs/ext4/extents.c | 92 ++++------------------------------------------- fs/ext4/inode.c | 2 -- fs/ext4/ioctl.c | 12 ------- 4 files changed, 9 insertions(+), 102 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 61b37a052052..54f0a003053b 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -414,7 +414,7 @@ struct flex_groups { #define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ #define EXT4_VERITY_FL 0x00100000 /* Verity protected inode */ #define EXT4_EA_INODE_FL 0x00200000 /* Inode used for large EA */ -#define EXT4_EOFBLOCKS_FL 0x00400000 /* Blocks allocated beyond EOF */ +/* 0x00400000 was formerly EXT4_EOFBLOCKS_FL */ #define EXT4_INLINE_DATA_FL 0x10000000 /* Inode has inline data. */ #define EXT4_PROJINHERIT_FL 0x20000000 /* Create with parents projid */ #define EXT4_CASEFOLD_FL 0x40000000 /* Casefolded file */ @@ -487,7 +487,7 @@ enum { EXT4_INODE_EXTENTS = 19, /* Inode uses extents */ EXT4_INODE_VERITY = 20, /* Verity protected inode */ EXT4_INODE_EA_INODE = 21, /* Inode used for large EA */ - EXT4_INODE_EOFBLOCKS = 22, /* Blocks allocated beyond EOF */ +/* 22 was formerly EXT4_INODE_EOFBLOCKS */ EXT4_INODE_INLINE_DATA = 28, /* Data in inode. */ EXT4_INODE_PROJINHERIT = 29, /* Create with parents projid */ EXT4_INODE_RESERVED = 31, /* reserved for ext4 lib */ @@ -533,7 +533,6 @@ static inline void ext4_check_flag_values(void) CHECK_FLAG_VALUE(EXTENTS); CHECK_FLAG_VALUE(VERITY); CHECK_FLAG_VALUE(EA_INODE); - CHECK_FLAG_VALUE(EOFBLOCKS); CHECK_FLAG_VALUE(INLINE_DATA); CHECK_FLAG_VALUE(PROJINHERIT); CHECK_FLAG_VALUE(RESERVED); diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 954013d6076b..89aa9c7ae293 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -3874,59 +3874,6 @@ out: return err; } -/* - * Handle EOFBLOCKS_FL flag, clearing it if necessary - */ -static int check_eofblocks_fl(handle_t *handle, struct inode *inode, - ext4_lblk_t lblk, - struct ext4_ext_path *path, - unsigned int len) -{ - int i, depth; - struct ext4_extent_header *eh; - struct ext4_extent *last_ex; - - if (!ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS)) - return 0; - - depth = ext_depth(inode); - eh = path[depth].p_hdr; - - /* - * We're going to remove EOFBLOCKS_FL entirely in future so we - * do not care for this case anymore. Simply remove the flag - * if there are no extents. - */ - if (unlikely(!eh->eh_entries)) - goto out; - last_ex = EXT_LAST_EXTENT(eh); - /* - * We should clear the EOFBLOCKS_FL flag if we are writing the - * last block in the last extent in the file. We test this by - * first checking to see if the caller to - * ext4_ext_get_blocks() was interested in the last block (or - * a block beyond the last block) in the current extent. If - * this turns out to be false, we can bail out from this - * function immediately. - */ - if (lblk + len < le32_to_cpu(last_ex->ee_block) + - ext4_ext_get_actual_len(last_ex)) - return 0; - /* - * If the caller does appear to be planning to write at or - * beyond the end of the current extent, we then test to see - * if the current extent is the last extent in the file, by - * checking to make sure it was reached via the rightmost node - * at each level of the tree. - */ - for (i = depth-1; i >= 0; i--) - if (path[i].p_idx != EXT_LAST_INDEX(path[i].p_hdr)) - return 0; -out: - ext4_clear_inode_flag(inode, EXT4_INODE_EOFBLOCKS); - return ext4_mark_inode_dirty(handle, inode); -} - static int convert_initialized_extent(handle_t *handle, struct inode *inode, struct ext4_map_blocks *map, @@ -3991,9 +3938,7 @@ convert_initialized_extent(handle_t *handle, struct inode *inode, ext4_ext_show_leaf(inode, path); ext4_update_inode_fsync_trans(handle, inode, 1); - err = check_eofblocks_fl(handle, inode, map->m_lblk, path, map->m_len); - if (err) - return err; + map->m_flags |= EXT4_MAP_UNWRITTEN; if (allocated > map->m_len) allocated = map->m_len; @@ -4007,7 +3952,9 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode, struct ext4_ext_path **ppath, int flags, unsigned int allocated, ext4_fsblk_t newblock) { +#ifdef EXT_DEBUG struct ext4_ext_path *path = *ppath; +#endif int ret = 0; int err = 0; @@ -4047,11 +3994,9 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode, } ret = ext4_convert_unwritten_extents_endio(handle, inode, map, ppath); - if (ret >= 0) { + if (ret >= 0) ext4_update_inode_fsync_trans(handle, inode, 1); - err = check_eofblocks_fl(handle, inode, map->m_lblk, - path, map->m_len); - } else + else err = ret; map->m_flags |= EXT4_MAP_MAPPED; map->m_pblk = newblock; @@ -4100,12 +4045,6 @@ out: map_out: map->m_flags |= EXT4_MAP_MAPPED; - if ((flags & EXT4_GET_BLOCKS_KEEP_SIZE) == 0) { - err = check_eofblocks_fl(handle, inode, map->m_lblk, path, - map->m_len); - if (err < 0) - goto out2; - } out1: if (allocated > map->m_len) allocated = map->m_len; @@ -4459,12 +4398,7 @@ got_allocated_blocks: } err = 0; - if ((flags & EXT4_GET_BLOCKS_KEEP_SIZE) == 0) - err = check_eofblocks_fl(handle, inode, map->m_lblk, - path, ar.len); - if (!err) - err = ext4_ext_insert_extent(handle, inode, &path, - &newex, flags); + err = ext4_ext_insert_extent(handle, inode, &path, &newex, flags); if (err && free_on_err) { int fb_flags = flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE ? @@ -4645,10 +4579,6 @@ retry: epos = new_size; if (ext4_update_inode_size(inode, epos) & 0x1) inode->i_mtime = inode->i_ctime; - } else { - if (epos > inode->i_size) - ext4_set_inode_flag(inode, - EXT4_INODE_EOFBLOCKS); } ext4_mark_inode_dirty(handle, inode); ext4_update_inode_fsync_trans(handle, inode, 1); @@ -4802,16 +4732,8 @@ static long ext4_zero_range(struct file *file, loff_t offset, } inode->i_mtime = inode->i_ctime = current_time(inode); - if (new_size) { + if (new_size) ext4_update_inode_size(inode, new_size); - } else { - /* - * Mark that we allocate beyond EOF so the subsequent truncate - * can proceed even if the new size is the same as i_size. - */ - if (offset + len > inode->i_size) - ext4_set_inode_flag(inode, EXT4_INODE_EOFBLOCKS); - } ext4_mark_inode_dirty(handle, inode); /* Zero out partial block at the edges of the range */ diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index fa0ff78dc033..416aec6d6c65 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4144,8 +4144,6 @@ int ext4_truncate(struct inode *inode) if (!ext4_can_truncate(inode)) return 0; - ext4_clear_inode_flag(inode, EXT4_INODE_EOFBLOCKS); - if (inode->i_size == 0 && !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC)) ext4_set_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE); diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index a0ec750018dd..d0b00fab0531 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -327,18 +327,6 @@ static int ext4_ioctl_setflags(struct inode *inode, if ((flags ^ oldflags) & EXT4_EXTENTS_FL) migrate = 1; - if (flags & EXT4_EOFBLOCKS_FL) { - /* we don't support adding EOFBLOCKS flag */ - if (!(oldflags & EXT4_EOFBLOCKS_FL)) { - err = -EOPNOTSUPP; - goto flags_out; - } - } else if (oldflags & EXT4_EOFBLOCKS_FL) { - err = ext4_truncate(inode); - if (err) - goto flags_out; - } - if ((flags ^ oldflags) & EXT4_CASEFOLD_FL) { if (!ext4_has_feature_casefold(sb)) { err = -EOPNOTSUPP; From 3133287b53ee88444e2294e601d2bad54a798f59 Mon Sep 17 00:00:00 2001 From: Alexandre Ghiti Date: Thu, 20 Feb 2020 01:10:23 -0500 Subject: [PATCH 1197/4444] riscv: Use p*d_leaf macros to define p*d_huge The newly introduced p*d_leaf macros allow to check if an entry of the page table map to a physical page instead of the next level. To avoid duplication of code, use those macros to determine if a page table entry points to a hugepage. Suggested-by: Paul Walmsley Signed-off-by: Alexandre Ghiti Reviewed-by: Anup Patel Signed-off-by: Palmer Dabbelt --- arch/riscv/mm/hugetlbpage.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c index 0d4747e9d5b5..a6189ed36c5f 100644 --- a/arch/riscv/mm/hugetlbpage.c +++ b/arch/riscv/mm/hugetlbpage.c @@ -4,14 +4,12 @@ int pud_huge(pud_t pud) { - return pud_present(pud) && - (pud_val(pud) & (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC)); + return pud_leaf(pud); } int pmd_huge(pmd_t pmd) { - return pmd_present(pmd) && - (pmd_val(pmd) & (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC)); + return pmd_leaf(pmd); } static __init int setup_hugepagesz(char *opt) From 15617dffa387d2d80eefb9935c3a3985c4021090 Mon Sep 17 00:00:00 2001 From: Ira Weiny Date: Fri, 21 Feb 2020 15:16:07 -0800 Subject: [PATCH 1198/4444] percpu_ref: Fix comment regarding percpu_ref_init flags The comment for percpu_ref_init() implies that using PERCPU_REF_ALLOW_REINIT will cause the refcount to start at 0. But this is not true. PERCPU_REF_ALLOW_REINIT starts the count at 1 as if the flags were zero. Add this fact to the kernel doc comment. Signed-off-by: Ira Weiny [Dennis: reworded] Signed-off-by: Dennis Zhou --- lib/percpu-refcount.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/percpu-refcount.c b/lib/percpu-refcount.c index 4f6c6ebbbbde..8d092609928e 100644 --- a/lib/percpu-refcount.c +++ b/lib/percpu-refcount.c @@ -50,9 +50,10 @@ static unsigned long __percpu *percpu_count_ptr(struct percpu_ref *ref) * @flags: PERCPU_REF_INIT_* flags * @gfp: allocation mask to use * - * Initializes @ref. If @flags is zero, @ref starts in percpu mode with a - * refcount of 1; analagous to atomic_long_set(ref, 1). See the - * definitions of PERCPU_REF_INIT_* flags for flag behaviors. + * Initializes @ref. @ref starts out in percpu mode with a refcount of 1 unless + * @flags contains PERCPU_REF_INIT_ATOMIC or PERCPU_REF_INIT_DEAD. These flags + * change the start state to atomic with the latter setting the initial refcount + * to 0. See the definitions of PERCPU_REF_INIT_* flags for flag behaviors. * * Note that @release must not sleep - it may potentially be called from RCU * callback context by percpu_ref_kill(). From 780d2a9c86dc12594e263752cd8426a5794f1cc8 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 4 Mar 2020 15:09:19 +0100 Subject: [PATCH 1199/4444] include/bitmap.h: add missing parameter in docs bitmap_find_next_zero_area_off() has an additional parameter which was not specified in the list of functions. Add it. Fixes: 5e19b013f55a ("lib: bitmap: add alignment offset for bitmap_find_next_zero_area()") Signed-off-by: Wolfram Sang Signed-off-by: Dennis Zhou --- include/linux/bitmap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index e52ceb1a73d3..804600f7dc35 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -50,7 +50,7 @@ * bitmap_set(dst, pos, nbits) Set specified bit area * bitmap_clear(dst, pos, nbits) Clear specified bit area * bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area - * bitmap_find_next_zero_area_off(buf, len, pos, n, mask) as above + * bitmap_find_next_zero_area_off(buf, len, pos, n, mask, mask_off) as above * bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n * bitmap_shift_left(dst, src, n, nbits) *dst = *src << n * bitmap_cut(dst, src, first, n, nbits) Cut n bits from first, copy rest From a392d26f32cdd87e09b1ea3849db79cfc4eae745 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 4 Mar 2020 15:09:20 +0100 Subject: [PATCH 1200/4444] include/bitmap.h: add new functions to documentation I found these functions only by chance although I was looking exactly for something like them. So, add them to the list of functions to make them more visible. Fixes: e837dfde15a4 ("bitmap: genericize percpu bitmap region iterators") Signed-off-by: Wolfram Sang Signed-off-by: Dennis Zhou --- include/linux/bitmap.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index 804600f7dc35..99058eb81042 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -51,6 +51,12 @@ * bitmap_clear(dst, pos, nbits) Clear specified bit area * bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area * bitmap_find_next_zero_area_off(buf, len, pos, n, mask, mask_off) as above + * bitmap_next_clear_region(map, &start, &end, nbits) Find next clear region + * bitmap_next_set_region(map, &start, &end, nbits) Find next set region + * bitmap_for_each_clear_region(map, rs, re, start, end) + * Iterate over all clear regions + * bitmap_for_each_set_region(map, rs, re, start, end) + * Iterate over all set regions * bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n * bitmap_shift_left(dst, src, n, nbits) *dst = *src << n * bitmap_cut(dst, src, first, n, nbits) Cut n bits from first, copy rest From 765bfcd59a1ff799b1c71cb3be0c43b0775ec166 Mon Sep 17 00:00:00 2001 From: Eric Whitney Date: Wed, 12 Feb 2020 11:21:41 -0500 Subject: [PATCH 1201/4444] ext4: delete declaration for ext4_split_extent() There are no forward references for ext4_split_extent() in extents.c, so delete its unnecessary declaration. Reviewed-by: Darrick J. Wong Signed-off-by: Eric Whitney Link: https://lore.kernel.org/r/20200212162141.22381-1-enwlinux@gmail.com Signed-off-by: Theodore Ts'o --- fs/ext4/extents.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 89aa9c7ae293..a5338a8da2ab 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -83,13 +83,6 @@ static void ext4_extent_block_csum_set(struct inode *inode, et->et_checksum = ext4_extent_block_csum(inode, eh); } -static int ext4_split_extent(handle_t *handle, - struct inode *inode, - struct ext4_ext_path **ppath, - struct ext4_map_blocks *map, - int split_flag, - int flags); - static int ext4_split_extent_at(handle_t *handle, struct inode *inode, struct ext4_ext_path **ppath, From 17ec2394d5888f77c2b11d329544d1be37549682 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Wed, 4 Mar 2020 08:40:49 +0100 Subject: [PATCH 1202/4444] ARM: dts: rockchip: add missing model properties A test with the command below gives these errors: arch/arm/boot/dts/rk3288-evb-act8846.dt.yaml: /: 'model' is a required property arch/arm/boot/dts/rk3288-evb-rk808.dt.yaml: /: 'model' is a required property arch/arm/boot/dts/rk3288-r89.dt.yaml: /: 'model' is a required property Fix this error by adding the missing model properties to the involved dts files. make ARCH=arm dtbs_check DT_SCHEMA_FILES=~/.local/lib/python3.5/site-packages/dtschema/ schemas/root-node.yaml Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200304074051.8742-1-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288-evb-act8846.dts | 1 + arch/arm/boot/dts/rk3288-evb-rk808.dts | 1 + arch/arm/boot/dts/rk3288-r89.dts | 1 + 3 files changed, 3 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-evb-act8846.dts b/arch/arm/boot/dts/rk3288-evb-act8846.dts index 80080767c365..be695b8c1f67 100644 --- a/arch/arm/boot/dts/rk3288-evb-act8846.dts +++ b/arch/arm/boot/dts/rk3288-evb-act8846.dts @@ -4,6 +4,7 @@ #include "rk3288-evb.dtsi" / { + model = "Rockchip RK3288 EVB ACT8846"; compatible = "rockchip,rk3288-evb-act8846", "rockchip,rk3288"; vcc_lcd: vcc-lcd { diff --git a/arch/arm/boot/dts/rk3288-evb-rk808.dts b/arch/arm/boot/dts/rk3288-evb-rk808.dts index 16788209625b..42384ea4ca21 100644 --- a/arch/arm/boot/dts/rk3288-evb-rk808.dts +++ b/arch/arm/boot/dts/rk3288-evb-rk808.dts @@ -4,6 +4,7 @@ #include "rk3288-evb.dtsi" / { + model = "Rockchip RK3288 EVB RK808"; compatible = "rockchip,rk3288-evb-rk808", "rockchip,rk3288"; }; diff --git a/arch/arm/boot/dts/rk3288-r89.dts b/arch/arm/boot/dts/rk3288-r89.dts index a6ffc381abaa..a258c7ae5329 100644 --- a/arch/arm/boot/dts/rk3288-r89.dts +++ b/arch/arm/boot/dts/rk3288-r89.dts @@ -9,6 +9,7 @@ #include "rk3288.dtsi" / { + model = "Netxeon R89"; compatible = "netxeon,r89", "rockchip,rk3288"; memory@0 { From e1577157c0e2096041d87153530b32f0bcadf5c9 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Thu, 5 Mar 2020 19:39:09 +0800 Subject: [PATCH 1203/4444] arm64: dts: rockchip: remove dvs2 pinctrl for pmic on rk3399 evb DVS2 of pmic is connected to GND, no pinctrl for it. Signed-off-by: Andy Yan Link: https://lore.kernel.org/r/20200305113912.32226-2-andy.yan@rock-chips.com Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3399-evb.dts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts index 77008dca45bc..eb501bb8f426 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts @@ -210,11 +210,6 @@ rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; }; - - pmic_dvs2: pmic-dvs2 { - rockchip,pins = - <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; - }; }; usb2 { From 2217a8519c5724fcdac0d78bc7695b28ef59d30d Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Thu, 5 Mar 2020 19:39:10 +0800 Subject: [PATCH 1204/4444] arm64: dts: rockchip: Add pmic dt tree for rk3399 evb RK3399 EVB use 2 SYR837/8 and a RK808 for power supply, Add regulator tree for it. Signed-off-by: Andy Yan Link: https://lore.kernel.org/r/20200305113912.32226-3-andy.yan@rock-chips.com Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3399-evb.dts | 222 ++++++++++++++++++++ 1 file changed, 222 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts index eb501bb8f426..7d254cbe62f2 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts @@ -134,6 +134,228 @@ status = "okay"; }; +&i2c0 { + status = "okay"; + + rk808: pmic@1b { + compatible = "rockchip,rk808"; + reg = <0x1b>; + interrupt-parent = <&gpio1>; + interrupts = <21 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + clock-output-names = "rk808-clkout1", "rk808-clkout2"; + + vcc1-supply = <&vcc3v3_sys>; + vcc2-supply = <&vcc3v3_sys>; + vcc3-supply = <&vcc3v3_sys>; + vcc4-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc3v3_sys>; + vcc10-supply = <&vcc3v3_sys>; + vcc11-supply = <&vcc3v3_sys>; + vcc12-supply = <&vcc3v3_sys>; + vddio-supply = <&vcc1v8_pmu>; + + regulators { + vdd_log: DCDC_REG1 { + regulator-name = "vdd_log"; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + vdd_cpu_l: DCDC_REG2 { + regulator-name = "vdd_cpu_l"; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG4 { + regulator-name = "vcc_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc1v8_dvp: LDO_REG1 { + regulator-name = "vcc1v8_dvp"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v0_tp: LDO_REG2 { + regulator-name = "vcc3v0_tp"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc1v8_pmu: LDO_REG3 { + regulator-name = "vcc1v8_pmu"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_sd: LDO_REG4 { + regulator-name = "vcc_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcca3v0_codec: LDO_REG5 { + regulator-name = "vcca3v0_codec"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v5: LDO_REG6 { + regulator-name = "vcc_1v5"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcca1v8_codec: LDO_REG7 { + regulator-name = "vcca1v8_codec"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v0: LDO_REG8 { + regulator-name = "vcc_3v0"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc3v3_s3: SWITCH_REG1 { + regulator-name = "vcc3v3_s3"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc3v3_s0: SWITCH_REG2 { + regulator-name = "vcc3v3_s0"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; + + vdd_cpu_b: regulator@40 { + compatible = "silergy,syr827"; + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_b"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-ramp-delay = <1000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: regulator@41 { + compatible = "silergy,syr828"; + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-ramp-delay = <1000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + &pwm0 { status = "okay"; }; From c5d24362cb1167f9c6708e26d4cb919b9cbdd0ee Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Thu, 5 Mar 2020 19:39:11 +0800 Subject: [PATCH 1205/4444] arm64: dts: rockchip: remove enable-gpio of backlight on rk3399 evb There is no enable-gpio for backlight control on rk3399 evb, actually GPIO1_B5 is for LCD panle enable. So remove it from backlight dt node. Signed-off-by: Andy Yan Link: https://lore.kernel.org/r/20200305113912.32226-4-andy.yan@rock-chips.com Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3399-evb.dts | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts index 7d254cbe62f2..6f83d947e228 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts @@ -48,7 +48,6 @@ 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255>; default-brightness-level = <200>; - enable-gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>; pwms = <&pwm0 0 25000 0>; }; From 6b1ed0390b9dfecd499b0a332d216de50af23356 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Thu, 5 Mar 2020 19:39:12 +0800 Subject: [PATCH 1206/4444] arm64: dts: rockchip: Enable eDP display on rk3399 evb Add eDP panle and enable relative dt node like vop/iommu to enable eDP display on rk3399 evb. Signed-off-by: Andy Yan Link: https://lore.kernel.org/r/20200305113912.32226-5-andy.yan@rock-chips.com Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3399-evb.dts | 39 +++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts index 6f83d947e228..5e5d49f3c229 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts @@ -51,6 +51,19 @@ pwms = <&pwm0 0 25000 0>; }; + edp_panel: edp-panel { + compatible ="lg,lp079qx1-sp0v"; + backlight = <&backlight>; + enable-gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>; + power-supply = <&vcc3v3_s0>; + + port { + panel_in_edp: endpoint { + remote-endpoint = <&edp_out_panel>; + }; + }; + }; + clkin_gmac: external-gmac-clock { compatible = "fixed-clock"; clock-frequency = <125000000>; @@ -113,6 +126,24 @@ }; +&edp { + status = "okay"; + force-hpd; + + ports { + edp_out: port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + edp_out_panel: endpoint@0 { + reg = <0>; + remote-endpoint = <&panel_in_edp>; + }; + }; + }; +}; + &emmc_phy { status = "okay"; }; @@ -440,3 +471,11 @@ }; }; }; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; From 9f40b6e77d2f888a8c0608036eb124cedb6d2434 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Mon, 24 Feb 2020 11:34:36 -0800 Subject: [PATCH 1207/4444] RISC-V: Move all address space definition macros to one place MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If both CONFIG_KASAN and CONFIG_SPARSEMEM_VMEMMAP are set, we get the following compilation error. --------------------------------------------------------------- ./arch/riscv/include/asm/pgtable-64.h: In function ‘pud_page’: ./include/asm-generic/memory_model.h:54:29: error: ‘vmemmap’ undeclared (first use in this function); did you mean ‘mem_map’? #define __pfn_to_page(pfn) (vmemmap + (pfn)) ^~~~~~~ ./include/asm-generic/memory_model.h:82:21: note: in expansion of macro ‘__pfn_to_page’ #define pfn_to_page __pfn_to_page ^~~~~~~~~~~~~ ./arch/riscv/include/asm/pgtable-64.h:70:9: note: in expansion of macro ‘pfn_to_page’ return pfn_to_page(pud_val(pud) >> _PAGE_PFN_SHIFT); --------------------------------------------------------------- Fix the compliation errors by moving all the address space definition macros before including pgtable-64.h. Fixes: 8ad8b72721d0 (riscv: Add KASAN support) Signed-off-by: Atish Patra Reviewed-by: Anup Patel Signed-off-by: Palmer Dabbelt --- arch/riscv/include/asm/pgtable.h | 78 +++++++++++++++++--------------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index e43041519edd..393f2014dfee 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -19,6 +19,47 @@ #include #include +#ifdef CONFIG_MMU + +#define VMALLOC_SIZE (KERN_VIRT_SIZE >> 1) +#define VMALLOC_END (PAGE_OFFSET - 1) +#define VMALLOC_START (PAGE_OFFSET - VMALLOC_SIZE) + +#define BPF_JIT_REGION_SIZE (SZ_128M) +#define BPF_JIT_REGION_START (PAGE_OFFSET - BPF_JIT_REGION_SIZE) +#define BPF_JIT_REGION_END (VMALLOC_END) + +/* + * Roughly size the vmemmap space to be large enough to fit enough + * struct pages to map half the virtual address space. Then + * position vmemmap directly below the VMALLOC region. + */ +#define VMEMMAP_SHIFT \ + (CONFIG_VA_BITS - PAGE_SHIFT - 1 + STRUCT_PAGE_MAX_SHIFT) +#define VMEMMAP_SIZE BIT(VMEMMAP_SHIFT) +#define VMEMMAP_END (VMALLOC_START - 1) +#define VMEMMAP_START (VMALLOC_START - VMEMMAP_SIZE) + +/* + * Define vmemmap for pfn_to_page & page_to_pfn calls. Needed if kernel + * is configured with CONFIG_SPARSEMEM_VMEMMAP enabled. + */ +#define vmemmap ((struct page *)VMEMMAP_START) + +#define PCI_IO_SIZE SZ_16M +#define PCI_IO_END VMEMMAP_START +#define PCI_IO_START (PCI_IO_END - PCI_IO_SIZE) + +#define FIXADDR_TOP PCI_IO_START +#ifdef CONFIG_64BIT +#define FIXADDR_SIZE PMD_SIZE +#else +#define FIXADDR_SIZE PGDIR_SIZE +#endif +#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) + +#endif + #ifdef CONFIG_64BIT #include #else @@ -90,31 +131,6 @@ extern pgd_t swapper_pg_dir[]; #define __S110 PAGE_SHARED_EXEC #define __S111 PAGE_SHARED_EXEC -#define VMALLOC_SIZE (KERN_VIRT_SIZE >> 1) -#define VMALLOC_END (PAGE_OFFSET - 1) -#define VMALLOC_START (PAGE_OFFSET - VMALLOC_SIZE) - -#define BPF_JIT_REGION_SIZE (SZ_128M) -#define BPF_JIT_REGION_START (PAGE_OFFSET - BPF_JIT_REGION_SIZE) -#define BPF_JIT_REGION_END (VMALLOC_END) - -/* - * Roughly size the vmemmap space to be large enough to fit enough - * struct pages to map half the virtual address space. Then - * position vmemmap directly below the VMALLOC region. - */ -#define VMEMMAP_SHIFT \ - (CONFIG_VA_BITS - PAGE_SHIFT - 1 + STRUCT_PAGE_MAX_SHIFT) -#define VMEMMAP_SIZE BIT(VMEMMAP_SHIFT) -#define VMEMMAP_END (VMALLOC_START - 1) -#define VMEMMAP_START (VMALLOC_START - VMEMMAP_SIZE) - -/* - * Define vmemmap for pfn_to_page & page_to_pfn calls. Needed if kernel - * is configured with CONFIG_SPARSEMEM_VMEMMAP enabled. - */ -#define vmemmap ((struct page *)VMEMMAP_START) - static inline int pmd_present(pmd_t pmd) { return (pmd_val(pmd) & (_PAGE_PRESENT | _PAGE_PROT_NONE)); @@ -432,18 +448,6 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma, #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -#define PCI_IO_SIZE SZ_16M -#define PCI_IO_END VMEMMAP_START -#define PCI_IO_START (PCI_IO_END - PCI_IO_SIZE) - -#define FIXADDR_TOP PCI_IO_START -#ifdef CONFIG_64BIT -#define FIXADDR_SIZE PMD_SIZE -#else -#define FIXADDR_SIZE PGDIR_SIZE -#endif -#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) - /* * Task size is 0x4000000000 for RV64 or 0x9fc00000 for RV32. * Note that PGDIR_SIZE must evenly divide TASK_SIZE. From e2e699bb44e0c162dee9ee7431b684c6868204a1 Mon Sep 17 00:00:00 2001 From: Emmanuel Vadot Date: Wed, 4 Mar 2020 22:30:22 +0100 Subject: [PATCH 1208/4444] dt-bindings: Add doc for Pine64 Pinebook Pro Add a compatible for Pine64 Pinebook Pro Signed-off-by: Emmanuel Vadot Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20200304213023.689983-2-t.schramm@manjaro.org Signed-off-by: Heiko Stuebner --- Documentation/devicetree/bindings/arm/rockchip.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml index 874b0eaa2a75..f4ba00d679e6 100644 --- a/Documentation/devicetree/bindings/arm/rockchip.yaml +++ b/Documentation/devicetree/bindings/arm/rockchip.yaml @@ -402,6 +402,11 @@ properties: - const: phytec,rk3288-phycore-som - const: rockchip,rk3288 + - description: Pine64 PinebookPro + items: + - const: pine64,pinebook-pro + - const: rockchip,rk3399 + - description: Pine64 Rock64 items: - const: pine64,rock64 From 92e9c58c5629762001e7294afbdf1283d5c7d2ed Mon Sep 17 00:00:00 2001 From: Madhuparna Bhowmik Date: Thu, 13 Feb 2020 20:55:58 +0530 Subject: [PATCH 1209/4444] ext4: use built-in RCU list checking in mballoc list_for_each_entry_rcu() has built-in RCU and lock checking. Pass cond argument to list_for_each_entry_rcu() to silence false lockdep warning when CONFIG_PROVE_RCU_LIST is enabled by default. Signed-off-by: Madhuparna Bhowmik Link: https://lore.kernel.org/r/20200213152558.7070-1-madhuparnabhowmik10@gmail.com Signed-off-by: Theodore Ts'o --- fs/ext4/mballoc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 51a78eb65f3c..1027e01c9011 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4302,7 +4302,8 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb, spin_lock(&lg->lg_prealloc_lock); list_for_each_entry_rcu(pa, &lg->lg_prealloc_list[order], - pa_inode_list) { + pa_inode_list, + lockdep_is_held(&lg->lg_prealloc_lock)) { spin_lock(&pa->pa_lock); if (atomic_read(&pa->pa_count)) { /* @@ -4386,7 +4387,8 @@ static void ext4_mb_add_n_trim(struct ext4_allocation_context *ac) /* Add the prealloc space to lg */ spin_lock(&lg->lg_prealloc_lock); list_for_each_entry_rcu(tmp_pa, &lg->lg_prealloc_list[order], - pa_inode_list) { + pa_inode_list, + lockdep_is_held(&lg->lg_prealloc_lock)) { spin_lock(&tmp_pa->pa_lock); if (tmp_pa->pa_deleted) { spin_unlock(&tmp_pa->pa_lock); From 6cfb061fe9e901dd0b6cfa3ed50bc39c81523532 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 13 Feb 2020 10:06:48 -0600 Subject: [PATCH 1210/4444] ext4: use flexible-array members in struct dx_node and struct dx_root The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200213160648.GA7054@embeddedor Signed-off-by: Theodore Ts'o --- fs/ext4/namei.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index b05ea72f38fd..5f0a758956f6 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -233,13 +233,13 @@ struct dx_root u8 unused_flags; } info; - struct dx_entry entries[0]; + struct dx_entry entries[]; }; struct dx_node { struct fake_dirent fake; - struct dx_entry entries[0]; + struct dx_entry entries[]; }; From 780f66e59231fcf882f36c63f287252ee47cc75a Mon Sep 17 00:00:00 2001 From: "zhangyi (F)" Date: Mon, 17 Feb 2020 19:27:06 +0800 Subject: [PATCH 1211/4444] jbd2: improve comments about freeing data buffers whose page mapping is NULL Improve comments in jbd2_journal_commit_transaction() to describe why we don't need to clear the buffer_mapped bit for freeing file mapping buffers whose page mapping is NULL. Link: https://lore.kernel.org/r/20200217112706.20085-1-yi.zhang@huawei.com Fixes: c96dceeabf76 ("jbd2: do not clear the BH_Mapped flag when forgetting a metadata buffer") Suggested-by: Jan Kara Reviewed-by: Jan Kara Signed-off-by: zhangyi (F) Signed-off-by: Theodore Ts'o --- fs/jbd2/commit.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 27373f5792a4..e855d8260433 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -997,9 +997,10 @@ restart_loop: * journalled data) we need to unmap buffer and clear * more bits. We also need to be careful about the check * because the data page mapping can get cleared under - * out hands, which alse need not to clear more bits - * because the page and buffers will be freed and can - * never be reused once we are done with them. + * our hands. Note that if mapping == NULL, we don't + * need to make buffer unmapped because the page is + * already detached from the mapping and buffers cannot + * get reused. */ mapping = READ_ONCE(bh->b_page->mapping); if (mapping && !sb_is_blkdev_sb(mapping->host->i_sb)) { From f064a9d6e7dbd3473e9da0ffa1a91c08a032d747 Mon Sep 17 00:00:00 2001 From: Eric Whitney Date: Tue, 18 Feb 2020 15:26:56 -0500 Subject: [PATCH 1212/4444] ext4: clean up error return for convert_initialized_extent() Although convert_initialized_extent() can potentially return an error code with a negative value, its returned value is assigned to an unsigned variable containing a block count in ext4_ext_map_blocks() and then returned to that function's caller. The code currently works, though the way this happens is obscure. The code would be more readable if it followed the error handling convention used elsewhere in ext4_ext_map_blocks(). This patch does not address any known test failure or bug report - it's simply a cleanup. It also addresses a nearby coding standard issue. Signed-off-by: Eric Whitney Link: https://lore.kernel.org/r/20200218202656.21561-1-enwlinux@gmail.com Signed-off-by: Theodore Ts'o --- fs/ext4/extents.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index a5338a8da2ab..bc96529d1509 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -3871,7 +3871,7 @@ static int convert_initialized_extent(handle_t *handle, struct inode *inode, struct ext4_map_blocks *map, struct ext4_ext_path **ppath, - unsigned int allocated) + unsigned int *allocated) { struct ext4_ext_path *path = *ppath; struct ext4_extent *ex; @@ -3933,10 +3933,10 @@ convert_initialized_extent(handle_t *handle, struct inode *inode, ext4_update_inode_fsync_trans(handle, inode, 1); map->m_flags |= EXT4_MAP_UNWRITTEN; - if (allocated > map->m_len) - allocated = map->m_len; - map->m_len = allocated; - return allocated; + if (*allocated > map->m_len) + *allocated = map->m_len; + map->m_len = *allocated; + return 0; } static int @@ -4240,12 +4240,12 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, */ if ((!ext4_ext_is_unwritten(ex)) && (flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN)) { - allocated = convert_initialized_extent( - handle, inode, map, &path, - allocated); + err = convert_initialized_extent(handle, + inode, map, &path, &allocated); goto out2; - } else if (!ext4_ext_is_unwritten(ex)) + } else if (!ext4_ext_is_unwritten(ex)) { goto out; + } ret = ext4_ext_handle_unwritten_extents( handle, inode, map, &path, flags, From 1acf1a564b6034b5af1e7fb23cb98cb3bb4f6003 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:32 +0900 Subject: [PATCH 1213/4444] exfat: add in-memory and on-disk structures and headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds in-memory and on-disk structures and headers. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/exfat/exfat_fs.h | 519 +++++++++++++++++++++++++++++++++++++++++++ fs/exfat/exfat_raw.h | 184 +++++++++++++++ 2 files changed, 703 insertions(+) create mode 100644 fs/exfat/exfat_fs.h create mode 100644 fs/exfat/exfat_raw.h diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h new file mode 100644 index 000000000000..67d4e46fb810 --- /dev/null +++ b/fs/exfat/exfat_fs.h @@ -0,0 +1,519 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#ifndef _EXFAT_FS_H +#define _EXFAT_FS_H + +#include +#include +#include + +#define EXFAT_SUPER_MAGIC 0x2011BAB0UL +#define EXFAT_ROOT_INO 1 + +#define EXFAT_SB_DIRTY 0 + +#define EXFAT_CLUSTERS_UNTRACKED (~0u) + +/* + * exfat error flags + */ +enum exfat_error_mode { + EXFAT_ERRORS_CONT, /* ignore error and continue */ + EXFAT_ERRORS_PANIC, /* panic on error */ + EXFAT_ERRORS_RO, /* remount r/o on error */ +}; + +/* + * exfat nls lossy flag + */ +enum { + NLS_NAME_NO_LOSSY, /* no lossy */ + NLS_NAME_LOSSY, /* just detected incorrect filename(s) */ + NLS_NAME_OVERLEN, /* the length is over than its limit */ +}; + +#define EXFAT_HASH_BITS 8 +#define EXFAT_HASH_SIZE (1UL << EXFAT_HASH_BITS) + +/* + * Type Definitions + */ +#define ES_2_ENTRIES 2 +#define ES_ALL_ENTRIES 0 + +#define DIR_DELETED 0xFFFF0321 + +/* type values */ +#define TYPE_UNUSED 0x0000 +#define TYPE_DELETED 0x0001 +#define TYPE_INVALID 0x0002 +#define TYPE_CRITICAL_PRI 0x0100 +#define TYPE_BITMAP 0x0101 +#define TYPE_UPCASE 0x0102 +#define TYPE_VOLUME 0x0103 +#define TYPE_DIR 0x0104 +#define TYPE_FILE 0x011F +#define TYPE_CRITICAL_SEC 0x0200 +#define TYPE_STREAM 0x0201 +#define TYPE_EXTEND 0x0202 +#define TYPE_ACL 0x0203 +#define TYPE_BENIGN_PRI 0x0400 +#define TYPE_GUID 0x0401 +#define TYPE_PADDING 0x0402 +#define TYPE_ACLTAB 0x0403 +#define TYPE_BENIGN_SEC 0x0800 +#define TYPE_ALL 0x0FFF + +#define MAX_CHARSET_SIZE 6 /* max size of multi-byte character */ +#define MAX_NAME_LENGTH 255 /* max len of file name excluding NULL */ +#define MAX_VFSNAME_BUF_SIZE ((MAX_NAME_LENGTH + 1) * MAX_CHARSET_SIZE) + +#define FAT_CACHE_SIZE 128 +#define FAT_CACHE_HASH_SIZE 64 +#define BUF_CACHE_SIZE 256 +#define BUF_CACHE_HASH_SIZE 64 + +#define EXFAT_HINT_NONE -1 +#define EXFAT_MIN_SUBDIR 2 + +/* + * helpers for cluster size to byte conversion. + */ +#define EXFAT_CLU_TO_B(b, sbi) ((b) << (sbi)->cluster_size_bits) +#define EXFAT_B_TO_CLU(b, sbi) ((b) >> (sbi)->cluster_size_bits) +#define EXFAT_B_TO_CLU_ROUND_UP(b, sbi) \ + (((b - 1) >> (sbi)->cluster_size_bits) + 1) +#define EXFAT_CLU_OFFSET(off, sbi) ((off) & ((sbi)->cluster_size - 1)) + +/* + * helpers for block size to byte conversion. + */ +#define EXFAT_BLK_TO_B(b, sb) ((b) << (sb)->s_blocksize_bits) +#define EXFAT_B_TO_BLK(b, sb) ((b) >> (sb)->s_blocksize_bits) +#define EXFAT_B_TO_BLK_ROUND_UP(b, sb) \ + (((b - 1) >> (sb)->s_blocksize_bits) + 1) +#define EXFAT_BLK_OFFSET(off, sb) ((off) & ((sb)->s_blocksize - 1)) + +/* + * helpers for block size to dentry size conversion. + */ +#define EXFAT_B_TO_DEN_IDX(b, sbi) \ + ((b) << ((sbi)->cluster_size_bits - DENTRY_SIZE_BITS)) +#define EXFAT_B_TO_DEN(b) ((b) >> DENTRY_SIZE_BITS) +#define EXFAT_DEN_TO_B(b) ((b) << DENTRY_SIZE_BITS) + +/* + * helpers for fat entry. + */ +#define FAT_ENT_SIZE (4) +#define FAT_ENT_SIZE_BITS (2) +#define FAT_ENT_OFFSET_SECTOR(sb, loc) (EXFAT_SB(sb)->FAT1_start_sector + \ + (((u64)loc << FAT_ENT_SIZE_BITS) >> sb->s_blocksize_bits)) +#define FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc) \ + ((loc << FAT_ENT_SIZE_BITS) & (sb->s_blocksize - 1)) + +/* + * helpers for bitmap. + */ +#define CLUSTER_TO_BITMAP_ENT(clu) ((clu) - EXFAT_RESERVED_CLUSTERS) +#define BITMAP_ENT_TO_CLUSTER(ent) ((ent) + EXFAT_RESERVED_CLUSTERS) +#define BITS_PER_SECTOR(sb) ((sb)->s_blocksize * BITS_PER_BYTE) +#define BITS_PER_SECTOR_MASK(sb) (BITS_PER_SECTOR(sb) - 1) +#define BITMAP_OFFSET_SECTOR_INDEX(sb, ent) \ + ((ent / BITS_PER_BYTE) >> (sb)->s_blocksize_bits) +#define BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent) (ent & BITS_PER_SECTOR_MASK(sb)) +#define BITMAP_OFFSET_BYTE_IN_SECTOR(sb, ent) \ + ((ent / BITS_PER_BYTE) & ((sb)->s_blocksize - 1)) +#define BITS_PER_BYTE_MASK 0x7 +#define IGNORED_BITS_REMAINED(clu, clu_base) ((1 << ((clu) - (clu_base))) - 1) + +struct exfat_dentry_namebuf { + char *lfn; + int lfnbuf_len; /* usally MAX_UNINAME_BUF_SIZE */ +}; + +/* unicode name structure */ +struct exfat_uni_name { + /* +3 for null and for converting */ + unsigned short name[MAX_NAME_LENGTH + 3]; + unsigned short name_hash; + unsigned char name_len; +}; + +/* directory structure */ +struct exfat_chain { + unsigned int dir; + unsigned int size; + unsigned char flags; +}; + +/* first empty entry hint information */ +struct exfat_hint_femp { + /* entry index of a directory */ + int eidx; + /* count of continuous empty entry */ + int count; + /* the cluster that first empty slot exists in */ + struct exfat_chain cur; +}; + +/* hint structure */ +struct exfat_hint { + unsigned int clu; + union { + unsigned int off; /* cluster offset */ + int eidx; /* entry index */ + }; +}; + +struct exfat_entry_set_cache { + /* sector number that contains file_entry */ + sector_t sector; + /* byte offset in the sector */ + unsigned int offset; + /* flag in stream entry. 01 for cluster chain, 03 for contig. */ + int alloc_flag; + unsigned int num_entries; + struct exfat_dentry entries[]; +}; + +struct exfat_dir_entry { + struct exfat_chain dir; + int entry; + unsigned int type; + unsigned int start_clu; + unsigned char flags; + unsigned short attr; + loff_t size; + unsigned int num_subdirs; + struct timespec64 atime; + struct timespec64 mtime; + struct timespec64 crtime; + struct exfat_dentry_namebuf namebuf; +}; + +/* + * exfat mount in-memory data + */ +struct exfat_mount_options { + kuid_t fs_uid; + kgid_t fs_gid; + unsigned short fs_fmask; + unsigned short fs_dmask; + /* permission for setting the [am]time */ + unsigned short allow_utime; + /* charset for filename input/display */ + char *iocharset; + /* on error: continue, panic, remount-ro */ + enum exfat_error_mode errors; + unsigned utf8:1, /* Use of UTF-8 character set */ + discard:1; /* Issue discard requests on deletions */ + int time_offset; /* Offset of timestamps from UTC (in minutes) */ +}; + +/* + * EXFAT file system superblock in-memory data + */ +struct exfat_sb_info { + unsigned long long num_sectors; /* num of sectors in volume */ + unsigned int num_clusters; /* num of clusters in volume */ + unsigned int cluster_size; /* cluster size in bytes */ + unsigned int cluster_size_bits; + unsigned int sect_per_clus; /* cluster size in sectors */ + unsigned int sect_per_clus_bits; + unsigned long long FAT1_start_sector; /* FAT1 start sector */ + unsigned long long FAT2_start_sector; /* FAT2 start sector */ + unsigned long long data_start_sector; /* data area start sector */ + unsigned int num_FAT_sectors; /* num of FAT sectors */ + unsigned int root_dir; /* root dir cluster */ + unsigned int dentries_per_clu; /* num of dentries per cluster */ + unsigned int vol_flag; /* volume dirty flag */ + struct buffer_head *pbr_bh; /* buffer_head of PBR sector */ + + unsigned int map_clu; /* allocation bitmap start cluster */ + unsigned int map_sectors; /* num of allocation bitmap sectors */ + struct buffer_head **vol_amap; /* allocation bitmap */ + + unsigned short *vol_utbl; /* upcase table */ + + unsigned int clu_srch_ptr; /* cluster search pointer */ + unsigned int used_clusters; /* number of used clusters */ + + unsigned long s_state; + struct mutex s_lock; /* superblock lock */ + struct exfat_mount_options options; + struct nls_table *nls_io; /* Charset used for input and display */ + struct ratelimit_state ratelimit; + + spinlock_t inode_hash_lock; + struct hlist_head inode_hashtable[EXFAT_HASH_SIZE]; + + struct rcu_head rcu; +}; + +/* + * EXFAT file system inode in-memory data + */ +struct exfat_inode_info { + struct exfat_chain dir; + int entry; + unsigned int type; + unsigned short attr; + unsigned int start_clu; + unsigned char flags; + /* + * the copy of low 32bit of i_version to check + * the validation of hint_stat. + */ + unsigned int version; + /* file offset or dentry index for readdir */ + loff_t rwoffset; + + /* hint for cluster last accessed */ + struct exfat_hint hint_bmap; + /* hint for entry index we try to lookup next time */ + struct exfat_hint hint_stat; + /* hint for first empty entry */ + struct exfat_hint_femp hint_femp; + + spinlock_t cache_lru_lock; + struct list_head cache_lru; + int nr_caches; + /* for avoiding the race between alloc and free */ + unsigned int cache_valid_id; + + /* + * NOTE: i_size_ondisk is 64bits, so must hold ->inode_lock to access. + * physically allocated size. + */ + loff_t i_size_ondisk; + /* block-aligned i_size (used in cont_write_begin) */ + loff_t i_size_aligned; + /* on-disk position of directory entry or 0 */ + loff_t i_pos; + /* hash by i_location */ + struct hlist_node i_hash_fat; + /* protect bmap against truncate */ + struct rw_semaphore truncate_lock; + struct inode vfs_inode; + /* File creation time */ + struct timespec64 i_crtime; +}; + +static inline struct exfat_sb_info *EXFAT_SB(struct super_block *sb) +{ + return sb->s_fs_info; +} + +static inline struct exfat_inode_info *EXFAT_I(struct inode *inode) +{ + return container_of(inode, struct exfat_inode_info, vfs_inode); +} + +/* + * If ->i_mode can't hold 0222 (i.e. ATTR_RO), we use ->i_attrs to + * save ATTR_RO instead of ->i_mode. + * + * If it's directory and !sbi->options.rodir, ATTR_RO isn't read-only + * bit, it's just used as flag for app. + */ +static inline int exfat_mode_can_hold_ro(struct inode *inode) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + + if (S_ISDIR(inode->i_mode)) + return 0; + + if ((~sbi->options.fs_fmask) & 0222) + return 1; + return 0; +} + +/* Convert attribute bits and a mask to the UNIX mode. */ +static inline mode_t exfat_make_mode(struct exfat_sb_info *sbi, + unsigned short attr, mode_t mode) +{ + if ((attr & ATTR_READONLY) && !(attr & ATTR_SUBDIR)) + mode &= ~0222; + + if (attr & ATTR_SUBDIR) + return (mode & ~sbi->options.fs_dmask) | S_IFDIR; + + return (mode & ~sbi->options.fs_fmask) | S_IFREG; +} + +/* Return the FAT attribute byte for this inode */ +static inline unsigned short exfat_make_attr(struct inode *inode) +{ + unsigned short attr = EXFAT_I(inode)->attr; + + if (S_ISDIR(inode->i_mode)) + attr |= ATTR_SUBDIR; + if (exfat_mode_can_hold_ro(inode) && !(inode->i_mode & 0222)) + attr |= ATTR_READONLY; + return attr; +} + +static inline void exfat_save_attr(struct inode *inode, unsigned short attr) +{ + if (exfat_mode_can_hold_ro(inode)) + EXFAT_I(inode)->attr = attr & (ATTR_RWMASK | ATTR_READONLY); + else + EXFAT_I(inode)->attr = attr & ATTR_RWMASK; +} + +static inline bool exfat_is_last_sector_in_cluster(struct exfat_sb_info *sbi, + sector_t sec) +{ + return ((sec - sbi->data_start_sector + 1) & + ((1 << sbi->sect_per_clus_bits) - 1)) == 0; +} + +static inline sector_t exfat_cluster_to_sector(struct exfat_sb_info *sbi, + unsigned int clus) +{ + return ((clus - EXFAT_RESERVED_CLUSTERS) << sbi->sect_per_clus_bits) + + sbi->data_start_sector; +} + +static inline int exfat_sector_to_cluster(struct exfat_sb_info *sbi, + sector_t sec) +{ + return ((sec - sbi->data_start_sector) >> sbi->sect_per_clus_bits) + + EXFAT_RESERVED_CLUSTERS; +} + +/* super.c */ +int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag); + +/* fatent.c */ +#define exfat_get_next_cluster(sb, pclu) exfat_ent_get(sb, *(pclu), pclu) + +int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc, + struct exfat_chain *p_chain); +int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain); +int exfat_ent_get(struct super_block *sb, unsigned int loc, + unsigned int *content); +int exfat_ent_set(struct super_block *sb, unsigned int loc, + unsigned int content); +int exfat_count_ext_entries(struct super_block *sb, struct exfat_chain *p_dir, + int entry, struct exfat_dentry *p_entry); +int exfat_chain_cont_cluster(struct super_block *sb, unsigned int chain, + unsigned int len); +int exfat_zeroed_cluster(struct inode *dir, unsigned int clu); +int exfat_find_last_cluster(struct super_block *sb, struct exfat_chain *p_chain, + unsigned int *ret_clu); +int exfat_count_num_clusters(struct super_block *sb, + struct exfat_chain *p_chain, unsigned int *ret_count); + +/* balloc.c */ +int exfat_load_bitmap(struct super_block *sb); +void exfat_free_bitmap(struct exfat_sb_info *sbi); +int exfat_set_bitmap(struct inode *inode, unsigned int clu); +void exfat_clear_bitmap(struct inode *inode, unsigned int clu); +unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu); +int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count); + +/* file.c */ +extern const struct file_operations exfat_file_operations; +int __exfat_truncate(struct inode *inode, loff_t new_size); +void exfat_truncate(struct inode *inode, loff_t size); +int exfat_setattr(struct dentry *dentry, struct iattr *attr); +int exfat_getattr(const struct path *path, struct kstat *stat, + unsigned int request_mask, unsigned int query_flags); + +/* namei.c */ +extern const struct dentry_operations exfat_dentry_ops; +extern const struct dentry_operations exfat_utf8_dentry_ops; + +/* cache.c */ +int exfat_cache_init(void); +void exfat_cache_shutdown(void); +void exfat_cache_init_inode(struct inode *inode); +void exfat_cache_inval_inode(struct inode *inode); +int exfat_get_cluster(struct inode *inode, unsigned int cluster, + unsigned int *fclus, unsigned int *dclus, + unsigned int *last_dclus, int allow_eof); + +/* dir.c */ +extern const struct inode_operations exfat_dir_inode_operations; +extern const struct file_operations exfat_dir_operations; +unsigned int exfat_get_entry_type(struct exfat_dentry *p_entry); +int exfat_init_dir_entry(struct inode *inode, struct exfat_chain *p_dir, + int entry, unsigned int type, unsigned int start_clu, + unsigned long long size); +int exfat_init_ext_entry(struct inode *inode, struct exfat_chain *p_dir, + int entry, int num_entries, struct exfat_uni_name *p_uniname); +int exfat_remove_entries(struct inode *inode, struct exfat_chain *p_dir, + int entry, int order, int num_entries); +int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir, + int entry); +int exfat_update_dir_chksum_with_entry_set(struct super_block *sb, + struct exfat_entry_set_cache *es, int sync); +int exfat_calc_num_entries(struct exfat_uni_name *p_uniname); +int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei, + struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname, + int num_entries, unsigned int type); +int exfat_alloc_new_dir(struct inode *inode, struct exfat_chain *clu); +int exfat_find_location(struct super_block *sb, struct exfat_chain *p_dir, + int entry, sector_t *sector, int *offset); +struct exfat_dentry *exfat_get_dentry(struct super_block *sb, + struct exfat_chain *p_dir, int entry, struct buffer_head **bh, + sector_t *sector); +struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb, + struct exfat_chain *p_dir, int entry, unsigned int type, + struct exfat_dentry **file_ep); +int exfat_count_dir_entries(struct super_block *sb, struct exfat_chain *p_dir); + +/* inode.c */ +extern const struct inode_operations exfat_file_inode_operations; +void exfat_sync_inode(struct inode *inode); +struct inode *exfat_build_inode(struct super_block *sb, + struct exfat_dir_entry *info, loff_t i_pos); +void exfat_hash_inode(struct inode *inode, loff_t i_pos); +void exfat_unhash_inode(struct inode *inode); +struct inode *exfat_iget(struct super_block *sb, loff_t i_pos); +int exfat_write_inode(struct inode *inode, struct writeback_control *wbc); +void exfat_evict_inode(struct inode *inode); +int exfat_block_truncate_page(struct inode *inode, loff_t from); + +/* exfat/nls.c */ +unsigned short exfat_toupper(struct super_block *sb, unsigned short a); +int exfat_uniname_ncmp(struct super_block *sb, unsigned short *a, + unsigned short *b, unsigned int len); +int exfat_utf16_to_nls(struct super_block *sb, + struct exfat_uni_name *uniname, unsigned char *p_cstring, + int len); +int exfat_nls_to_utf16(struct super_block *sb, + const unsigned char *p_cstring, const int len, + struct exfat_uni_name *uniname, int *p_lossy); +int exfat_create_upcase_table(struct super_block *sb); +void exfat_free_upcase_table(struct exfat_sb_info *sbi); +unsigned short exfat_high_surrogate(unicode_t u); +unsigned short exfat_low_surrogate(unicode_t u); + +/* exfat/misc.c */ +void __exfat_fs_error(struct super_block *sb, int report, const char *fmt, ...) + __printf(3, 4) __cold; +#define exfat_fs_error(sb, fmt, args...) \ + __exfat_fs_error(sb, 1, fmt, ## args) +#define exfat_fs_error_ratelimit(sb, fmt, args...) \ + __exfat_fs_error(sb, __ratelimit(&EXFAT_SB(sb)->ratelimit), \ + fmt, ## args) +void exfat_msg(struct super_block *sb, const char *lv, const char *fmt, ...) + __printf(3, 4) __cold; +void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, + u8 tz, __le16 time, __le16 date, u8 time_ms); +void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, + u8 *tz, __le16 *time, __le16 *date, u8 *time_ms); +unsigned short exfat_calc_chksum_2byte(void *data, int len, + unsigned short chksum, int type); +void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int sync); +void exfat_chain_set(struct exfat_chain *ec, unsigned int dir, + unsigned int size, unsigned char flags); +void exfat_chain_dup(struct exfat_chain *dup, struct exfat_chain *ec); + +#endif /* !_EXFAT_FS_H */ diff --git a/fs/exfat/exfat_raw.h b/fs/exfat/exfat_raw.h new file mode 100644 index 000000000000..2a841010e649 --- /dev/null +++ b/fs/exfat/exfat_raw.h @@ -0,0 +1,184 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#ifndef _EXFAT_RAW_H +#define _EXFAT_RAW_H + +#include + +#define PBR_SIGNATURE 0xAA55 + +#define EXFAT_MAX_FILE_LEN 255 + +#define VOL_CLEAN 0x0000 +#define VOL_DIRTY 0x0002 + +#define EXFAT_EOF_CLUSTER 0xFFFFFFFFu +#define EXFAT_BAD_CLUSTER 0xFFFFFFF7u +#define EXFAT_FREE_CLUSTER 0 +/* Cluster 0, 1 are reserved, the first cluster is 2 in the cluster heap. */ +#define EXFAT_RESERVED_CLUSTERS 2 +#define EXFAT_FIRST_CLUSTER 2 +#define EXFAT_DATA_CLUSTER_COUNT(sbi) \ + ((sbi)->num_clusters - EXFAT_RESERVED_CLUSTERS) + +/* AllocationPossible and NoFatChain field in GeneralSecondaryFlags Field */ +#define ALLOC_FAT_CHAIN 0x01 +#define ALLOC_NO_FAT_CHAIN 0x03 + +#define DENTRY_SIZE 32 /* directory entry size */ +#define DENTRY_SIZE_BITS 5 +/* exFAT allows 8388608(256MB) directory entries */ +#define MAX_EXFAT_DENTRIES 8388608 + +/* dentry types */ +#define EXFAT_UNUSED 0x00 /* end of directory */ +#define EXFAT_DELETE (~0x80) +#define IS_EXFAT_DELETED(x) ((x) < 0x80) /* deleted file (0x01~0x7F) */ +#define EXFAT_INVAL 0x80 /* invalid value */ +#define EXFAT_BITMAP 0x81 /* allocation bitmap */ +#define EXFAT_UPCASE 0x82 /* upcase table */ +#define EXFAT_VOLUME 0x83 /* volume label */ +#define EXFAT_FILE 0x85 /* file or dir */ +#define EXFAT_GUID 0xA0 +#define EXFAT_PADDING 0xA1 +#define EXFAT_ACLTAB 0xA2 +#define EXFAT_STREAM 0xC0 /* stream entry */ +#define EXFAT_NAME 0xC1 /* file name entry */ +#define EXFAT_ACL 0xC2 /* stream entry */ + +#define IS_EXFAT_CRITICAL_PRI(x) (x < 0xA0) +#define IS_EXFAT_BENIGN_PRI(x) (x < 0xC0) +#define IS_EXFAT_CRITICAL_SEC(x) (x < 0xE0) + +/* checksum types */ +#define CS_DIR_ENTRY 0 +#define CS_PBR_SECTOR 1 +#define CS_DEFAULT 2 + +/* file attributes */ +#define ATTR_READONLY 0x0001 +#define ATTR_HIDDEN 0x0002 +#define ATTR_SYSTEM 0x0004 +#define ATTR_VOLUME 0x0008 +#define ATTR_SUBDIR 0x0010 +#define ATTR_ARCHIVE 0x0020 + +#define ATTR_RWMASK (ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME | \ + ATTR_SUBDIR | ATTR_ARCHIVE) + +#define PBR64_JUMP_BOOT_LEN 3 +#define PBR64_OEM_NAME_LEN 8 +#define PBR64_RESERVED_LEN 53 + +#define EXFAT_FILE_NAME_LEN 15 + +/* EXFAT BIOS parameter block (64 bytes) */ +struct bpb64 { + __u8 jmp_boot[PBR64_JUMP_BOOT_LEN]; + __u8 oem_name[PBR64_OEM_NAME_LEN]; + __u8 res_zero[PBR64_RESERVED_LEN]; +} __packed; + +/* EXFAT EXTEND BIOS parameter block (56 bytes) */ +struct bsx64 { + __le64 vol_offset; + __le64 vol_length; + __le32 fat_offset; + __le32 fat_length; + __le32 clu_offset; + __le32 clu_count; + __le32 root_cluster; + __le32 vol_serial; + __u8 fs_version[2]; + __le16 vol_flags; + __u8 sect_size_bits; + __u8 sect_per_clus_bits; + __u8 num_fats; + __u8 phy_drv_no; + __u8 perc_in_use; + __u8 reserved2[7]; +} __packed; + +/* EXFAT PBR[BPB+BSX] (120 bytes) */ +struct pbr64 { + struct bpb64 bpb; + struct bsx64 bsx; +} __packed; + +/* Common PBR[Partition Boot Record] (512 bytes) */ +struct pbr { + union { + __u8 raw[64]; + struct bpb64 f64; + } bpb; + union { + __u8 raw[56]; + struct bsx64 f64; + } bsx; + __u8 boot_code[390]; + __le16 signature; +} __packed; + +struct exfat_dentry { + __u8 type; + union { + struct { + __u8 num_ext; + __le16 checksum; + __le16 attr; + __le16 reserved1; + __le16 create_time; + __le16 create_date; + __le16 modify_time; + __le16 modify_date; + __le16 access_time; + __le16 access_date; + __u8 create_time_ms; + __u8 modify_time_ms; + __u8 create_tz; + __u8 modify_tz; + __u8 access_tz; + __u8 reserved2[7]; + } __packed file; /* file directory entry */ + struct { + __u8 flags; + __u8 reserved1; + __u8 name_len; + __le16 name_hash; + __le16 reserved2; + __le64 valid_size; + __le32 reserved3; + __le32 start_clu; + __le64 size; + } __packed stream; /* stream extension directory entry */ + struct { + __u8 flags; + __le16 unicode_0_14[EXFAT_FILE_NAME_LEN]; + } __packed name; /* file name directory entry */ + struct { + __u8 flags; + __u8 reserved[18]; + __le32 start_clu; + __le64 size; + } __packed bitmap; /* allocation bitmap directory entry */ + struct { + __u8 reserved1[3]; + __le32 checksum; + __u8 reserved2[12]; + __le32 start_clu; + __le64 size; + } __packed upcase; /* up-case table directory entry */ + } __packed dentry; +} __packed; + +#define EXFAT_TZ_VALID (1 << 7) + +/* Jan 1 GMT 00:00:00 1980 */ +#define EXFAT_MIN_TIMESTAMP_SECS 315532800LL +/* Dec 31 GMT 23:59:59 2107 */ +#define EXFAT_MAX_TIMESTAMP_SECS 4354819199LL + +#endif /* !_EXFAT_RAW_H */ From 719c1e1829166da399903b13da6dcc5344e73449 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:33 +0900 Subject: [PATCH 1214/4444] exfat: add super block operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of superblock operations for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Reviewed-by: Arnd Bergmann Signed-off-by: Al Viro --- fs/exfat/super.c | 728 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 728 insertions(+) create mode 100644 fs/exfat/super.c diff --git a/fs/exfat/super.c b/fs/exfat/super.c new file mode 100644 index 000000000000..f06e0b53e393 --- /dev/null +++ b/fs/exfat/super.c @@ -0,0 +1,728 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET; +static struct kmem_cache *exfat_inode_cachep; + +static void exfat_free_iocharset(struct exfat_sb_info *sbi) +{ + if (sbi->options.iocharset != exfat_default_iocharset) + kfree(sbi->options.iocharset); +} + +static void exfat_delayed_free(struct rcu_head *p) +{ + struct exfat_sb_info *sbi = container_of(p, struct exfat_sb_info, rcu); + + unload_nls(sbi->nls_io); + exfat_free_iocharset(sbi); + exfat_free_upcase_table(sbi); + kfree(sbi); +} + +static void exfat_put_super(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + mutex_lock(&sbi->s_lock); + if (test_and_clear_bit(EXFAT_SB_DIRTY, &sbi->s_state)) + sync_blockdev(sb->s_bdev); + exfat_set_vol_flags(sb, VOL_CLEAN); + exfat_free_bitmap(sbi); + mutex_unlock(&sbi->s_lock); + + call_rcu(&sbi->rcu, exfat_delayed_free); +} + +static int exfat_sync_fs(struct super_block *sb, int wait) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + int err = 0; + + /* If there are some dirty buffers in the bdev inode */ + mutex_lock(&sbi->s_lock); + if (test_and_clear_bit(EXFAT_SB_DIRTY, &sbi->s_state)) { + sync_blockdev(sb->s_bdev); + if (exfat_set_vol_flags(sb, VOL_CLEAN)) + err = -EIO; + } + mutex_unlock(&sbi->s_lock); + return err; +} + +static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct super_block *sb = dentry->d_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + unsigned long long id = huge_encode_dev(sb->s_bdev->bd_dev); + + if (sbi->used_clusters == EXFAT_CLUSTERS_UNTRACKED) { + mutex_lock(&sbi->s_lock); + if (exfat_count_used_clusters(sb, &sbi->used_clusters)) { + mutex_unlock(&sbi->s_lock); + return -EIO; + } + mutex_unlock(&sbi->s_lock); + } + + buf->f_type = sb->s_magic; + buf->f_bsize = sbi->cluster_size; + buf->f_blocks = sbi->num_clusters - 2; /* clu 0 & 1 */ + buf->f_bfree = buf->f_blocks - sbi->used_clusters; + buf->f_bavail = buf->f_bfree; + buf->f_fsid.val[0] = (unsigned int)id; + buf->f_fsid.val[1] = (unsigned int)(id >> 32); + /* Unicode utf16 255 characters */ + buf->f_namelen = EXFAT_MAX_FILE_LEN * NLS_MAX_CHARSET_SIZE; + return 0; +} + +int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct pbr64 *bpb; + bool sync = 0; + + /* flags are not changed */ + if (sbi->vol_flag == new_flag) + return 0; + + sbi->vol_flag = new_flag; + + /* skip updating volume dirty flag, + * if this volume has been mounted with read-only + */ + if (sb_rdonly(sb)) + return 0; + + if (!sbi->pbr_bh) { + sbi->pbr_bh = sb_bread(sb, 0); + if (!sbi->pbr_bh) { + exfat_msg(sb, KERN_ERR, "failed to read boot sector"); + return -ENOMEM; + } + } + + bpb = (struct pbr64 *)sbi->pbr_bh->b_data; + bpb->bsx.vol_flags = cpu_to_le16(new_flag); + + if (new_flag == VOL_DIRTY && !buffer_dirty(sbi->pbr_bh)) + sync = true; + else + sync = false; + + set_buffer_uptodate(sbi->pbr_bh); + mark_buffer_dirty(sbi->pbr_bh); + + if (sync) + sync_dirty_buffer(sbi->pbr_bh); + return 0; +} + +static int exfat_show_options(struct seq_file *m, struct dentry *root) +{ + struct super_block *sb = root->d_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_mount_options *opts = &sbi->options; + + /* Show partition info */ + if (!uid_eq(opts->fs_uid, GLOBAL_ROOT_UID)) + seq_printf(m, ",uid=%u", + from_kuid_munged(&init_user_ns, opts->fs_uid)); + if (!gid_eq(opts->fs_gid, GLOBAL_ROOT_GID)) + seq_printf(m, ",gid=%u", + from_kgid_munged(&init_user_ns, opts->fs_gid)); + seq_printf(m, ",fmask=%04o,dmask=%04o", opts->fs_fmask, opts->fs_dmask); + if (opts->allow_utime) + seq_printf(m, ",allow_utime=%04o", opts->allow_utime); + if (opts->utf8) + seq_puts(m, ",iocharset=utf8"); + else if (sbi->nls_io) + seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); + seq_printf(m, ",bps=%ld", sb->s_blocksize); + if (opts->errors == EXFAT_ERRORS_CONT) + seq_puts(m, ",errors=continue"); + else if (opts->errors == EXFAT_ERRORS_PANIC) + seq_puts(m, ",errors=panic"); + else + seq_puts(m, ",errors=remount-ro"); + if (opts->discard) + seq_puts(m, ",discard"); + if (opts->time_offset) + seq_printf(m, ",time_offset=%d", opts->time_offset); + return 0; +} + +static struct inode *exfat_alloc_inode(struct super_block *sb) +{ + struct exfat_inode_info *ei; + + ei = kmem_cache_alloc(exfat_inode_cachep, GFP_NOFS); + if (!ei) + return NULL; + + init_rwsem(&ei->truncate_lock); + return &ei->vfs_inode; +} + +static void exfat_free_inode(struct inode *inode) +{ + kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode)); +} + +static const struct super_operations exfat_sops = { + .alloc_inode = exfat_alloc_inode, + .free_inode = exfat_free_inode, + .write_inode = exfat_write_inode, + .evict_inode = exfat_evict_inode, + .put_super = exfat_put_super, + .sync_fs = exfat_sync_fs, + .statfs = exfat_statfs, + .show_options = exfat_show_options, +}; + +enum { + Opt_uid, + Opt_gid, + Opt_umask, + Opt_dmask, + Opt_fmask, + Opt_allow_utime, + Opt_charset, + Opt_errors, + Opt_discard, + Opt_time_offset, +}; + +static const struct fs_parameter_spec exfat_param_specs[] = { + fsparam_u32("uid", Opt_uid), + fsparam_u32("gid", Opt_gid), + fsparam_u32oct("umask", Opt_umask), + fsparam_u32oct("dmask", Opt_dmask), + fsparam_u32oct("fmask", Opt_fmask), + fsparam_u32oct("allow_utime", Opt_allow_utime), + fsparam_string("iocharset", Opt_charset), + fsparam_enum("errors", Opt_errors), + fsparam_flag("discard", Opt_discard), + fsparam_s32("time_offset", Opt_time_offset), + {} +}; + +static const struct fs_parameter_enum exfat_param_enums[] = { + { Opt_errors, "continue", EXFAT_ERRORS_CONT }, + { Opt_errors, "panic", EXFAT_ERRORS_PANIC }, + { Opt_errors, "remount-ro", EXFAT_ERRORS_RO }, + {} +}; + +static const struct fs_parameter_description exfat_parameters = { + .name = "exfat", + .specs = exfat_param_specs, + .enums = exfat_param_enums, +}; + +static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param) +{ + struct exfat_sb_info *sbi = fc->s_fs_info; + struct exfat_mount_options *opts = &sbi->options; + struct fs_parse_result result; + int opt; + + opt = fs_parse(fc, &exfat_parameters, param, &result); + if (opt < 0) + return opt; + + switch (opt) { + case Opt_uid: + opts->fs_uid = make_kuid(current_user_ns(), result.uint_32); + break; + case Opt_gid: + opts->fs_gid = make_kgid(current_user_ns(), result.uint_32); + break; + case Opt_umask: + opts->fs_fmask = result.uint_32; + opts->fs_dmask = result.uint_32; + break; + case Opt_dmask: + opts->fs_dmask = result.uint_32; + break; + case Opt_fmask: + opts->fs_fmask = result.uint_32; + break; + case Opt_allow_utime: + opts->allow_utime = result.uint_32 & 0022; + break; + case Opt_charset: + exfat_free_iocharset(sbi); + opts->iocharset = kstrdup(param->string, GFP_KERNEL); + if (!opts->iocharset) + return -ENOMEM; + break; + case Opt_errors: + opts->errors = result.uint_32; + break; + case Opt_discard: + opts->discard = 1; + break; + case Opt_time_offset: + /* + * Make the limit 24 just in case someone invents something + * unusual. + */ + if (result.int_32 < -24 * 60 || result.int_32 > 24 * 60) + return -EINVAL; + opts->time_offset = result.int_32; + break; + default: + return -EINVAL; + } + + return 0; +} + +static void exfat_hash_init(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + int i; + + spin_lock_init(&sbi->inode_hash_lock); + for (i = 0; i < EXFAT_HASH_SIZE; i++) + INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); +} + +static int exfat_read_root(struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + struct exfat_chain cdir; + int num_subdirs, num_clu = 0; + + exfat_chain_set(&ei->dir, sbi->root_dir, 0, ALLOC_FAT_CHAIN); + ei->entry = -1; + ei->start_clu = sbi->root_dir; + ei->flags = ALLOC_FAT_CHAIN; + ei->type = TYPE_DIR; + ei->version = 0; + ei->rwoffset = 0; + ei->hint_bmap.off = EXFAT_EOF_CLUSTER; + ei->hint_stat.eidx = 0; + ei->hint_stat.clu = sbi->root_dir; + ei->hint_femp.eidx = EXFAT_HINT_NONE; + + exfat_chain_set(&cdir, sbi->root_dir, 0, ALLOC_FAT_CHAIN); + if (exfat_count_num_clusters(sb, &cdir, &num_clu)) + return -EIO; + i_size_write(inode, num_clu << sbi->cluster_size_bits); + + num_subdirs = exfat_count_dir_entries(sb, &cdir); + if (num_subdirs < 0) + return -EIO; + set_nlink(inode, num_subdirs + EXFAT_MIN_SUBDIR); + + inode->i_uid = sbi->options.fs_uid; + inode->i_gid = sbi->options.fs_gid; + inode_inc_iversion(inode); + inode->i_generation = 0; + inode->i_mode = exfat_make_mode(sbi, ATTR_SUBDIR, 0777); + inode->i_op = &exfat_dir_inode_operations; + inode->i_fop = &exfat_dir_operations; + + inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1)) + & ~(sbi->cluster_size - 1)) >> inode->i_blkbits; + EXFAT_I(inode)->i_pos = ((loff_t)sbi->root_dir << 32) | 0xffffffff; + EXFAT_I(inode)->i_size_aligned = i_size_read(inode); + EXFAT_I(inode)->i_size_ondisk = i_size_read(inode); + + exfat_save_attr(inode, ATTR_SUBDIR); + inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime = + current_time(inode); + exfat_cache_init_inode(inode); + return 0; +} + +static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb, + struct buffer_head **prev_bh) +{ + struct pbr *p_pbr = (struct pbr *) (*prev_bh)->b_data; + unsigned short logical_sect = 0; + + logical_sect = 1 << p_pbr->bsx.f64.sect_size_bits; + + if (!is_power_of_2(logical_sect) || + logical_sect < 512 || logical_sect > 4096) { + exfat_msg(sb, KERN_ERR, "bogus logical sector size %u", + logical_sect); + return NULL; + } + + if (logical_sect < sb->s_blocksize) { + exfat_msg(sb, KERN_ERR, + "logical sector size too small for device (logical sector size = %u)", + logical_sect); + return NULL; + } + + if (logical_sect > sb->s_blocksize) { + struct buffer_head *bh = NULL; + + __brelse(*prev_bh); + *prev_bh = NULL; + + if (!sb_set_blocksize(sb, logical_sect)) { + exfat_msg(sb, KERN_ERR, + "unable to set blocksize %u", logical_sect); + return NULL; + } + bh = sb_bread(sb, 0); + if (!bh) { + exfat_msg(sb, KERN_ERR, + "unable to read boot sector (logical sector size = %lu)", + sb->s_blocksize); + return NULL; + } + + *prev_bh = bh; + p_pbr = (struct pbr *) bh->b_data; + } + return p_pbr; +} + +/* mount the file system volume */ +static int __exfat_fill_super(struct super_block *sb) +{ + int ret; + struct pbr *p_pbr; + struct pbr64 *p_bpb; + struct buffer_head *bh; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + /* set block size to read super block */ + sb_min_blocksize(sb, 512); + + /* read boot sector */ + bh = sb_bread(sb, 0); + if (!bh) { + exfat_msg(sb, KERN_ERR, "unable to read boot sector"); + return -EIO; + } + + /* PRB is read */ + p_pbr = (struct pbr *)bh->b_data; + + /* check the validity of PBR */ + if (le16_to_cpu((p_pbr->signature)) != PBR_SIGNATURE) { + exfat_msg(sb, KERN_ERR, "invalid boot record signature"); + ret = -EINVAL; + goto free_bh; + } + + + /* check logical sector size */ + p_pbr = exfat_read_pbr_with_logical_sector(sb, &bh); + if (!p_pbr) { + ret = -EIO; + goto free_bh; + } + + /* + * res_zero field must be filled with zero to prevent mounting + * from FAT volume. + */ + if (memchr_inv(p_pbr->bpb.f64.res_zero, 0, + sizeof(p_pbr->bpb.f64.res_zero))) { + ret = -EINVAL; + goto free_bh; + } + + p_bpb = (struct pbr64 *)p_pbr; + if (!p_bpb->bsx.num_fats) { + exfat_msg(sb, KERN_ERR, "bogus number of FAT structure"); + ret = -EINVAL; + goto free_bh; + } + + sbi->sect_per_clus = 1 << p_bpb->bsx.sect_per_clus_bits; + sbi->sect_per_clus_bits = p_bpb->bsx.sect_per_clus_bits; + sbi->cluster_size_bits = sbi->sect_per_clus_bits + sb->s_blocksize_bits; + sbi->cluster_size = 1 << sbi->cluster_size_bits; + sbi->num_FAT_sectors = le32_to_cpu(p_bpb->bsx.fat_length); + sbi->FAT1_start_sector = le32_to_cpu(p_bpb->bsx.fat_offset); + sbi->FAT2_start_sector = p_bpb->bsx.num_fats == 1 ? + sbi->FAT1_start_sector : + sbi->FAT1_start_sector + sbi->num_FAT_sectors; + sbi->data_start_sector = le32_to_cpu(p_bpb->bsx.clu_offset); + sbi->num_sectors = le64_to_cpu(p_bpb->bsx.vol_length); + /* because the cluster index starts with 2 */ + sbi->num_clusters = le32_to_cpu(p_bpb->bsx.clu_count) + + EXFAT_RESERVED_CLUSTERS; + + sbi->root_dir = le32_to_cpu(p_bpb->bsx.root_cluster); + sbi->dentries_per_clu = 1 << + (sbi->cluster_size_bits - DENTRY_SIZE_BITS); + + sbi->vol_flag = le16_to_cpu(p_bpb->bsx.vol_flags); + sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER; + sbi->used_clusters = EXFAT_CLUSTERS_UNTRACKED; + + if (le16_to_cpu(p_bpb->bsx.vol_flags) & VOL_DIRTY) { + sbi->vol_flag |= VOL_DIRTY; + exfat_msg(sb, KERN_WARNING, + "Volume was not properly unmounted. Some data may be corrupt. Please run fsck."); + } + + /* exFAT file size is limited by a disk volume size */ + sb->s_maxbytes = (u64)(sbi->num_clusters - EXFAT_RESERVED_CLUSTERS) << + sbi->cluster_size_bits; + + ret = exfat_create_upcase_table(sb); + if (ret) { + exfat_msg(sb, KERN_ERR, "failed to load upcase table"); + goto free_bh; + } + + ret = exfat_load_bitmap(sb); + if (ret) { + exfat_msg(sb, KERN_ERR, "failed to load alloc-bitmap"); + goto free_upcase_table; + } + + ret = exfat_count_used_clusters(sb, &sbi->used_clusters); + if (ret) { + exfat_msg(sb, KERN_ERR, "failed to scan clusters"); + goto free_alloc_bitmap; + } + + return 0; + +free_alloc_bitmap: + exfat_free_bitmap(sbi); +free_upcase_table: + exfat_free_upcase_table(sbi); +free_bh: + brelse(bh); + return ret; +} + +static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) +{ + struct exfat_sb_info *sbi = sb->s_fs_info; + struct exfat_mount_options *opts = &sbi->options; + struct inode *root_inode; + int err; + + if (opts->allow_utime == (unsigned short)-1) + opts->allow_utime = ~opts->fs_dmask & 0022; + + if (opts->discard) { + struct request_queue *q = bdev_get_queue(sb->s_bdev); + + if (!blk_queue_discard(q)) + exfat_msg(sb, KERN_WARNING, + "mounting with \"discard\" option, but the device does not support discard"); + opts->discard = 0; + } + + sb->s_flags |= SB_NODIRATIME; + sb->s_magic = EXFAT_SUPER_MAGIC; + sb->s_op = &exfat_sops; + + sb->s_time_gran = 1; + sb->s_time_min = EXFAT_MIN_TIMESTAMP_SECS; + sb->s_time_max = EXFAT_MAX_TIMESTAMP_SECS; + + err = __exfat_fill_super(sb); + if (err) { + exfat_msg(sb, KERN_ERR, "failed to recognize exfat type"); + goto check_nls_io; + } + + /* set up enough so that it can read an inode */ + exfat_hash_init(sb); + + if (!strcmp(sbi->options.iocharset, "utf8")) + opts->utf8 = 1; + else { + sbi->nls_io = load_nls(sbi->options.iocharset); + if (!sbi->nls_io) { + exfat_msg(sb, KERN_ERR, "IO charset %s not found", + sbi->options.iocharset); + err = -EINVAL; + goto free_table; + } + } + + if (sbi->options.utf8) + sb->s_d_op = &exfat_utf8_dentry_ops; + else + sb->s_d_op = &exfat_dentry_ops; + + root_inode = new_inode(sb); + if (!root_inode) { + exfat_msg(sb, KERN_ERR, "failed to allocate root inode."); + err = -ENOMEM; + goto free_table; + } + + root_inode->i_ino = EXFAT_ROOT_INO; + inode_set_iversion(root_inode, 1); + err = exfat_read_root(root_inode); + if (err) { + exfat_msg(sb, KERN_ERR, "failed to initialize root inode."); + goto put_inode; + } + + exfat_hash_inode(root_inode, EXFAT_I(root_inode)->i_pos); + insert_inode_hash(root_inode); + + sb->s_root = d_make_root(root_inode); + if (!sb->s_root) { + exfat_msg(sb, KERN_ERR, "failed to get the root dentry"); + err = -ENOMEM; + goto put_inode; + } + + return 0; + +put_inode: + iput(root_inode); + sb->s_root = NULL; + +free_table: + exfat_free_upcase_table(sbi); + exfat_free_bitmap(sbi); + +check_nls_io: + unload_nls(sbi->nls_io); + exfat_free_iocharset(sbi); + sb->s_fs_info = NULL; + kfree(sbi); + return err; +} + +static int exfat_get_tree(struct fs_context *fc) +{ + return get_tree_bdev(fc, exfat_fill_super); +} + +static void exfat_free(struct fs_context *fc) +{ + kfree(fc->s_fs_info); +} + +static const struct fs_context_operations exfat_context_ops = { + .parse_param = exfat_parse_param, + .get_tree = exfat_get_tree, + .free = exfat_free, +}; + +static int exfat_init_fs_context(struct fs_context *fc) +{ + struct exfat_sb_info *sbi; + + sbi = kzalloc(sizeof(struct exfat_sb_info), GFP_KERNEL); + if (!sbi) + return -ENOMEM; + + mutex_init(&sbi->s_lock); + ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL, + DEFAULT_RATELIMIT_BURST); + + sbi->options.fs_uid = current_uid(); + sbi->options.fs_gid = current_gid(); + sbi->options.fs_fmask = current->fs->umask; + sbi->options.fs_dmask = current->fs->umask; + sbi->options.allow_utime = -1; + sbi->options.iocharset = exfat_default_iocharset; + sbi->options.errors = EXFAT_ERRORS_RO; + + fc->s_fs_info = sbi; + fc->ops = &exfat_context_ops; + return 0; +} + +static struct file_system_type exfat_fs_type = { + .owner = THIS_MODULE, + .name = "exfat", + .init_fs_context = exfat_init_fs_context, + .parameters = &exfat_parameters, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV, +}; + +static void exfat_inode_init_once(void *foo) +{ + struct exfat_inode_info *ei = (struct exfat_inode_info *)foo; + + INIT_HLIST_NODE(&ei->i_hash_fat); + inode_init_once(&ei->vfs_inode); +} + +static int __init init_exfat_fs(void) +{ + int err; + + err = exfat_cache_init(); + if (err) + return err; + + exfat_inode_cachep = kmem_cache_create("exfat_inode_cache", + sizeof(struct exfat_inode_info), + 0, SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, + exfat_inode_init_once); + if (!exfat_inode_cachep) { + err = -ENOMEM; + goto shutdown_cache; + } + + err = register_filesystem(&exfat_fs_type); + if (err) + goto destroy_cache; + + return 0; + +destroy_cache: + kmem_cache_destroy(exfat_inode_cachep); +shutdown_cache: + exfat_cache_shutdown(); + return err; +} + +static void __exit exit_exfat_fs(void) +{ + /* + * Make sure all delayed rcu free inodes are flushed before we + * destroy cache. + */ + rcu_barrier(); + kmem_cache_destroy(exfat_inode_cachep); + unregister_filesystem(&exfat_fs_type); + exfat_cache_shutdown(); +} + +module_init(init_exfat_fs); +module_exit(exit_exfat_fs); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("exFAT filesystem support"); +MODULE_AUTHOR("Samsung Electronics Co., Ltd."); From 5f2aa075070cf5b2e6aae011d5a3390408d7d913 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:34 +0900 Subject: [PATCH 1215/4444] exfat: add inode operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of inode operations for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/exfat/inode.c | 671 +++++++++++++++++++++ fs/exfat/namei.c | 1448 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2119 insertions(+) create mode 100644 fs/exfat/inode.c create mode 100644 fs/exfat/namei.c diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c new file mode 100644 index 000000000000..06887492f54b --- /dev/null +++ b/fs/exfat/inode.c @@ -0,0 +1,671 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +static int __exfat_write_inode(struct inode *inode, int sync) +{ + int ret = -EIO; + unsigned long long on_disk_size; + struct exfat_dentry *ep, *ep2; + struct exfat_entry_set_cache *es = NULL; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + bool is_dir = (ei->type == TYPE_DIR) ? true : false; + + if (inode->i_ino == EXFAT_ROOT_INO) + return 0; + + /* + * If the indode is already unlinked, there is no need for updating it. + */ + if (ei->dir.dir == DIR_DELETED) + return 0; + + if (is_dir && ei->dir.dir == sbi->root_dir && ei->entry == -1) + return 0; + + exfat_set_vol_flags(sb, VOL_DIRTY); + + /* get the directory entry of given file or directory */ + es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry, ES_ALL_ENTRIES, + &ep); + if (!es) + return -EIO; + ep2 = ep + 1; + + ep->dentry.file.attr = cpu_to_le16(exfat_make_attr(inode)); + + /* set FILE_INFO structure using the acquired struct exfat_dentry */ + exfat_set_entry_time(sbi, &ei->i_crtime, + &ep->dentry.file.create_tz, + &ep->dentry.file.create_time, + &ep->dentry.file.create_date, + &ep->dentry.file.create_time_ms); + exfat_set_entry_time(sbi, &inode->i_mtime, + &ep->dentry.file.modify_tz, + &ep->dentry.file.modify_time, + &ep->dentry.file.modify_date, + &ep->dentry.file.modify_time_ms); + exfat_set_entry_time(sbi, &inode->i_atime, + &ep->dentry.file.access_tz, + &ep->dentry.file.access_time, + &ep->dentry.file.access_date, + NULL); + + /* File size should be zero if there is no cluster allocated */ + on_disk_size = i_size_read(inode); + + if (ei->start_clu == EXFAT_EOF_CLUSTER) + on_disk_size = 0; + + ep2->dentry.stream.valid_size = cpu_to_le64(on_disk_size); + ep2->dentry.stream.size = ep2->dentry.stream.valid_size; + + ret = exfat_update_dir_chksum_with_entry_set(sb, es, sync); + kfree(es); + return ret; +} + +int exfat_write_inode(struct inode *inode, struct writeback_control *wbc) +{ + int ret; + + mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock); + ret = __exfat_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL); + mutex_unlock(&EXFAT_SB(inode->i_sb)->s_lock); + + return ret; +} + +void exfat_sync_inode(struct inode *inode) +{ + lockdep_assert_held(&EXFAT_SB(inode->i_sb)->s_lock); + __exfat_write_inode(inode, 1); +} + +/* + * Input: inode, (logical) clu_offset, target allocation area + * Output: errcode, cluster number + * *clu = (~0), if it's unable to allocate a new cluster + */ +static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset, + unsigned int *clu, int create) +{ + int ret, modified = false; + unsigned int last_clu; + struct exfat_chain new_clu; + struct exfat_dentry *ep; + struct exfat_entry_set_cache *es = NULL; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + unsigned int local_clu_offset = clu_offset; + unsigned int num_to_be_allocated = 0, num_clusters = 0; + + ei->rwoffset = EXFAT_CLU_TO_B(clu_offset, sbi); + + if (EXFAT_I(inode)->i_size_ondisk > 0) + num_clusters = + EXFAT_B_TO_CLU_ROUND_UP(EXFAT_I(inode)->i_size_ondisk, + sbi); + + if (clu_offset >= num_clusters) + num_to_be_allocated = clu_offset - num_clusters + 1; + + if (!create && (num_to_be_allocated > 0)) { + *clu = EXFAT_EOF_CLUSTER; + return 0; + } + + *clu = last_clu = ei->start_clu; + + if (ei->flags == ALLOC_NO_FAT_CHAIN) { + if (clu_offset > 0 && *clu != EXFAT_EOF_CLUSTER) { + last_clu += clu_offset - 1; + + if (clu_offset == num_clusters) + *clu = EXFAT_EOF_CLUSTER; + else + *clu += clu_offset; + } + } else if (ei->type == TYPE_FILE) { + unsigned int fclus = 0; + int err = exfat_get_cluster(inode, clu_offset, + &fclus, clu, &last_clu, 1); + if (err) + return -EIO; + + clu_offset -= fclus; + } else { + /* hint information */ + if (clu_offset > 0 && ei->hint_bmap.off != EXFAT_EOF_CLUSTER && + ei->hint_bmap.off > 0 && clu_offset >= ei->hint_bmap.off) { + clu_offset -= ei->hint_bmap.off; + /* hint_bmap.clu should be valid */ + WARN_ON(ei->hint_bmap.clu < 2); + *clu = ei->hint_bmap.clu; + } + + while (clu_offset > 0 && *clu != EXFAT_EOF_CLUSTER) { + last_clu = *clu; + if (exfat_get_next_cluster(sb, clu)) + return -EIO; + clu_offset--; + } + } + + if (*clu == EXFAT_EOF_CLUSTER) { + exfat_set_vol_flags(sb, VOL_DIRTY); + + new_clu.dir = (last_clu == EXFAT_EOF_CLUSTER) ? + EXFAT_EOF_CLUSTER : last_clu + 1; + new_clu.size = 0; + new_clu.flags = ei->flags; + + /* allocate a cluster */ + if (num_to_be_allocated < 1) { + /* Broken FAT (i_sze > allocated FAT) */ + exfat_fs_error(sb, "broken FAT chain."); + return -EIO; + } + + ret = exfat_alloc_cluster(inode, num_to_be_allocated, &new_clu); + if (ret) + return ret; + + if (new_clu.dir == EXFAT_EOF_CLUSTER || + new_clu.dir == EXFAT_FREE_CLUSTER) { + exfat_fs_error(sb, + "bogus cluster new allocated (last_clu : %u, new_clu : %u)", + last_clu, new_clu.dir); + return -EIO; + } + + /* append to the FAT chain */ + if (last_clu == EXFAT_EOF_CLUSTER) { + if (new_clu.flags == ALLOC_FAT_CHAIN) + ei->flags = ALLOC_FAT_CHAIN; + ei->start_clu = new_clu.dir; + modified = true; + } else { + if (new_clu.flags != ei->flags) { + /* no-fat-chain bit is disabled, + * so fat-chain should be synced with + * alloc-bitmap + */ + exfat_chain_cont_cluster(sb, ei->start_clu, + num_clusters); + ei->flags = ALLOC_FAT_CHAIN; + modified = true; + } + if (new_clu.flags == ALLOC_FAT_CHAIN) + if (exfat_ent_set(sb, last_clu, new_clu.dir)) + return -EIO; + } + + num_clusters += num_to_be_allocated; + *clu = new_clu.dir; + + if (ei->dir.dir != DIR_DELETED) { + es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry, + ES_ALL_ENTRIES, &ep); + if (!es) + return -EIO; + /* get stream entry */ + ep++; + + /* update directory entry */ + if (modified) { + if (ep->dentry.stream.flags != ei->flags) + ep->dentry.stream.flags = ei->flags; + + if (le32_to_cpu(ep->dentry.stream.start_clu) != + ei->start_clu) + ep->dentry.stream.start_clu = + cpu_to_le32(ei->start_clu); + + ep->dentry.stream.valid_size = + cpu_to_le64(i_size_read(inode)); + ep->dentry.stream.size = + ep->dentry.stream.valid_size; + } + + if (exfat_update_dir_chksum_with_entry_set(sb, es, + inode_needs_sync(inode))) + return -EIO; + kfree(es); + + } /* end of if != DIR_DELETED */ + + inode->i_blocks += + num_to_be_allocated << sbi->sect_per_clus_bits; + + /* + * Move *clu pointer along FAT chains (hole care) because the + * caller of this function expect *clu to be the last cluster. + * This only works when num_to_be_allocated >= 2, + * *clu = (the first cluster of the allocated chain) => + * (the last cluster of ...) + */ + if (ei->flags == ALLOC_NO_FAT_CHAIN) { + *clu += num_to_be_allocated - 1; + } else { + while (num_to_be_allocated > 1) { + if (exfat_get_next_cluster(sb, clu)) + return -EIO; + num_to_be_allocated--; + } + } + + } + + /* hint information */ + ei->hint_bmap.off = local_clu_offset; + ei->hint_bmap.clu = *clu; + + return 0; +} + +static int exfat_map_new_buffer(struct exfat_inode_info *ei, + struct buffer_head *bh, loff_t pos) +{ + if (buffer_delay(bh) && pos > ei->i_size_aligned) + return -EIO; + set_buffer_new(bh); + + /* + * Adjust i_size_aligned if i_size_ondisk is bigger than it. + */ + if (ei->i_size_ondisk > ei->i_size_aligned) + ei->i_size_aligned = ei->i_size_ondisk; + return 0; +} + +static int exfat_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; + int err = 0; + unsigned long mapped_blocks = 0; + unsigned int cluster, sec_offset; + sector_t last_block; + sector_t phys = 0; + loff_t pos; + + mutex_lock(&sbi->s_lock); + last_block = EXFAT_B_TO_BLK_ROUND_UP(i_size_read(inode), sb); + if (iblock >= last_block && !create) + goto done; + + /* Is this block already allocated? */ + err = exfat_map_cluster(inode, iblock >> sbi->sect_per_clus_bits, + &cluster, create); + if (err) { + if (err != -ENOSPC) + exfat_fs_error_ratelimit(sb, + "failed to bmap (inode : %p iblock : %llu, err : %d)", + inode, (unsigned long long)iblock, err); + goto unlock_ret; + } + + if (cluster == EXFAT_EOF_CLUSTER) + goto done; + + /* sector offset in cluster */ + sec_offset = iblock & (sbi->sect_per_clus - 1); + + phys = exfat_cluster_to_sector(sbi, cluster) + sec_offset; + mapped_blocks = sbi->sect_per_clus - sec_offset; + max_blocks = min(mapped_blocks, max_blocks); + + /* Treat newly added block / cluster */ + if (iblock < last_block) + create = 0; + + if (create || buffer_delay(bh_result)) { + pos = EXFAT_BLK_TO_B((iblock + 1), sb); + if (ei->i_size_ondisk < pos) + ei->i_size_ondisk = pos; + } + + if (create) { + err = exfat_map_new_buffer(ei, bh_result, pos); + if (err) { + exfat_fs_error(sb, + "requested for bmap out of range(pos : (%llu) > i_size_aligned(%llu)\n", + pos, ei->i_size_aligned); + goto unlock_ret; + } + } + + if (buffer_delay(bh_result)) + clear_buffer_delay(bh_result); + map_bh(bh_result, sb, phys); +done: + bh_result->b_size = EXFAT_BLK_TO_B(max_blocks, sb); +unlock_ret: + mutex_unlock(&sbi->s_lock); + return err; +} + +static int exfat_readpage(struct file *file, struct page *page) +{ + return mpage_readpage(page, exfat_get_block); +} + +static int exfat_readpages(struct file *file, struct address_space *mapping, + struct list_head *pages, unsigned int nr_pages) +{ + return mpage_readpages(mapping, pages, nr_pages, exfat_get_block); +} + +static int exfat_writepage(struct page *page, struct writeback_control *wbc) +{ + return block_write_full_page(page, exfat_get_block, wbc); +} + +static int exfat_writepages(struct address_space *mapping, + struct writeback_control *wbc) +{ + return mpage_writepages(mapping, wbc, exfat_get_block); +} + +static void exfat_write_failed(struct address_space *mapping, loff_t to) +{ + struct inode *inode = mapping->host; + + if (to > i_size_read(inode)) { + truncate_pagecache(inode, i_size_read(inode)); + exfat_truncate(inode, EXFAT_I(inode)->i_size_aligned); + } +} + +static int exfat_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned int len, unsigned int flags, + struct page **pagep, void **fsdata) +{ + int ret; + + *pagep = NULL; + ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, + exfat_get_block, + &EXFAT_I(mapping->host)->i_size_ondisk); + + if (ret < 0) + exfat_write_failed(mapping, pos+len); + + return ret; +} + +static int exfat_write_end(struct file *file, struct address_space *mapping, + loff_t pos, unsigned int len, unsigned int copied, + struct page *pagep, void *fsdata) +{ + struct inode *inode = mapping->host; + struct exfat_inode_info *ei = EXFAT_I(inode); + int err; + + err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata); + + if (EXFAT_I(inode)->i_size_aligned < i_size_read(inode)) { + exfat_fs_error(inode->i_sb, + "invalid size(size(%llu) > aligned(%llu)\n", + i_size_read(inode), EXFAT_I(inode)->i_size_aligned); + return -EIO; + } + + if (err < len) + exfat_write_failed(mapping, pos+len); + + if (!(err < 0) && !(ei->attr & ATTR_ARCHIVE)) { + inode->i_mtime = inode->i_ctime = current_time(inode); + ei->attr |= ATTR_ARCHIVE; + mark_inode_dirty(inode); + } + + return err; +} + +static ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter) +{ + struct address_space *mapping = iocb->ki_filp->f_mapping; + struct inode *inode = mapping->host; + loff_t size = iocb->ki_pos + iov_iter_count(iter); + int rw = iov_iter_rw(iter); + ssize_t ret; + + if (rw == WRITE) { + /* + * FIXME: blockdev_direct_IO() doesn't use ->write_begin(), + * so we need to update the ->i_size_aligned to block boundary. + * + * But we must fill the remaining area or hole by nul for + * updating ->i_size_aligned + * + * Return 0, and fallback to normal buffered write. + */ + if (EXFAT_I(inode)->i_size_aligned < size) + return 0; + } + + /* + * Need to use the DIO_LOCKING for avoiding the race + * condition of exfat_get_block() and ->truncate(). + */ + ret = blockdev_direct_IO(iocb, inode, iter, exfat_get_block); + if (ret < 0 && (rw & WRITE)) + exfat_write_failed(mapping, size); + return ret; +} + +static sector_t exfat_aop_bmap(struct address_space *mapping, sector_t block) +{ + sector_t blocknr; + + /* exfat_get_cluster() assumes the requested blocknr isn't truncated. */ + down_read(&EXFAT_I(mapping->host)->truncate_lock); + blocknr = generic_block_bmap(mapping, block, exfat_get_block); + up_read(&EXFAT_I(mapping->host)->truncate_lock); + return blocknr; +} + +/* + * exfat_block_truncate_page() zeroes out a mapping from file offset `from' + * up to the end of the block which corresponds to `from'. + * This is required during truncate to physically zeroout the tail end + * of that block so it doesn't yield old data if the file is later grown. + * Also, avoid causing failure from fsx for cases of "data past EOF" + */ +int exfat_block_truncate_page(struct inode *inode, loff_t from) +{ + return block_truncate_page(inode->i_mapping, from, exfat_get_block); +} + +static const struct address_space_operations exfat_aops = { + .readpage = exfat_readpage, + .readpages = exfat_readpages, + .writepage = exfat_writepage, + .writepages = exfat_writepages, + .write_begin = exfat_write_begin, + .write_end = exfat_write_end, + .direct_IO = exfat_direct_IO, + .bmap = exfat_aop_bmap +}; + +static inline unsigned long exfat_hash(loff_t i_pos) +{ + return hash_32(i_pos, EXFAT_HASH_BITS); +} + +void exfat_hash_inode(struct inode *inode, loff_t i_pos) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos); + + spin_lock(&sbi->inode_hash_lock); + EXFAT_I(inode)->i_pos = i_pos; + hlist_add_head(&EXFAT_I(inode)->i_hash_fat, head); + spin_unlock(&sbi->inode_hash_lock); +} + +void exfat_unhash_inode(struct inode *inode) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + + spin_lock(&sbi->inode_hash_lock); + hlist_del_init(&EXFAT_I(inode)->i_hash_fat); + EXFAT_I(inode)->i_pos = 0; + spin_unlock(&sbi->inode_hash_lock); +} + +struct inode *exfat_iget(struct super_block *sb, loff_t i_pos) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *info; + struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos); + struct inode *inode = NULL; + + spin_lock(&sbi->inode_hash_lock); + hlist_for_each_entry(info, head, i_hash_fat) { + WARN_ON(info->vfs_inode.i_sb != sb); + + if (i_pos != info->i_pos) + continue; + inode = igrab(&info->vfs_inode); + if (inode) + break; + } + spin_unlock(&sbi->inode_hash_lock); + return inode; +} + +/* doesn't deal with root inode */ +static int exfat_fill_inode(struct inode *inode, struct exfat_dir_entry *info) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + loff_t size = info->size; + + memcpy(&ei->dir, &info->dir, sizeof(struct exfat_chain)); + ei->entry = info->entry; + ei->attr = info->attr; + ei->start_clu = info->start_clu; + ei->flags = info->flags; + ei->type = info->type; + + ei->version = 0; + ei->hint_stat.eidx = 0; + ei->hint_stat.clu = info->start_clu; + ei->hint_femp.eidx = EXFAT_HINT_NONE; + ei->rwoffset = 0; + ei->hint_bmap.off = EXFAT_EOF_CLUSTER; + ei->i_pos = 0; + + inode->i_uid = sbi->options.fs_uid; + inode->i_gid = sbi->options.fs_gid; + inode_inc_iversion(inode); + inode->i_generation = prandom_u32(); + + if (info->attr & ATTR_SUBDIR) { /* directory */ + inode->i_generation &= ~1; + inode->i_mode = exfat_make_mode(sbi, info->attr, 0777); + inode->i_op = &exfat_dir_inode_operations; + inode->i_fop = &exfat_dir_operations; + set_nlink(inode, info->num_subdirs); + } else { /* regular file */ + inode->i_generation |= 1; + inode->i_mode = exfat_make_mode(sbi, info->attr, 0777); + inode->i_op = &exfat_file_inode_operations; + inode->i_fop = &exfat_file_operations; + inode->i_mapping->a_ops = &exfat_aops; + inode->i_mapping->nrpages = 0; + } + + i_size_write(inode, size); + + /* ondisk and aligned size should be aligned with block size */ + if (size & (inode->i_sb->s_blocksize - 1)) { + size |= (inode->i_sb->s_blocksize - 1); + size++; + } + + ei->i_size_aligned = size; + ei->i_size_ondisk = size; + + exfat_save_attr(inode, info->attr); + + inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1)) & + ~(sbi->cluster_size - 1)) >> inode->i_blkbits; + inode->i_mtime = info->mtime; + inode->i_ctime = info->mtime; + ei->i_crtime = info->crtime; + inode->i_atime = info->atime; + + exfat_cache_init_inode(inode); + + return 0; +} + +struct inode *exfat_build_inode(struct super_block *sb, + struct exfat_dir_entry *info, loff_t i_pos) +{ + struct inode *inode; + int err; + + inode = exfat_iget(sb, i_pos); + if (inode) + goto out; + inode = new_inode(sb); + if (!inode) { + inode = ERR_PTR(-ENOMEM); + goto out; + } + inode->i_ino = iunique(sb, EXFAT_ROOT_INO); + inode_set_iversion(inode, 1); + err = exfat_fill_inode(inode, info); + if (err) { + iput(inode); + inode = ERR_PTR(err); + goto out; + } + exfat_hash_inode(inode, i_pos); + insert_inode_hash(inode); +out: + return inode; +} + +void exfat_evict_inode(struct inode *inode) +{ + truncate_inode_pages(&inode->i_data, 0); + + if (!inode->i_nlink) { + i_size_write(inode, 0); + mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock); + __exfat_truncate(inode, 0); + mutex_unlock(&EXFAT_SB(inode->i_sb)->s_lock); + } + + invalidate_inode_buffers(inode); + clear_inode(inode); + exfat_cache_inval_inode(inode); + exfat_unhash_inode(inode); +} diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c new file mode 100644 index 000000000000..a8681d91f569 --- /dev/null +++ b/fs/exfat/namei.c @@ -0,0 +1,1448 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +static inline unsigned long exfat_d_version(struct dentry *dentry) +{ + return (unsigned long) dentry->d_fsdata; +} + +static inline void exfat_d_version_set(struct dentry *dentry, + unsigned long version) +{ + dentry->d_fsdata = (void *) version; +} + +/* + * If new entry was created in the parent, it could create the 8.3 alias (the + * shortname of logname). So, the parent may have the negative-dentry which + * matches the created 8.3 alias. + * + * If it happened, the negative dentry isn't actually negative anymore. So, + * drop it. + */ +static int exfat_d_revalidate(struct dentry *dentry, unsigned int flags) +{ + int ret; + + if (flags & LOOKUP_RCU) + return -ECHILD; + + /* + * This is not negative dentry. Always valid. + * + * Note, rename() to existing directory entry will have ->d_inode, and + * will use existing name which isn't specified name by user. + * + * We may be able to drop this positive dentry here. But dropping + * positive dentry isn't good idea. So it's unsupported like + * rename("filename", "FILENAME") for now. + */ + if (d_really_is_positive(dentry)) + return 1; + + /* + * Drop the negative dentry, in order to make sure to use the case + * sensitive name which is specified by user if this is for creation. + */ + if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) + return 0; + + spin_lock(&dentry->d_lock); + ret = inode_eq_iversion(d_inode(dentry->d_parent), + exfat_d_version(dentry)); + spin_unlock(&dentry->d_lock); + return ret; +} + +/* returns the length of a struct qstr, ignoring trailing dots */ +static unsigned int exfat_striptail_len(unsigned int len, const char *name) +{ + while (len && name[len - 1] == '.') + len--; + return len; +} + +/* + * Compute the hash for the exfat name corresponding to the dentry. If the name + * is invalid, we leave the hash code unchanged so that the existing dentry can + * be used. The exfat fs routines will return ENOENT or EINVAL as appropriate. + */ +static int exfat_d_hash(const struct dentry *dentry, struct qstr *qstr) +{ + struct super_block *sb = dentry->d_sb; + struct nls_table *t = EXFAT_SB(sb)->nls_io; + const unsigned char *name = qstr->name; + unsigned int len = exfat_striptail_len(qstr->len, qstr->name); + unsigned long hash = init_name_hash(dentry); + int i, charlen; + wchar_t c; + + for (i = 0; i < len; i += charlen) { + charlen = t->char2uni(&name[i], len - i, &c); + if (charlen < 0) + return charlen; + hash = partial_name_hash(exfat_toupper(sb, c), hash); + } + + qstr->hash = end_name_hash(hash); + return 0; +} + +static int exfat_d_cmp(const struct dentry *dentry, unsigned int len, + const char *str, const struct qstr *name) +{ + struct super_block *sb = dentry->d_sb; + struct nls_table *t = EXFAT_SB(sb)->nls_io; + unsigned int alen = exfat_striptail_len(name->len, name->name); + unsigned int blen = exfat_striptail_len(len, str); + wchar_t c1, c2; + int charlen, i; + + if (alen != blen) + return 1; + + for (i = 0; i < len; i += charlen) { + charlen = t->char2uni(&name->name[i], alen - i, &c1); + if (charlen < 0) + return 1; + if (charlen != t->char2uni(&str[i], blen - i, &c2)) + return 1; + + if (exfat_toupper(sb, c1) != exfat_toupper(sb, c2)) + return 1; + } + + return 0; +} + +const struct dentry_operations exfat_dentry_ops = { + .d_revalidate = exfat_d_revalidate, + .d_hash = exfat_d_hash, + .d_compare = exfat_d_cmp, +}; + +static int exfat_utf8_d_hash(const struct dentry *dentry, struct qstr *qstr) +{ + struct super_block *sb = dentry->d_sb; + const unsigned char *name = qstr->name; + unsigned int len = exfat_striptail_len(qstr->len, qstr->name); + unsigned long hash = init_name_hash(dentry); + int i, charlen; + unicode_t u; + + for (i = 0; i < len; i += charlen) { + charlen = utf8_to_utf32(&name[i], len - i, &u); + if (charlen < 0) + return charlen; + + /* + * Convert to UTF-16: code points above U+FFFF are encoded as + * surrogate pairs. + * exfat_toupper() works only for code points up to the U+FFFF. + */ + if (u > 0xFFFF) { + hash = partial_name_hash(exfat_high_surrogate(u), hash); + hash = partial_name_hash(exfat_low_surrogate(u), hash); + } else { + hash = partial_name_hash(exfat_toupper(sb, u), hash); + } + } + + qstr->hash = end_name_hash(hash); + return 0; +} + +static int exfat_utf8_d_cmp(const struct dentry *dentry, unsigned int len, + const char *str, const struct qstr *name) +{ + struct super_block *sb = dentry->d_sb; + unsigned int alen = exfat_striptail_len(name->len, name->name); + unsigned int blen = exfat_striptail_len(len, str); + unicode_t u_a, u_b; + int charlen, i; + + if (alen != blen) + return 1; + + for (i = 0; i < alen; i += charlen) { + charlen = utf8_to_utf32(&name->name[i], alen - i, &u_a); + if (charlen < 0) + return 1; + if (charlen != utf8_to_utf32(&str[i], blen - i, &u_b)) + return 1; + + if (u_a <= 0xFFFF && u_b <= 0xFFFF) { + if (exfat_toupper(sb, u_a) != exfat_toupper(sb, u_b)) + return 1; + } else if (u_a > 0xFFFF && u_b > 0xFFFF) { + if (exfat_low_surrogate(u_a) != + exfat_low_surrogate(u_b) || + exfat_high_surrogate(u_a) != + exfat_high_surrogate(u_b)) + return 1; + } else { + return 1; + } + } + + return 0; +} + +const struct dentry_operations exfat_utf8_dentry_ops = { + .d_revalidate = exfat_d_revalidate, + .d_hash = exfat_utf8_d_hash, + .d_compare = exfat_utf8_d_cmp, +}; + +/* used only in search empty_slot() */ +#define CNT_UNUSED_NOHIT (-1) +#define CNT_UNUSED_HIT (-2) +/* search EMPTY CONTINUOUS "num_entries" entries */ +static int exfat_search_empty_slot(struct super_block *sb, + struct exfat_hint_femp *hint_femp, struct exfat_chain *p_dir, + int num_entries) +{ + int i, dentry, num_empty = 0; + int dentries_per_clu; + unsigned int type; + struct exfat_chain clu; + struct exfat_dentry *ep; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct buffer_head *bh; + + dentries_per_clu = sbi->dentries_per_clu; + + if (hint_femp->eidx != EXFAT_HINT_NONE) { + dentry = hint_femp->eidx; + if (num_entries <= hint_femp->count) { + hint_femp->eidx = EXFAT_HINT_NONE; + return dentry; + } + + exfat_chain_dup(&clu, &hint_femp->cur); + } else { + exfat_chain_dup(&clu, p_dir); + dentry = 0; + } + + while (clu.dir != EXFAT_EOF_CLUSTER) { + i = dentry & (dentries_per_clu - 1); + + for (; i < dentries_per_clu; i++, dentry++) { + ep = exfat_get_dentry(sb, &clu, i, &bh, NULL); + if (!ep) + return -EIO; + type = exfat_get_entry_type(ep); + brelse(bh); + + if (type == TYPE_UNUSED || type == TYPE_DELETED) { + num_empty++; + if (hint_femp->eidx == EXFAT_HINT_NONE) { + hint_femp->eidx = dentry; + hint_femp->count = CNT_UNUSED_NOHIT; + exfat_chain_set(&hint_femp->cur, + clu.dir, clu.size, clu.flags); + } + + if (type == TYPE_UNUSED && + hint_femp->count != CNT_UNUSED_HIT) + hint_femp->count = CNT_UNUSED_HIT; + } else { + if (hint_femp->eidx != EXFAT_HINT_NONE && + hint_femp->count == CNT_UNUSED_HIT) { + /* unused empty group means + * an empty group which includes + * unused dentry + */ + exfat_fs_error(sb, + "found bogus dentry(%d) beyond unused empty group(%d) (start_clu : %u, cur_clu : %u)", + dentry, hint_femp->eidx, + p_dir->dir, clu.dir); + return -EIO; + } + + num_empty = 0; + hint_femp->eidx = EXFAT_HINT_NONE; + } + + if (num_empty >= num_entries) { + /* found and invalidate hint_femp */ + hint_femp->eidx = EXFAT_HINT_NONE; + return (dentry - (num_entries - 1)); + } + } + + if (clu.flags == ALLOC_NO_FAT_CHAIN) { + if (--clu.size > 0) + clu.dir++; + else + clu.dir = EXFAT_EOF_CLUSTER; + } else { + if (exfat_get_next_cluster(sb, &clu.dir)) + return -EIO; + } + } + + return -ENOSPC; +} + +static int exfat_check_max_dentries(struct inode *inode) +{ + if (EXFAT_B_TO_DEN(i_size_read(inode)) >= MAX_EXFAT_DENTRIES) { + /* + * exFAT spec allows a dir to grow upto 8388608(256MB) + * dentries + */ + return -ENOSPC; + } + return 0; +} + +/* find empty directory entry. + * if there isn't any empty slot, expand cluster chain. + */ +static int exfat_find_empty_entry(struct inode *inode, + struct exfat_chain *p_dir, int num_entries) +{ + int dentry; + unsigned int ret, last_clu; + sector_t sector; + loff_t size = 0; + struct exfat_chain clu; + struct exfat_dentry *ep = NULL; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + struct exfat_hint_femp hint_femp; + + hint_femp.eidx = EXFAT_HINT_NONE; + + if (ei->hint_femp.eidx != EXFAT_HINT_NONE) { + memcpy(&hint_femp, &ei->hint_femp, + sizeof(struct exfat_hint_femp)); + ei->hint_femp.eidx = EXFAT_HINT_NONE; + } + + while ((dentry = exfat_search_empty_slot(sb, &hint_femp, p_dir, + num_entries)) < 0) { + if (dentry == -EIO) + break; + + if (exfat_check_max_dentries(inode)) + return -ENOSPC; + + /* we trust p_dir->size regardless of FAT type */ + if (exfat_find_last_cluster(sb, p_dir, &last_clu)) + return -EIO; + + /* + * Allocate new cluster to this directory + */ + exfat_chain_set(&clu, last_clu + 1, 0, p_dir->flags); + + /* allocate a cluster */ + ret = exfat_alloc_cluster(inode, 1, &clu); + if (ret) + return ret; + + if (exfat_zeroed_cluster(inode, clu.dir)) + return -EIO; + + /* append to the FAT chain */ + if (clu.flags != p_dir->flags) { + /* no-fat-chain bit is disabled, + * so fat-chain should be synced with alloc-bitmap + */ + exfat_chain_cont_cluster(sb, p_dir->dir, p_dir->size); + p_dir->flags = ALLOC_FAT_CHAIN; + hint_femp.cur.flags = ALLOC_FAT_CHAIN; + } + + if (clu.flags == ALLOC_FAT_CHAIN) + if (exfat_ent_set(sb, last_clu, clu.dir)) + return -EIO; + + if (hint_femp.eidx == EXFAT_HINT_NONE) { + /* the special case that new dentry + * should be allocated from the start of new cluster + */ + hint_femp.eidx = EXFAT_B_TO_DEN_IDX(p_dir->size, sbi); + hint_femp.count = sbi->dentries_per_clu; + + exfat_chain_set(&hint_femp.cur, clu.dir, 0, clu.flags); + } + hint_femp.cur.size++; + p_dir->size++; + size = EXFAT_CLU_TO_B(p_dir->size, sbi); + + /* update the directory entry */ + if (p_dir->dir != sbi->root_dir) { + struct buffer_head *bh; + + ep = exfat_get_dentry(sb, + &(ei->dir), ei->entry + 1, &bh, §or); + if (!ep) + return -EIO; + + ep->dentry.stream.valid_size = cpu_to_le64(size); + ep->dentry.stream.size = ep->dentry.stream.valid_size; + ep->dentry.stream.flags = p_dir->flags; + exfat_update_bh(sb, bh, IS_DIRSYNC(inode)); + brelse(bh); + if (exfat_update_dir_chksum(inode, &(ei->dir), + ei->entry)) + return -EIO; + } + + /* directory inode should be updated in here */ + i_size_write(inode, size); + EXFAT_I(inode)->i_size_ondisk += sbi->cluster_size; + EXFAT_I(inode)->i_size_aligned += sbi->cluster_size; + EXFAT_I(inode)->flags = p_dir->flags; + inode->i_blocks += 1 << sbi->sect_per_clus_bits; + } + + return dentry; +} + +/* + * Name Resolution Functions : + * Zero if it was successful; otherwise nonzero. + */ +static int __exfat_resolve_path(struct inode *inode, const unsigned char *path, + struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname, + int lookup) +{ + int namelen; + int lossy = NLS_NAME_NO_LOSSY; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + + /* strip all trailing periods */ + namelen = exfat_striptail_len(strlen(path), path); + if (!namelen) + return -ENOENT; + + if (strlen(path) > (MAX_NAME_LENGTH * MAX_CHARSET_SIZE)) + return -ENAMETOOLONG; + + /* + * strip all leading spaces : + * "MS windows 7" supports leading spaces. + * So we should skip this preprocessing for compatibility. + */ + + /* file name conversion : + * If lookup case, we allow bad-name for compatibility. + */ + namelen = exfat_nls_to_utf16(sb, path, namelen, p_uniname, + &lossy); + if (namelen < 0) + return namelen; /* return error value */ + + if ((lossy && !lookup) || !namelen) + return -EINVAL; + + exfat_chain_set(p_dir, ei->start_clu, + EXFAT_B_TO_CLU(i_size_read(inode), sbi), ei->flags); + + return 0; +} + +static inline int exfat_resolve_path(struct inode *inode, + const unsigned char *path, struct exfat_chain *dir, + struct exfat_uni_name *uni) +{ + return __exfat_resolve_path(inode, path, dir, uni, 0); +} + +static inline int exfat_resolve_path_for_lookup(struct inode *inode, + const unsigned char *path, struct exfat_chain *dir, + struct exfat_uni_name *uni) +{ + return __exfat_resolve_path(inode, path, dir, uni, 1); +} + +static inline loff_t exfat_make_i_pos(struct exfat_dir_entry *info) +{ + return ((loff_t) info->dir.dir << 32) | (info->entry & 0xffffffff); +} + +static int exfat_add_entry(struct inode *inode, const char *path, + struct exfat_chain *p_dir, unsigned int type, + struct exfat_dir_entry *info) +{ + int ret, dentry, num_entries; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_uni_name uniname; + struct exfat_chain clu; + int clu_size = 0; + unsigned int start_clu = EXFAT_FREE_CLUSTER; + + ret = exfat_resolve_path(inode, path, p_dir, &uniname); + if (ret) + goto out; + + num_entries = exfat_calc_num_entries(&uniname); + if (num_entries < 0) { + ret = num_entries; + goto out; + } + + /* exfat_find_empty_entry must be called before alloc_cluster() */ + dentry = exfat_find_empty_entry(inode, p_dir, num_entries); + if (dentry < 0) { + ret = dentry; /* -EIO or -ENOSPC */ + goto out; + } + + if (type == TYPE_DIR) { + ret = exfat_alloc_new_dir(inode, &clu); + if (ret) + goto out; + start_clu = clu.dir; + clu_size = sbi->cluster_size; + } + + /* update the directory entry */ + /* fill the dos name directory entry information of the created file. + * the first cluster is not determined yet. (0) + */ + ret = exfat_init_dir_entry(inode, p_dir, dentry, type, + start_clu, clu_size); + if (ret) + goto out; + + ret = exfat_init_ext_entry(inode, p_dir, dentry, num_entries, &uniname); + if (ret) + goto out; + + memcpy(&info->dir, p_dir, sizeof(struct exfat_chain)); + info->entry = dentry; + info->flags = ALLOC_NO_FAT_CHAIN; + info->type = type; + + if (type == TYPE_FILE) { + info->attr = ATTR_ARCHIVE; + info->start_clu = EXFAT_EOF_CLUSTER; + info->size = 0; + info->num_subdirs = 0; + } else { + int count; + struct exfat_chain cdir; + + info->attr = ATTR_SUBDIR; + info->start_clu = start_clu; + info->size = clu_size; + + exfat_chain_set(&cdir, info->start_clu, + EXFAT_B_TO_CLU(info->size, sbi), info->flags); + count = exfat_count_dir_entries(sb, &cdir); + if (count < 0) + return -EIO; + info->num_subdirs = count + EXFAT_MIN_SUBDIR; + } + memset(&info->crtime, 0, sizeof(info->crtime)); + memset(&info->mtime, 0, sizeof(info->mtime)); + memset(&info->atime, 0, sizeof(info->atime)); +out: + return ret; +} + +static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, + bool excl) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct exfat_chain cdir; + struct exfat_dir_entry info; + loff_t i_pos; + int err; + + mutex_lock(&EXFAT_SB(sb)->s_lock); + exfat_set_vol_flags(sb, VOL_DIRTY); + err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_FILE, + &info); + exfat_set_vol_flags(sb, VOL_CLEAN); + if (err) + goto unlock; + + inode_inc_iversion(dir); + dir->i_ctime = dir->i_mtime = current_time(dir); + if (IS_DIRSYNC(dir)) + exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + i_pos = exfat_make_i_pos(&info); + inode = exfat_build_inode(sb, &info, i_pos); + if (IS_ERR(inode)) + goto unlock; + + inode_inc_iversion(inode); + inode->i_mtime = inode->i_atime = inode->i_ctime = + EXFAT_I(inode)->i_crtime = current_time(inode); + /* timestamp is already written, so mark_inode_dirty() is unneeded. */ + + d_instantiate(dentry, inode); +unlock: + mutex_unlock(&EXFAT_SB(sb)->s_lock); + return err; +} + +/* lookup a file */ +static int exfat_find(struct inode *dir, struct qstr *qname, + struct exfat_dir_entry *info) +{ + int ret, dentry, num_entries, count; + struct exfat_chain cdir; + struct exfat_uni_name uni_name; + struct exfat_dentry *ep, *ep2; + struct exfat_entry_set_cache *es = NULL; + struct super_block *sb = dir->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(dir); + + if (qname->len == 0) + return -ENOENT; + + /* check the validity of directory name in the given pathname */ + ret = exfat_resolve_path_for_lookup(dir, qname->name, &cdir, &uni_name); + if (ret) + return ret; + + num_entries = exfat_calc_num_entries(&uni_name); + if (num_entries < 0) + return num_entries; + + /* check the validation of hint_stat and initialize it if required */ + if (ei->version != (inode_peek_iversion_raw(dir) & 0xffffffff)) { + ei->hint_stat.clu = cdir.dir; + ei->hint_stat.eidx = 0; + ei->version = (inode_peek_iversion_raw(dir) & 0xffffffff); + ei->hint_femp.eidx = EXFAT_HINT_NONE; + } + + /* search the file name for directories */ + dentry = exfat_find_dir_entry(sb, ei, &cdir, &uni_name, + num_entries, TYPE_ALL); + + if ((dentry < 0) && (dentry != -EEXIST)) + return dentry; /* -error value */ + + memcpy(&info->dir, &cdir.dir, sizeof(struct exfat_chain)); + info->entry = dentry; + info->num_subdirs = 0; + + /* root directory itself */ + if (unlikely(dentry == -EEXIST)) { + int num_clu = 0; + + info->type = TYPE_DIR; + info->attr = ATTR_SUBDIR; + info->flags = ALLOC_FAT_CHAIN; + info->start_clu = sbi->root_dir; + memset(&info->crtime, 0, sizeof(info->crtime)); + memset(&info->mtime, 0, sizeof(info->mtime)); + memset(&info->atime, 0, sizeof(info->atime)); + + exfat_chain_set(&cdir, sbi->root_dir, 0, ALLOC_FAT_CHAIN); + if (exfat_count_num_clusters(sb, &cdir, &num_clu)) + return -EIO; + info->size = num_clu << sbi->cluster_size_bits; + + count = exfat_count_dir_entries(sb, &cdir); + if (count < 0) + return -EIO; + + info->num_subdirs = count; + } else { + es = exfat_get_dentry_set(sb, &cdir, dentry, ES_2_ENTRIES, &ep); + if (!es) + return -EIO; + ep2 = ep + 1; + + info->type = exfat_get_entry_type(ep); + info->attr = le16_to_cpu(ep->dentry.file.attr); + info->size = le64_to_cpu(ep2->dentry.stream.valid_size); + if ((info->type == TYPE_FILE) && (info->size == 0)) { + info->flags = ALLOC_NO_FAT_CHAIN; + info->start_clu = EXFAT_EOF_CLUSTER; + } else { + info->flags = ep2->dentry.stream.flags; + info->start_clu = + le32_to_cpu(ep2->dentry.stream.start_clu); + } + + if (ei->start_clu == EXFAT_FREE_CLUSTER) { + exfat_fs_error(sb, + "non-zero size file starts with zero cluster (size : %llu, p_dir : %u, entry : 0x%08x)", + i_size_read(dir), ei->dir.dir, ei->entry); + return -EIO; + } + + exfat_get_entry_time(sbi, &info->crtime, + ep->dentry.file.create_tz, + ep->dentry.file.create_time, + ep->dentry.file.create_date, + ep->dentry.file.create_time_ms); + exfat_get_entry_time(sbi, &info->mtime, + ep->dentry.file.modify_tz, + ep->dentry.file.modify_time, + ep->dentry.file.modify_date, + ep->dentry.file.modify_time_ms); + exfat_get_entry_time(sbi, &info->atime, + ep->dentry.file.access_tz, + ep->dentry.file.access_time, + ep->dentry.file.access_date, + 0); + kfree(es); + + if (info->type == TYPE_DIR) { + exfat_chain_set(&cdir, info->start_clu, + EXFAT_B_TO_CLU(info->size, sbi), info->flags); + count = exfat_count_dir_entries(sb, &cdir); + if (count < 0) + return -EIO; + + info->num_subdirs = count + EXFAT_MIN_SUBDIR; + } + } + return 0; +} + +static int exfat_d_anon_disconn(struct dentry *dentry) +{ + return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED); +} + +static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry, + unsigned int flags) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct dentry *alias; + struct exfat_dir_entry info; + int err; + loff_t i_pos; + mode_t i_mode; + + mutex_lock(&EXFAT_SB(sb)->s_lock); + err = exfat_find(dir, &dentry->d_name, &info); + if (err) { + if (err == -ENOENT) { + inode = NULL; + goto out; + } + goto unlock; + } + + i_pos = exfat_make_i_pos(&info); + inode = exfat_build_inode(sb, &info, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto unlock; + } + + i_mode = inode->i_mode; + alias = d_find_alias(inode); + + /* + * Checking "alias->d_parent == dentry->d_parent" to make sure + * FS is not corrupted (especially double linked dir). + */ + if (alias && alias->d_parent == dentry->d_parent && + !exfat_d_anon_disconn(alias)) { + + /* + * Unhashed alias is able to exist because of revalidate() + * called by lookup_fast. You can easily make this status + * by calling create and lookup concurrently + * In such case, we reuse an alias instead of new dentry + */ + if (d_unhashed(alias)) { + WARN_ON(alias->d_name.hash_len != + dentry->d_name.hash_len); + exfat_msg(sb, KERN_INFO, + "rehashed a dentry(%p) in read lookup", alias); + d_drop(dentry); + d_rehash(alias); + } else if (!S_ISDIR(i_mode)) { + /* + * This inode has non anonymous-DCACHE_DISCONNECTED + * dentry. This means, the user did ->lookup() by an + * another name (longname vs 8.3 alias of it) in past. + * + * Switch to new one for reason of locality if possible. + */ + d_move(alias, dentry); + } + iput(inode); + mutex_unlock(&EXFAT_SB(sb)->s_lock); + return alias; + } + dput(alias); +out: + mutex_unlock(&EXFAT_SB(sb)->s_lock); + if (!inode) + exfat_d_version_set(dentry, inode_query_iversion(dir)); + + return d_splice_alias(inode, dentry); +unlock: + mutex_unlock(&EXFAT_SB(sb)->s_lock); + return ERR_PTR(err); +} + +/* remove an entry, BUT don't truncate */ +static int exfat_unlink(struct inode *dir, struct dentry *dentry) +{ + struct exfat_chain cdir; + struct exfat_dentry *ep; + struct super_block *sb = dir->i_sb; + struct inode *inode = dentry->d_inode; + struct exfat_inode_info *ei = EXFAT_I(inode); + struct buffer_head *bh; + sector_t sector; + int num_entries, entry, err = 0; + + mutex_lock(&EXFAT_SB(sb)->s_lock); + exfat_chain_dup(&cdir, &ei->dir); + entry = ei->entry; + if (ei->dir.dir == DIR_DELETED) { + exfat_msg(sb, KERN_ERR, "abnormal access to deleted dentry"); + err = -ENOENT; + goto unlock; + } + + ep = exfat_get_dentry(sb, &cdir, entry, &bh, §or); + if (!ep) { + err = -EIO; + goto unlock; + } + num_entries = exfat_count_ext_entries(sb, &cdir, entry, ep); + if (num_entries < 0) { + err = -EIO; + brelse(bh); + goto unlock; + } + num_entries++; + brelse(bh); + + exfat_set_vol_flags(sb, VOL_DIRTY); + /* update the directory entry */ + if (exfat_remove_entries(dir, &cdir, entry, 0, num_entries)) { + err = -EIO; + goto unlock; + } + + /* This doesn't modify ei */ + ei->dir.dir = DIR_DELETED; + exfat_set_vol_flags(sb, VOL_CLEAN); + + inode_inc_iversion(dir); + dir->i_mtime = dir->i_atime = current_time(dir); + if (IS_DIRSYNC(dir)) + exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + clear_nlink(inode); + inode->i_mtime = inode->i_atime = current_time(inode); + exfat_unhash_inode(inode); + exfat_d_version_set(dentry, inode_query_iversion(dir)); +unlock: + mutex_unlock(&EXFAT_SB(sb)->s_lock); + return err; +} + +static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct exfat_dir_entry info; + struct exfat_chain cdir; + loff_t i_pos; + int err; + + mutex_lock(&EXFAT_SB(sb)->s_lock); + exfat_set_vol_flags(sb, VOL_DIRTY); + err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_DIR, + &info); + exfat_set_vol_flags(sb, VOL_CLEAN); + if (err) + goto unlock; + + inode_inc_iversion(dir); + dir->i_ctime = dir->i_mtime = current_time(dir); + if (IS_DIRSYNC(dir)) + exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + inc_nlink(dir); + + i_pos = exfat_make_i_pos(&info); + inode = exfat_build_inode(sb, &info, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto unlock; + } + + inode_inc_iversion(inode); + inode->i_mtime = inode->i_atime = inode->i_ctime = + EXFAT_I(inode)->i_crtime = current_time(inode); + /* timestamp is already written, so mark_inode_dirty() is unneeded. */ + + d_instantiate(dentry, inode); + +unlock: + mutex_unlock(&EXFAT_SB(sb)->s_lock); + return err; +} + +static int exfat_check_dir_empty(struct super_block *sb, + struct exfat_chain *p_dir) +{ + int i, dentries_per_clu; + unsigned int type; + struct exfat_chain clu; + struct exfat_dentry *ep; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct buffer_head *bh; + + dentries_per_clu = sbi->dentries_per_clu; + + exfat_chain_dup(&clu, p_dir); + + while (clu.dir != EXFAT_EOF_CLUSTER) { + for (i = 0; i < dentries_per_clu; i++) { + ep = exfat_get_dentry(sb, &clu, i, &bh, NULL); + if (!ep) + return -EIO; + type = exfat_get_entry_type(ep); + brelse(bh); + if (type == TYPE_UNUSED) + return 0; + + if (type != TYPE_FILE && type != TYPE_DIR) + continue; + + return -ENOTEMPTY; + } + + if (clu.flags == ALLOC_NO_FAT_CHAIN) { + if (--clu.size > 0) + clu.dir++; + else + clu.dir = EXFAT_EOF_CLUSTER; + } else { + if (exfat_get_next_cluster(sb, &(clu.dir))) + return -EIO; + } + } + + return 0; +} + +static int exfat_rmdir(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + struct exfat_dentry *ep; + struct exfat_chain cdir, clu_to_free; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + struct buffer_head *bh; + sector_t sector; + int num_entries, entry, err; + + mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock); + + exfat_chain_dup(&cdir, &ei->dir); + entry = ei->entry; + + if (ei->dir.dir == DIR_DELETED) { + exfat_msg(sb, KERN_ERR, "abnormal access to deleted dentry"); + err = -ENOENT; + goto unlock; + } + + exfat_set_vol_flags(sb, VOL_DIRTY); + exfat_chain_set(&clu_to_free, ei->start_clu, + EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi), ei->flags); + + err = exfat_check_dir_empty(sb, &clu_to_free); + if (err) { + if (err == -EIO) + exfat_msg(sb, KERN_ERR, + "failed to exfat_check_dir_empty : err(%d)", + err); + goto unlock; + } + + ep = exfat_get_dentry(sb, &cdir, entry, &bh, §or); + if (!ep) { + err = -EIO; + goto unlock; + } + + num_entries = exfat_count_ext_entries(sb, &cdir, entry, ep); + if (num_entries < 0) { + err = -EIO; + brelse(bh); + goto unlock; + } + num_entries++; + brelse(bh); + + err = exfat_remove_entries(dir, &cdir, entry, 0, num_entries); + if (err) { + exfat_msg(sb, KERN_ERR, + "failed to exfat_remove_entries : err(%d)", + err); + goto unlock; + } + ei->dir.dir = DIR_DELETED; + exfat_set_vol_flags(sb, VOL_CLEAN); + + inode_inc_iversion(dir); + dir->i_mtime = dir->i_atime = current_time(dir); + if (IS_DIRSYNC(dir)) + exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + drop_nlink(dir); + + clear_nlink(inode); + inode->i_mtime = inode->i_atime = current_time(inode); + exfat_unhash_inode(inode); + exfat_d_version_set(dentry, inode_query_iversion(dir)); +unlock: + mutex_unlock(&EXFAT_SB(inode->i_sb)->s_lock); + return err; +} + +static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir, + int oldentry, struct exfat_uni_name *p_uniname, + struct exfat_inode_info *ei) +{ + int ret, num_old_entries, num_new_entries; + sector_t sector_old, sector_new; + struct exfat_dentry *epold, *epnew; + struct super_block *sb = inode->i_sb; + struct buffer_head *new_bh, *old_bh; + int sync = IS_DIRSYNC(inode); + + epold = exfat_get_dentry(sb, p_dir, oldentry, &old_bh, §or_old); + if (!epold) + return -EIO; + + num_old_entries = exfat_count_ext_entries(sb, p_dir, oldentry, epold); + if (num_old_entries < 0) + return -EIO; + num_old_entries++; + + num_new_entries = exfat_calc_num_entries(p_uniname); + if (num_new_entries < 0) + return num_new_entries; + + if (num_old_entries < num_new_entries) { + int newentry; + + newentry = + exfat_find_empty_entry(inode, p_dir, num_new_entries); + if (newentry < 0) + return newentry; /* -EIO or -ENOSPC */ + + epnew = exfat_get_dentry(sb, p_dir, newentry, &new_bh, + §or_new); + if (!epnew) + return -EIO; + + memcpy(epnew, epold, DENTRY_SIZE); + if (exfat_get_entry_type(epnew) == TYPE_FILE) { + epnew->dentry.file.attr |= cpu_to_le16(ATTR_ARCHIVE); + ei->attr |= ATTR_ARCHIVE; + } + exfat_update_bh(sb, new_bh, sync); + brelse(old_bh); + brelse(new_bh); + + epold = exfat_get_dentry(sb, p_dir, oldentry + 1, &old_bh, + §or_old); + epnew = exfat_get_dentry(sb, p_dir, newentry + 1, &new_bh, + §or_new); + if (!epold || !epnew) + return -EIO; + + memcpy(epnew, epold, DENTRY_SIZE); + exfat_update_bh(sb, new_bh, sync); + brelse(old_bh); + brelse(new_bh); + + ret = exfat_init_ext_entry(inode, p_dir, newentry, + num_new_entries, p_uniname); + if (ret) + return ret; + + exfat_remove_entries(inode, p_dir, oldentry, 0, + num_old_entries); + ei->entry = newentry; + } else { + if (exfat_get_entry_type(epold) == TYPE_FILE) { + epold->dentry.file.attr |= cpu_to_le16(ATTR_ARCHIVE); + ei->attr |= ATTR_ARCHIVE; + } + exfat_update_bh(sb, old_bh, sync); + brelse(old_bh); + ret = exfat_init_ext_entry(inode, p_dir, oldentry, + num_new_entries, p_uniname); + if (ret) + return ret; + + exfat_remove_entries(inode, p_dir, oldentry, num_new_entries, + num_old_entries); + } + return 0; +} + +static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir, + int oldentry, struct exfat_chain *p_newdir, + struct exfat_uni_name *p_uniname, struct exfat_inode_info *ei) +{ + int ret, newentry, num_new_entries, num_old_entries; + sector_t sector_mov, sector_new; + struct exfat_dentry *epmov, *epnew; + struct super_block *sb = inode->i_sb; + struct buffer_head *mov_bh, *new_bh; + + epmov = exfat_get_dentry(sb, p_olddir, oldentry, &mov_bh, §or_mov); + if (!epmov) + return -EIO; + + /* check if the source and target directory is the same */ + if (exfat_get_entry_type(epmov) == TYPE_DIR && + le32_to_cpu(epmov->dentry.stream.start_clu) == p_newdir->dir) + return -EINVAL; + + num_old_entries = exfat_count_ext_entries(sb, p_olddir, oldentry, + epmov); + if (num_old_entries < 0) + return -EIO; + num_old_entries++; + + num_new_entries = exfat_calc_num_entries(p_uniname); + if (num_new_entries < 0) + return num_new_entries; + + newentry = exfat_find_empty_entry(inode, p_newdir, num_new_entries); + if (newentry < 0) + return newentry; /* -EIO or -ENOSPC */ + + epnew = exfat_get_dentry(sb, p_newdir, newentry, &new_bh, §or_new); + if (!epnew) + return -EIO; + + memcpy(epnew, epmov, DENTRY_SIZE); + if (exfat_get_entry_type(epnew) == TYPE_FILE) { + epnew->dentry.file.attr |= cpu_to_le16(ATTR_ARCHIVE); + ei->attr |= ATTR_ARCHIVE; + } + exfat_update_bh(sb, new_bh, IS_DIRSYNC(inode)); + brelse(mov_bh); + brelse(new_bh); + + epmov = exfat_get_dentry(sb, p_olddir, oldentry + 1, &mov_bh, + §or_mov); + epnew = exfat_get_dentry(sb, p_newdir, newentry + 1, &new_bh, + §or_new); + if (!epmov || !epnew) + return -EIO; + + memcpy(epnew, epmov, DENTRY_SIZE); + exfat_update_bh(sb, new_bh, IS_DIRSYNC(inode)); + brelse(mov_bh); + brelse(new_bh); + + ret = exfat_init_ext_entry(inode, p_newdir, newentry, num_new_entries, + p_uniname); + if (ret) + return ret; + + exfat_remove_entries(inode, p_olddir, oldentry, 0, num_old_entries); + + exfat_chain_set(&ei->dir, p_newdir->dir, p_newdir->size, + p_newdir->flags); + + ei->entry = newentry; + return 0; +} + +static void exfat_update_parent_info(struct exfat_inode_info *ei, + struct inode *parent_inode) +{ + struct exfat_sb_info *sbi = EXFAT_SB(parent_inode->i_sb); + struct exfat_inode_info *parent_ei = EXFAT_I(parent_inode); + loff_t parent_isize = i_size_read(parent_inode); + + /* + * the problem that struct exfat_inode_info caches wrong parent info. + * + * because of flag-mismatch of ei->dir, + * there is abnormal traversing cluster chain. + */ + if (unlikely(parent_ei->flags != ei->dir.flags || + parent_isize != EXFAT_CLU_TO_B(ei->dir.size, sbi) || + parent_ei->start_clu != ei->dir.dir)) { + exfat_chain_set(&ei->dir, parent_ei->start_clu, + EXFAT_B_TO_CLU_ROUND_UP(parent_isize, sbi), + parent_ei->flags); + } +} + +/* rename or move a old file into a new file */ +static int __exfat_rename(struct inode *old_parent_inode, + struct exfat_inode_info *ei, struct inode *new_parent_inode, + struct dentry *new_dentry) +{ + int ret; + int dentry; + struct exfat_chain olddir, newdir; + struct exfat_chain *p_dir = NULL; + struct exfat_uni_name uni_name; + struct exfat_dentry *ep; + struct super_block *sb = old_parent_inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + const unsigned char *new_path = new_dentry->d_name.name; + struct inode *new_inode = new_dentry->d_inode; + int num_entries; + struct exfat_inode_info *new_ei = NULL; + unsigned int new_entry_type = TYPE_UNUSED; + int new_entry = 0; + struct buffer_head *old_bh, *new_bh = NULL; + + /* check the validity of pointer parameters */ + if (new_path == NULL || strlen(new_path) == 0) + return -EINVAL; + + if (ei->dir.dir == DIR_DELETED) { + exfat_msg(sb, KERN_ERR, + "abnormal access to deleted source dentry"); + return -ENOENT; + } + + exfat_update_parent_info(ei, old_parent_inode); + + exfat_chain_dup(&olddir, &ei->dir); + dentry = ei->entry; + + ep = exfat_get_dentry(sb, &olddir, dentry, &old_bh, NULL); + if (!ep) { + ret = -EIO; + goto out; + } + brelse(old_bh); + + /* check whether new dir is existing directory and empty */ + if (new_inode) { + ret = -EIO; + new_ei = EXFAT_I(new_inode); + + if (new_ei->dir.dir == DIR_DELETED) { + exfat_msg(sb, KERN_ERR, + "abnormal access to deleted target dentry"); + goto out; + } + + exfat_update_parent_info(new_ei, new_parent_inode); + + p_dir = &(new_ei->dir); + new_entry = new_ei->entry; + ep = exfat_get_dentry(sb, p_dir, new_entry, &new_bh, NULL); + if (!ep) + goto out; + + new_entry_type = exfat_get_entry_type(ep); + brelse(new_bh); + + /* if new_inode exists, update ei */ + if (new_entry_type == TYPE_DIR) { + struct exfat_chain new_clu; + + new_clu.dir = new_ei->start_clu; + new_clu.size = + EXFAT_B_TO_CLU_ROUND_UP(i_size_read(new_inode), + sbi); + new_clu.flags = new_ei->flags; + + ret = exfat_check_dir_empty(sb, &new_clu); + if (ret) + goto out; + } + } + + /* check the validity of directory name in the given new pathname */ + ret = exfat_resolve_path(new_parent_inode, new_path, &newdir, + &uni_name); + if (ret) + goto out; + + exfat_set_vol_flags(sb, VOL_DIRTY); + + if (olddir.dir == newdir.dir) + ret = exfat_rename_file(new_parent_inode, &olddir, dentry, + &uni_name, ei); + else + ret = exfat_move_file(new_parent_inode, &olddir, dentry, + &newdir, &uni_name, ei); + + if (!ret && new_inode) { + /* delete entries of new_dir */ + ep = exfat_get_dentry(sb, p_dir, new_entry, &new_bh, NULL); + if (!ep) { + ret = -EIO; + goto del_out; + } + + num_entries = exfat_count_ext_entries(sb, p_dir, new_entry, ep); + if (num_entries < 0) { + ret = -EIO; + goto del_out; + } + brelse(new_bh); + + if (exfat_remove_entries(new_inode, p_dir, new_entry, 0, + num_entries + 1)) { + ret = -EIO; + goto del_out; + } + + /* Free the clusters if new_inode is a dir(as if exfat_rmdir) */ + if (new_entry_type == TYPE_DIR) { + /* new_ei, new_clu_to_free */ + struct exfat_chain new_clu_to_free; + + exfat_chain_set(&new_clu_to_free, new_ei->start_clu, + EXFAT_B_TO_CLU_ROUND_UP(i_size_read(new_inode), + sbi), new_ei->flags); + + if (exfat_free_cluster(new_inode, &new_clu_to_free)) { + /* just set I/O error only */ + ret = -EIO; + } + + i_size_write(new_inode, 0); + new_ei->start_clu = EXFAT_EOF_CLUSTER; + new_ei->flags = ALLOC_NO_FAT_CHAIN; + } +del_out: + /* Update new_inode ei + * Prevent syncing removed new_inode + * (new_ei is already initialized above code ("if (new_inode)") + */ + new_ei->dir.dir = DIR_DELETED; + } + exfat_set_vol_flags(sb, VOL_CLEAN); +out: + return ret; +} + +static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, + unsigned int flags) +{ + struct inode *old_inode, *new_inode; + struct super_block *sb = old_dir->i_sb; + loff_t i_pos; + int err; + + /* + * The VFS already checks for existence, so for local filesystems + * the RENAME_NOREPLACE implementation is equivalent to plain rename. + * Don't support any other flags + */ + if (flags & ~RENAME_NOREPLACE) + return -EINVAL; + + mutex_lock(&EXFAT_SB(sb)->s_lock); + old_inode = old_dentry->d_inode; + new_inode = new_dentry->d_inode; + + err = __exfat_rename(old_dir, EXFAT_I(old_inode), new_dir, new_dentry); + if (err) + goto unlock; + + inode_inc_iversion(new_dir); + new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = + EXFAT_I(new_dir)->i_crtime = current_time(new_dir); + if (IS_DIRSYNC(new_dir)) + exfat_sync_inode(new_dir); + else + mark_inode_dirty(new_dir); + + i_pos = ((loff_t)EXFAT_I(old_inode)->dir.dir << 32) | + (EXFAT_I(old_inode)->entry & 0xffffffff); + exfat_unhash_inode(old_inode); + exfat_hash_inode(old_inode, i_pos); + if (IS_DIRSYNC(new_dir)) + exfat_sync_inode(old_inode); + else + mark_inode_dirty(old_inode); + + if (S_ISDIR(old_inode->i_mode) && old_dir != new_dir) { + drop_nlink(old_dir); + if (!new_inode) + inc_nlink(new_dir); + } + + inode_inc_iversion(old_dir); + old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir); + if (IS_DIRSYNC(old_dir)) + exfat_sync_inode(old_dir); + else + mark_inode_dirty(old_dir); + + if (new_inode) { + exfat_unhash_inode(new_inode); + + /* skip drop_nlink if new_inode already has been dropped */ + if (new_inode->i_nlink) { + drop_nlink(new_inode); + if (S_ISDIR(new_inode->i_mode)) + drop_nlink(new_inode); + } else { + exfat_msg(sb, KERN_WARNING, + "abnormal access to an inode dropped"); + WARN_ON(new_inode->i_nlink == 0); + } + new_inode->i_ctime = EXFAT_I(new_inode)->i_crtime = + current_time(new_inode); + } + +unlock: + mutex_unlock(&EXFAT_SB(sb)->s_lock); + return err; +} + +const struct inode_operations exfat_dir_inode_operations = { + .create = exfat_create, + .lookup = exfat_lookup, + .unlink = exfat_unlink, + .mkdir = exfat_mkdir, + .rmdir = exfat_rmdir, + .rename = exfat_rename, + .setattr = exfat_setattr, + .getattr = exfat_getattr, +}; From ca06197382bde0a3bc20215595d1c9ce20c6e341 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:35 +0900 Subject: [PATCH 1216/4444] exfat: add directory operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of directory operations for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/exfat/dir.c | 1238 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1238 insertions(+) create mode 100644 fs/exfat/dir.c diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c new file mode 100644 index 000000000000..4b91afb0f051 --- /dev/null +++ b/fs/exfat/dir.c @@ -0,0 +1,1238 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +static int exfat_extract_uni_name(struct exfat_dentry *ep, + unsigned short *uniname) +{ + int i, len = 0; + + for (i = 0; i < EXFAT_FILE_NAME_LEN; i++) { + *uniname = le16_to_cpu(ep->dentry.name.unicode_0_14[i]); + if (*uniname == 0x0) + return len; + uniname++; + len++; + } + + *uniname = 0x0; + return len; + +} + +static void exfat_get_uniname_from_ext_entry(struct super_block *sb, + struct exfat_chain *p_dir, int entry, unsigned short *uniname) +{ + int i; + struct exfat_dentry *ep; + struct exfat_entry_set_cache *es; + + es = exfat_get_dentry_set(sb, p_dir, entry, ES_ALL_ENTRIES, &ep); + if (!es) + return; + + if (es->num_entries < 3) + goto free_es; + + ep += 2; + + /* + * First entry : file entry + * Second entry : stream-extension entry + * Third entry : first file-name entry + * So, the index of first file-name dentry should start from 2. + */ + for (i = 2; i < es->num_entries; i++, ep++) { + /* end of name entry */ + if (exfat_get_entry_type(ep) != TYPE_EXTEND) + goto free_es; + + exfat_extract_uni_name(ep, uniname); + uniname += EXFAT_FILE_NAME_LEN; + } + +free_es: + kfree(es); +} + +/* read a directory entry from the opened directory */ +static int exfat_readdir(struct inode *inode, struct exfat_dir_entry *dir_entry) +{ + int i, dentries_per_clu, dentries_per_clu_bits = 0; + unsigned int type, clu_offset; + sector_t sector; + struct exfat_chain dir, clu; + struct exfat_uni_name uni_name; + struct exfat_dentry *ep; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + unsigned int dentry = ei->rwoffset & 0xFFFFFFFF; + struct buffer_head *bh; + + /* check if the given file ID is opened */ + if (ei->type != TYPE_DIR) + return -EPERM; + + if (ei->entry == -1) + exfat_chain_set(&dir, sbi->root_dir, 0, ALLOC_FAT_CHAIN); + else + exfat_chain_set(&dir, ei->start_clu, + EXFAT_B_TO_CLU(i_size_read(inode), sbi), ei->flags); + + dentries_per_clu = sbi->dentries_per_clu; + dentries_per_clu_bits = ilog2(dentries_per_clu); + + clu_offset = dentry >> dentries_per_clu_bits; + exfat_chain_dup(&clu, &dir); + + if (clu.flags == ALLOC_NO_FAT_CHAIN) { + clu.dir += clu_offset; + clu.size -= clu_offset; + } else { + /* hint_information */ + if (clu_offset > 0 && ei->hint_bmap.off != EXFAT_EOF_CLUSTER && + ei->hint_bmap.off > 0 && clu_offset >= ei->hint_bmap.off) { + clu_offset -= ei->hint_bmap.off; + clu.dir = ei->hint_bmap.clu; + } + + while (clu_offset > 0) { + if (exfat_get_next_cluster(sb, &(clu.dir))) + return -EIO; + + clu_offset--; + } + } + + while (clu.dir != EXFAT_EOF_CLUSTER) { + i = dentry & (dentries_per_clu - 1); + + for ( ; i < dentries_per_clu; i++, dentry++) { + ep = exfat_get_dentry(sb, &clu, i, &bh, §or); + if (!ep) + return -EIO; + + type = exfat_get_entry_type(ep); + if (type == TYPE_UNUSED) { + brelse(bh); + break; + } + + if (type != TYPE_FILE && type != TYPE_DIR) { + brelse(bh); + continue; + } + + dir_entry->attr = le16_to_cpu(ep->dentry.file.attr); + exfat_get_entry_time(sbi, &dir_entry->crtime, + ep->dentry.file.create_tz, + ep->dentry.file.create_time, + ep->dentry.file.create_date, + ep->dentry.file.create_time_ms); + exfat_get_entry_time(sbi, &dir_entry->mtime, + ep->dentry.file.modify_tz, + ep->dentry.file.modify_time, + ep->dentry.file.modify_date, + ep->dentry.file.modify_time_ms); + exfat_get_entry_time(sbi, &dir_entry->atime, + ep->dentry.file.access_tz, + ep->dentry.file.access_time, + ep->dentry.file.access_date, + 0); + + *uni_name.name = 0x0; + exfat_get_uniname_from_ext_entry(sb, &dir, dentry, + uni_name.name); + exfat_utf16_to_nls(sb, &uni_name, + dir_entry->namebuf.lfn, + dir_entry->namebuf.lfnbuf_len); + brelse(bh); + + ep = exfat_get_dentry(sb, &clu, i + 1, &bh, NULL); + if (!ep) + return -EIO; + dir_entry->size = + le64_to_cpu(ep->dentry.stream.valid_size); + brelse(bh); + + ei->hint_bmap.off = dentry >> dentries_per_clu_bits; + ei->hint_bmap.clu = clu.dir; + + ei->rwoffset = ++dentry; + return 0; + } + + if (clu.flags == ALLOC_NO_FAT_CHAIN) { + if (--clu.size > 0) + clu.dir++; + else + clu.dir = EXFAT_EOF_CLUSTER; + } else { + if (exfat_get_next_cluster(sb, &(clu.dir))) + return -EIO; + } + } + + dir_entry->namebuf.lfn[0] = '\0'; + ei->rwoffset = dentry; + return 0; +} + +static void exfat_init_namebuf(struct exfat_dentry_namebuf *nb) +{ + nb->lfn = NULL; + nb->lfnbuf_len = 0; +} + +static int exfat_alloc_namebuf(struct exfat_dentry_namebuf *nb) +{ + nb->lfn = __getname(); + if (!nb->lfn) + return -ENOMEM; + nb->lfnbuf_len = MAX_VFSNAME_BUF_SIZE; + return 0; +} + +static void exfat_free_namebuf(struct exfat_dentry_namebuf *nb) +{ + if (!nb->lfn) + return; + + __putname(nb->lfn); + exfat_init_namebuf(nb); +} + +/* skip iterating emit_dots when dir is empty */ +#define ITER_POS_FILLED_DOTS (2) +static int exfat_iterate(struct file *filp, struct dir_context *ctx) +{ + struct inode *inode = filp->f_path.dentry->d_inode; + struct super_block *sb = inode->i_sb; + struct inode *tmp; + struct exfat_dir_entry de; + struct exfat_dentry_namebuf *nb = &(de.namebuf); + struct exfat_inode_info *ei = EXFAT_I(inode); + unsigned long inum; + loff_t cpos, i_pos; + int err = 0, fake_offset = 0; + + exfat_init_namebuf(nb); + mutex_lock(&EXFAT_SB(sb)->s_lock); + + cpos = ctx->pos; + if (!dir_emit_dots(filp, ctx)) + goto unlock; + + if (ctx->pos == ITER_POS_FILLED_DOTS) { + cpos = 0; + fake_offset = 1; + } + + if (cpos & (DENTRY_SIZE - 1)) { + err = -ENOENT; + goto unlock; + } + + /* name buffer should be allocated before use */ + err = exfat_alloc_namebuf(nb); + if (err) + goto unlock; +get_new: + ei->rwoffset = EXFAT_B_TO_DEN(cpos); + + if (cpos >= i_size_read(inode)) + goto end_of_dir; + + err = exfat_readdir(inode, &de); + if (err) { + /* + * At least we tried to read a sector. Move cpos to next sector + * position (should be aligned). + */ + if (err == -EIO) { + cpos += 1 << (sb->s_blocksize_bits); + cpos &= ~(sb->s_blocksize - 1); + } + + err = -EIO; + goto end_of_dir; + } + + cpos = EXFAT_DEN_TO_B(ei->rwoffset); + + if (!nb->lfn[0]) + goto end_of_dir; + + i_pos = ((loff_t)ei->start_clu << 32) | + ((ei->rwoffset - 1) & 0xffffffff); + tmp = exfat_iget(sb, i_pos); + if (tmp) { + inum = tmp->i_ino; + iput(tmp); + } else { + inum = iunique(sb, EXFAT_ROOT_INO); + } + + /* + * Before calling dir_emit(), sb_lock should be released. + * Because page fault can occur in dir_emit() when the size + * of buffer given from user is larger than one page size. + */ + mutex_unlock(&EXFAT_SB(sb)->s_lock); + if (!dir_emit(ctx, nb->lfn, strlen(nb->lfn), inum, + (de.attr & ATTR_SUBDIR) ? DT_DIR : DT_REG)) + goto out_unlocked; + mutex_lock(&EXFAT_SB(sb)->s_lock); + ctx->pos = cpos; + goto get_new; + +end_of_dir: + if (!cpos && fake_offset) + cpos = ITER_POS_FILLED_DOTS; + ctx->pos = cpos; +unlock: + mutex_unlock(&EXFAT_SB(sb)->s_lock); +out_unlocked: + /* + * To improve performance, free namebuf after unlock sb_lock. + * If namebuf is not allocated, this function do nothing + */ + exfat_free_namebuf(nb); + return err; +} + +const struct file_operations exfat_dir_operations = { + .llseek = generic_file_llseek, + .read = generic_read_dir, + .iterate = exfat_iterate, + .fsync = generic_file_fsync, +}; + +int exfat_alloc_new_dir(struct inode *inode, struct exfat_chain *clu) +{ + int ret; + + exfat_chain_set(clu, EXFAT_EOF_CLUSTER, 0, ALLOC_NO_FAT_CHAIN); + + ret = exfat_alloc_cluster(inode, 1, clu); + if (ret) + return ret; + + return exfat_zeroed_cluster(inode, clu->dir); +} + +int exfat_calc_num_entries(struct exfat_uni_name *p_uniname) +{ + int len; + + len = p_uniname->name_len; + if (len == 0) + return -EINVAL; + + /* 1 file entry + 1 stream entry + name entries */ + return ((len - 1) / EXFAT_FILE_NAME_LEN + 3); +} + +unsigned int exfat_get_entry_type(struct exfat_dentry *ep) +{ + if (ep->type == EXFAT_UNUSED) + return TYPE_UNUSED; + if (IS_EXFAT_DELETED(ep->type)) + return TYPE_DELETED; + if (ep->type == EXFAT_INVAL) + return TYPE_INVALID; + if (IS_EXFAT_CRITICAL_PRI(ep->type)) { + if (ep->type == EXFAT_BITMAP) + return TYPE_BITMAP; + if (ep->type == EXFAT_UPCASE) + return TYPE_UPCASE; + if (ep->type == EXFAT_VOLUME) + return TYPE_VOLUME; + if (ep->type == EXFAT_FILE) { + if (le16_to_cpu(ep->dentry.file.attr) & ATTR_SUBDIR) + return TYPE_DIR; + return TYPE_FILE; + } + return TYPE_CRITICAL_PRI; + } + if (IS_EXFAT_BENIGN_PRI(ep->type)) { + if (ep->type == EXFAT_GUID) + return TYPE_GUID; + if (ep->type == EXFAT_PADDING) + return TYPE_PADDING; + if (ep->type == EXFAT_ACLTAB) + return TYPE_ACLTAB; + return TYPE_BENIGN_PRI; + } + if (IS_EXFAT_CRITICAL_SEC(ep->type)) { + if (ep->type == EXFAT_STREAM) + return TYPE_STREAM; + if (ep->type == EXFAT_NAME) + return TYPE_EXTEND; + if (ep->type == EXFAT_ACL) + return TYPE_ACL; + return TYPE_CRITICAL_SEC; + } + return TYPE_BENIGN_SEC; +} + +static void exfat_set_entry_type(struct exfat_dentry *ep, unsigned int type) +{ + if (type == TYPE_UNUSED) { + ep->type = EXFAT_UNUSED; + } else if (type == TYPE_DELETED) { + ep->type &= EXFAT_DELETE; + } else if (type == TYPE_STREAM) { + ep->type = EXFAT_STREAM; + } else if (type == TYPE_EXTEND) { + ep->type = EXFAT_NAME; + } else if (type == TYPE_BITMAP) { + ep->type = EXFAT_BITMAP; + } else if (type == TYPE_UPCASE) { + ep->type = EXFAT_UPCASE; + } else if (type == TYPE_VOLUME) { + ep->type = EXFAT_VOLUME; + } else if (type == TYPE_DIR) { + ep->type = EXFAT_FILE; + ep->dentry.file.attr = cpu_to_le16(ATTR_SUBDIR); + } else if (type == TYPE_FILE) { + ep->type = EXFAT_FILE; + ep->dentry.file.attr = cpu_to_le16(ATTR_ARCHIVE); + } +} + +static void exfat_init_stream_entry(struct exfat_dentry *ep, + unsigned char flags, unsigned int start_clu, + unsigned long long size) +{ + exfat_set_entry_type(ep, TYPE_STREAM); + ep->dentry.stream.flags = flags; + ep->dentry.stream.start_clu = cpu_to_le32(start_clu); + ep->dentry.stream.valid_size = cpu_to_le64(size); + ep->dentry.stream.size = cpu_to_le64(size); +} + +static void exfat_init_name_entry(struct exfat_dentry *ep, + unsigned short *uniname) +{ + int i; + + exfat_set_entry_type(ep, TYPE_EXTEND); + ep->dentry.name.flags = 0x0; + + for (i = 0; i < EXFAT_FILE_NAME_LEN; i++) { + ep->dentry.name.unicode_0_14[i] = cpu_to_le16(*uniname); + if (*uniname == 0x0) + break; + uniname++; + } +} + +int exfat_init_dir_entry(struct inode *inode, struct exfat_chain *p_dir, + int entry, unsigned int type, unsigned int start_clu, + unsigned long long size) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct timespec64 ts = current_time(inode); + sector_t sector; + struct exfat_dentry *ep; + struct buffer_head *bh; + + /* + * We cannot use exfat_get_dentry_set here because file ep is not + * initialized yet. + */ + ep = exfat_get_dentry(sb, p_dir, entry, &bh, §or); + if (!ep) + return -EIO; + + exfat_set_entry_type(ep, type); + exfat_set_entry_time(sbi, &ts, + &ep->dentry.file.create_tz, + &ep->dentry.file.create_time, + &ep->dentry.file.create_date, + &ep->dentry.file.create_time_ms); + exfat_set_entry_time(sbi, &ts, + &ep->dentry.file.modify_tz, + &ep->dentry.file.modify_time, + &ep->dentry.file.modify_date, + &ep->dentry.file.modify_time_ms); + exfat_set_entry_time(sbi, &ts, + &ep->dentry.file.access_tz, + &ep->dentry.file.access_time, + &ep->dentry.file.access_date, + NULL); + + exfat_update_bh(sb, bh, IS_DIRSYNC(inode)); + brelse(bh); + + ep = exfat_get_dentry(sb, p_dir, entry + 1, &bh, §or); + if (!ep) + return -EIO; + + exfat_init_stream_entry(ep, + (type == TYPE_FILE) ? ALLOC_FAT_CHAIN : ALLOC_NO_FAT_CHAIN, + start_clu, size); + exfat_update_bh(sb, bh, IS_DIRSYNC(inode)); + brelse(bh); + + return 0; +} + +int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir, + int entry) +{ + struct super_block *sb = inode->i_sb; + int ret = 0; + int i, num_entries; + sector_t sector; + unsigned short chksum; + struct exfat_dentry *ep, *fep; + struct buffer_head *fbh, *bh; + + fep = exfat_get_dentry(sb, p_dir, entry, &fbh, §or); + if (!fep) + return -EIO; + + num_entries = fep->dentry.file.num_ext + 1; + chksum = exfat_calc_chksum_2byte(fep, DENTRY_SIZE, 0, CS_DIR_ENTRY); + + for (i = 1; i < num_entries; i++) { + ep = exfat_get_dentry(sb, p_dir, entry + i, &bh, NULL); + if (!ep) { + ret = -EIO; + goto release_fbh; + } + chksum = exfat_calc_chksum_2byte(ep, DENTRY_SIZE, chksum, + CS_DEFAULT); + brelse(bh); + } + + fep->dentry.file.checksum = cpu_to_le16(chksum); + exfat_update_bh(sb, fbh, IS_DIRSYNC(inode)); +release_fbh: + brelse(fbh); + return ret; +} + +int exfat_init_ext_entry(struct inode *inode, struct exfat_chain *p_dir, + int entry, int num_entries, struct exfat_uni_name *p_uniname) +{ + struct super_block *sb = inode->i_sb; + int i; + sector_t sector; + unsigned short *uniname = p_uniname->name; + struct exfat_dentry *ep; + struct buffer_head *bh; + int sync = IS_DIRSYNC(inode); + + ep = exfat_get_dentry(sb, p_dir, entry, &bh, §or); + if (!ep) + return -EIO; + + ep->dentry.file.num_ext = (unsigned char)(num_entries - 1); + exfat_update_bh(sb, bh, sync); + brelse(bh); + + ep = exfat_get_dentry(sb, p_dir, entry + 1, &bh, §or); + if (!ep) + return -EIO; + + ep->dentry.stream.name_len = p_uniname->name_len; + ep->dentry.stream.name_hash = cpu_to_le16(p_uniname->name_hash); + exfat_update_bh(sb, bh, sync); + brelse(bh); + + for (i = EXFAT_FIRST_CLUSTER; i < num_entries; i++) { + ep = exfat_get_dentry(sb, p_dir, entry + i, &bh, §or); + if (!ep) + return -EIO; + + exfat_init_name_entry(ep, uniname); + exfat_update_bh(sb, bh, sync); + brelse(bh); + uniname += EXFAT_FILE_NAME_LEN; + } + + exfat_update_dir_chksum(inode, p_dir, entry); + return 0; +} + +int exfat_remove_entries(struct inode *inode, struct exfat_chain *p_dir, + int entry, int order, int num_entries) +{ + struct super_block *sb = inode->i_sb; + int i; + sector_t sector; + struct exfat_dentry *ep; + struct buffer_head *bh; + + for (i = order; i < num_entries; i++) { + ep = exfat_get_dentry(sb, p_dir, entry + i, &bh, §or); + if (!ep) + return -EIO; + + exfat_set_entry_type(ep, TYPE_DELETED); + exfat_update_bh(sb, bh, IS_DIRSYNC(inode)); + brelse(bh); + } + + return 0; +} + +int exfat_update_dir_chksum_with_entry_set(struct super_block *sb, + struct exfat_entry_set_cache *es, int sync) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct buffer_head *bh; + sector_t sec = es->sector; + unsigned int off = es->offset; + int chksum_type = CS_DIR_ENTRY, i, num_entries = es->num_entries; + unsigned int buf_off = (off - es->offset); + unsigned int remaining_byte_in_sector, copy_entries, clu; + unsigned short chksum = 0; + + for (i = 0; i < num_entries; i++) { + chksum = exfat_calc_chksum_2byte(&es->entries[i], DENTRY_SIZE, + chksum, chksum_type); + chksum_type = CS_DEFAULT; + } + + es->entries[0].dentry.file.checksum = cpu_to_le16(chksum); + + while (num_entries) { + /* write per sector base */ + remaining_byte_in_sector = (1 << sb->s_blocksize_bits) - off; + copy_entries = min_t(int, + EXFAT_B_TO_DEN(remaining_byte_in_sector), + num_entries); + bh = sb_bread(sb, sec); + if (!bh) + goto err_out; + memcpy(bh->b_data + off, + (unsigned char *)&es->entries[0] + buf_off, + EXFAT_DEN_TO_B(copy_entries)); + exfat_update_bh(sb, bh, sync); + brelse(bh); + num_entries -= copy_entries; + + if (num_entries) { + /* get next sector */ + if (exfat_is_last_sector_in_cluster(sbi, sec)) { + clu = exfat_sector_to_cluster(sbi, sec); + if (es->alloc_flag == ALLOC_NO_FAT_CHAIN) + clu++; + else if (exfat_get_next_cluster(sb, &clu)) + goto err_out; + sec = exfat_cluster_to_sector(sbi, clu); + } else { + sec++; + } + off = 0; + buf_off += EXFAT_DEN_TO_B(copy_entries); + } + } + + return 0; +err_out: + return -EIO; +} + +static int exfat_walk_fat_chain(struct super_block *sb, + struct exfat_chain *p_dir, unsigned int byte_offset, + unsigned int *clu) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + unsigned int clu_offset; + unsigned int cur_clu; + + clu_offset = EXFAT_B_TO_CLU(byte_offset, sbi); + cur_clu = p_dir->dir; + + if (p_dir->flags == ALLOC_NO_FAT_CHAIN) { + cur_clu += clu_offset; + } else { + while (clu_offset > 0) { + if (exfat_get_next_cluster(sb, &cur_clu)) + return -EIO; + if (cur_clu == EXFAT_EOF_CLUSTER) { + exfat_fs_error(sb, + "invalid dentry access beyond EOF (clu : %u, eidx : %d)", + p_dir->dir, + EXFAT_B_TO_DEN(byte_offset)); + return -EIO; + } + clu_offset--; + } + } + + *clu = cur_clu; + return 0; +} + +int exfat_find_location(struct super_block *sb, struct exfat_chain *p_dir, + int entry, sector_t *sector, int *offset) +{ + int ret; + unsigned int off, clu = 0; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + off = EXFAT_DEN_TO_B(entry); + + ret = exfat_walk_fat_chain(sb, p_dir, off, &clu); + if (ret) + return ret; + + /* byte offset in cluster */ + off = EXFAT_CLU_OFFSET(off, sbi); + + /* byte offset in sector */ + *offset = EXFAT_BLK_OFFSET(off, sb); + + /* sector offset in cluster */ + *sector = EXFAT_B_TO_BLK(off, sb); + *sector += exfat_cluster_to_sector(sbi, clu); + return 0; +} + +#define EXFAT_MAX_RA_SIZE (128*1024) +static int exfat_dir_readahead(struct super_block *sb, sector_t sec) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct buffer_head *bh; + unsigned int max_ra_count = EXFAT_MAX_RA_SIZE >> sb->s_blocksize_bits; + unsigned int page_ra_count = PAGE_SIZE >> sb->s_blocksize_bits; + unsigned int adj_ra_count = max(sbi->sect_per_clus, page_ra_count); + unsigned int ra_count = min(adj_ra_count, max_ra_count); + + /* Read-ahead is not required */ + if (sbi->sect_per_clus == 1) + return 0; + + if (sec < sbi->data_start_sector) { + exfat_msg(sb, KERN_ERR, + "requested sector is invalid(sect:%llu, root:%llu)", + (unsigned long long)sec, sbi->data_start_sector); + return -EIO; + } + + /* Not sector aligned with ra_count, resize ra_count to page size */ + if ((sec - sbi->data_start_sector) & (ra_count - 1)) + ra_count = page_ra_count; + + bh = sb_find_get_block(sb, sec); + if (!bh || !buffer_uptodate(bh)) { + unsigned int i; + + for (i = 0; i < ra_count; i++) + sb_breadahead(sb, (sector_t)(sec + i)); + } + brelse(bh); + return 0; +} + +struct exfat_dentry *exfat_get_dentry(struct super_block *sb, + struct exfat_chain *p_dir, int entry, struct buffer_head **bh, + sector_t *sector) +{ + unsigned int dentries_per_page = EXFAT_B_TO_DEN(PAGE_SIZE); + int off; + sector_t sec; + + if (p_dir->dir == DIR_DELETED) { + exfat_msg(sb, KERN_ERR, "abnormal access to deleted dentry\n"); + return NULL; + } + + if (exfat_find_location(sb, p_dir, entry, &sec, &off)) + return NULL; + + if (p_dir->dir != EXFAT_FREE_CLUSTER && + !(entry & (dentries_per_page - 1))) + exfat_dir_readahead(sb, sec); + + *bh = sb_bread(sb, sec); + if (!*bh) + return NULL; + + if (sector) + *sector = sec; + return (struct exfat_dentry *)((*bh)->b_data + off); +} + +enum exfat_validate_dentry_mode { + ES_MODE_STARTED, + ES_MODE_GET_FILE_ENTRY, + ES_MODE_GET_STRM_ENTRY, + ES_MODE_GET_NAME_ENTRY, + ES_MODE_GET_CRITICAL_SEC_ENTRY, +}; + +static bool exfat_validate_entry(unsigned int type, + enum exfat_validate_dentry_mode *mode) +{ + if (type == TYPE_UNUSED || type == TYPE_DELETED) + return false; + + switch (*mode) { + case ES_MODE_STARTED: + if (type != TYPE_FILE && type != TYPE_DIR) + return false; + *mode = ES_MODE_GET_FILE_ENTRY; + return true; + case ES_MODE_GET_FILE_ENTRY: + if (type != TYPE_STREAM) + return false; + *mode = ES_MODE_GET_STRM_ENTRY; + return true; + case ES_MODE_GET_STRM_ENTRY: + if (type != TYPE_EXTEND) + return false; + *mode = ES_MODE_GET_NAME_ENTRY; + return true; + case ES_MODE_GET_NAME_ENTRY: + if (type == TYPE_STREAM) + return false; + if (type != TYPE_EXTEND) { + if (!(type & TYPE_CRITICAL_SEC)) + return false; + *mode = ES_MODE_GET_CRITICAL_SEC_ENTRY; + } + return true; + case ES_MODE_GET_CRITICAL_SEC_ENTRY: + if (type == TYPE_EXTEND || type == TYPE_STREAM) + return false; + if ((type & TYPE_CRITICAL_SEC) != TYPE_CRITICAL_SEC) + return false; + return true; + default: + WARN_ON_ONCE(1); + return false; + } +} + +/* + * Returns a set of dentries for a file or dir. + * + * Note that this is a copy (dump) of dentries so that user should + * call write_entry_set() to apply changes made in this entry set + * to the real device. + * + * in: + * sb+p_dir+entry: indicates a file/dir + * type: specifies how many dentries should be included. + * out: + * file_ep: will point the first dentry(= file dentry) on success + * return: + * pointer of entry set on success, + * NULL on failure. + */ +struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb, + struct exfat_chain *p_dir, int entry, unsigned int type, + struct exfat_dentry **file_ep) +{ + int ret; + unsigned int off, byte_offset, clu = 0; + unsigned int entry_type; + sector_t sec; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_entry_set_cache *es; + struct exfat_dentry *ep, *pos; + unsigned char num_entries; + enum exfat_validate_dentry_mode mode = ES_MODE_STARTED; + struct buffer_head *bh; + + if (p_dir->dir == DIR_DELETED) { + exfat_msg(sb, KERN_ERR, "access to deleted dentry\n"); + return NULL; + } + + byte_offset = EXFAT_DEN_TO_B(entry); + ret = exfat_walk_fat_chain(sb, p_dir, byte_offset, &clu); + if (ret) + return NULL; + + /* byte offset in cluster */ + byte_offset = EXFAT_CLU_OFFSET(byte_offset, sbi); + + /* byte offset in sector */ + off = EXFAT_BLK_OFFSET(byte_offset, sb); + + /* sector offset in cluster */ + sec = EXFAT_B_TO_BLK(byte_offset, sb); + sec += exfat_cluster_to_sector(sbi, clu); + + bh = sb_bread(sb, sec); + if (!bh) + return NULL; + + ep = (struct exfat_dentry *)(bh->b_data + off); + entry_type = exfat_get_entry_type(ep); + + if (entry_type != TYPE_FILE && entry_type != TYPE_DIR) + goto release_bh; + + num_entries = type == ES_ALL_ENTRIES ? + ep->dentry.file.num_ext + 1 : type; + es = kmalloc(struct_size(es, entries, num_entries), GFP_KERNEL); + if (!es) + goto release_bh; + + es->num_entries = num_entries; + es->sector = sec; + es->offset = off; + es->alloc_flag = p_dir->flags; + + pos = &es->entries[0]; + + while (num_entries) { + if (!exfat_validate_entry(exfat_get_entry_type(ep), &mode)) + goto free_es; + + /* copy dentry */ + memcpy(pos, ep, sizeof(struct exfat_dentry)); + + if (--num_entries == 0) + break; + + if (((off + DENTRY_SIZE) & (sb->s_blocksize - 1)) < + (off & (sb->s_blocksize - 1))) { + /* get the next sector */ + if (exfat_is_last_sector_in_cluster(sbi, sec)) { + if (es->alloc_flag == ALLOC_NO_FAT_CHAIN) + clu++; + else if (exfat_get_next_cluster(sb, &clu)) + goto free_es; + sec = exfat_cluster_to_sector(sbi, clu); + } else { + sec++; + } + + brelse(bh); + bh = sb_bread(sb, sec); + if (!bh) + goto free_es; + off = 0; + ep = (struct exfat_dentry *)bh->b_data; + } else { + ep++; + off += DENTRY_SIZE; + } + pos++; + } + + if (file_ep) + *file_ep = &es->entries[0]; + brelse(bh); + return es; + +free_es: + kfree(es); +release_bh: + brelse(bh); + return NULL; +} + +enum { + DIRENT_STEP_FILE, + DIRENT_STEP_STRM, + DIRENT_STEP_NAME, + DIRENT_STEP_SECD, +}; + +/* + * return values: + * >= 0 : return dir entiry position with the name in dir + * -EEXIST : (root dir, ".") it is the root dir itself + * -ENOENT : entry with the name does not exist + * -EIO : I/O error + */ +int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei, + struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname, + int num_entries, unsigned int type) +{ + int i, rewind = 0, dentry = 0, end_eidx = 0, num_ext = 0, len; + int order, step, name_len = 0; + int dentries_per_clu, num_empty = 0; + unsigned int entry_type; + unsigned short *uniname = NULL; + struct exfat_chain clu; + struct exfat_hint *hint_stat = &ei->hint_stat; + struct exfat_hint_femp candi_empty; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + dentries_per_clu = sbi->dentries_per_clu; + + exfat_chain_dup(&clu, p_dir); + + if (hint_stat->eidx) { + clu.dir = hint_stat->clu; + dentry = hint_stat->eidx; + end_eidx = dentry; + } + + candi_empty.eidx = EXFAT_HINT_NONE; +rewind: + order = 0; + step = DIRENT_STEP_FILE; + while (clu.dir != EXFAT_EOF_CLUSTER) { + i = dentry & (dentries_per_clu - 1); + for (; i < dentries_per_clu; i++, dentry++) { + struct exfat_dentry *ep; + struct buffer_head *bh; + + if (rewind && dentry == end_eidx) + goto not_found; + + ep = exfat_get_dentry(sb, &clu, i, &bh, NULL); + if (!ep) + return -EIO; + + entry_type = exfat_get_entry_type(ep); + + if (entry_type == TYPE_UNUSED || + entry_type == TYPE_DELETED) { + step = DIRENT_STEP_FILE; + + num_empty++; + if (candi_empty.eidx == EXFAT_HINT_NONE && + num_empty == 1) { + exfat_chain_set(&candi_empty.cur, + clu.dir, clu.size, clu.flags); + } + + if (candi_empty.eidx == EXFAT_HINT_NONE && + num_empty >= num_entries) { + candi_empty.eidx = + dentry - (num_empty - 1); + WARN_ON(candi_empty.eidx < 0); + candi_empty.count = num_empty; + + if (ei->hint_femp.eidx == + EXFAT_HINT_NONE || + candi_empty.eidx <= + ei->hint_femp.eidx) { + memcpy(&ei->hint_femp, + &candi_empty, + sizeof(candi_empty)); + } + } + + brelse(bh); + if (entry_type == TYPE_UNUSED) + goto not_found; + continue; + } + + num_empty = 0; + candi_empty.eidx = EXFAT_HINT_NONE; + + if (entry_type == TYPE_FILE || entry_type == TYPE_DIR) { + step = DIRENT_STEP_FILE; + if (type == TYPE_ALL || type == entry_type) { + num_ext = ep->dentry.file.num_ext; + step = DIRENT_STEP_STRM; + } + brelse(bh); + continue; + } + + if (entry_type == TYPE_STREAM) { + unsigned short name_hash; + + if (step != DIRENT_STEP_STRM) { + step = DIRENT_STEP_FILE; + brelse(bh); + continue; + } + step = DIRENT_STEP_FILE; + name_hash = le16_to_cpu( + ep->dentry.stream.name_hash); + if (p_uniname->name_hash == name_hash && + p_uniname->name_len == + ep->dentry.stream.name_len) { + step = DIRENT_STEP_NAME; + order = 1; + name_len = 0; + } + brelse(bh); + continue; + } + + brelse(bh); + if (entry_type == TYPE_EXTEND) { + unsigned short entry_uniname[16], unichar; + + if (step != DIRENT_STEP_NAME) { + step = DIRENT_STEP_FILE; + continue; + } + + if (++order == 2) + uniname = p_uniname->name; + else + uniname += EXFAT_FILE_NAME_LEN; + + len = exfat_extract_uni_name(ep, entry_uniname); + name_len += len; + + unichar = *(uniname+len); + *(uniname+len) = 0x0; + + if (exfat_uniname_ncmp(sb, uniname, + entry_uniname, len)) { + step = DIRENT_STEP_FILE; + } else if (p_uniname->name_len == name_len) { + if (order == num_ext) + goto found; + step = DIRENT_STEP_SECD; + } + + *(uniname+len) = unichar; + continue; + } + + if (entry_type & + (TYPE_CRITICAL_SEC | TYPE_BENIGN_SEC)) { + if (step == DIRENT_STEP_SECD) { + if (++order == num_ext) + goto found; + continue; + } + } + step = DIRENT_STEP_FILE; + } + + if (clu.flags == ALLOC_NO_FAT_CHAIN) { + if (--clu.size > 0) + clu.dir++; + else + clu.dir = EXFAT_EOF_CLUSTER; + } else { + if (exfat_get_next_cluster(sb, &clu.dir)) + return -EIO; + } + } + +not_found: + /* + * We started at not 0 index,so we should try to find target + * from 0 index to the index we started at. + */ + if (!rewind && end_eidx) { + rewind = 1; + dentry = 0; + clu.dir = p_dir->dir; + /* reset empty hint */ + num_empty = 0; + candi_empty.eidx = EXFAT_HINT_NONE; + goto rewind; + } + + /* initialized hint_stat */ + hint_stat->clu = p_dir->dir; + hint_stat->eidx = 0; + return -ENOENT; + +found: + /* next dentry we'll find is out of this cluster */ + if (!((dentry + 1) & (dentries_per_clu - 1))) { + int ret = 0; + + if (clu.flags == ALLOC_NO_FAT_CHAIN) { + if (--clu.size > 0) + clu.dir++; + else + clu.dir = EXFAT_EOF_CLUSTER; + } else { + ret = exfat_get_next_cluster(sb, &clu.dir); + } + + if (ret || clu.dir != EXFAT_EOF_CLUSTER) { + /* just initialized hint_stat */ + hint_stat->clu = p_dir->dir; + hint_stat->eidx = 0; + return (dentry - num_ext); + } + } + + hint_stat->clu = clu.dir; + hint_stat->eidx = dentry + 1; + return dentry - num_ext; +} + +int exfat_count_ext_entries(struct super_block *sb, struct exfat_chain *p_dir, + int entry, struct exfat_dentry *ep) +{ + int i, count = 0; + unsigned int type; + struct exfat_dentry *ext_ep; + struct buffer_head *bh; + + for (i = 0, entry++; i < ep->dentry.file.num_ext; i++, entry++) { + ext_ep = exfat_get_dentry(sb, p_dir, entry, &bh, NULL); + if (!ext_ep) + return -EIO; + + type = exfat_get_entry_type(ext_ep); + brelse(bh); + if (type == TYPE_EXTEND || type == TYPE_STREAM) + count++; + else + break; + } + return count; +} + +int exfat_count_dir_entries(struct super_block *sb, struct exfat_chain *p_dir) +{ + int i, count = 0; + int dentries_per_clu; + unsigned int entry_type; + struct exfat_chain clu; + struct exfat_dentry *ep; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct buffer_head *bh; + + dentries_per_clu = sbi->dentries_per_clu; + + exfat_chain_dup(&clu, p_dir); + + while (clu.dir != EXFAT_EOF_CLUSTER) { + for (i = 0; i < dentries_per_clu; i++) { + ep = exfat_get_dentry(sb, &clu, i, &bh, NULL); + if (!ep) + return -EIO; + entry_type = exfat_get_entry_type(ep); + brelse(bh); + + if (entry_type == TYPE_UNUSED) + return count; + if (entry_type != TYPE_DIR) + continue; + count++; + } + + if (clu.flags == ALLOC_NO_FAT_CHAIN) { + if (--clu.size > 0) + clu.dir++; + else + clu.dir = EXFAT_EOF_CLUSTER; + } else { + if (exfat_get_next_cluster(sb, &(clu.dir))) + return -EIO; + } + } + + return count; +} From 98d917047e8b7f4bb2ff61d81b0ccd94a00444f9 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:36 +0900 Subject: [PATCH 1217/4444] exfat: add file operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of file operations for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Reviewed-by: Arnd Bergmann Signed-off-by: Al Viro --- fs/exfat/file.c | 360 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 fs/exfat/file.c diff --git a/fs/exfat/file.c b/fs/exfat/file.c new file mode 100644 index 000000000000..483f683757aa --- /dev/null +++ b/fs/exfat/file.c @@ -0,0 +1,360 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +static int exfat_cont_expand(struct inode *inode, loff_t size) +{ + struct address_space *mapping = inode->i_mapping; + loff_t start = i_size_read(inode), count = size - i_size_read(inode); + int err, err2; + + err = generic_cont_expand_simple(inode, size); + if (err) + return err; + + inode->i_ctime = inode->i_mtime = current_time(inode); + mark_inode_dirty(inode); + + if (!IS_SYNC(inode)) + return 0; + + err = filemap_fdatawrite_range(mapping, start, start + count - 1); + err2 = sync_mapping_buffers(mapping); + if (!err) + err = err2; + err2 = write_inode_now(inode, 1); + if (!err) + err = err2; + if (err) + return err; + + return filemap_fdatawait_range(mapping, start, start + count - 1); +} + +static bool exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode) +{ + mode_t allow_utime = sbi->options.allow_utime; + + if (!uid_eq(current_fsuid(), inode->i_uid)) { + if (in_group_p(inode->i_gid)) + allow_utime >>= 3; + if (allow_utime & MAY_WRITE) + return true; + } + + /* use a default check */ + return false; +} + +static int exfat_sanitize_mode(const struct exfat_sb_info *sbi, + struct inode *inode, umode_t *mode_ptr) +{ + mode_t i_mode, mask, perm; + + i_mode = inode->i_mode; + + mask = (S_ISREG(i_mode) || S_ISLNK(i_mode)) ? + sbi->options.fs_fmask : sbi->options.fs_dmask; + perm = *mode_ptr & ~(S_IFMT | mask); + + /* Of the r and x bits, all (subject to umask) must be present.*/ + if ((perm & 0555) != (i_mode & 0555)) + return -EPERM; + + if (exfat_mode_can_hold_ro(inode)) { + /* + * Of the w bits, either all (subject to umask) or none must + * be present. + */ + if ((perm & 0222) && ((perm & 0222) != (0222 & ~mask))) + return -EPERM; + } else { + /* + * If exfat_mode_can_hold_ro(inode) is false, can't change + * w bits. + */ + if ((perm & 0222) != (0222 & ~mask)) + return -EPERM; + } + + *mode_ptr &= S_IFMT | perm; + + return 0; +} + +/* resize the file length */ +int __exfat_truncate(struct inode *inode, loff_t new_size) +{ + unsigned int num_clusters_new, num_clusters_phys; + unsigned int last_clu = EXFAT_FREE_CLUSTER; + struct exfat_chain clu; + struct exfat_dentry *ep, *ep2; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *ei = EXFAT_I(inode); + struct exfat_entry_set_cache *es = NULL; + int evict = (ei->dir.dir == DIR_DELETED) ? 1 : 0; + + /* check if the given file ID is opened */ + if (ei->type != TYPE_FILE && ei->type != TYPE_DIR) + return -EPERM; + + exfat_set_vol_flags(sb, VOL_DIRTY); + + num_clusters_new = EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi); + num_clusters_phys = + EXFAT_B_TO_CLU_ROUND_UP(EXFAT_I(inode)->i_size_ondisk, sbi); + + exfat_chain_set(&clu, ei->start_clu, num_clusters_phys, ei->flags); + + if (new_size > 0) { + /* + * Truncate FAT chain num_clusters after the first cluster + * num_clusters = min(new, phys); + */ + unsigned int num_clusters = + min(num_clusters_new, num_clusters_phys); + + /* + * Follow FAT chain + * (defensive coding - works fine even with corrupted FAT table + */ + if (clu.flags == ALLOC_NO_FAT_CHAIN) { + clu.dir += num_clusters; + clu.size -= num_clusters; + } else { + while (num_clusters > 0) { + last_clu = clu.dir; + if (exfat_get_next_cluster(sb, &(clu.dir))) + return -EIO; + + num_clusters--; + clu.size--; + } + } + } else { + ei->flags = ALLOC_NO_FAT_CHAIN; + ei->start_clu = EXFAT_EOF_CLUSTER; + } + + i_size_write(inode, new_size); + + if (ei->type == TYPE_FILE) + ei->attr |= ATTR_ARCHIVE; + + /* update the directory entry */ + if (!evict) { + struct timespec64 ts; + + es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry, + ES_ALL_ENTRIES, &ep); + if (!es) + return -EIO; + ep2 = ep + 1; + + ts = current_time(inode); + exfat_set_entry_time(sbi, &ts, + &ep->dentry.file.modify_tz, + &ep->dentry.file.modify_time, + &ep->dentry.file.modify_date, + &ep->dentry.file.modify_time_ms); + ep->dentry.file.attr = cpu_to_le16(ei->attr); + + /* File size should be zero if there is no cluster allocated */ + if (ei->start_clu == EXFAT_EOF_CLUSTER) { + ep->dentry.stream.valid_size = 0; + ep->dentry.stream.size = 0; + } else { + ep->dentry.stream.valid_size = cpu_to_le64(new_size); + ep->dentry.stream.size = ep->dentry.stream.valid_size; + } + + if (new_size == 0) { + /* Any directory can not be truncated to zero */ + WARN_ON(ei->type != TYPE_FILE); + + ep2->dentry.stream.flags = ALLOC_FAT_CHAIN; + ep2->dentry.stream.start_clu = EXFAT_FREE_CLUSTER; + } + + if (exfat_update_dir_chksum_with_entry_set(sb, es, + inode_needs_sync(inode))) + return -EIO; + kfree(es); + } + + /* cut off from the FAT chain */ + if (ei->flags == ALLOC_FAT_CHAIN && last_clu != EXFAT_FREE_CLUSTER && + last_clu != EXFAT_EOF_CLUSTER) { + if (exfat_ent_set(sb, last_clu, EXFAT_EOF_CLUSTER)) + return -EIO; + } + + /* invalidate cache and free the clusters */ + /* clear exfat cache */ + exfat_cache_inval_inode(inode); + + /* hint information */ + ei->hint_bmap.off = EXFAT_EOF_CLUSTER; + ei->hint_bmap.clu = EXFAT_EOF_CLUSTER; + if (ei->rwoffset > new_size) + ei->rwoffset = new_size; + + /* hint_stat will be used if this is directory. */ + ei->hint_stat.eidx = 0; + ei->hint_stat.clu = ei->start_clu; + ei->hint_femp.eidx = EXFAT_HINT_NONE; + + /* free the clusters */ + if (exfat_free_cluster(inode, &clu)) + return -EIO; + + exfat_set_vol_flags(sb, VOL_CLEAN); + + return 0; +} + +void exfat_truncate(struct inode *inode, loff_t size) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + unsigned int blocksize = 1 << inode->i_blkbits; + loff_t aligned_size; + int err; + + mutex_lock(&sbi->s_lock); + if (EXFAT_I(inode)->start_clu == 0) { + /* + * Empty start_clu != ~0 (not allocated) + */ + exfat_fs_error(sb, "tried to truncate zeroed cluster."); + goto write_size; + } + + err = __exfat_truncate(inode, i_size_read(inode)); + if (err) + goto write_size; + + inode->i_ctime = inode->i_mtime = current_time(inode); + if (IS_DIRSYNC(inode)) + exfat_sync_inode(inode); + else + mark_inode_dirty(inode); + + inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1)) & + ~(sbi->cluster_size - 1)) >> inode->i_blkbits; +write_size: + aligned_size = i_size_read(inode); + if (aligned_size & (blocksize - 1)) { + aligned_size |= (blocksize - 1); + aligned_size++; + } + + if (EXFAT_I(inode)->i_size_ondisk > i_size_read(inode)) + EXFAT_I(inode)->i_size_ondisk = aligned_size; + + if (EXFAT_I(inode)->i_size_aligned > i_size_read(inode)) + EXFAT_I(inode)->i_size_aligned = aligned_size; + mutex_unlock(&sbi->s_lock); +} + +int exfat_getattr(const struct path *path, struct kstat *stat, + unsigned int request_mask, unsigned int query_flags) +{ + struct inode *inode = d_backing_inode(path->dentry); + struct exfat_inode_info *ei = EXFAT_I(inode); + + generic_fillattr(inode, stat); + stat->result_mask |= STATX_BTIME; + stat->btime.tv_sec = ei->i_crtime.tv_sec; + stat->btime.tv_nsec = ei->i_crtime.tv_nsec; + stat->blksize = EXFAT_SB(inode->i_sb)->cluster_size; + return 0; +} + +int exfat_setattr(struct dentry *dentry, struct iattr *attr) +{ + struct exfat_sb_info *sbi = EXFAT_SB(dentry->d_sb); + struct inode *inode = dentry->d_inode; + unsigned int ia_valid; + int error; + + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size > i_size_read(inode)) { + error = exfat_cont_expand(inode, attr->ia_size); + if (error || attr->ia_valid == ATTR_SIZE) + return error; + attr->ia_valid &= ~ATTR_SIZE; + } + + /* Check for setting the inode time. */ + ia_valid = attr->ia_valid; + if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) && + exfat_allow_set_time(sbi, inode)) { + attr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET | + ATTR_TIMES_SET); + } + + error = setattr_prepare(dentry, attr); + attr->ia_valid = ia_valid; + if (error) + goto out; + + if (((attr->ia_valid & ATTR_UID) && + !uid_eq(attr->ia_uid, sbi->options.fs_uid)) || + ((attr->ia_valid & ATTR_GID) && + !gid_eq(attr->ia_gid, sbi->options.fs_gid)) || + ((attr->ia_valid & ATTR_MODE) && + (attr->ia_mode & ~(S_IFREG | S_IFLNK | S_IFDIR | 0777)))) { + error = -EPERM; + goto out; + } + + /* + * We don't return -EPERM here. Yes, strange, but this is too + * old behavior. + */ + if (attr->ia_valid & ATTR_MODE) { + if (exfat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0) + attr->ia_valid &= ~ATTR_MODE; + } + + if (attr->ia_valid & ATTR_SIZE) { + error = exfat_block_truncate_page(inode, attr->ia_size); + if (error) + goto out; + + down_write(&EXFAT_I(inode)->truncate_lock); + truncate_setsize(inode, attr->ia_size); + exfat_truncate(inode, attr->ia_size); + up_write(&EXFAT_I(inode)->truncate_lock); + } + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + +out: + return error; +} + +const struct file_operations exfat_file_operations = { + .llseek = generic_file_llseek, + .read_iter = generic_file_read_iter, + .write_iter = generic_file_write_iter, + .mmap = generic_file_mmap, + .fsync = generic_file_fsync, + .splice_read = generic_file_splice_read, +}; + +const struct inode_operations exfat_file_inode_operations = { + .setattr = exfat_setattr, + .getattr = exfat_getattr, +}; From 31023864e67a5f390cefbe92f72343027dc3aa33 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:37 +0900 Subject: [PATCH 1218/4444] exfat: add fat entry operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of fat entry operations for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/exfat/fatent.c | 463 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 463 insertions(+) create mode 100644 fs/exfat/fatent.c diff --git a/fs/exfat/fatent.c b/fs/exfat/fatent.c new file mode 100644 index 000000000000..a855b1769a96 --- /dev/null +++ b/fs/exfat/fatent.c @@ -0,0 +1,463 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +static int exfat_mirror_bh(struct super_block *sb, sector_t sec, + struct buffer_head *bh) +{ + struct buffer_head *c_bh; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + sector_t sec2; + int err = 0; + + if (sbi->FAT2_start_sector != sbi->FAT1_start_sector) { + sec2 = sec - sbi->FAT1_start_sector + sbi->FAT2_start_sector; + c_bh = sb_getblk(sb, sec2); + if (!c_bh) + return -ENOMEM; + memcpy(c_bh->b_data, bh->b_data, sb->s_blocksize); + set_buffer_uptodate(c_bh); + mark_buffer_dirty(c_bh); + if (sb->s_flags & SB_SYNCHRONOUS) + err = sync_dirty_buffer(c_bh); + brelse(c_bh); + } + + return err; +} + +static int __exfat_ent_get(struct super_block *sb, unsigned int loc, + unsigned int *content) +{ + unsigned int off; + sector_t sec; + struct buffer_head *bh; + + sec = FAT_ENT_OFFSET_SECTOR(sb, loc); + off = FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc); + + bh = sb_bread(sb, sec); + if (!bh) + return -EIO; + + *content = le32_to_cpu(*(__le32 *)(&bh->b_data[off])); + + /* remap reserved clusters to simplify code */ + if (*content > EXFAT_BAD_CLUSTER) + *content = EXFAT_EOF_CLUSTER; + + brelse(bh); + return 0; +} + +int exfat_ent_set(struct super_block *sb, unsigned int loc, + unsigned int content) +{ + unsigned int off; + sector_t sec; + __le32 *fat_entry; + struct buffer_head *bh; + + sec = FAT_ENT_OFFSET_SECTOR(sb, loc); + off = FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc); + + bh = sb_bread(sb, sec); + if (!bh) + return -EIO; + + fat_entry = (__le32 *)&(bh->b_data[off]); + *fat_entry = cpu_to_le32(content); + exfat_update_bh(sb, bh, sb->s_flags & SB_SYNCHRONOUS); + exfat_mirror_bh(sb, sec, bh); + brelse(bh); + return 0; +} + +static inline bool is_valid_cluster(struct exfat_sb_info *sbi, + unsigned int clus) +{ + if (clus < EXFAT_FIRST_CLUSTER || sbi->num_clusters <= clus) + return false; + return true; +} + +int exfat_ent_get(struct super_block *sb, unsigned int loc, + unsigned int *content) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + int err; + + if (!is_valid_cluster(sbi, loc)) { + exfat_fs_error(sb, "invalid access to FAT (entry 0x%08x)", + loc); + return -EIO; + } + + err = __exfat_ent_get(sb, loc, content); + if (err) { + exfat_fs_error(sb, + "failed to access to FAT (entry 0x%08x, err:%d)", + loc, err); + return err; + } + + if (*content == EXFAT_FREE_CLUSTER) { + exfat_fs_error(sb, + "invalid access to FAT free cluster (entry 0x%08x)", + loc); + return -EIO; + } + + if (*content == EXFAT_BAD_CLUSTER) { + exfat_fs_error(sb, + "invalid access to FAT bad cluster (entry 0x%08x)", + loc); + return -EIO; + } + + if (*content != EXFAT_EOF_CLUSTER && !is_valid_cluster(sbi, *content)) { + exfat_fs_error(sb, + "invalid access to FAT (entry 0x%08x) bogus content (0x%08x)", + loc, *content); + return -EIO; + } + + return 0; +} + +int exfat_chain_cont_cluster(struct super_block *sb, unsigned int chain, + unsigned int len) +{ + if (!len) + return 0; + + while (len > 1) { + if (exfat_ent_set(sb, chain, chain + 1)) + return -EIO; + chain++; + len--; + } + + if (exfat_ent_set(sb, chain, EXFAT_EOF_CLUSTER)) + return -EIO; + return 0; +} + +int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain) +{ + unsigned int num_clusters = 0; + unsigned int clu; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + /* invalid cluster number */ + if (p_chain->dir == EXFAT_FREE_CLUSTER || + p_chain->dir == EXFAT_EOF_CLUSTER || + p_chain->dir < EXFAT_FIRST_CLUSTER) + return 0; + + /* no cluster to truncate */ + if (p_chain->size == 0) + return 0; + + /* check cluster validation */ + if (p_chain->dir < 2 && p_chain->dir >= sbi->num_clusters) { + exfat_msg(sb, KERN_ERR, "invalid start cluster (%u)", + p_chain->dir); + return -EIO; + } + + set_bit(EXFAT_SB_DIRTY, &sbi->s_state); + clu = p_chain->dir; + + if (p_chain->flags == ALLOC_NO_FAT_CHAIN) { + do { + exfat_clear_bitmap(inode, clu); + clu++; + + num_clusters++; + } while (num_clusters < p_chain->size); + } else { + do { + exfat_clear_bitmap(inode, clu); + + if (exfat_get_next_cluster(sb, &clu)) + goto dec_used_clus; + + num_clusters++; + } while (clu != EXFAT_EOF_CLUSTER); + } + +dec_used_clus: + sbi->used_clusters -= num_clusters; + return 0; +} + +int exfat_find_last_cluster(struct super_block *sb, struct exfat_chain *p_chain, + unsigned int *ret_clu) +{ + unsigned int clu, next; + unsigned int count = 0; + + next = p_chain->dir; + if (p_chain->flags == ALLOC_NO_FAT_CHAIN) { + *ret_clu = next + p_chain->size - 1; + return 0; + } + + do { + count++; + clu = next; + if (exfat_ent_get(sb, clu, &next)) + return -EIO; + } while (next != EXFAT_EOF_CLUSTER); + + if (p_chain->size != count) { + exfat_fs_error(sb, + "bogus directory size (clus : ondisk(%d) != counted(%d))", + p_chain->size, count); + return -EIO; + } + + *ret_clu = clu; + return 0; +} + +static inline int exfat_sync_bhs(struct buffer_head **bhs, int nr_bhs) +{ + int i, err = 0; + + for (i = 0; i < nr_bhs; i++) + write_dirty_buffer(bhs[i], 0); + + for (i = 0; i < nr_bhs; i++) { + wait_on_buffer(bhs[i]); + if (!err && !buffer_uptodate(bhs[i])) + err = -EIO; + } + return err; +} + +int exfat_zeroed_cluster(struct inode *dir, unsigned int clu) +{ + struct super_block *sb = dir->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct buffer_head *bhs[MAX_BUF_PER_PAGE]; + int nr_bhs = MAX_BUF_PER_PAGE; + sector_t blknr, last_blknr; + int err, i, n; + + blknr = exfat_cluster_to_sector(sbi, clu); + last_blknr = blknr + sbi->sect_per_clus; + + if (last_blknr > sbi->num_sectors && sbi->num_sectors > 0) { + exfat_fs_error_ratelimit(sb, + "%s: out of range(sect:%llu len:%u)", + __func__, (unsigned long long)blknr, + sbi->sect_per_clus); + return -EIO; + } + + /* Zeroing the unused blocks on this cluster */ + n = 0; + while (blknr < last_blknr) { + bhs[n] = sb_getblk(sb, blknr); + if (!bhs[n]) { + err = -ENOMEM; + goto release_bhs; + } + memset(bhs[n]->b_data, 0, sb->s_blocksize); + exfat_update_bh(sb, bhs[n], 0); + + n++; + blknr++; + + if (n == nr_bhs) { + if (IS_DIRSYNC(dir)) { + err = exfat_sync_bhs(bhs, n); + if (err) + goto release_bhs; + } + + for (i = 0; i < n; i++) + brelse(bhs[i]); + n = 0; + } + } + + if (IS_DIRSYNC(dir)) { + err = exfat_sync_bhs(bhs, n); + if (err) + goto release_bhs; + } + + for (i = 0; i < n; i++) + brelse(bhs[i]); + + return 0; + +release_bhs: + exfat_msg(sb, KERN_ERR, "failed zeroed sect %llu\n", + (unsigned long long)blknr); + for (i = 0; i < n; i++) + bforget(bhs[i]); + return err; +} + +int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc, + struct exfat_chain *p_chain) +{ + int ret = -ENOSPC; + unsigned int num_clusters = 0, total_cnt; + unsigned int hint_clu, new_clu, last_clu = EXFAT_EOF_CLUSTER; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + total_cnt = EXFAT_DATA_CLUSTER_COUNT(sbi); + + if (unlikely(total_cnt < sbi->used_clusters)) { + exfat_fs_error_ratelimit(sb, + "%s: invalid used clusters(t:%u,u:%u)\n", + __func__, total_cnt, sbi->used_clusters); + return -EIO; + } + + if (num_alloc > total_cnt - sbi->used_clusters) + return -ENOSPC; + + hint_clu = p_chain->dir; + /* find new cluster */ + if (hint_clu == EXFAT_EOF_CLUSTER) { + if (sbi->clu_srch_ptr < EXFAT_FIRST_CLUSTER) { + exfat_msg(sb, KERN_ERR, + "sbi->clu_srch_ptr is invalid (%u)\n", + sbi->clu_srch_ptr); + sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER; + } + + hint_clu = exfat_find_free_bitmap(sb, sbi->clu_srch_ptr); + if (hint_clu == EXFAT_EOF_CLUSTER) + return -ENOSPC; + } + + /* check cluster validation */ + if (hint_clu < EXFAT_FIRST_CLUSTER && hint_clu >= sbi->num_clusters) { + exfat_msg(sb, KERN_ERR, "hint_cluster is invalid (%u)\n", + hint_clu); + hint_clu = EXFAT_FIRST_CLUSTER; + if (p_chain->flags == ALLOC_NO_FAT_CHAIN) { + if (exfat_chain_cont_cluster(sb, p_chain->dir, + num_clusters)) + return -EIO; + p_chain->flags = ALLOC_FAT_CHAIN; + } + } + + set_bit(EXFAT_SB_DIRTY, &sbi->s_state); + + p_chain->dir = EXFAT_EOF_CLUSTER; + + while ((new_clu = exfat_find_free_bitmap(sb, hint_clu)) != + EXFAT_EOF_CLUSTER) { + if (new_clu != hint_clu && + p_chain->flags == ALLOC_NO_FAT_CHAIN) { + if (exfat_chain_cont_cluster(sb, p_chain->dir, + num_clusters)) { + ret = -EIO; + goto free_cluster; + } + p_chain->flags = ALLOC_FAT_CHAIN; + } + + /* update allocation bitmap */ + if (exfat_set_bitmap(inode, new_clu)) { + ret = -EIO; + goto free_cluster; + } + + num_clusters++; + + /* update FAT table */ + if (p_chain->flags == ALLOC_FAT_CHAIN) { + if (exfat_ent_set(sb, new_clu, EXFAT_EOF_CLUSTER)) { + ret = -EIO; + goto free_cluster; + } + } + + if (p_chain->dir == EXFAT_EOF_CLUSTER) { + p_chain->dir = new_clu; + } else if (p_chain->flags == ALLOC_FAT_CHAIN) { + if (exfat_ent_set(sb, last_clu, new_clu)) { + ret = -EIO; + goto free_cluster; + } + } + last_clu = new_clu; + + if (--num_alloc == 0) { + sbi->clu_srch_ptr = hint_clu; + sbi->used_clusters += num_clusters; + + p_chain->size += num_clusters; + return 0; + } + + hint_clu = new_clu + 1; + if (hint_clu >= sbi->num_clusters) { + hint_clu = EXFAT_FIRST_CLUSTER; + + if (p_chain->flags == ALLOC_NO_FAT_CHAIN) { + if (exfat_chain_cont_cluster(sb, p_chain->dir, + num_clusters)) { + ret = -EIO; + goto free_cluster; + } + p_chain->flags = ALLOC_FAT_CHAIN; + } + } + } +free_cluster: + if (num_clusters) + exfat_free_cluster(inode, p_chain); + return ret; +} + +int exfat_count_num_clusters(struct super_block *sb, + struct exfat_chain *p_chain, unsigned int *ret_count) +{ + unsigned int i, count; + unsigned int clu; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + if (!p_chain->dir || p_chain->dir == EXFAT_EOF_CLUSTER) { + *ret_count = 0; + return 0; + } + + if (p_chain->flags == ALLOC_NO_FAT_CHAIN) { + *ret_count = p_chain->size; + return 0; + } + + clu = p_chain->dir; + count = 0; + for (i = EXFAT_FIRST_CLUSTER; i < sbi->num_clusters; i++) { + count++; + if (exfat_ent_get(sb, clu, &clu)) + return -EIO; + if (clu == EXFAT_EOF_CLUSTER) + break; + } + + *ret_count = count; + return 0; +} From 1e49a94cf707204b66a3fb242f2814712c941f52 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:38 +0900 Subject: [PATCH 1219/4444] exfat: add bitmap operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of bitmap operations for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/exfat/balloc.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+) create mode 100644 fs/exfat/balloc.c diff --git a/fs/exfat/balloc.c b/fs/exfat/balloc.c new file mode 100644 index 000000000000..6a04cc02565a --- /dev/null +++ b/fs/exfat/balloc.c @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +static const unsigned char free_bit[] = { + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,/* 0 ~ 19*/ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3,/* 20 ~ 39*/ + 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/* 40 ~ 59*/ + 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,/* 60 ~ 79*/ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2,/* 80 ~ 99*/ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3,/*100 ~ 119*/ + 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/*120 ~ 139*/ + 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,/*140 ~ 159*/ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,/*160 ~ 179*/ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3,/*180 ~ 199*/ + 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/*200 ~ 219*/ + 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,/*220 ~ 239*/ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /*240 ~ 254*/ +}; + +static const unsigned char used_bit[] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3,/* 0 ~ 19*/ + 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4,/* 20 ~ 39*/ + 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,/* 40 ~ 59*/ + 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,/* 60 ~ 79*/ + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4,/* 80 ~ 99*/ + 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,/*100 ~ 119*/ + 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4,/*120 ~ 139*/ + 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,/*140 ~ 159*/ + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5,/*160 ~ 179*/ + 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,/*180 ~ 199*/ + 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6,/*200 ~ 219*/ + 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,/*220 ~ 239*/ + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 /*240 ~ 255*/ +}; + +/* + * Allocation Bitmap Management Functions + */ +static int exfat_allocate_bitmap(struct super_block *sb, + struct exfat_dentry *ep) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + long long map_size; + unsigned int i, need_map_size; + sector_t sector; + + sbi->map_clu = le32_to_cpu(ep->dentry.bitmap.start_clu); + map_size = le64_to_cpu(ep->dentry.bitmap.size); + need_map_size = ((EXFAT_DATA_CLUSTER_COUNT(sbi) - 1) / BITS_PER_BYTE) + + 1; + if (need_map_size != map_size) { + exfat_msg(sb, KERN_ERR, + "bogus allocation bitmap size(need : %u, cur : %lld)", + need_map_size, map_size); + /* + * Only allowed when bogus allocation + * bitmap size is large + */ + if (need_map_size > map_size) + return -EIO; + } + sbi->map_sectors = ((need_map_size - 1) >> + (sb->s_blocksize_bits)) + 1; + sbi->vol_amap = kmalloc_array(sbi->map_sectors, + sizeof(struct buffer_head *), GFP_KERNEL); + if (!sbi->vol_amap) + return -ENOMEM; + + sector = exfat_cluster_to_sector(sbi, sbi->map_clu); + for (i = 0; i < sbi->map_sectors; i++) { + sbi->vol_amap[i] = sb_bread(sb, sector + i); + if (!sbi->vol_amap[i]) { + /* release all buffers and free vol_amap */ + int j = 0; + + while (j < i) + brelse(sbi->vol_amap[j++]); + + kfree(sbi->vol_amap); + sbi->vol_amap = NULL; + return -EIO; + } + } + + sbi->pbr_bh = NULL; + return 0; +} + +int exfat_load_bitmap(struct super_block *sb) +{ + unsigned int i, type; + struct exfat_chain clu; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + exfat_chain_set(&clu, sbi->root_dir, 0, ALLOC_FAT_CHAIN); + while (clu.dir != EXFAT_EOF_CLUSTER) { + for (i = 0; i < sbi->dentries_per_clu; i++) { + struct exfat_dentry *ep; + struct buffer_head *bh; + + ep = exfat_get_dentry(sb, &clu, i, &bh, NULL); + if (!ep) + return -EIO; + + type = exfat_get_entry_type(ep); + if (type == TYPE_UNUSED) + break; + if (type != TYPE_BITMAP) + continue; + if (ep->dentry.bitmap.flags == 0x0) { + int err; + + err = exfat_allocate_bitmap(sb, ep); + brelse(bh); + return err; + } + brelse(bh); + } + + if (exfat_get_next_cluster(sb, &clu.dir)) + return -EIO; + } + + return -EINVAL; +} + +void exfat_free_bitmap(struct exfat_sb_info *sbi) +{ + int i; + + brelse(sbi->pbr_bh); + + for (i = 0; i < sbi->map_sectors; i++) + __brelse(sbi->vol_amap[i]); + + kfree(sbi->vol_amap); +} + +/* + * If the value of "clu" is 0, it means cluster 2 which is the first cluster of + * the cluster heap. + */ +int exfat_set_bitmap(struct inode *inode, unsigned int clu) +{ + int i, b; + unsigned int ent_idx; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + WARN_ON(clu < EXFAT_FIRST_CLUSTER); + ent_idx = CLUSTER_TO_BITMAP_ENT(clu); + i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx); + b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx); + + set_bit_le(b, sbi->vol_amap[i]->b_data); + exfat_update_bh(sb, sbi->vol_amap[i], IS_DIRSYNC(inode)); + return 0; +} + +/* + * If the value of "clu" is 0, it means cluster 2 which is the first cluster of + * the cluster heap. + */ +void exfat_clear_bitmap(struct inode *inode, unsigned int clu) +{ + int i, b; + unsigned int ent_idx; + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_mount_options *opts = &sbi->options; + + WARN_ON(clu < EXFAT_FIRST_CLUSTER); + ent_idx = CLUSTER_TO_BITMAP_ENT(clu); + i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx); + b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx); + + clear_bit_le(b, sbi->vol_amap[i]->b_data); + exfat_update_bh(sb, sbi->vol_amap[i], IS_DIRSYNC(inode)); + + if (opts->discard) { + int ret_discard; + + ret_discard = sb_issue_discard(sb, + exfat_cluster_to_sector(sbi, clu + + EXFAT_RESERVED_CLUSTERS), + (1 << sbi->sect_per_clus_bits), GFP_NOFS, 0); + + if (ret_discard == -EOPNOTSUPP) { + exfat_msg(sb, KERN_ERR, + "discard not supported by device, disabling"); + opts->discard = 0; + } + } +} + +/* + * If the value of "clu" is 0, it means cluster 2 which is the first cluster of + * the cluster heap. + */ +unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu) +{ + unsigned int i, map_i, map_b, ent_idx; + unsigned int clu_base, clu_free; + unsigned char k, clu_mask; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + WARN_ON(clu < EXFAT_FIRST_CLUSTER); + ent_idx = CLUSTER_TO_BITMAP_ENT(clu); + clu_base = BITMAP_ENT_TO_CLUSTER(ent_idx & ~(BITS_PER_BYTE_MASK)); + clu_mask = IGNORED_BITS_REMAINED(clu, clu_base); + + map_i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx); + map_b = BITMAP_OFFSET_BYTE_IN_SECTOR(sb, ent_idx); + + for (i = EXFAT_FIRST_CLUSTER; i < sbi->num_clusters; + i += BITS_PER_BYTE) { + k = *(sbi->vol_amap[map_i]->b_data + map_b); + if (clu_mask > 0) { + k |= clu_mask; + clu_mask = 0; + } + if (k < 0xFF) { + clu_free = clu_base + free_bit[k]; + if (clu_free < sbi->num_clusters) + return clu_free; + } + clu_base += BITS_PER_BYTE; + + if (++map_b >= sb->s_blocksize || + clu_base >= sbi->num_clusters) { + if (++map_i >= sbi->map_sectors) { + clu_base = EXFAT_FIRST_CLUSTER; + map_i = 0; + } + map_b = 0; + } + } + + return EXFAT_EOF_CLUSTER; +} + +int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + unsigned int count = 0; + unsigned int i, map_i = 0, map_b = 0; + unsigned int total_clus = EXFAT_DATA_CLUSTER_COUNT(sbi); + unsigned int last_mask = total_clus & BITS_PER_BYTE_MASK; + unsigned char clu_bits; + const unsigned char last_bit_mask[] = {0, 0b00000001, 0b00000011, + 0b00000111, 0b00001111, 0b00011111, 0b00111111, 0b01111111}; + + total_clus &= ~last_mask; + for (i = 0; i < total_clus; i += BITS_PER_BYTE) { + clu_bits = *(sbi->vol_amap[map_i]->b_data + map_b); + count += used_bit[clu_bits]; + if (++map_b >= (unsigned int)sb->s_blocksize) { + map_i++; + map_b = 0; + } + } + + if (last_mask) { + clu_bits = *(sbi->vol_amap[map_i]->b_data + map_b); + clu_bits &= last_bit_mask[last_mask]; + count += used_bit[clu_bits]; + } + + *ret_count = count; + return 0; +} From c35b6810c4952ae5776607e2c1d6a587425d5834 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:39 +0900 Subject: [PATCH 1220/4444] exfat: add exfat cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of exfat cache. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/exfat/cache.c | 325 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 fs/exfat/cache.c diff --git a/fs/exfat/cache.c b/fs/exfat/cache.c new file mode 100644 index 000000000000..03d0824fc368 --- /dev/null +++ b/fs/exfat/cache.c @@ -0,0 +1,325 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * linux/fs/fat/cache.c + * + * Written 1992,1993 by Werner Almesberger + * + * Mar 1999. AV. Changed cache, so that it uses the starting cluster instead + * of inode number. + * May 1999. AV. Fixed the bogosity with FAT32 (read "FAT28"). Fscking lusers. + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +#define EXFAT_CACHE_VALID 0 +#define EXFAT_MAX_CACHE 16 + +struct exfat_cache { + struct list_head cache_list; + unsigned int nr_contig; /* number of contiguous clusters */ + unsigned int fcluster; /* cluster number in the file. */ + unsigned int dcluster; /* cluster number on disk. */ +}; + +struct exfat_cache_id { + unsigned int id; + unsigned int nr_contig; + unsigned int fcluster; + unsigned int dcluster; +}; + +static struct kmem_cache *exfat_cachep; + +static void exfat_cache_init_once(void *c) +{ + struct exfat_cache *cache = (struct exfat_cache *)c; + + INIT_LIST_HEAD(&cache->cache_list); +} + +int exfat_cache_init(void) +{ + exfat_cachep = kmem_cache_create("exfat_cache", + sizeof(struct exfat_cache), + 0, SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, + exfat_cache_init_once); + if (!exfat_cachep) + return -ENOMEM; + return 0; +} + +void exfat_cache_shutdown(void) +{ + if (!exfat_cachep) + return; + kmem_cache_destroy(exfat_cachep); +} + +void exfat_cache_init_inode(struct inode *inode) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + + spin_lock_init(&ei->cache_lru_lock); + ei->nr_caches = 0; + ei->cache_valid_id = EXFAT_CACHE_VALID + 1; + INIT_LIST_HEAD(&ei->cache_lru); +} + +static inline struct exfat_cache *exfat_cache_alloc(void) +{ + return kmem_cache_alloc(exfat_cachep, GFP_NOFS); +} + +static inline void exfat_cache_free(struct exfat_cache *cache) +{ + WARN_ON(!list_empty(&cache->cache_list)); + kmem_cache_free(exfat_cachep, cache); +} + +static inline void exfat_cache_update_lru(struct inode *inode, + struct exfat_cache *cache) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + + if (ei->cache_lru.next != &cache->cache_list) + list_move(&cache->cache_list, &ei->cache_lru); +} + +static unsigned int exfat_cache_lookup(struct inode *inode, + unsigned int fclus, struct exfat_cache_id *cid, + unsigned int *cached_fclus, unsigned int *cached_dclus) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + static struct exfat_cache nohit = { .fcluster = 0, }; + struct exfat_cache *hit = &nohit, *p; + unsigned int offset = EXFAT_EOF_CLUSTER; + + spin_lock(&ei->cache_lru_lock); + list_for_each_entry(p, &ei->cache_lru, cache_list) { + /* Find the cache of "fclus" or nearest cache. */ + if (p->fcluster <= fclus && hit->fcluster < p->fcluster) { + hit = p; + if (hit->fcluster + hit->nr_contig < fclus) { + offset = hit->nr_contig; + } else { + offset = fclus - hit->fcluster; + break; + } + } + } + if (hit != &nohit) { + exfat_cache_update_lru(inode, hit); + + cid->id = ei->cache_valid_id; + cid->nr_contig = hit->nr_contig; + cid->fcluster = hit->fcluster; + cid->dcluster = hit->dcluster; + *cached_fclus = cid->fcluster + offset; + *cached_dclus = cid->dcluster + offset; + } + spin_unlock(&ei->cache_lru_lock); + + return offset; +} + +static struct exfat_cache *exfat_cache_merge(struct inode *inode, + struct exfat_cache_id *new) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + struct exfat_cache *p; + + list_for_each_entry(p, &ei->cache_lru, cache_list) { + /* Find the same part as "new" in cluster-chain. */ + if (p->fcluster == new->fcluster) { + if (new->nr_contig > p->nr_contig) + p->nr_contig = new->nr_contig; + return p; + } + } + return NULL; +} + +static void exfat_cache_add(struct inode *inode, + struct exfat_cache_id *new) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + struct exfat_cache *cache, *tmp; + + if (new->fcluster == EXFAT_EOF_CLUSTER) /* dummy cache */ + return; + + spin_lock(&ei->cache_lru_lock); + if (new->id != EXFAT_CACHE_VALID && + new->id != ei->cache_valid_id) + goto unlock; /* this cache was invalidated */ + + cache = exfat_cache_merge(inode, new); + if (cache == NULL) { + if (ei->nr_caches < EXFAT_MAX_CACHE) { + ei->nr_caches++; + spin_unlock(&ei->cache_lru_lock); + + tmp = exfat_cache_alloc(); + if (!tmp) { + spin_lock(&ei->cache_lru_lock); + ei->nr_caches--; + spin_unlock(&ei->cache_lru_lock); + return; + } + + spin_lock(&ei->cache_lru_lock); + cache = exfat_cache_merge(inode, new); + if (cache != NULL) { + ei->nr_caches--; + exfat_cache_free(tmp); + goto out_update_lru; + } + cache = tmp; + } else { + struct list_head *p = ei->cache_lru.prev; + + cache = list_entry(p, + struct exfat_cache, cache_list); + } + cache->fcluster = new->fcluster; + cache->dcluster = new->dcluster; + cache->nr_contig = new->nr_contig; + } +out_update_lru: + exfat_cache_update_lru(inode, cache); +unlock: + spin_unlock(&ei->cache_lru_lock); +} + +/* + * Cache invalidation occurs rarely, thus the LRU chain is not updated. It + * fixes itself after a while. + */ +static void __exfat_cache_inval_inode(struct inode *inode) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + struct exfat_cache *cache; + + while (!list_empty(&ei->cache_lru)) { + cache = list_entry(ei->cache_lru.next, + struct exfat_cache, cache_list); + list_del_init(&cache->cache_list); + ei->nr_caches--; + exfat_cache_free(cache); + } + /* Update. The copy of caches before this id is discarded. */ + ei->cache_valid_id++; + if (ei->cache_valid_id == EXFAT_CACHE_VALID) + ei->cache_valid_id++; +} + +void exfat_cache_inval_inode(struct inode *inode) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + + spin_lock(&ei->cache_lru_lock); + __exfat_cache_inval_inode(inode); + spin_unlock(&ei->cache_lru_lock); +} + +static inline int cache_contiguous(struct exfat_cache_id *cid, + unsigned int dclus) +{ + cid->nr_contig++; + return cid->dcluster + cid->nr_contig == dclus; +} + +static inline void cache_init(struct exfat_cache_id *cid, + unsigned int fclus, unsigned int dclus) +{ + cid->id = EXFAT_CACHE_VALID; + cid->fcluster = fclus; + cid->dcluster = dclus; + cid->nr_contig = 0; +} + +int exfat_get_cluster(struct inode *inode, unsigned int cluster, + unsigned int *fclus, unsigned int *dclus, + unsigned int *last_dclus, int allow_eof) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + unsigned int limit = sbi->num_clusters; + struct exfat_inode_info *ei = EXFAT_I(inode); + struct exfat_cache_id cid; + unsigned int content; + + if (ei->start_clu == EXFAT_FREE_CLUSTER) { + exfat_fs_error(sb, + "invalid access to exfat cache (entry 0x%08x)", + ei->start_clu); + return -EIO; + } + + *fclus = 0; + *dclus = ei->start_clu; + *last_dclus = *dclus; + + /* + * Don`t use exfat_cache if zero offset or non-cluster allocation + */ + if (cluster == 0 || *dclus == EXFAT_EOF_CLUSTER) + return 0; + + cache_init(&cid, EXFAT_EOF_CLUSTER, EXFAT_EOF_CLUSTER); + + if (exfat_cache_lookup(inode, cluster, &cid, fclus, dclus) == + EXFAT_EOF_CLUSTER) { + /* + * dummy, always not contiguous + * This is reinitialized by cache_init(), later. + */ + WARN_ON(cid.id != EXFAT_CACHE_VALID || + cid.fcluster != EXFAT_EOF_CLUSTER || + cid.dcluster != EXFAT_EOF_CLUSTER || + cid.nr_contig != 0); + } + + if (*fclus == cluster) + return 0; + + while (*fclus < cluster) { + /* prevent the infinite loop of cluster chain */ + if (*fclus > limit) { + exfat_fs_error(sb, + "detected the cluster chain loop (i_pos %u)", + (*fclus)); + return -EIO; + } + + if (exfat_ent_get(sb, *dclus, &content)) + return -EIO; + + *last_dclus = *dclus; + *dclus = content; + (*fclus)++; + + if (content == EXFAT_EOF_CLUSTER) { + if (!allow_eof) { + exfat_fs_error(sb, + "invalid cluster chain (i_pos %u, last_clus 0x%08x is EOF)", + *fclus, (*last_dclus)); + return -EIO; + } + + break; + } + + if (!cache_contiguous(&cid, *dclus)) + cache_init(&cid, *fclus, *dclus); + } + + exfat_cache_add(inode, &cid); + return 0; +} From 772b29cca528fcb21374bb3e597d848779938d16 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:40 +0900 Subject: [PATCH 1221/4444] exfat: add misc operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of misc operations for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Arnd Bergmann Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/exfat/misc.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 fs/exfat/misc.c diff --git a/fs/exfat/misc.c b/fs/exfat/misc.c new file mode 100644 index 000000000000..14a3300848f6 --- /dev/null +++ b/fs/exfat/misc.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Written 1992,1993 by Werner Almesberger + * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980 + * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru) + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +/* + * exfat_fs_error reports a file system problem that might indicate fa data + * corruption/inconsistency. Depending on 'errors' mount option the + * panic() is called, or error message is printed FAT and nothing is done, + * or filesystem is remounted read-only (default behavior). + * In case the file system is remounted read-only, it can be made writable + * again by remounting it. + */ +void __exfat_fs_error(struct super_block *sb, int report, const char *fmt, ...) +{ + struct exfat_mount_options *opts = &EXFAT_SB(sb)->options; + va_list args; + struct va_format vaf; + + if (report) { + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + exfat_msg(sb, KERN_ERR, "error, %pV\n", &vaf); + va_end(args); + } + + if (opts->errors == EXFAT_ERRORS_PANIC) { + panic("exFAT-fs (%s): fs panic from previous error\n", + sb->s_id); + } else if (opts->errors == EXFAT_ERRORS_RO && !sb_rdonly(sb)) { + sb->s_flags |= SB_RDONLY; + exfat_msg(sb, KERN_ERR, "Filesystem has been set read-only"); + } +} + +/* + * exfat_msg() - print preformated EXFAT specific messages. + * All logs except what uses exfat_fs_error() should be written by exfat_msg() + */ +void exfat_msg(struct super_block *sb, const char *level, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + /* level means KERN_ pacility level */ + printk("%sexFAT-fs (%s): %pV\n", level, sb->s_id, &vaf); + va_end(args); +} + +#define SECS_PER_MIN (60) +#define TIMEZONE_SEC(x) ((x) * 15 * SECS_PER_MIN) + +static void exfat_adjust_tz(struct timespec64 *ts, u8 tz_off) +{ + if (tz_off <= 0x3F) + ts->tv_sec -= TIMEZONE_SEC(tz_off); + else /* 0x40 <= (tz_off & 0x7F) <=0x7F */ + ts->tv_sec += TIMEZONE_SEC(0x80 - tz_off); +} + +/* Convert a EXFAT time/date pair to a UNIX date (seconds since 1 1 70). */ +void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, + u8 tz, __le16 time, __le16 date, u8 time_ms) +{ + u16 t = le16_to_cpu(time); + u16 d = le16_to_cpu(date); + + ts->tv_sec = mktime64(1980 + (d >> 9), d >> 5 & 0x000F, d & 0x001F, + t >> 11, (t >> 5) & 0x003F, (t & 0x001F) << 1); + + + /* time_ms field represent 0 ~ 199(1990 ms) */ + if (time_ms) { + ts->tv_sec += time_ms / 100; + ts->tv_nsec = (time_ms % 100) * 10 * NSEC_PER_MSEC; + } + + if (tz & EXFAT_TZ_VALID) + /* Adjust timezone to UTC0. */ + exfat_adjust_tz(ts, tz & ~EXFAT_TZ_VALID); + else + /* Convert from local time to UTC using time_offset. */ + ts->tv_sec -= sbi->options.time_offset * SECS_PER_MIN; +} + +/* Convert linear UNIX date to a EXFAT time/date pair. */ +void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, + u8 *tz, __le16 *time, __le16 *date, u8 *time_ms) +{ + struct tm tm; + u16 t, d; + + time64_to_tm(ts->tv_sec, 0, &tm); + t = (tm.tm_hour << 11) | (tm.tm_min << 5) | (tm.tm_sec >> 1); + d = ((tm.tm_year - 80) << 9) | ((tm.tm_mon + 1) << 5) | tm.tm_mday; + + *time = cpu_to_le16(t); + *date = cpu_to_le16(d); + + /* time_ms field represent 0 ~ 199(1990 ms) */ + if (time_ms) + *time_ms = (tm.tm_sec & 1) * 100 + + ts->tv_nsec / (10 * NSEC_PER_MSEC); + + /* + * Record 00h value for OffsetFromUtc field and 1 value for OffsetValid + * to indicate that local time and UTC are the same. + */ + *tz = EXFAT_TZ_VALID; +} + +unsigned short exfat_calc_chksum_2byte(void *data, int len, + unsigned short chksum, int type) +{ + int i; + unsigned char *c = (unsigned char *)data; + + for (i = 0; i < len; i++, c++) { + if (((i == 2) || (i == 3)) && (type == CS_DIR_ENTRY)) + continue; + chksum = (((chksum & 1) << 15) | ((chksum & 0xFFFE) >> 1)) + + (unsigned short)*c; + } + return chksum; +} + +void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int sync) +{ + set_bit(EXFAT_SB_DIRTY, &EXFAT_SB(sb)->s_state); + set_buffer_uptodate(bh); + mark_buffer_dirty(bh); + + if (sync) + sync_dirty_buffer(bh); +} + +void exfat_chain_set(struct exfat_chain *ec, unsigned int dir, + unsigned int size, unsigned char flags) +{ + ec->dir = dir; + ec->size = size; + ec->flags = flags; +} + +void exfat_chain_dup(struct exfat_chain *dup, struct exfat_chain *ec) +{ + return exfat_chain_set(dup, ec->dir, ec->size, ec->flags); +} From 370e812b3ec190fa492c9fd5a80c38b086d105c0 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:41 +0900 Subject: [PATCH 1222/4444] exfat: add nls operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the implementation of nls operations for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/exfat/nls.c | 831 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 831 insertions(+) create mode 100644 fs/exfat/nls.c diff --git a/fs/exfat/nls.c b/fs/exfat/nls.c new file mode 100644 index 000000000000..6d1c3ae130ff --- /dev/null +++ b/fs/exfat/nls.c @@ -0,0 +1,831 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include +#include + +#include "exfat_raw.h" +#include "exfat_fs.h" + +/* Upcase tabel macro */ +#define EXFAT_NUM_UPCASE (2918) +#define UTBL_COUNT (0x10000) + +/* + * Upcase table in compressed format (7.2.5.1 Recommended Up-case Table + * in exfat specification, See: + * https://docs.microsoft.com/en-us/windows/win32/fileio/exfat-specification). + */ +static const unsigned short uni_def_upcase[EXFAT_NUM_UPCASE] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, + 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, + 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00f7, + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x0178, + 0x0100, 0x0100, 0x0102, 0x0102, 0x0104, 0x0104, 0x0106, 0x0106, + 0x0108, 0x0108, 0x010a, 0x010a, 0x010c, 0x010c, 0x010e, 0x010e, + 0x0110, 0x0110, 0x0112, 0x0112, 0x0114, 0x0114, 0x0116, 0x0116, + 0x0118, 0x0118, 0x011a, 0x011a, 0x011c, 0x011c, 0x011e, 0x011e, + 0x0120, 0x0120, 0x0122, 0x0122, 0x0124, 0x0124, 0x0126, 0x0126, + 0x0128, 0x0128, 0x012a, 0x012a, 0x012c, 0x012c, 0x012e, 0x012e, + 0x0130, 0x0131, 0x0132, 0x0132, 0x0134, 0x0134, 0x0136, 0x0136, + 0x0138, 0x0139, 0x0139, 0x013b, 0x013b, 0x013d, 0x013d, 0x013f, + 0x013f, 0x0141, 0x0141, 0x0143, 0x0143, 0x0145, 0x0145, 0x0147, + 0x0147, 0x0149, 0x014a, 0x014a, 0x014c, 0x014c, 0x014e, 0x014e, + 0x0150, 0x0150, 0x0152, 0x0152, 0x0154, 0x0154, 0x0156, 0x0156, + 0x0158, 0x0158, 0x015a, 0x015a, 0x015c, 0x015c, 0x015e, 0x015e, + 0x0160, 0x0160, 0x0162, 0x0162, 0x0164, 0x0164, 0x0166, 0x0166, + 0x0168, 0x0168, 0x016a, 0x016a, 0x016c, 0x016c, 0x016e, 0x016e, + 0x0170, 0x0170, 0x0172, 0x0172, 0x0174, 0x0174, 0x0176, 0x0176, + 0x0178, 0x0179, 0x0179, 0x017b, 0x017b, 0x017d, 0x017d, 0x017f, + 0x0243, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187, + 0x0187, 0x0189, 0x018a, 0x018b, 0x018b, 0x018d, 0x018e, 0x018f, + 0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01f6, 0x0196, 0x0197, + 0x0198, 0x0198, 0x023d, 0x019b, 0x019c, 0x019d, 0x0220, 0x019f, + 0x01a0, 0x01a0, 0x01a2, 0x01a2, 0x01a4, 0x01a4, 0x01a6, 0x01a7, + 0x01a7, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ac, 0x01ae, 0x01af, + 0x01af, 0x01b1, 0x01b2, 0x01b3, 0x01b3, 0x01b5, 0x01b5, 0x01b7, + 0x01b8, 0x01b8, 0x01ba, 0x01bb, 0x01bc, 0x01bc, 0x01be, 0x01f7, + 0x01c0, 0x01c1, 0x01c2, 0x01c3, 0x01c4, 0x01c5, 0x01c4, 0x01c7, + 0x01c8, 0x01c7, 0x01ca, 0x01cb, 0x01ca, 0x01cd, 0x01cd, 0x01cf, + 0x01cf, 0x01d1, 0x01d1, 0x01d3, 0x01d3, 0x01d5, 0x01d5, 0x01d7, + 0x01d7, 0x01d9, 0x01d9, 0x01db, 0x01db, 0x018e, 0x01de, 0x01de, + 0x01e0, 0x01e0, 0x01e2, 0x01e2, 0x01e4, 0x01e4, 0x01e6, 0x01e6, + 0x01e8, 0x01e8, 0x01ea, 0x01ea, 0x01ec, 0x01ec, 0x01ee, 0x01ee, + 0x01f0, 0x01f1, 0x01f2, 0x01f1, 0x01f4, 0x01f4, 0x01f6, 0x01f7, + 0x01f8, 0x01f8, 0x01fa, 0x01fa, 0x01fc, 0x01fc, 0x01fe, 0x01fe, + 0x0200, 0x0200, 0x0202, 0x0202, 0x0204, 0x0204, 0x0206, 0x0206, + 0x0208, 0x0208, 0x020a, 0x020a, 0x020c, 0x020c, 0x020e, 0x020e, + 0x0210, 0x0210, 0x0212, 0x0212, 0x0214, 0x0214, 0x0216, 0x0216, + 0x0218, 0x0218, 0x021a, 0x021a, 0x021c, 0x021c, 0x021e, 0x021e, + 0x0220, 0x0221, 0x0222, 0x0222, 0x0224, 0x0224, 0x0226, 0x0226, + 0x0228, 0x0228, 0x022a, 0x022a, 0x022c, 0x022c, 0x022e, 0x022e, + 0x0230, 0x0230, 0x0232, 0x0232, 0x0234, 0x0235, 0x0236, 0x0237, + 0x0238, 0x0239, 0x2c65, 0x023b, 0x023b, 0x023d, 0x2c66, 0x023f, + 0x0240, 0x0241, 0x0241, 0x0243, 0x0244, 0x0245, 0x0246, 0x0246, + 0x0248, 0x0248, 0x024a, 0x024a, 0x024c, 0x024c, 0x024e, 0x024e, + 0x0250, 0x0251, 0x0252, 0x0181, 0x0186, 0x0255, 0x0189, 0x018a, + 0x0258, 0x018f, 0x025a, 0x0190, 0x025c, 0x025d, 0x025e, 0x025f, + 0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267, + 0x0197, 0x0196, 0x026a, 0x2c62, 0x026c, 0x026d, 0x026e, 0x019c, + 0x0270, 0x0271, 0x019d, 0x0273, 0x0274, 0x019f, 0x0276, 0x0277, + 0x0278, 0x0279, 0x027a, 0x027b, 0x027c, 0x2c64, 0x027e, 0x027f, + 0x01a6, 0x0281, 0x0282, 0x01a9, 0x0284, 0x0285, 0x0286, 0x0287, + 0x01ae, 0x0244, 0x01b1, 0x01b2, 0x0245, 0x028d, 0x028e, 0x028f, + 0x0290, 0x0291, 0x01b7, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297, + 0x0298, 0x0299, 0x029a, 0x029b, 0x029c, 0x029d, 0x029e, 0x029f, + 0x02a0, 0x02a1, 0x02a2, 0x02a3, 0x02a4, 0x02a5, 0x02a6, 0x02a7, + 0x02a8, 0x02a9, 0x02aa, 0x02ab, 0x02ac, 0x02ad, 0x02ae, 0x02af, + 0x02b0, 0x02b1, 0x02b2, 0x02b3, 0x02b4, 0x02b5, 0x02b6, 0x02b7, + 0x02b8, 0x02b9, 0x02ba, 0x02bb, 0x02bc, 0x02bd, 0x02be, 0x02bf, + 0x02c0, 0x02c1, 0x02c2, 0x02c3, 0x02c4, 0x02c5, 0x02c6, 0x02c7, + 0x02c8, 0x02c9, 0x02ca, 0x02cb, 0x02cc, 0x02cd, 0x02ce, 0x02cf, + 0x02d0, 0x02d1, 0x02d2, 0x02d3, 0x02d4, 0x02d5, 0x02d6, 0x02d7, + 0x02d8, 0x02d9, 0x02da, 0x02db, 0x02dc, 0x02dd, 0x02de, 0x02df, + 0x02e0, 0x02e1, 0x02e2, 0x02e3, 0x02e4, 0x02e5, 0x02e6, 0x02e7, + 0x02e8, 0x02e9, 0x02ea, 0x02eb, 0x02ec, 0x02ed, 0x02ee, 0x02ef, + 0x02f0, 0x02f1, 0x02f2, 0x02f3, 0x02f4, 0x02f5, 0x02f6, 0x02f7, + 0x02f8, 0x02f9, 0x02fa, 0x02fb, 0x02fc, 0x02fd, 0x02fe, 0x02ff, + 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, + 0x0308, 0x0309, 0x030a, 0x030b, 0x030c, 0x030d, 0x030e, 0x030f, + 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, + 0x0318, 0x0319, 0x031a, 0x031b, 0x031c, 0x031d, 0x031e, 0x031f, + 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, + 0x0328, 0x0329, 0x032a, 0x032b, 0x032c, 0x032d, 0x032e, 0x032f, + 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, + 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, 0x033d, 0x033e, 0x033f, + 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347, + 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, 0x034d, 0x034e, 0x034f, + 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, + 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, 0x035d, 0x035e, 0x035f, + 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, + 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f, + 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377, + 0x0378, 0x0379, 0x037a, 0x03fd, 0x03fe, 0x03ff, 0x037e, 0x037f, + 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387, + 0x0388, 0x0389, 0x038a, 0x038b, 0x038c, 0x038d, 0x038e, 0x038f, + 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, + 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, + 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x0386, 0x0388, 0x0389, 0x038a, + 0x03b0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, + 0x03a0, 0x03a1, 0x03a3, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, + 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x038c, 0x038e, 0x038f, 0x03cf, + 0x03d0, 0x03d1, 0x03d2, 0x03d3, 0x03d4, 0x03d5, 0x03d6, 0x03d7, + 0x03d8, 0x03d8, 0x03da, 0x03da, 0x03dc, 0x03dc, 0x03de, 0x03de, + 0x03e0, 0x03e0, 0x03e2, 0x03e2, 0x03e4, 0x03e4, 0x03e6, 0x03e6, + 0x03e8, 0x03e8, 0x03ea, 0x03ea, 0x03ec, 0x03ec, 0x03ee, 0x03ee, + 0x03f0, 0x03f1, 0x03f9, 0x03f3, 0x03f4, 0x03f5, 0x03f6, 0x03f7, + 0x03f7, 0x03f9, 0x03fa, 0x03fa, 0x03fc, 0x03fd, 0x03fe, 0x03ff, + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, + 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x040d, 0x040e, 0x040f, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, + 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x040d, 0x040e, 0x040f, + 0x0460, 0x0460, 0x0462, 0x0462, 0x0464, 0x0464, 0x0466, 0x0466, + 0x0468, 0x0468, 0x046a, 0x046a, 0x046c, 0x046c, 0x046e, 0x046e, + 0x0470, 0x0470, 0x0472, 0x0472, 0x0474, 0x0474, 0x0476, 0x0476, + 0x0478, 0x0478, 0x047a, 0x047a, 0x047c, 0x047c, 0x047e, 0x047e, + 0x0480, 0x0480, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, + 0x0488, 0x0489, 0x048a, 0x048a, 0x048c, 0x048c, 0x048e, 0x048e, + 0x0490, 0x0490, 0x0492, 0x0492, 0x0494, 0x0494, 0x0496, 0x0496, + 0x0498, 0x0498, 0x049a, 0x049a, 0x049c, 0x049c, 0x049e, 0x049e, + 0x04a0, 0x04a0, 0x04a2, 0x04a2, 0x04a4, 0x04a4, 0x04a6, 0x04a6, + 0x04a8, 0x04a8, 0x04aa, 0x04aa, 0x04ac, 0x04ac, 0x04ae, 0x04ae, + 0x04b0, 0x04b0, 0x04b2, 0x04b2, 0x04b4, 0x04b4, 0x04b6, 0x04b6, + 0x04b8, 0x04b8, 0x04ba, 0x04ba, 0x04bc, 0x04bc, 0x04be, 0x04be, + 0x04c0, 0x04c1, 0x04c1, 0x04c3, 0x04c3, 0x04c5, 0x04c5, 0x04c7, + 0x04c7, 0x04c9, 0x04c9, 0x04cb, 0x04cb, 0x04cd, 0x04cd, 0x04c0, + 0x04d0, 0x04d0, 0x04d2, 0x04d2, 0x04d4, 0x04d4, 0x04d6, 0x04d6, + 0x04d8, 0x04d8, 0x04da, 0x04da, 0x04dc, 0x04dc, 0x04de, 0x04de, + 0x04e0, 0x04e0, 0x04e2, 0x04e2, 0x04e4, 0x04e4, 0x04e6, 0x04e6, + 0x04e8, 0x04e8, 0x04ea, 0x04ea, 0x04ec, 0x04ec, 0x04ee, 0x04ee, + 0x04f0, 0x04f0, 0x04f2, 0x04f2, 0x04f4, 0x04f4, 0x04f6, 0x04f6, + 0x04f8, 0x04f8, 0x04fa, 0x04fa, 0x04fc, 0x04fc, 0x04fe, 0x04fe, + 0x0500, 0x0500, 0x0502, 0x0502, 0x0504, 0x0504, 0x0506, 0x0506, + 0x0508, 0x0508, 0x050a, 0x050a, 0x050c, 0x050c, 0x050e, 0x050e, + 0x0510, 0x0510, 0x0512, 0x0512, 0x0514, 0x0515, 0x0516, 0x0517, + 0x0518, 0x0519, 0x051a, 0x051b, 0x051c, 0x051d, 0x051e, 0x051f, + 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527, + 0x0528, 0x0529, 0x052a, 0x052b, 0x052c, 0x052d, 0x052e, 0x052f, + 0x0530, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537, + 0x0538, 0x0539, 0x053a, 0x053b, 0x053c, 0x053d, 0x053e, 0x053f, + 0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547, + 0x0548, 0x0549, 0x054a, 0x054b, 0x054c, 0x054d, 0x054e, 0x054f, + 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0557, + 0x0558, 0x0559, 0x055a, 0x055b, 0x055c, 0x055d, 0x055e, 0x055f, + 0x0560, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537, + 0x0538, 0x0539, 0x053a, 0x053b, 0x053c, 0x053d, 0x053e, 0x053f, + 0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547, + 0x0548, 0x0549, 0x054a, 0x054b, 0x054c, 0x054d, 0x054e, 0x054f, + 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0xffff, + 0x17f6, 0x2c63, 0x1d7e, 0x1d7f, 0x1d80, 0x1d81, 0x1d82, 0x1d83, + 0x1d84, 0x1d85, 0x1d86, 0x1d87, 0x1d88, 0x1d89, 0x1d8a, 0x1d8b, + 0x1d8c, 0x1d8d, 0x1d8e, 0x1d8f, 0x1d90, 0x1d91, 0x1d92, 0x1d93, + 0x1d94, 0x1d95, 0x1d96, 0x1d97, 0x1d98, 0x1d99, 0x1d9a, 0x1d9b, + 0x1d9c, 0x1d9d, 0x1d9e, 0x1d9f, 0x1da0, 0x1da1, 0x1da2, 0x1da3, + 0x1da4, 0x1da5, 0x1da6, 0x1da7, 0x1da8, 0x1da9, 0x1daa, 0x1dab, + 0x1dac, 0x1dad, 0x1dae, 0x1daf, 0x1db0, 0x1db1, 0x1db2, 0x1db3, + 0x1db4, 0x1db5, 0x1db6, 0x1db7, 0x1db8, 0x1db9, 0x1dba, 0x1dbb, + 0x1dbc, 0x1dbd, 0x1dbe, 0x1dbf, 0x1dc0, 0x1dc1, 0x1dc2, 0x1dc3, + 0x1dc4, 0x1dc5, 0x1dc6, 0x1dc7, 0x1dc8, 0x1dc9, 0x1dca, 0x1dcb, + 0x1dcc, 0x1dcd, 0x1dce, 0x1dcf, 0x1dd0, 0x1dd1, 0x1dd2, 0x1dd3, + 0x1dd4, 0x1dd5, 0x1dd6, 0x1dd7, 0x1dd8, 0x1dd9, 0x1dda, 0x1ddb, + 0x1ddc, 0x1ddd, 0x1dde, 0x1ddf, 0x1de0, 0x1de1, 0x1de2, 0x1de3, + 0x1de4, 0x1de5, 0x1de6, 0x1de7, 0x1de8, 0x1de9, 0x1dea, 0x1deb, + 0x1dec, 0x1ded, 0x1dee, 0x1def, 0x1df0, 0x1df1, 0x1df2, 0x1df3, + 0x1df4, 0x1df5, 0x1df6, 0x1df7, 0x1df8, 0x1df9, 0x1dfa, 0x1dfb, + 0x1dfc, 0x1dfd, 0x1dfe, 0x1dff, 0x1e00, 0x1e00, 0x1e02, 0x1e02, + 0x1e04, 0x1e04, 0x1e06, 0x1e06, 0x1e08, 0x1e08, 0x1e0a, 0x1e0a, + 0x1e0c, 0x1e0c, 0x1e0e, 0x1e0e, 0x1e10, 0x1e10, 0x1e12, 0x1e12, + 0x1e14, 0x1e14, 0x1e16, 0x1e16, 0x1e18, 0x1e18, 0x1e1a, 0x1e1a, + 0x1e1c, 0x1e1c, 0x1e1e, 0x1e1e, 0x1e20, 0x1e20, 0x1e22, 0x1e22, + 0x1e24, 0x1e24, 0x1e26, 0x1e26, 0x1e28, 0x1e28, 0x1e2a, 0x1e2a, + 0x1e2c, 0x1e2c, 0x1e2e, 0x1e2e, 0x1e30, 0x1e30, 0x1e32, 0x1e32, + 0x1e34, 0x1e34, 0x1e36, 0x1e36, 0x1e38, 0x1e38, 0x1e3a, 0x1e3a, + 0x1e3c, 0x1e3c, 0x1e3e, 0x1e3e, 0x1e40, 0x1e40, 0x1e42, 0x1e42, + 0x1e44, 0x1e44, 0x1e46, 0x1e46, 0x1e48, 0x1e48, 0x1e4a, 0x1e4a, + 0x1e4c, 0x1e4c, 0x1e4e, 0x1e4e, 0x1e50, 0x1e50, 0x1e52, 0x1e52, + 0x1e54, 0x1e54, 0x1e56, 0x1e56, 0x1e58, 0x1e58, 0x1e5a, 0x1e5a, + 0x1e5c, 0x1e5c, 0x1e5e, 0x1e5e, 0x1e60, 0x1e60, 0x1e62, 0x1e62, + 0x1e64, 0x1e64, 0x1e66, 0x1e66, 0x1e68, 0x1e68, 0x1e6a, 0x1e6a, + 0x1e6c, 0x1e6c, 0x1e6e, 0x1e6e, 0x1e70, 0x1e70, 0x1e72, 0x1e72, + 0x1e74, 0x1e74, 0x1e76, 0x1e76, 0x1e78, 0x1e78, 0x1e7a, 0x1e7a, + 0x1e7c, 0x1e7c, 0x1e7e, 0x1e7e, 0x1e80, 0x1e80, 0x1e82, 0x1e82, + 0x1e84, 0x1e84, 0x1e86, 0x1e86, 0x1e88, 0x1e88, 0x1e8a, 0x1e8a, + 0x1e8c, 0x1e8c, 0x1e8e, 0x1e8e, 0x1e90, 0x1e90, 0x1e92, 0x1e92, + 0x1e94, 0x1e94, 0x1e96, 0x1e97, 0x1e98, 0x1e99, 0x1e9a, 0x1e9b, + 0x1e9c, 0x1e9d, 0x1e9e, 0x1e9f, 0x1ea0, 0x1ea0, 0x1ea2, 0x1ea2, + 0x1ea4, 0x1ea4, 0x1ea6, 0x1ea6, 0x1ea8, 0x1ea8, 0x1eaa, 0x1eaa, + 0x1eac, 0x1eac, 0x1eae, 0x1eae, 0x1eb0, 0x1eb0, 0x1eb2, 0x1eb2, + 0x1eb4, 0x1eb4, 0x1eb6, 0x1eb6, 0x1eb8, 0x1eb8, 0x1eba, 0x1eba, + 0x1ebc, 0x1ebc, 0x1ebe, 0x1ebe, 0x1ec0, 0x1ec0, 0x1ec2, 0x1ec2, + 0x1ec4, 0x1ec4, 0x1ec6, 0x1ec6, 0x1ec8, 0x1ec8, 0x1eca, 0x1eca, + 0x1ecc, 0x1ecc, 0x1ece, 0x1ece, 0x1ed0, 0x1ed0, 0x1ed2, 0x1ed2, + 0x1ed4, 0x1ed4, 0x1ed6, 0x1ed6, 0x1ed8, 0x1ed8, 0x1eda, 0x1eda, + 0x1edc, 0x1edc, 0x1ede, 0x1ede, 0x1ee0, 0x1ee0, 0x1ee2, 0x1ee2, + 0x1ee4, 0x1ee4, 0x1ee6, 0x1ee6, 0x1ee8, 0x1ee8, 0x1eea, 0x1eea, + 0x1eec, 0x1eec, 0x1eee, 0x1eee, 0x1ef0, 0x1ef0, 0x1ef2, 0x1ef2, + 0x1ef4, 0x1ef4, 0x1ef6, 0x1ef6, 0x1ef8, 0x1ef8, 0x1efa, 0x1efb, + 0x1efc, 0x1efd, 0x1efe, 0x1eff, 0x1f08, 0x1f09, 0x1f0a, 0x1f0b, + 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f, 0x1f08, 0x1f09, 0x1f0a, 0x1f0b, + 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f, 0x1f18, 0x1f19, 0x1f1a, 0x1f1b, + 0x1f1c, 0x1f1d, 0x1f16, 0x1f17, 0x1f18, 0x1f19, 0x1f1a, 0x1f1b, + 0x1f1c, 0x1f1d, 0x1f1e, 0x1f1f, 0x1f28, 0x1f29, 0x1f2a, 0x1f2b, + 0x1f2c, 0x1f2d, 0x1f2e, 0x1f2f, 0x1f28, 0x1f29, 0x1f2a, 0x1f2b, + 0x1f2c, 0x1f2d, 0x1f2e, 0x1f2f, 0x1f38, 0x1f39, 0x1f3a, 0x1f3b, + 0x1f3c, 0x1f3d, 0x1f3e, 0x1f3f, 0x1f38, 0x1f39, 0x1f3a, 0x1f3b, + 0x1f3c, 0x1f3d, 0x1f3e, 0x1f3f, 0x1f48, 0x1f49, 0x1f4a, 0x1f4b, + 0x1f4c, 0x1f4d, 0x1f46, 0x1f47, 0x1f48, 0x1f49, 0x1f4a, 0x1f4b, + 0x1f4c, 0x1f4d, 0x1f4e, 0x1f4f, 0x1f50, 0x1f59, 0x1f52, 0x1f5b, + 0x1f54, 0x1f5d, 0x1f56, 0x1f5f, 0x1f58, 0x1f59, 0x1f5a, 0x1f5b, + 0x1f5c, 0x1f5d, 0x1f5e, 0x1f5f, 0x1f68, 0x1f69, 0x1f6a, 0x1f6b, + 0x1f6c, 0x1f6d, 0x1f6e, 0x1f6f, 0x1f68, 0x1f69, 0x1f6a, 0x1f6b, + 0x1f6c, 0x1f6d, 0x1f6e, 0x1f6f, 0x1fba, 0x1fbb, 0x1fc8, 0x1fc9, + 0x1fca, 0x1fcb, 0x1fda, 0x1fdb, 0x1ff8, 0x1ff9, 0x1fea, 0x1feb, + 0x1ffa, 0x1ffb, 0x1f7e, 0x1f7f, 0x1f88, 0x1f89, 0x1f8a, 0x1f8b, + 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f, 0x1f88, 0x1f89, 0x1f8a, 0x1f8b, + 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f, 0x1f98, 0x1f99, 0x1f9a, 0x1f9b, + 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, 0x1f98, 0x1f99, 0x1f9a, 0x1f9b, + 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, 0x1fa8, 0x1fa9, 0x1faa, 0x1fab, + 0x1fac, 0x1fad, 0x1fae, 0x1faf, 0x1fa8, 0x1fa9, 0x1faa, 0x1fab, + 0x1fac, 0x1fad, 0x1fae, 0x1faf, 0x1fb8, 0x1fb9, 0x1fb2, 0x1fbc, + 0x1fb4, 0x1fb5, 0x1fb6, 0x1fb7, 0x1fb8, 0x1fb9, 0x1fba, 0x1fbb, + 0x1fbc, 0x1fbd, 0x1fbe, 0x1fbf, 0x1fc0, 0x1fc1, 0x1fc2, 0x1fc3, + 0x1fc4, 0x1fc5, 0x1fc6, 0x1fc7, 0x1fc8, 0x1fc9, 0x1fca, 0x1fcb, + 0x1fc3, 0x1fcd, 0x1fce, 0x1fcf, 0x1fd8, 0x1fd9, 0x1fd2, 0x1fd3, + 0x1fd4, 0x1fd5, 0x1fd6, 0x1fd7, 0x1fd8, 0x1fd9, 0x1fda, 0x1fdb, + 0x1fdc, 0x1fdd, 0x1fde, 0x1fdf, 0x1fe8, 0x1fe9, 0x1fe2, 0x1fe3, + 0x1fe4, 0x1fec, 0x1fe6, 0x1fe7, 0x1fe8, 0x1fe9, 0x1fea, 0x1feb, + 0x1fec, 0x1fed, 0x1fee, 0x1fef, 0x1ff0, 0x1ff1, 0x1ff2, 0x1ff3, + 0x1ff4, 0x1ff5, 0x1ff6, 0x1ff7, 0x1ff8, 0x1ff9, 0x1ffa, 0x1ffb, + 0x1ff3, 0x1ffd, 0x1ffe, 0x1fff, 0x2000, 0x2001, 0x2002, 0x2003, + 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200a, 0x200b, + 0x200c, 0x200d, 0x200e, 0x200f, 0x2010, 0x2011, 0x2012, 0x2013, + 0x2014, 0x2015, 0x2016, 0x2017, 0x2018, 0x2019, 0x201a, 0x201b, + 0x201c, 0x201d, 0x201e, 0x201f, 0x2020, 0x2021, 0x2022, 0x2023, + 0x2024, 0x2025, 0x2026, 0x2027, 0x2028, 0x2029, 0x202a, 0x202b, + 0x202c, 0x202d, 0x202e, 0x202f, 0x2030, 0x2031, 0x2032, 0x2033, + 0x2034, 0x2035, 0x2036, 0x2037, 0x2038, 0x2039, 0x203a, 0x203b, + 0x203c, 0x203d, 0x203e, 0x203f, 0x2040, 0x2041, 0x2042, 0x2043, + 0x2044, 0x2045, 0x2046, 0x2047, 0x2048, 0x2049, 0x204a, 0x204b, + 0x204c, 0x204d, 0x204e, 0x204f, 0x2050, 0x2051, 0x2052, 0x2053, + 0x2054, 0x2055, 0x2056, 0x2057, 0x2058, 0x2059, 0x205a, 0x205b, + 0x205c, 0x205d, 0x205e, 0x205f, 0x2060, 0x2061, 0x2062, 0x2063, + 0x2064, 0x2065, 0x2066, 0x2067, 0x2068, 0x2069, 0x206a, 0x206b, + 0x206c, 0x206d, 0x206e, 0x206f, 0x2070, 0x2071, 0x2072, 0x2073, + 0x2074, 0x2075, 0x2076, 0x2077, 0x2078, 0x2079, 0x207a, 0x207b, + 0x207c, 0x207d, 0x207e, 0x207f, 0x2080, 0x2081, 0x2082, 0x2083, + 0x2084, 0x2085, 0x2086, 0x2087, 0x2088, 0x2089, 0x208a, 0x208b, + 0x208c, 0x208d, 0x208e, 0x208f, 0x2090, 0x2091, 0x2092, 0x2093, + 0x2094, 0x2095, 0x2096, 0x2097, 0x2098, 0x2099, 0x209a, 0x209b, + 0x209c, 0x209d, 0x209e, 0x209f, 0x20a0, 0x20a1, 0x20a2, 0x20a3, + 0x20a4, 0x20a5, 0x20a6, 0x20a7, 0x20a8, 0x20a9, 0x20aa, 0x20ab, + 0x20ac, 0x20ad, 0x20ae, 0x20af, 0x20b0, 0x20b1, 0x20b2, 0x20b3, + 0x20b4, 0x20b5, 0x20b6, 0x20b7, 0x20b8, 0x20b9, 0x20ba, 0x20bb, + 0x20bc, 0x20bd, 0x20be, 0x20bf, 0x20c0, 0x20c1, 0x20c2, 0x20c3, + 0x20c4, 0x20c5, 0x20c6, 0x20c7, 0x20c8, 0x20c9, 0x20ca, 0x20cb, + 0x20cc, 0x20cd, 0x20ce, 0x20cf, 0x20d0, 0x20d1, 0x20d2, 0x20d3, + 0x20d4, 0x20d5, 0x20d6, 0x20d7, 0x20d8, 0x20d9, 0x20da, 0x20db, + 0x20dc, 0x20dd, 0x20de, 0x20df, 0x20e0, 0x20e1, 0x20e2, 0x20e3, + 0x20e4, 0x20e5, 0x20e6, 0x20e7, 0x20e8, 0x20e9, 0x20ea, 0x20eb, + 0x20ec, 0x20ed, 0x20ee, 0x20ef, 0x20f0, 0x20f1, 0x20f2, 0x20f3, + 0x20f4, 0x20f5, 0x20f6, 0x20f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, + 0x20fc, 0x20fd, 0x20fe, 0x20ff, 0x2100, 0x2101, 0x2102, 0x2103, + 0x2104, 0x2105, 0x2106, 0x2107, 0x2108, 0x2109, 0x210a, 0x210b, + 0x210c, 0x210d, 0x210e, 0x210f, 0x2110, 0x2111, 0x2112, 0x2113, + 0x2114, 0x2115, 0x2116, 0x2117, 0x2118, 0x2119, 0x211a, 0x211b, + 0x211c, 0x211d, 0x211e, 0x211f, 0x2120, 0x2121, 0x2122, 0x2123, + 0x2124, 0x2125, 0x2126, 0x2127, 0x2128, 0x2129, 0x212a, 0x212b, + 0x212c, 0x212d, 0x212e, 0x212f, 0x2130, 0x2131, 0x2132, 0x2133, + 0x2134, 0x2135, 0x2136, 0x2137, 0x2138, 0x2139, 0x213a, 0x213b, + 0x213c, 0x213d, 0x213e, 0x213f, 0x2140, 0x2141, 0x2142, 0x2143, + 0x2144, 0x2145, 0x2146, 0x2147, 0x2148, 0x2149, 0x214a, 0x214b, + 0x214c, 0x214d, 0x2132, 0x214f, 0x2150, 0x2151, 0x2152, 0x2153, + 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, 0x215b, + 0x215c, 0x215d, 0x215e, 0x215f, 0x2160, 0x2161, 0x2162, 0x2163, + 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216a, 0x216b, + 0x216c, 0x216d, 0x216e, 0x216f, 0x2160, 0x2161, 0x2162, 0x2163, + 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216a, 0x216b, + 0x216c, 0x216d, 0x216e, 0x216f, 0x2180, 0x2181, 0x2182, 0x2183, + 0x2183, 0xffff, 0x034b, 0x24b6, 0x24b7, 0x24b8, 0x24b9, 0x24ba, + 0x24bb, 0x24bc, 0x24bd, 0x24be, 0x24bf, 0x24c0, 0x24c1, 0x24c2, + 0x24c3, 0x24c4, 0x24c5, 0x24c6, 0x24c7, 0x24c8, 0x24c9, 0x24ca, + 0x24cb, 0x24cc, 0x24cd, 0x24ce, 0x24cf, 0xffff, 0x0746, 0x2c00, + 0x2c01, 0x2c02, 0x2c03, 0x2c04, 0x2c05, 0x2c06, 0x2c07, 0x2c08, + 0x2c09, 0x2c0a, 0x2c0b, 0x2c0c, 0x2c0d, 0x2c0e, 0x2c0f, 0x2c10, + 0x2c11, 0x2c12, 0x2c13, 0x2c14, 0x2c15, 0x2c16, 0x2c17, 0x2c18, + 0x2c19, 0x2c1a, 0x2c1b, 0x2c1c, 0x2c1d, 0x2c1e, 0x2c1f, 0x2c20, + 0x2c21, 0x2c22, 0x2c23, 0x2c24, 0x2c25, 0x2c26, 0x2c27, 0x2c28, + 0x2c29, 0x2c2a, 0x2c2b, 0x2c2c, 0x2c2d, 0x2c2e, 0x2c5f, 0x2c60, + 0x2c60, 0x2c62, 0x2c63, 0x2c64, 0x2c65, 0x2c66, 0x2c67, 0x2c67, + 0x2c69, 0x2c69, 0x2c6b, 0x2c6b, 0x2c6d, 0x2c6e, 0x2c6f, 0x2c70, + 0x2c71, 0x2c72, 0x2c73, 0x2c74, 0x2c75, 0x2c75, 0x2c77, 0x2c78, + 0x2c79, 0x2c7a, 0x2c7b, 0x2c7c, 0x2c7d, 0x2c7e, 0x2c7f, 0x2c80, + 0x2c80, 0x2c82, 0x2c82, 0x2c84, 0x2c84, 0x2c86, 0x2c86, 0x2c88, + 0x2c88, 0x2c8a, 0x2c8a, 0x2c8c, 0x2c8c, 0x2c8e, 0x2c8e, 0x2c90, + 0x2c90, 0x2c92, 0x2c92, 0x2c94, 0x2c94, 0x2c96, 0x2c96, 0x2c98, + 0x2c98, 0x2c9a, 0x2c9a, 0x2c9c, 0x2c9c, 0x2c9e, 0x2c9e, 0x2ca0, + 0x2ca0, 0x2ca2, 0x2ca2, 0x2ca4, 0x2ca4, 0x2ca6, 0x2ca6, 0x2ca8, + 0x2ca8, 0x2caa, 0x2caa, 0x2cac, 0x2cac, 0x2cae, 0x2cae, 0x2cb0, + 0x2cb0, 0x2cb2, 0x2cb2, 0x2cb4, 0x2cb4, 0x2cb6, 0x2cb6, 0x2cb8, + 0x2cb8, 0x2cba, 0x2cba, 0x2cbc, 0x2cbc, 0x2cbe, 0x2cbe, 0x2cc0, + 0x2cc0, 0x2cc2, 0x2cc2, 0x2cc4, 0x2cc4, 0x2cc6, 0x2cc6, 0x2cc8, + 0x2cc8, 0x2cca, 0x2cca, 0x2ccc, 0x2ccc, 0x2cce, 0x2cce, 0x2cd0, + 0x2cd0, 0x2cd2, 0x2cd2, 0x2cd4, 0x2cd4, 0x2cd6, 0x2cd6, 0x2cd8, + 0x2cd8, 0x2cda, 0x2cda, 0x2cdc, 0x2cdc, 0x2cde, 0x2cde, 0x2ce0, + 0x2ce0, 0x2ce2, 0x2ce2, 0x2ce4, 0x2ce5, 0x2ce6, 0x2ce7, 0x2ce8, + 0x2ce9, 0x2cea, 0x2ceb, 0x2cec, 0x2ced, 0x2cee, 0x2cef, 0x2cf0, + 0x2cf1, 0x2cf2, 0x2cf3, 0x2cf4, 0x2cf5, 0x2cf6, 0x2cf7, 0x2cf8, + 0x2cf9, 0x2cfa, 0x2cfb, 0x2cfc, 0x2cfd, 0x2cfe, 0x2cff, 0x10a0, + 0x10a1, 0x10a2, 0x10a3, 0x10a4, 0x10a5, 0x10a6, 0x10a7, 0x10a8, + 0x10a9, 0x10aa, 0x10ab, 0x10ac, 0x10ad, 0x10ae, 0x10af, 0x10b0, + 0x10b1, 0x10b2, 0x10b3, 0x10b4, 0x10b5, 0x10b6, 0x10b7, 0x10b8, + 0x10b9, 0x10ba, 0x10bb, 0x10bc, 0x10bd, 0x10be, 0x10bf, 0x10c0, + 0x10c1, 0x10c2, 0x10c3, 0x10c4, 0x10c5, 0xffff, 0xd21b, 0xff21, + 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27, 0xff28, 0xff29, + 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f, 0xff30, 0xff31, + 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37, 0xff38, 0xff39, + 0xff3a, 0xff5b, 0xff5c, 0xff5d, 0xff5e, 0xff5f, 0xff60, 0xff61, + 0xff62, 0xff63, 0xff64, 0xff65, 0xff66, 0xff67, 0xff68, 0xff69, + 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f, 0xff70, 0xff71, + 0xff72, 0xff73, 0xff74, 0xff75, 0xff76, 0xff77, 0xff78, 0xff79, + 0xff7a, 0xff7b, 0xff7c, 0xff7d, 0xff7e, 0xff7f, 0xff80, 0xff81, + 0xff82, 0xff83, 0xff84, 0xff85, 0xff86, 0xff87, 0xff88, 0xff89, + 0xff8a, 0xff8b, 0xff8c, 0xff8d, 0xff8e, 0xff8f, 0xff90, 0xff91, + 0xff92, 0xff93, 0xff94, 0xff95, 0xff96, 0xff97, 0xff98, 0xff99, + 0xff9a, 0xff9b, 0xff9c, 0xff9d, 0xff9e, 0xff9f, 0xffa0, 0xffa1, + 0xffa2, 0xffa3, 0xffa4, 0xffa5, 0xffa6, 0xffa7, 0xffa8, 0xffa9, + 0xffaa, 0xffab, 0xffac, 0xffad, 0xffae, 0xffaf, 0xffb0, 0xffb1, + 0xffb2, 0xffb3, 0xffb4, 0xffb5, 0xffb6, 0xffb7, 0xffb8, 0xffb9, + 0xffba, 0xffbb, 0xffbc, 0xffbd, 0xffbe, 0xffbf, 0xffc0, 0xffc1, + 0xffc2, 0xffc3, 0xffc4, 0xffc5, 0xffc6, 0xffc7, 0xffc8, 0xffc9, + 0xffca, 0xffcb, 0xffcc, 0xffcd, 0xffce, 0xffcf, 0xffd0, 0xffd1, + 0xffd2, 0xffd3, 0xffd4, 0xffd5, 0xffd6, 0xffd7, 0xffd8, 0xffd9, + 0xffda, 0xffdb, 0xffdc, 0xffdd, 0xffde, 0xffdf, 0xffe0, 0xffe1, + 0xffe2, 0xffe3, 0xffe4, 0xffe5, 0xffe6, 0xffe7, 0xffe8, 0xffe9, + 0xffea, 0xffeb, 0xffec, 0xffed, 0xffee, 0xffef, 0xfff0, 0xfff1, + 0xfff2, 0xfff3, 0xfff4, 0xfff5, 0xfff6, 0xfff7, 0xfff8, 0xfff9, + 0xfffa, 0xfffb, 0xfffc, 0xfffd, 0xfffe, 0xffff, +}; + +/* + * Allow full-width illegal characters : + * "MS windows 7" supports full-width-invalid-name-characters. + * So we should check half-width-invalid-name-characters(ASCII) only + * for compatibility. + * + * " * / : < > ? \ | + */ +static unsigned short bad_uni_chars[] = { + 0x0022, 0x002A, 0x002F, 0x003A, + 0x003C, 0x003E, 0x003F, 0x005C, 0x007C, + 0 +}; + +static int exfat_convert_char_to_ucs2(struct nls_table *nls, + const unsigned char *ch, int ch_len, unsigned short *ucs2, + int *lossy) +{ + int len; + + *ucs2 = 0x0; + + if (ch[0] < 0x80) { + *ucs2 = ch[0]; + return 1; + } + + len = nls->char2uni(ch, ch_len, ucs2); + if (len < 0) { + /* conversion failed */ + if (lossy != NULL) + *lossy |= NLS_NAME_LOSSY; + *ucs2 = '_'; + return 1; + } + return len; +} + +static int exfat_convert_ucs2_to_char(struct nls_table *nls, + unsigned short ucs2, unsigned char *ch, int *lossy) +{ + int len; + + ch[0] = 0x0; + + if (ucs2 < 0x0080) { + ch[0] = ucs2; + return 1; + } + + len = nls->uni2char(ucs2, ch, MAX_CHARSET_SIZE); + if (len < 0) { + /* conversion failed */ + if (lossy != NULL) + *lossy |= NLS_NAME_LOSSY; + ch[0] = '_'; + return 1; + } + return len; +} + +unsigned short exfat_toupper(struct super_block *sb, unsigned short a) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + return sbi->vol_utbl[a] ? sbi->vol_utbl[a] : a; +} + +static unsigned short *exfat_wstrchr(unsigned short *str, unsigned short wchar) +{ + while (*str) { + if (*(str++) == wchar) + return str; + } + return NULL; +} + +int exfat_uniname_ncmp(struct super_block *sb, unsigned short *a, + unsigned short *b, unsigned int len) +{ + int i; + + for (i = 0; i < len; i++, a++, b++) + if (exfat_toupper(sb, *a) != exfat_toupper(sb, *b)) + return 1; + return 0; +} + +static int exfat_utf16_to_utf8(struct super_block *sb, + struct exfat_uni_name *p_uniname, unsigned char *p_cstring, + int buflen) +{ + int len; + const unsigned short *uniname = p_uniname->name; + + /* always len >= 0 */ + len = utf16s_to_utf8s(uniname, MAX_NAME_LENGTH, UTF16_HOST_ENDIAN, + p_cstring, buflen); + p_cstring[len] = '\0'; + return len; +} + +static int exfat_utf8_to_utf16(struct super_block *sb, + const unsigned char *p_cstring, const int len, + struct exfat_uni_name *p_uniname, int *p_lossy) +{ + int i, unilen, lossy = NLS_NAME_NO_LOSSY; + unsigned short upname[MAX_NAME_LENGTH + 1]; + unsigned short *uniname = p_uniname->name; + + WARN_ON(!len); + + unilen = utf8s_to_utf16s(p_cstring, len, UTF16_HOST_ENDIAN, + (wchar_t *)uniname, MAX_NAME_LENGTH + 2); + if (unilen < 0) { + exfat_msg(sb, KERN_ERR, + "failed to %s (err : %d) nls len : %d", + __func__, unilen, len); + return unilen; + } + + if (unilen > MAX_NAME_LENGTH) { + exfat_msg(sb, KERN_ERR, + "failed to %s (estr:ENAMETOOLONG) nls len : %d, unilen : %d > %d", + __func__, len, unilen, MAX_NAME_LENGTH); + return -ENAMETOOLONG; + } + + p_uniname->name_len = unilen & 0xFF; + + for (i = 0; i < unilen; i++) { + if (*uniname < 0x0020 || + exfat_wstrchr(bad_uni_chars, *uniname)) + lossy |= NLS_NAME_LOSSY; + + upname[i] = exfat_toupper(sb, *uniname); + uniname++; + } + + *uniname = '\0'; + p_uniname->name_len = unilen; + p_uniname->name_hash = exfat_calc_chksum_2byte(upname, unilen << 1, 0, + CS_DEFAULT); + + if (p_lossy) + *p_lossy = lossy; + return unilen; +} + +#define PLANE_SIZE 0x00010000 +#define SURROGATE_MASK 0xfffff800 +#define SURROGATE_PAIR 0x0000d800 +#define SURROGATE_LOW 0x00000400 +#define SURROGATE_BITS 0x000003ff + +unsigned short exfat_high_surrogate(unicode_t u) +{ + return ((u - PLANE_SIZE) >> 10) + SURROGATE_PAIR; +} + +unsigned short exfat_low_surrogate(unicode_t u) +{ + return ((u - PLANE_SIZE) & SURROGATE_BITS) | SURROGATE_PAIR | + SURROGATE_LOW; +} + +static int __exfat_utf16_to_nls(struct super_block *sb, + struct exfat_uni_name *p_uniname, unsigned char *p_cstring, + int buflen) +{ + int i, j, len, out_len = 0; + unsigned char buf[MAX_CHARSET_SIZE]; + const unsigned short *uniname = p_uniname->name; + struct nls_table *nls = EXFAT_SB(sb)->nls_io; + + i = 0; + while (i < MAX_NAME_LENGTH && out_len < (buflen - 1)) { + if (*uniname == '\0') + break; + if ((*uniname & SURROGATE_MASK) != SURROGATE_PAIR) { + len = exfat_convert_ucs2_to_char(nls, *uniname, buf, + NULL); + } else { + /* Process UTF-16 surrogate pair as one character */ + if (!(*uniname & SURROGATE_LOW) && + i+1 < MAX_NAME_LENGTH && + (*(uniname+1) & SURROGATE_MASK) == SURROGATE_PAIR && + (*(uniname+1) & SURROGATE_LOW)) { + uniname++; + i++; + } + + /* + * UTF-16 surrogate pair encodes code points above + * U+FFFF. Code points above U+FFFF are not supported + * by kernel NLS framework therefore use replacement + * character + */ + len = 1; + buf[0] = '_'; + } + + if (out_len + len >= buflen) + len = buflen - 1 - out_len; + out_len += len; + + if (len > 1) { + for (j = 0; j < len; j++) + *p_cstring++ = buf[j]; + } else { /* len == 1 */ + *p_cstring++ = *buf; + } + + uniname++; + i++; + } + + *p_cstring = '\0'; + return out_len; +} + +static int exfat_nls_to_ucs2(struct super_block *sb, + const unsigned char *p_cstring, const int len, + struct exfat_uni_name *p_uniname, int *p_lossy) +{ + int i = 0, unilen = 0, lossy = NLS_NAME_NO_LOSSY; + unsigned short upname[MAX_NAME_LENGTH + 1]; + unsigned short *uniname = p_uniname->name; + struct nls_table *nls = EXFAT_SB(sb)->nls_io; + + WARN_ON(!len); + + while (unilen < MAX_NAME_LENGTH && i < len) { + i += exfat_convert_char_to_ucs2(nls, p_cstring + i, len - i, + uniname, &lossy); + + if (*uniname < 0x0020 || + exfat_wstrchr(bad_uni_chars, *uniname)) + lossy |= NLS_NAME_LOSSY; + + upname[unilen] = exfat_toupper(sb, *uniname); + uniname++; + unilen++; + } + + if (p_cstring[i] != '\0') + lossy |= NLS_NAME_OVERLEN; + + *uniname = '\0'; + p_uniname->name_len = unilen; + p_uniname->name_hash = exfat_calc_chksum_2byte(upname, unilen << 1, 0, + CS_DEFAULT); + + if (p_lossy) + *p_lossy = lossy; + return unilen; +} + +int exfat_utf16_to_nls(struct super_block *sb, struct exfat_uni_name *uniname, + unsigned char *p_cstring, int buflen) +{ + if (EXFAT_SB(sb)->options.utf8) + return exfat_utf16_to_utf8(sb, uniname, p_cstring, + buflen); + return __exfat_utf16_to_nls(sb, uniname, p_cstring, buflen); +} + +int exfat_nls_to_utf16(struct super_block *sb, const unsigned char *p_cstring, + const int len, struct exfat_uni_name *uniname, int *p_lossy) +{ + if (EXFAT_SB(sb)->options.utf8) + return exfat_utf8_to_utf16(sb, p_cstring, len, + uniname, p_lossy); + return exfat_nls_to_ucs2(sb, p_cstring, len, uniname, p_lossy); +} + +static int exfat_load_upcase_table(struct super_block *sb, + sector_t sector, unsigned long long num_sectors, + unsigned int utbl_checksum) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + unsigned int sect_size = sb->s_blocksize; + unsigned int i, index = 0, checksum = 0; + int ret; + unsigned char skip = false; + unsigned short *upcase_table; + + upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL); + if (!upcase_table) + return -ENOMEM; + + sbi->vol_utbl = upcase_table; + num_sectors += sector; + + while (sector < num_sectors) { + struct buffer_head *bh; + + bh = sb_bread(sb, sector); + if (!bh) { + exfat_msg(sb, KERN_ERR, + "failed to read sector(0x%llx)\n", + (unsigned long long)sector); + ret = -EIO; + goto free_table; + } + sector++; + for (i = 0; i < sect_size && index <= 0xFFFF; i += 2) { + unsigned short uni = get_unaligned_le16(bh->b_data + i); + + checksum = ((checksum & 1) ? 0x80000000 : 0) + + (checksum >> 1) + + *(((unsigned char *)bh->b_data) + i); + checksum = ((checksum & 1) ? 0x80000000 : 0) + + (checksum >> 1) + + *(((unsigned char *)bh->b_data) + (i + 1)); + + if (skip) { + index += uni; + skip = false; + } else if (uni == index) { + index++; + } else if (uni == 0xFFFF) { + skip = true; + } else { /* uni != index , uni != 0xFFFF */ + upcase_table[index] = uni; + index++; + } + } + brelse(bh); + } + + if (index >= 0xFFFF && utbl_checksum == checksum) + return 0; + + exfat_msg(sb, KERN_ERR, + "failed to load upcase table (idx : 0x%08x, chksum : 0x%08x, utbl_chksum : 0x%08x)\n", + index, checksum, utbl_checksum); + ret = -EINVAL; +free_table: + exfat_free_upcase_table(sbi); + return ret; +} + +static int exfat_load_default_upcase_table(struct super_block *sb) +{ + int i, ret = -EIO; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + unsigned char skip = false; + unsigned short uni = 0, *upcase_table; + unsigned int index = 0; + + upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL); + if (!upcase_table) + return -ENOMEM; + + sbi->vol_utbl = upcase_table; + + for (i = 0; index <= 0xFFFF && i < EXFAT_NUM_UPCASE; i++) { + uni = uni_def_upcase[i]; + if (skip) { + index += uni; + skip = false; + } else if (uni == index) { + index++; + } else if (uni == 0xFFFF) { + skip = true; + } else { + upcase_table[index] = uni; + index++; + } + } + + if (index >= 0xFFFF) + return 0; + + /* FATAL error: default upcase table has error */ + exfat_free_upcase_table(sbi); + return ret; +} + +int exfat_create_upcase_table(struct super_block *sb) +{ + int i, ret; + unsigned int tbl_clu, type; + sector_t sector; + unsigned long long tbl_size, num_sectors; + unsigned char blksize_bits = sb->s_blocksize_bits; + struct exfat_chain clu; + struct exfat_dentry *ep; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct buffer_head *bh; + + clu.dir = sbi->root_dir; + clu.flags = ALLOC_FAT_CHAIN; + + while (clu.dir != EXFAT_EOF_CLUSTER) { + for (i = 0; i < sbi->dentries_per_clu; i++) { + ep = exfat_get_dentry(sb, &clu, i, &bh, NULL); + if (!ep) + return -EIO; + + type = exfat_get_entry_type(ep); + if (type == TYPE_UNUSED) { + brelse(bh); + break; + } + + if (type != TYPE_UPCASE) { + brelse(bh); + continue; + } + + tbl_clu = le32_to_cpu(ep->dentry.upcase.start_clu); + tbl_size = le64_to_cpu(ep->dentry.upcase.size); + + sector = exfat_cluster_to_sector(sbi, tbl_clu); + num_sectors = ((tbl_size - 1) >> blksize_bits) + 1; + ret = exfat_load_upcase_table(sb, sector, num_sectors, + le32_to_cpu(ep->dentry.upcase.checksum)); + + brelse(bh); + if (ret && ret != -EIO) + goto load_default; + + /* load successfully */ + return ret; + } + + if (exfat_get_next_cluster(sb, &(clu.dir))) + return -EIO; + } + +load_default: + /* load default upcase table */ + return exfat_load_default_upcase_table(sb); +} + +void exfat_free_upcase_table(struct exfat_sb_info *sbi) +{ + kfree(sbi->vol_utbl); +} From b9d1e2e6265f5dc25e9f5dbfbde3e53d8a4958ac Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:42 +0900 Subject: [PATCH 1223/4444] exfat: add Kconfig and Makefile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the Kconfig and Makefile for exfat. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/Kconfig | 3 ++- fs/Makefile | 1 + fs/exfat/Kconfig | 21 +++++++++++++++++++++ fs/exfat/Makefile | 8 ++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 fs/exfat/Kconfig create mode 100644 fs/exfat/Makefile diff --git a/fs/Kconfig b/fs/Kconfig index 708ba336e689..f08fbbfafd9a 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -140,9 +140,10 @@ endmenu endif # BLOCK if BLOCK -menu "DOS/FAT/NT Filesystems" +menu "DOS/FAT/EXFAT/NT Filesystems" source "fs/fat/Kconfig" +source "fs/exfat/Kconfig" source "fs/ntfs/Kconfig" endmenu diff --git a/fs/Makefile b/fs/Makefile index 505e51166973..2ce5112b02c8 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -83,6 +83,7 @@ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ obj-$(CONFIG_MINIX_FS) += minix/ obj-$(CONFIG_FAT_FS) += fat/ +obj-$(CONFIG_EXFAT_FS) += exfat/ obj-$(CONFIG_BFS_FS) += bfs/ obj-$(CONFIG_ISO9660_FS) += isofs/ obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+ diff --git a/fs/exfat/Kconfig b/fs/exfat/Kconfig new file mode 100644 index 000000000000..2d3636dc5b8c --- /dev/null +++ b/fs/exfat/Kconfig @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +config EXFAT_FS + tristate "exFAT filesystem support" + select NLS + help + This allows you to mount devices formatted with the exFAT file system. + exFAT is typically used on SD-Cards or USB sticks. + + To compile this as a module, choose M here: the module will be called + exfat. + +config EXFAT_DEFAULT_IOCHARSET + string "Default iocharset for exFAT" + default "utf8" + depends on EXFAT_FS + help + Set this to the default input/output character set to use for + converting between the encoding is used for user visible filename and + UTF-16 character that exfat filesystem use, and can be overridden with + the "iocharset" mount option for exFAT filesystems. diff --git a/fs/exfat/Makefile b/fs/exfat/Makefile new file mode 100644 index 000000000000..ed51926a4971 --- /dev/null +++ b/fs/exfat/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Makefile for the linux exFAT filesystem support. +# +obj-$(CONFIG_EXFAT_FS) += exfat.o + +exfat-y := inode.o namei.o dir.o super.o fatent.o cache.o nls.o misc.o \ + file.o balloc.o From 88ab55f16aae90e2e974eb67cc2380edb92b0661 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:43 +0900 Subject: [PATCH 1224/4444] MAINTAINERS: add exfat filesystem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add myself and Sungjong Seo as exfat maintainer. Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 38fe2f3f7b6f..27d912bc5ae2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6305,6 +6305,13 @@ F: include/trace/events/mdio.h F: include/uapi/linux/mdio.h F: include/uapi/linux/mii.h +EXFAT FILE SYSTEM +M: Namjae Jeon +M: Sungjong Seo +L: linux-fsdevel@vger.kernel.org +S: Maintained +F: fs/exfat/ + EXFAT FILE SYSTEM M: Valdis Kletnieks L: linux-fsdevel@vger.kernel.org From 1a3c0509ce83ce48104907207423c6eb929caa59 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 2 Mar 2020 15:21:44 +0900 Subject: [PATCH 1225/4444] staging: exfat: make staging/exfat and fs/exfat mutually exclusive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make staging/exfat and fs/exfat mutually exclusive to select the one between two same filesystem. Suggested-by: Amir Goldstein Signed-off-by: Namjae Jeon Signed-off-by: Sungjong Seo Acked-by: Greg Kroah-Hartman Reviewed-by: Pali Rohár Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro --- drivers/staging/exfat/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/exfat/Kconfig b/drivers/staging/exfat/Kconfig index 292a19dfcaf5..9a0fccec65d9 100644 --- a/drivers/staging/exfat/Kconfig +++ b/drivers/staging/exfat/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 config STAGING_EXFAT_FS tristate "exFAT fs support" - depends on BLOCK + depends on BLOCK && !EXFAT_FS select NLS help This adds support for the exFAT file system. From 9acd0d53800c55c6e2186e29b6433daf24617451 Mon Sep 17 00:00:00 2001 From: Valdis Kletnieks Date: Mon, 2 Mar 2020 15:21:45 +0900 Subject: [PATCH 1226/4444] exfat: update file system parameter handling Al Viro recently reworked the way file system parameters are handled Update super.c to work with it in linux-next 20200203. Signed-off-by: Valdis Kletnieks Reviewed-by: Christoph Hellwig Acked-by: Namjae Jeon Signed-off-by: Al Viro --- fs/exfat/super.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/fs/exfat/super.c b/fs/exfat/super.c index f06e0b53e393..16ed202ef527 100644 --- a/fs/exfat/super.c +++ b/fs/exfat/super.c @@ -214,7 +214,14 @@ enum { Opt_time_offset, }; -static const struct fs_parameter_spec exfat_param_specs[] = { +static const struct constant_table exfat_param_enums[] = { + { "continue", EXFAT_ERRORS_CONT }, + { "panic", EXFAT_ERRORS_PANIC }, + { "remount-ro", EXFAT_ERRORS_RO }, + {} +}; + +static const struct fs_parameter_spec exfat_parameters[] = { fsparam_u32("uid", Opt_uid), fsparam_u32("gid", Opt_gid), fsparam_u32oct("umask", Opt_umask), @@ -222,25 +229,12 @@ static const struct fs_parameter_spec exfat_param_specs[] = { fsparam_u32oct("fmask", Opt_fmask), fsparam_u32oct("allow_utime", Opt_allow_utime), fsparam_string("iocharset", Opt_charset), - fsparam_enum("errors", Opt_errors), + fsparam_enum("errors", Opt_errors, exfat_param_enums), fsparam_flag("discard", Opt_discard), fsparam_s32("time_offset", Opt_time_offset), {} }; -static const struct fs_parameter_enum exfat_param_enums[] = { - { Opt_errors, "continue", EXFAT_ERRORS_CONT }, - { Opt_errors, "panic", EXFAT_ERRORS_PANIC }, - { Opt_errors, "remount-ro", EXFAT_ERRORS_RO }, - {} -}; - -static const struct fs_parameter_description exfat_parameters = { - .name = "exfat", - .specs = exfat_param_specs, - .enums = exfat_param_enums, -}; - static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param) { struct exfat_sb_info *sbi = fc->s_fs_info; @@ -248,7 +242,7 @@ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param) struct fs_parse_result result; int opt; - opt = fs_parse(fc, &exfat_parameters, param, &result); + opt = fs_parse(fc, exfat_parameters, param, &result); if (opt < 0) return opt; @@ -665,7 +659,7 @@ static struct file_system_type exfat_fs_type = { .owner = THIS_MODULE, .name = "exfat", .init_fs_context = exfat_init_fs_context, - .parameters = &exfat_parameters, + .parameters = exfat_parameters, .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, }; From 28936b62e71e41600bab319f262ea9f9b1027629 Mon Sep 17 00:00:00 2001 From: Qian Cai Date: Fri, 21 Feb 2020 23:32:58 -0500 Subject: [PATCH 1227/4444] ext4: fix a data race at inode->i_blocks inode->i_blocks could be accessed concurrently as noticed by KCSAN, BUG: KCSAN: data-race in ext4_do_update_inode [ext4] / inode_add_bytes write to 0xffff9a00d4b982d0 of 8 bytes by task 22100 on cpu 118: inode_add_bytes+0x65/0xf0 __inode_add_bytes at fs/stat.c:689 (inlined by) inode_add_bytes at fs/stat.c:702 ext4_mb_new_blocks+0x418/0xca0 [ext4] ext4_ext_map_blocks+0x1a6b/0x27b0 [ext4] ext4_map_blocks+0x1a9/0x950 [ext4] _ext4_get_block+0xfc/0x270 [ext4] ext4_get_block_unwritten+0x33/0x50 [ext4] __block_write_begin_int+0x22e/0xae0 __block_write_begin+0x39/0x50 ext4_write_begin+0x388/0xb50 [ext4] ext4_da_write_begin+0x35f/0x8f0 [ext4] generic_perform_write+0x15d/0x290 ext4_buffered_write_iter+0x11f/0x210 [ext4] ext4_file_write_iter+0xce/0x9e0 [ext4] new_sync_write+0x29c/0x3b0 __vfs_write+0x92/0xa0 vfs_write+0x103/0x260 ksys_write+0x9d/0x130 __x64_sys_write+0x4c/0x60 do_syscall_64+0x91/0xb05 entry_SYSCALL_64_after_hwframe+0x49/0xbe read to 0xffff9a00d4b982d0 of 8 bytes by task 8 on cpu 65: ext4_do_update_inode+0x4a0/0xf60 [ext4] ext4_inode_blocks_set at fs/ext4/inode.c:4815 ext4_mark_iloc_dirty+0xaf/0x160 [ext4] ext4_mark_inode_dirty+0x129/0x3e0 [ext4] ext4_convert_unwritten_extents+0x253/0x2d0 [ext4] ext4_convert_unwritten_io_end_vec+0xc5/0x150 [ext4] ext4_end_io_rsv_work+0x22c/0x350 [ext4] process_one_work+0x54f/0xb90 worker_thread+0x80/0x5f0 kthread+0x1cd/0x1f0 ret_from_fork+0x27/0x50 4 locks held by kworker/u256:0/8: #0: ffff9a025abc4328 ((wq_completion)ext4-rsv-conversion){+.+.}, at: process_one_work+0x443/0xb90 #1: ffffab5a862dbe20 ((work_completion)(&ei->i_rsv_conversion_work)){+.+.}, at: process_one_work+0x443/0xb90 #2: ffff9a025a9d0f58 (jbd2_handle){++++}, at: start_this_handle+0x1c1/0x9d0 [jbd2] #3: ffff9a00d4b985d8 (&(&ei->i_raw_lock)->rlock){+.+.}, at: ext4_do_update_inode+0xaa/0xf60 [ext4] irq event stamp: 3009267 hardirqs last enabled at (3009267): [] __find_get_block+0x107/0x790 hardirqs last disabled at (3009266): [] __find_get_block+0x49/0x790 softirqs last enabled at (3009230): [] __do_softirq+0x34c/0x57c softirqs last disabled at (3009223): [] irq_exit+0xa2/0xc0 Reported by Kernel Concurrency Sanitizer on: CPU: 65 PID: 8 Comm: kworker/u256:0 Tainted: G L 5.6.0-rc2-next-20200221+ #7 Hardware name: HPE ProLiant DL385 Gen10/ProLiant DL385 Gen10, BIOS A40 07/10/2019 Workqueue: ext4-rsv-conversion ext4_end_io_rsv_work [ext4] The plain read is outside of inode->i_lock critical section which results in a data race. Fix it by adding READ_ONCE() there. Link: https://lore.kernel.org/r/20200222043258.2279-1-cai@lca.pw Signed-off-by: Qian Cai Signed-off-by: Theodore Ts'o Cc: stable@kernel.org --- fs/ext4/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 416aec6d6c65..fa70ae21d032 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4810,7 +4810,7 @@ static int ext4_inode_blocks_set(handle_t *handle, struct ext4_inode_info *ei) { struct inode *inode = &(ei->vfs_inode); - u64 i_blocks = inode->i_blocks; + u64 i_blocks = READ_ONCE(inode->i_blocks); struct super_block *sb = inode->i_sb; if (i_blocks <= ~0U) { From dce8e237100f60c28cc66effb526ba65a01d8cb3 Mon Sep 17 00:00:00 2001 From: Qiujun Huang Date: Mon, 24 Feb 2020 23:02:46 +0800 Subject: [PATCH 1228/4444] ext4: fix a data race at inode->i_disksize KCSAN find inode->i_disksize could be accessed concurrently. BUG: KCSAN: data-race in ext4_mark_iloc_dirty / ext4_write_end write (marked) to 0xffff8b8932f40090 of 8 bytes by task 66792 on cpu 0: ext4_write_end+0x53f/0x5b0 ext4_da_write_end+0x237/0x510 generic_perform_write+0x1c4/0x2a0 ext4_buffered_write_iter+0x13a/0x210 ext4_file_write_iter+0xe2/0x9b0 new_sync_write+0x29c/0x3a0 __vfs_write+0x92/0xa0 vfs_write+0xfc/0x2a0 ksys_write+0xe8/0x140 __x64_sys_write+0x4c/0x60 do_syscall_64+0x8a/0x2a0 entry_SYSCALL_64_after_hwframe+0x44/0xa9 read to 0xffff8b8932f40090 of 8 bytes by task 14414 on cpu 1: ext4_mark_iloc_dirty+0x716/0x1190 ext4_mark_inode_dirty+0xc9/0x360 ext4_convert_unwritten_extents+0x1bc/0x2a0 ext4_convert_unwritten_io_end_vec+0xc5/0x150 ext4_put_io_end+0x82/0x130 ext4_writepages+0xae7/0x16f0 do_writepages+0x64/0x120 __writeback_single_inode+0x7d/0x650 writeback_sb_inodes+0x3a4/0x860 __writeback_inodes_wb+0xc4/0x150 wb_writeback+0x43f/0x510 wb_workfn+0x3b2/0x8a0 process_one_work+0x39b/0x7e0 worker_thread+0x88/0x650 kthread+0x1d4/0x1f0 ret_from_fork+0x35/0x40 The plain read is outside of inode->i_data_sem critical section which results in a data race. Fix it by adding READ_ONCE(). Signed-off-by: Qiujun Huang Link: https://lore.kernel.org/r/1582556566-3909-1-git-send-email-hqjagain@gmail.com Signed-off-by: Theodore Ts'o --- fs/ext4/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index fa70ae21d032..27d009bf183f 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4980,7 +4980,7 @@ static int ext4_do_update_inode(handle_t *handle, raw_inode->i_file_acl_high = cpu_to_le16(ei->i_file_acl >> 32); raw_inode->i_file_acl_lo = cpu_to_le32(ei->i_file_acl); - if (ei->i_disksize != ext4_isize(inode->i_sb, raw_inode)) { + if (READ_ONCE(ei->i_disksize) != ext4_isize(inode->i_sb, raw_inode)) { ext4_isize_set(raw_inode, ei->i_disksize); need_datasync = 1; } From 950d3fb6fb61bd59a86b1f41ea10401ce86cb965 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 6 Jan 2020 00:05:46 -0800 Subject: [PATCH 1229/4444] arm64: dts: qcom: msm8996: Define parent clocks for gcc The CLKREF clocks in GCC are parented by RPM_SMD_LN_BB_CLK, through the CXO2 pad. Wire this up so that this is properly enabled when need by the various PHYs. Reviewed-by: Vinod Koul Link: https://lore.kernel.org/r/20200106080546.3192125-3-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/msm8996.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index 4afd0d85633e..7b800b1f631e 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -443,6 +443,9 @@ #reset-cells = <1>; #power-domain-cells = <1>; reg = <0x00300000 0x90000>; + + clocks = <&rpmcc RPM_SMD_LN_BB_CLK>; + clock-names = "cxo2"; }; tsens0: thermal-sensor@4a9000 { From 27520210e8816afc2b91909171412a2deb7cbfe0 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 24 Jan 2020 16:12:34 -0800 Subject: [PATCH 1230/4444] arm64: dts: qcom: msm8996: Use generic QMP driver for UFS With support for the MSM8996 UFS PHY added to the common QMP driver, migrate the DTS to use the common QMP binding. Reviewed-by: Vinod Koul Link: https://lore.kernel.org/r/20200125001234.435384-1-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi | 6 ----- arch/arm64/boot/dts/qcom/msm8996.dtsi | 25 +++++++++++++------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi index fff6115f2670..af87350b5547 100644 --- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi @@ -999,13 +999,7 @@ vdda-phy-supply = <&vreg_l28a_0p925>; vdda-pll-supply = <&vreg_l12a_1p8>; - - vdda-phy-max-microamp = <18380>; - vdda-pll-max-microamp = <9440>; - vddp-ref-clk-supply = <&vreg_l25a_1p2>; - vddp-ref-clk-max-microamp = <100>; - vddp-ref-clk-always-on; }; &ufshc { diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index 7b800b1f631e..14827adebd94 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -886,7 +886,7 @@ reg = <0x00624000 0x2500>; interrupts = ; - phys = <&ufsphy>; + phys = <&ufsphy_lane>; phy-names = "ufsphy"; power-domains = <&gcc UFS_GDSC>; @@ -938,16 +938,25 @@ }; ufsphy: phy@627000 { - compatible = "qcom,msm8996-ufs-phy-qmp-14nm"; - reg = <0x00627000 0xda8>; - reg-names = "phy_mem"; - #phy-cells = <0>; + compatible = "qcom,msm8996-qmp-ufs-phy"; + reg = <0x00627000 0x1c4>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + clocks = <&gcc GCC_UFS_CLKREF_CLK>; + clock-names = "ref"; - clock-names = "ref_clk_src", "ref_clk"; - clocks = <&rpmcc RPM_SMD_LN_BB_CLK>, - <&gcc GCC_UFS_CLKREF_CLK>; resets = <&ufshc 0>; + reset-names = "ufsphy"; status = "disabled"; + + ufsphy_lane: lanes@627400 { + reg = <0x627400 0x12c>, + <0x627600 0x200>, + <0x627c00 0x1b4>; + #phy-cells = <0>; + }; }; camss: camss@a00000 { From b1b24dd7a676b4f2403535d82307f0911a77c1ad Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Tue, 25 Feb 2020 21:29:44 +0530 Subject: [PATCH 1231/4444] arm64: dts: sc7180: Add interconnect provider DT nodes Add the DT nodes for the network-on-chip interconnect buses found on sc7180-based platforms. Signed-off-by: Odelu Kukatla Link: https://lore.kernel.org/r/1582646384-1458-4-git-send-email-okukatla@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sc7180.dtsi | 95 ++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index b0092a0fb1e4..959221365266 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -835,6 +835,69 @@ }; }; + config_noc: interconnect@1500000 { + compatible = "qcom,sc7180-config-noc"; + reg = <0 0x01500000 0 0x28000>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + system_noc: interconnect@1620000 { + compatible = "qcom,sc7180-system-noc"; + reg = <0 0x01620000 0 0x17080>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + mc_virt: interconnect@1638000 { + compatible = "qcom,sc7180-mc-virt"; + reg = <0 0x01638000 0 0x1000>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + qup_virt: interconnect@1650000 { + compatible = "qcom,sc7180-qup-virt"; + reg = <0 0x01650000 0 0x1000>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + aggre1_noc: interconnect@16e0000 { + compatible = "qcom,sc7180-aggre1-noc"; + reg = <0 0x016e0000 0 0x15080>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + aggre2_noc: interconnect@1705000 { + compatible = "qcom,sc7180-aggre2-noc"; + reg = <0 0x01705000 0 0x9000>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + compute_noc: interconnect@170e000 { + compatible = "qcom,sc7180-compute-noc"; + reg = <0 0x0170e000 0 0x6000>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + mmss_noc: interconnect@1740000 { + compatible = "qcom,sc7180-mmss-noc"; + reg = <0 0x01740000 0 0x1c100>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + ipa_virt: interconnect@1e00000 { + compatible = "qcom,sc7180-ipa-virt"; + reg = <0 0x01e00000 0 0x1000>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + tcsr_mutex_regs: syscon@1f40000 { compatible = "syscon"; reg = <0 0x01f40000 0 0x40000>; @@ -1325,6 +1388,13 @@ }; }; + dc_noc: interconnect@9160000 { + compatible = "qcom,sc7180-dc-noc"; + reg = <0 0x09160000 0 0x03200>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + system-cache-controller@9200000 { compatible = "qcom,sc7180-llcc"; reg = <0 0x09200000 0 0x200000>, <0 0x09600000 0 0x50000>; @@ -1332,6 +1402,20 @@ interrupts = ; }; + gem_noc: interconnect@9680000 { + compatible = "qcom,sc7180-gem-noc"; + reg = <0 0x09680000 0 0x3e200>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + npu_noc: interconnect@9990000 { + compatible = "qcom,sc7180-npu-noc"; + reg = <0 0x09990000 0 0x1600>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + usb_1: usb@a6f8800 { compatible = "qcom,sc7180-dwc3", "qcom,dwc3"; reg = <0 0x0a6f8800 0 0x400>; @@ -1412,6 +1496,13 @@ #power-domain-cells = <1>; }; + camnoc_virt: interconnect@ac00000 { + compatible = "qcom,sc7180-camnoc-virt"; + reg = <0 0x0ac00000 0 0x1000>; + #interconnect-cells = <1>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + mdss: mdss@ae00000 { compatible = "qcom,sc7180-mdss"; reg = <0 0x0ae00000 0 0x1000>; @@ -1891,6 +1982,10 @@ }; }; }; + + apps_bcm_voter: bcm_voter { + compatible = "qcom,bcm-voter"; + }; }; cpufreq_hw: cpufreq@18323000 { From 74f26599809c870c2d744332591e7622b104de26 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Thu, 27 Feb 2020 16:26:30 +0530 Subject: [PATCH 1232/4444] arm64: dts: qcom: sdm845: Add OSM L3 interconnect provider Add Operation State Manager (OSM) L3 interconnect provider on SDM845 SoCs. Acked-by: Georgi Djakov Reviewed-by: Evan Green Signed-off-by: Sibi Sankar Link: https://lore.kernel.org/r/20200227105632.15041-7-sibis@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index 3da382b502e9..c7ddf215c57e 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -3560,6 +3560,16 @@ }; }; + osm_l3: interconnect@17d41000 { + compatible = "qcom,sdm845-osm-l3"; + reg = <0 0x17d41000 0 0x1400>; + + clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>; + clock-names = "xo", "alternate"; + + #interconnect-cells = <1>; + }; + cpufreq_hw: cpufreq@17d43000 { compatible = "qcom,cpufreq-hw"; reg = <0 0x17d43000 0 0x1400>, <0 0x17d45800 0 0x1400>; From b21bb61d243a12d993a498947e8fbd9045f44182 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Thu, 27 Feb 2020 16:26:31 +0530 Subject: [PATCH 1233/4444] arm64: dts: qcom: sc7180: Add OSM L3 interconnect provider Add Operation State Manager (OSM) L3 interconnect provider on SC7180 SoCs. Acked-by: Georgi Djakov Reviewed-by: Evan Green Signed-off-by: Sibi Sankar Link: https://lore.kernel.org/r/20200227105632.15041-8-sibis@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sc7180.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index 959221365266..c51fda655195 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -1988,6 +1988,16 @@ }; }; + osm_l3: interconnect@18321000 { + compatible = "qcom,sc7180-osm-l3"; + reg = <0 0x18321000 0 0x1400>; + + clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>; + clock-names = "xo", "alternate"; + + #interconnect-cells = <1>; + }; + cpufreq_hw: cpufreq@18323000 { compatible = "qcom,cpufreq-hw"; reg = <0 0x18323000 0 0x1400>, <0 0x18325800 0 0x1400>; From 663b7d41d5beab7fd0a5df123a1ac65e97718fc5 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Fri, 6 Mar 2020 03:30:14 +0530 Subject: [PATCH 1234/4444] arm64: dts: qcom: msm8998: Fix cpu compatible "arm,armv8" compatible should only be used for software models. Replace it with the real cpu type. Signed-off-by: Amit Kucheria Link: https://lore.kernel.org/r/0535d640e9cd01887b5532f893ce4d61feca6d6d.1583445235.git.amit.kucheria@linaro.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/msm8998.dtsi | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi index 91f7f2d07597..c07fee6fd7eb 100644 --- a/arch/arm64/boot/dts/qcom/msm8998.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi @@ -130,7 +130,7 @@ CPU0: cpu@0 { device_type = "cpu"; - compatible = "arm,armv8"; + compatible = "qcom,kryo280"; reg = <0x0 0x0>; enable-method = "psci"; cpu-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; @@ -149,7 +149,7 @@ CPU1: cpu@1 { device_type = "cpu"; - compatible = "arm,armv8"; + compatible = "qcom,kryo280"; reg = <0x0 0x1>; enable-method = "psci"; cpu-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; @@ -164,7 +164,7 @@ CPU2: cpu@2 { device_type = "cpu"; - compatible = "arm,armv8"; + compatible = "qcom,kryo280"; reg = <0x0 0x2>; enable-method = "psci"; cpu-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; @@ -179,7 +179,7 @@ CPU3: cpu@3 { device_type = "cpu"; - compatible = "arm,armv8"; + compatible = "qcom,kryo280"; reg = <0x0 0x3>; enable-method = "psci"; cpu-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; @@ -194,7 +194,7 @@ CPU4: cpu@100 { device_type = "cpu"; - compatible = "arm,armv8"; + compatible = "qcom,kryo280"; reg = <0x0 0x100>; enable-method = "psci"; cpu-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>; @@ -213,7 +213,7 @@ CPU5: cpu@101 { device_type = "cpu"; - compatible = "arm,armv8"; + compatible = "qcom,kryo280"; reg = <0x0 0x101>; enable-method = "psci"; cpu-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>; @@ -228,7 +228,7 @@ CPU6: cpu@102 { device_type = "cpu"; - compatible = "arm,armv8"; + compatible = "qcom,kryo280"; reg = <0x0 0x102>; enable-method = "psci"; cpu-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>; @@ -243,7 +243,7 @@ CPU7: cpu@103 { device_type = "cpu"; - compatible = "arm,armv8"; + compatible = "qcom,kryo280"; reg = <0x0 0x103>; enable-method = "psci"; cpu-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>; From 54c22ae53d6b4af582a8d5116c77f4ce37feec07 Mon Sep 17 00:00:00 2001 From: Rajeshwari Date: Thu, 5 Mar 2020 13:19:07 +0530 Subject: [PATCH 1235/4444] arm64: dts: qcom: sc7180: Added critical trip point Thermal-zones node To enable kernel critical shutdown feature added critical trip point to all non CPU sensors to perform shutdown in orderly manner. Reviewed-by: Amit Kucheria Signed-off-by: Rajeshwari Link: https://lore.kernel.org/r/1583394547-12779-2-git-send-email-rkambl@codeaurora.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sc7180.dtsi | 78 ++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index c51fda655195..89ba01246f95 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -2471,6 +2471,12 @@ hysteresis = <2000>; type = "hot"; }; + + aoss0_crit: aoss0_crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; }; }; @@ -2526,6 +2532,12 @@ hysteresis = <2000>; type = "hot"; }; + + gpuss0_crit: gpuss0_crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; }; }; @@ -2541,6 +2553,12 @@ hysteresis = <2000>; type = "hot"; }; + + gpuss1_crit: gpuss1_crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; }; }; @@ -2556,6 +2574,12 @@ hysteresis = <2000>; type = "hot"; }; + + aoss1_crit: aoss1_crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; }; }; @@ -2571,6 +2595,12 @@ hysteresis = <2000>; type = "hot"; }; + + cwlan_crit: cwlan_crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; }; }; @@ -2586,6 +2616,12 @@ hysteresis = <2000>; type = "hot"; }; + + audio_crit: audio_crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; }; }; @@ -2601,6 +2637,12 @@ hysteresis = <2000>; type = "hot"; }; + + ddr_crit: ddr_crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; }; }; @@ -2616,6 +2658,12 @@ hysteresis = <2000>; type = "hot"; }; + + q6_hvx_crit: q6_hvx_crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; }; }; @@ -2631,6 +2679,12 @@ hysteresis = <2000>; type = "hot"; }; + + camera_crit: camera_crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; }; }; @@ -2646,6 +2700,12 @@ hysteresis = <2000>; type = "hot"; }; + + mdm_crit: mdm_crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; }; }; @@ -2661,6 +2721,12 @@ hysteresis = <2000>; type = "hot"; }; + + mdm_dsp_crit: mdm_dsp_crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; }; }; @@ -2676,6 +2742,12 @@ hysteresis = <2000>; type = "hot"; }; + + npu_crit: npu_crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; }; }; @@ -2691,6 +2763,12 @@ hysteresis = <2000>; type = "hot"; }; + + video_crit: video_crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; }; }; }; From 66db29588dd6c55591b0f93dc8044a018d78d501 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 25 Feb 2020 21:32:49 -0800 Subject: [PATCH 1236/4444] ALSA: korg1212: fix if-statement empty body warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix gcc warnings when -Wextra is used by using an empty do-while block instead of . Fixes these build warnings: ../sound/pci/korg1212/korg1212.c:674:44: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] ../sound/pci/korg1212/korg1212.c:708:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] ../sound/pci/korg1212/korg1212.c:730:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] ../sound/pci/korg1212/korg1212.c:853:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] ../sound/pci/korg1212/korg1212.c:1013:44: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] ../sound/pci/korg1212/korg1212.c:1035:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] ../sound/pci/korg1212/korg1212.c:1052:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] ../sound/pci/korg1212/korg1212.c:1066:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] ../sound/pci/korg1212/korg1212.c:1087:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] ../sound/pci/korg1212/korg1212.c:1094:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] ../sound/pci/korg1212/korg1212.c:1208:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] ../sound/pci/korg1212/korg1212.c:2360:102: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] Signed-off-by: Randy Dunlap Link: https://lore.kernel.org/r/91fb1e97-a773-5790-3f65-8198403341e1@infradead.org Signed-off-by: Takashi Iwai --- sound/pci/korg1212/korg1212.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 21ab9cc50c71..65a887b217ee 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -30,7 +30,7 @@ #if K1212_DEBUG_LEVEL > 0 #define K1212_DEBUG_PRINTK(fmt,args...) printk(KERN_DEBUG fmt,##args) #else -#define K1212_DEBUG_PRINTK(fmt,...) +#define K1212_DEBUG_PRINTK(fmt,...) do { } while (0) #endif #if K1212_DEBUG_LEVEL > 1 #define K1212_DEBUG_PRINTK_VERBOSE(fmt,args...) printk(KERN_DEBUG fmt,##args) From 2edb84e3047b93da2f2b234219cdc304df042d9e Mon Sep 17 00:00:00 2001 From: Alexander Tsoy Date: Sat, 29 Feb 2020 18:18:15 +0300 Subject: [PATCH 1237/4444] ALSA: usb-audio: Add support for MOTU MicroBook IIc MicroBook IIc operates in UAC2 mode by default. This patch addresses several issues with it: - MicroBook II and IIc shares the same USB ID. We can distinguish them by interface class. - MaxPacketsOnly attribute is erroneously set in endpoint descriptors. As a result this card produces noise with all sample rates other than 96 KHz. This also causes issues like IOMMU page faults and other problems with host controller. - Sample rate changes takes more than 2 seconds for this device. Clock validity request returns false during that period, so the clock validity quirk is required. Signed-off-by: Alexander Tsoy Link: https://lore.kernel.org/r/20200229151815.14199-1-alexander@tsoy.me Signed-off-by: Takashi Iwai --- sound/usb/clock.c | 59 ++++++++++++++++++++++++++++++++-------- sound/usb/pcm.c | 7 ++++- sound/usb/quirks-table.h | 2 +- sound/usb/quirks.c | 18 +++++++++++- 4 files changed, 72 insertions(+), 14 deletions(-) diff --git a/sound/usb/clock.c b/sound/usb/clock.c index a48313dfa967..b118cf97607f 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -151,16 +151,15 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i return ret; } -/* - * Assume the clock is valid if clock source supports only one single sample - * rate, the terminal is connected directly to it (there is no clock selector) - * and clock type is internal. This is to deal with some Denon DJ controllers - * that always reports that clock is invalid. - */ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip, struct audioformat *fmt, int source_id) { + bool ret = false; + int count; + unsigned char data; + struct usb_device *dev = chip->dev; + if (fmt->protocol == UAC_VERSION_2) { struct uac_clock_source_descriptor *cs_desc = snd_usb_find_clock_source(chip->ctrl_intf, source_id); @@ -168,13 +167,51 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip, if (!cs_desc) return false; - return (fmt->nr_rates == 1 && - (fmt->clock & 0xff) == cs_desc->bClockID && - (cs_desc->bmAttributes & 0x3) != - UAC_CLOCK_SOURCE_TYPE_EXT); + /* + * Assume the clock is valid if clock source supports only one + * single sample rate, the terminal is connected directly to it + * (there is no clock selector) and clock type is internal. + * This is to deal with some Denon DJ controllers that always + * reports that clock is invalid. + */ + if (fmt->nr_rates == 1 && + (fmt->clock & 0xff) == cs_desc->bClockID && + (cs_desc->bmAttributes & 0x3) != + UAC_CLOCK_SOURCE_TYPE_EXT) + return true; } - return false; + /* + * MOTU MicroBook IIc + * Sample rate changes takes more than 2 seconds for this device. Clock + * validity request returns false during that period. + */ + if (chip->usb_id == USB_ID(0x07fd, 0x0004)) { + count = 0; + + while ((!ret) && (count < 50)) { + int err; + + msleep(100); + + err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, + UAC2_CS_CONTROL_CLOCK_VALID << 8, + snd_usb_ctrl_intf(chip) | (source_id << 8), + &data, sizeof(data)); + if (err < 0) { + dev_warn(&dev->dev, + "%s(): cannot get clock validity for id %d\n", + __func__, source_id); + return false; + } + + ret = !!data; + count++; + } + } + + return ret; } static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index bd258f1ec2dd..a4e4064f9aee 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -357,7 +357,12 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, ep = 0x81; ifnum = 1; goto add_sync_ep_from_ifnum; - case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook II */ + case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook II/IIc */ + /* MicroBook IIc */ + if (altsd->bInterfaceClass == USB_CLASS_AUDIO) + return 0; + + /* MicroBook II */ ep = 0x84; ifnum = 0; goto add_sync_ep_from_ifnum; diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index d187aa6d50db..1c8719292eee 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -3472,7 +3472,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), }, /* MOTU Microbook II */ { - USB_DEVICE(0x07fd, 0x0004), + USB_DEVICE_VENDOR_SPEC(0x07fd, 0x0004), .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { .vendor_name = "MOTU", .product_name = "MicroBookII", diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 915aea256f65..3cc745fe24d8 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1352,7 +1352,15 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, case USB_ID(0x2466, 0x8010): /* Fractal Audio Axe-Fx 3 */ return snd_usb_axefx3_boot_quirk(dev); case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook II */ - return snd_usb_motu_microbookii_boot_quirk(dev); + /* + * For some reason interface 3 with vendor-spec class is + * detected on MicroBook IIc. + */ + if (get_iface_desc(intf->altsetting)->bInterfaceClass == + USB_CLASS_VENDOR_SPEC && + get_iface_desc(intf->altsetting)->bInterfaceNumber < 3) + return snd_usb_motu_microbookii_boot_quirk(dev); + break; } return 0; @@ -1790,5 +1798,13 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip, else fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC; break; + case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook IIc */ + /* + * MaxPacketsOnly attribute is erroneously set in endpoint + * descriptors. As a result this card produces noise with + * all sample rates other than 96 KHz. + */ + fp->attributes &= ~UAC_EP_CS_ATTR_FILL_MAX; + break; } } From d0ee674bb5d3787ca0122c5ae8e52680de0e7c52 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 6 Mar 2020 09:12:31 +0100 Subject: [PATCH 1238/4444] ALSA: usb-audio: Fix missing braces in some struct inits The struct s1810c_state_packet contains the array in the first field hence zero-initialization requires a more couple of braces. Fix the compile warning pointing it out: sound/usb/mixer_s1810c.c: In function 'snd_sc1810c_get_status_field': sound/usb/mixer_s1810c.c:178:9: warning: missing braces around initializer [-Wmissing-braces] Reported-by: kbuild test robot Fixes: 8dc5efe3d17c ("ALSA: usb-audio: Add support for Presonus Studio 1810c") Link: https://lore.kernel.org/r/202002210251.WgMfvKJP%lkp@intel.com Link: https://lore.kernel.org/r/20200306081231.7940-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/mixer_s1810c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/usb/mixer_s1810c.c b/sound/usb/mixer_s1810c.c index 816879a07f82..6483e47bafd0 100644 --- a/sound/usb/mixer_s1810c.c +++ b/sound/usb/mixer_s1810c.c @@ -175,8 +175,8 @@ static int snd_sc1810c_get_status_field(struct usb_device *dev, u32 *field, int field_idx, uint16_t *seqnum) { - struct s1810c_state_packet pkt_out = { 0 }; - struct s1810c_state_packet pkt_in = { 0 }; + struct s1810c_state_packet pkt_out = { { 0 } }; + struct s1810c_state_packet pkt_in = { { 0 } }; int ret = 0; pkt_out.fields[SC1810C_STATE_F1_IDX] = SC1810C_SET_STATE_F1; From f9ad0f361cf3b58fd26d409c6150126547259772 Mon Sep 17 00:00:00 2001 From: Long Li Date: Tue, 25 Feb 2020 21:06:07 -0800 Subject: [PATCH 1239/4444] PCI: hv: Decouple the func definition in hv_dr_state from VSP message hv_dr_state is used to find present PCI devices on the bus. The structure reuses struct pci_function_description from VSP message to describe a device. To prepare support for pci_function_description v2, decouple this dependence in hv_dr_state so it can work with both v1 and v2 VSP messages. There is no functionality change. Signed-off-by: Long Li Signed-off-by: Lorenzo Pieralisi Reviewed-by: Michael Kelley --- drivers/pci/controller/pci-hyperv.c | 100 +++++++++++++++++++--------- 1 file changed, 70 insertions(+), 30 deletions(-) diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index 15011a349520..dea197f0fc0b 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -505,10 +505,24 @@ struct hv_dr_work { struct hv_pcibus_device *bus; }; +struct hv_pcidev_description { + u16 v_id; /* vendor ID */ + u16 d_id; /* device ID */ + u8 rev; + u8 prog_intf; + u8 subclass; + u8 base_class; + u32 subsystem_id; + union win_slot_encoding win_slot; + u32 ser; /* serial number */ + u32 flags; + u16 virtual_numa_node; +}; + struct hv_dr_state { struct list_head list_entry; u32 device_count; - struct pci_function_description func[0]; + struct hv_pcidev_description func[0]; }; enum hv_pcichild_state { @@ -525,7 +539,7 @@ struct hv_pci_dev { refcount_t refs; enum hv_pcichild_state state; struct pci_slot *pci_slot; - struct pci_function_description desc; + struct hv_pcidev_description desc; bool reported_missing; struct hv_pcibus_device *hbus; struct work_struct wrk; @@ -1877,7 +1891,7 @@ static void q_resource_requirements(void *context, struct pci_response *resp, * Return: Pointer to the new tracking struct */ static struct hv_pci_dev *new_pcichild_device(struct hv_pcibus_device *hbus, - struct pci_function_description *desc) + struct hv_pcidev_description *desc) { struct hv_pci_dev *hpdev; struct pci_child_message *res_req; @@ -1988,7 +2002,7 @@ static void pci_devices_present_work(struct work_struct *work) { u32 child_no; bool found; - struct pci_function_description *new_desc; + struct hv_pcidev_description *new_desc; struct hv_pci_dev *hpdev; struct hv_pcibus_device *hbus; struct list_head removed; @@ -2107,17 +2121,15 @@ static void pci_devices_present_work(struct work_struct *work) } /** - * hv_pci_devices_present() - Handles list of new children + * hv_pci_start_relations_work() - Queue work to start device discovery * @hbus: Root PCI bus, as understood by this driver - * @relations: Packet from host listing children + * @dr: The list of children returned from host * - * This function is invoked whenever a new list of devices for - * this bus appears. + * Return: 0 on success, -errno on failure */ -static void hv_pci_devices_present(struct hv_pcibus_device *hbus, - struct pci_bus_relations *relations) +static int hv_pci_start_relations_work(struct hv_pcibus_device *hbus, + struct hv_dr_state *dr) { - struct hv_dr_state *dr; struct hv_dr_work *dr_wrk; unsigned long flags; bool pending_dr; @@ -2125,29 +2137,15 @@ static void hv_pci_devices_present(struct hv_pcibus_device *hbus, if (hbus->state == hv_pcibus_removing) { dev_info(&hbus->hdev->device, "PCI VMBus BUS_RELATIONS: ignored\n"); - return; + return -ENOENT; } dr_wrk = kzalloc(sizeof(*dr_wrk), GFP_NOWAIT); if (!dr_wrk) - return; - - dr = kzalloc(offsetof(struct hv_dr_state, func) + - (sizeof(struct pci_function_description) * - (relations->device_count)), GFP_NOWAIT); - if (!dr) { - kfree(dr_wrk); - return; - } + return -ENOMEM; INIT_WORK(&dr_wrk->wrk, pci_devices_present_work); dr_wrk->bus = hbus; - dr->device_count = relations->device_count; - if (dr->device_count != 0) { - memcpy(dr->func, relations->func, - sizeof(struct pci_function_description) * - dr->device_count); - } spin_lock_irqsave(&hbus->device_list_lock, flags); /* @@ -2165,6 +2163,47 @@ static void hv_pci_devices_present(struct hv_pcibus_device *hbus, get_hvpcibus(hbus); queue_work(hbus->wq, &dr_wrk->wrk); } + + return 0; +} + +/** + * hv_pci_devices_present() - Handle list of new children + * @hbus: Root PCI bus, as understood by this driver + * @relations: Packet from host listing children + * + * Process a new list of devices on the bus. The list of devices is + * discovered by VSP and sent to us via VSP message PCI_BUS_RELATIONS, + * whenever a new list of devices for this bus appears. + */ +static void hv_pci_devices_present(struct hv_pcibus_device *hbus, + struct pci_bus_relations *relations) +{ + struct hv_dr_state *dr; + int i; + + dr = kzalloc(offsetof(struct hv_dr_state, func) + + (sizeof(struct hv_pcidev_description) * + (relations->device_count)), GFP_NOWAIT); + + if (!dr) + return; + + dr->device_count = relations->device_count; + for (i = 0; i < dr->device_count; i++) { + dr->func[i].v_id = relations->func[i].v_id; + dr->func[i].d_id = relations->func[i].d_id; + dr->func[i].rev = relations->func[i].rev; + dr->func[i].prog_intf = relations->func[i].prog_intf; + dr->func[i].subclass = relations->func[i].subclass; + dr->func[i].base_class = relations->func[i].base_class; + dr->func[i].subsystem_id = relations->func[i].subsystem_id; + dr->func[i].win_slot = relations->func[i].win_slot; + dr->func[i].ser = relations->func[i].ser; + } + + if (hv_pci_start_relations_work(hbus, dr)) + kfree(dr); } /** @@ -3069,7 +3108,7 @@ static int hv_pci_bus_exit(struct hv_device *hdev, bool hibernating) struct pci_packet teardown_packet; u8 buffer[sizeof(struct pci_message)]; } pkt; - struct pci_bus_relations relations; + struct hv_dr_state *dr; struct hv_pci_compl comp_pkt; int ret; @@ -3082,8 +3121,9 @@ static int hv_pci_bus_exit(struct hv_device *hdev, bool hibernating) if (!hibernating) { /* Delete any children which might still exist. */ - memset(&relations, 0, sizeof(relations)); - hv_pci_devices_present(hbus, &relations); + dr = kzalloc(sizeof(*dr), GFP_KERNEL); + if (dr && hv_pci_start_relations_work(hbus, dr)) + kfree(dr); } ret = hv_send_resources_released(hdev); From 999dd956d8389f3a512808f36fac97e1c8e87c7f Mon Sep 17 00:00:00 2001 From: Long Li Date: Tue, 25 Feb 2020 21:06:08 -0800 Subject: [PATCH 1240/4444] PCI: hv: Add support for protocol 1.3 and support PCI_BUS_RELATIONS2 Starting with Hyper-V PCI protocol version 1.3, the host VSP can send PCI_BUS_RELATIONS2 and pass the vNUMA node information for devices on the bus. The vNUMA node tells which guest NUMA node this device is on based on guest VM configuration topology and physical device information. Add code to negotiate v1.3 and process PCI_BUS_RELATIONS2. Signed-off-by: Long Li Signed-off-by: Lorenzo Pieralisi Reviewed-by: Michael Kelley --- drivers/pci/controller/pci-hyperv.c | 109 ++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index dea197f0fc0b..98d377677bdb 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -63,6 +63,7 @@ enum pci_protocol_version_t { PCI_PROTOCOL_VERSION_1_1 = PCI_MAKE_VERSION(1, 1), /* Win10 */ PCI_PROTOCOL_VERSION_1_2 = PCI_MAKE_VERSION(1, 2), /* RS1 */ + PCI_PROTOCOL_VERSION_1_3 = PCI_MAKE_VERSION(1, 3), /* Vibranium */ }; #define CPU_AFFINITY_ALL -1ULL @@ -72,6 +73,7 @@ enum pci_protocol_version_t { * first. */ static enum pci_protocol_version_t pci_protocol_versions[] = { + PCI_PROTOCOL_VERSION_1_3, PCI_PROTOCOL_VERSION_1_2, PCI_PROTOCOL_VERSION_1_1, }; @@ -119,6 +121,7 @@ enum pci_message_type { PCI_RESOURCES_ASSIGNED2 = PCI_MESSAGE_BASE + 0x16, PCI_CREATE_INTERRUPT_MESSAGE2 = PCI_MESSAGE_BASE + 0x17, PCI_DELETE_INTERRUPT_MESSAGE2 = PCI_MESSAGE_BASE + 0x18, /* unused */ + PCI_BUS_RELATIONS2 = PCI_MESSAGE_BASE + 0x19, PCI_MESSAGE_MAXIMUM }; @@ -164,6 +167,26 @@ struct pci_function_description { u32 ser; /* serial number */ } __packed; +enum pci_device_description_flags { + HV_PCI_DEVICE_FLAG_NONE = 0x0, + HV_PCI_DEVICE_FLAG_NUMA_AFFINITY = 0x1, +}; + +struct pci_function_description2 { + u16 v_id; /* vendor ID */ + u16 d_id; /* device ID */ + u8 rev; + u8 prog_intf; + u8 subclass; + u8 base_class; + u32 subsystem_id; + union win_slot_encoding win_slot; + u32 ser; /* serial number */ + u32 flags; + u16 virtual_numa_node; + u16 reserved; +} __packed; + /** * struct hv_msi_desc * @vector: IDT entry @@ -299,6 +322,12 @@ struct pci_bus_relations { struct pci_function_description func[0]; } __packed; +struct pci_bus_relations2 { + struct pci_incoming_message incoming; + u32 device_count; + struct pci_function_description2 func[0]; +} __packed; + struct pci_q_res_req_response { struct vmpacket_descriptor hdr; s32 status; /* negative values are failures */ @@ -1415,6 +1444,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) break; case PCI_PROTOCOL_VERSION_1_2: + case PCI_PROTOCOL_VERSION_1_3: size = hv_compose_msi_req_v2(&ctxt.int_pkts.v2, dest, hpdev->desc.win_slot.slot, @@ -1813,6 +1843,27 @@ static void hv_pci_remove_slots(struct hv_pcibus_device *hbus) } } +/* + * Set NUMA node for the devices on the bus + */ +static void hv_pci_assign_numa_node(struct hv_pcibus_device *hbus) +{ + struct pci_dev *dev; + struct pci_bus *bus = hbus->pci_bus; + struct hv_pci_dev *hv_dev; + + list_for_each_entry(dev, &bus->devices, bus_list) { + hv_dev = get_pcichild_wslot(hbus, devfn_to_wslot(dev->devfn)); + if (!hv_dev) + continue; + + if (hv_dev->desc.flags & HV_PCI_DEVICE_FLAG_NUMA_AFFINITY) + set_dev_node(&dev->dev, hv_dev->desc.virtual_numa_node); + + put_pcichild(hv_dev); + } +} + /** * create_root_hv_pci_bus() - Expose a new root PCI bus * @hbus: Root PCI bus, as understood by this driver @@ -1835,6 +1886,7 @@ static int create_root_hv_pci_bus(struct hv_pcibus_device *hbus) pci_lock_rescan_remove(); pci_scan_child_bus(hbus->pci_bus); + hv_pci_assign_numa_node(hbus); pci_bus_assign_resources(hbus->pci_bus); hv_pci_assign_slots(hbus); pci_bus_add_devices(hbus->pci_bus); @@ -2103,6 +2155,7 @@ static void pci_devices_present_work(struct work_struct *work) */ pci_lock_rescan_remove(); pci_scan_child_bus(hbus->pci_bus); + hv_pci_assign_numa_node(hbus); hv_pci_assign_slots(hbus); pci_unlock_rescan_remove(); break; @@ -2206,6 +2259,46 @@ static void hv_pci_devices_present(struct hv_pcibus_device *hbus, kfree(dr); } +/** + * hv_pci_devices_present2() - Handle list of new children + * @hbus: Root PCI bus, as understood by this driver + * @relations: Packet from host listing children + * + * This function is the v2 version of hv_pci_devices_present() + */ +static void hv_pci_devices_present2(struct hv_pcibus_device *hbus, + struct pci_bus_relations2 *relations) +{ + struct hv_dr_state *dr; + int i; + + dr = kzalloc(offsetof(struct hv_dr_state, func) + + (sizeof(struct hv_pcidev_description) * + (relations->device_count)), GFP_NOWAIT); + + if (!dr) + return; + + dr->device_count = relations->device_count; + for (i = 0; i < dr->device_count; i++) { + dr->func[i].v_id = relations->func[i].v_id; + dr->func[i].d_id = relations->func[i].d_id; + dr->func[i].rev = relations->func[i].rev; + dr->func[i].prog_intf = relations->func[i].prog_intf; + dr->func[i].subclass = relations->func[i].subclass; + dr->func[i].base_class = relations->func[i].base_class; + dr->func[i].subsystem_id = relations->func[i].subsystem_id; + dr->func[i].win_slot = relations->func[i].win_slot; + dr->func[i].ser = relations->func[i].ser; + dr->func[i].flags = relations->func[i].flags; + dr->func[i].virtual_numa_node = + relations->func[i].virtual_numa_node; + } + + if (hv_pci_start_relations_work(hbus, dr)) + kfree(dr); +} + /** * hv_eject_device_work() - Asynchronously handles ejection * @work: Work struct embedded in internal device struct @@ -2319,6 +2412,7 @@ static void hv_pci_onchannelcallback(void *context) struct pci_response *response; struct pci_incoming_message *new_message; struct pci_bus_relations *bus_rel; + struct pci_bus_relations2 *bus_rel2; struct pci_dev_inval_block *inval; struct pci_dev_incoming *dev_message; struct hv_pci_dev *hpdev; @@ -2386,6 +2480,21 @@ static void hv_pci_onchannelcallback(void *context) hv_pci_devices_present(hbus, bus_rel); break; + case PCI_BUS_RELATIONS2: + + bus_rel2 = (struct pci_bus_relations2 *)buffer; + if (bytes_recvd < + offsetof(struct pci_bus_relations2, func) + + (sizeof(struct pci_function_description2) * + (bus_rel2->device_count))) { + dev_err(&hbus->hdev->device, + "bus relations v2 too small\n"); + break; + } + + hv_pci_devices_present2(hbus, bus_rel2); + break; + case PCI_EJECT: dev_message = (struct pci_dev_incoming *)buffer; From 067fb6c97e7e6a503c058b1f7509bfa709d05ed4 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 12 Feb 2020 18:50:48 -0600 Subject: [PATCH 1241/4444] PCI: hv: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Lorenzo Pieralisi Reviewed-by: Dexuan Cui --- drivers/pci/controller/pci-hyperv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index 98d377677bdb..88fd39254e0c 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -283,7 +283,7 @@ struct pci_packet { int resp_packet_size); void *compl_ctxt; - struct pci_message message[0]; + struct pci_message message[]; }; /* @@ -319,13 +319,13 @@ struct pci_bus_d0_entry { struct pci_bus_relations { struct pci_incoming_message incoming; u32 device_count; - struct pci_function_description func[0]; + struct pci_function_description func[]; } __packed; struct pci_bus_relations2 { struct pci_incoming_message incoming; u32 device_count; - struct pci_function_description2 func[0]; + struct pci_function_description2 func[]; } __packed; struct pci_q_res_req_response { @@ -551,7 +551,7 @@ struct hv_pcidev_description { struct hv_dr_state { struct list_head list_entry; u32 device_count; - struct hv_pcidev_description func[0]; + struct hv_pcidev_description func[]; }; enum hv_pcichild_state { From 014b020475d4b9670d3cff11b751a7c20208f78b Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Tue, 25 Feb 2020 12:44:06 +0100 Subject: [PATCH 1242/4444] s390/mm: cleanup phys_to_pfn() and friends Make page, frame, virtual and physical address conversion macros more expressive by avoiding redundant definitions and defining new macros using existing ones. Signed-off-by: Alexander Gordeev Reviewed-by: Heiko Carstens Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/page.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index 85e944f04c70..2e53b27f4f1a 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h @@ -161,20 +161,20 @@ static inline int devmem_is_allowed(unsigned long pfn) #define __pa(x) ((unsigned long)(x)) #define __va(x) ((void *)(unsigned long)(x)) -#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) -#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT) +#define phys_to_pfn(phys) ((phys) >> PAGE_SHIFT) +#define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT) + +#define phys_to_page(phys) pfn_to_page(phys_to_pfn(phys)) +#define page_to_phys(page) pfn_to_phys(page_to_pfn(page)) + +#define pfn_to_virt(pfn) __va(pfn_to_phys(pfn)) +#define virt_to_pfn(kaddr) (phys_to_pfn(__pa(kaddr))) #define pfn_to_kaddr(pfn) pfn_to_virt(pfn) #define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr)) #define page_to_virt(page) pfn_to_virt(page_to_pfn(page)) -#define phys_to_pfn(kaddr) ((kaddr) >> PAGE_SHIFT) -#define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT) - -#define phys_to_page(kaddr) pfn_to_page(phys_to_pfn(kaddr)) -#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) - -#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) +#define virt_addr_valid(kaddr) pfn_valid(virt_to_pfn(kaddr)) #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) From ad451abee4ba787508c2a344aae4c9316b96cab9 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Mon, 24 Feb 2020 09:53:47 +0100 Subject: [PATCH 1243/4444] s390/qdio: export SSQD via debugfs While we print out various SSQD fields at initialization time, having raw & full access to the current SSQD can help with debugging. Signed-off-by: Julian Wiedmann Signed-off-by: Vasily Gorbik --- drivers/s390/cio/qdio_debug.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index bf8d82503870..8544faddf80c 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c @@ -190,6 +190,23 @@ static int qstat_show(struct seq_file *m, void *v) DEFINE_SHOW_ATTRIBUTE(qstat); +static int ssqd_show(struct seq_file *m, void *v) +{ + struct ccw_device *cdev = m->private; + struct qdio_ssqd_desc ssqd; + int rc; + + rc = qdio_get_ssqd_desc(cdev, &ssqd); + if (rc) + return rc; + + seq_hex_dump(m, "", DUMP_PREFIX_NONE, 16, 4, &ssqd, sizeof(ssqd), + false); + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(ssqd); + static char *qperf_names[] = { "Assumed adapter interrupts", "QDIO interrupts", @@ -303,6 +320,8 @@ void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev) debugfs_root); debugfs_create_file("statistics", S_IFREG | S_IRUGO | S_IWUSR, irq_ptr->debugfs_dev, irq_ptr, &debugfs_perf_fops); + debugfs_create_file("ssqd", 0444, irq_ptr->debugfs_dev, cdev, + &ssqd_fops); for_each_input_queue(irq_ptr, q, i) setup_debugfs_entry(irq_ptr->debugfs_dev, q); From 05fb806718408ae8c44bb1c42e40f555a94225a9 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 3 Mar 2020 21:13:47 +0800 Subject: [PATCH 1244/4444] dmaengine: fsl-dpaa2-qdma: remove set but not used variable 'dpaa2_qdma' drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c: In function dpaa2_qdma_shutdown: drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c:795:28: warning: variable dpaa2_qdma set but not used [-Wunused-but-set-variable] commit 3e0ca3c38dc2 ("dmaengine: fsl-dpaa2-qdma: Adding shutdown hook") involved this, remove it. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20200303131347.28392-1-yuehaibing@huawei.com Signed-off-by: Vinod Koul --- drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c index fabbbb90b2c7..4ec909e0b810 100644 --- a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c +++ b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c @@ -792,13 +792,11 @@ static int dpaa2_qdma_remove(struct fsl_mc_device *ls_dev) static void dpaa2_qdma_shutdown(struct fsl_mc_device *ls_dev) { - struct dpaa2_qdma_engine *dpaa2_qdma; struct dpaa2_qdma_priv *priv; struct device *dev; dev = &ls_dev->dev; priv = dev_get_drvdata(dev); - dpaa2_qdma = priv->dpaa2_qdma; dpdmai_disable(priv->mc_io, 0, ls_dev->mc_handle); dpaa2_dpdmai_dpio_unbind(priv); From 820766c1e16651b46bfb771afae8d789da1986cf Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 6 Mar 2020 13:28:05 +0000 Subject: [PATCH 1245/4444] ASoC: wcd934x: fix High Accuracy Buck enable High Accuracy buck is not applicable when we use RCO Band Gap source, so move it back to correct place. Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20200306132806.19684-2-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd934x.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index aefaadfba8a1..83d643a07775 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -1202,11 +1202,6 @@ static int wcd934x_set_sido_input_src(struct wcd934x_codec *wcd, int sido_src) regmap_update_bits(wcd->regmap, WCD934X_ANA_RCO, WCD934X_ANA_RCO_BG_EN_MASK, 0); usleep_range(100, 110); - } else if (sido_src == SIDO_SOURCE_RCO_BG) { - regmap_update_bits(wcd->regmap, WCD934X_ANA_RCO, - WCD934X_ANA_RCO_BG_EN_MASK, - WCD934X_ANA_RCO_BG_ENABLE); - usleep_range(100, 110); regmap_update_bits(wcd->regmap, WCD934X_ANA_BUCK_CTL, WCD934X_ANA_BUCK_PRE_EN1_MASK, WCD934X_ANA_BUCK_PRE_EN1_ENABLE); @@ -1219,6 +1214,11 @@ static int wcd934x_set_sido_input_src(struct wcd934x_codec *wcd, int sido_src) WCD934X_ANA_BUCK_HI_ACCU_EN_MASK, WCD934X_ANA_BUCK_HI_ACCU_ENABLE); usleep_range(100, 110); + } else if (sido_src == SIDO_SOURCE_RCO_BG) { + regmap_update_bits(wcd->regmap, WCD934X_ANA_RCO, + WCD934X_ANA_RCO_BG_EN_MASK, + WCD934X_ANA_RCO_BG_ENABLE); + usleep_range(100, 110); } wcd->sido_input_src = sido_src; From e0e247d593f78f4ac5647a9ef2c6db8f918ecbdc Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 6 Mar 2020 13:28:06 +0000 Subject: [PATCH 1246/4444] ASoC: wcd934x: remove unused headers Looks like there are some unused headers, remove them. Seems to be missed while moving to mfd. Reported-by: Stephen Boyd Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20200306132806.19684-3-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd934x.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 83d643a07775..5269857e2746 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -3,7 +3,6 @@ #include #include -#include #include #include #include @@ -11,10 +10,7 @@ #include #include #include -#include -#include #include -#include #include #include #include From 4769bfb9dada678b31a2ec275372624dbfeed9d1 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Wed, 4 Mar 2020 23:11:41 -0600 Subject: [PATCH 1247/4444] ALSA: pcm: Add a standalone version of snd_pcm_limit_hw_rates It can be useful to derive min/max rates of a snd_pcm_hardware without having a snd_pcm_runtime, such as before constructing an ASoC DAI link. Create a new helper that takes a pointer to a snd_pcm_hardware directly, and refactor the original function as a wrapper around it, to avoid needing to update any call sites. Signed-off-by: Samuel Holland Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20200305051143.60691-2-samuel@sholland.org Signed-off-by: Mark Brown --- include/sound/pcm.h | 9 ++++++++- sound/core/pcm_misc.c | 18 +++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 2628246b76fa..f7a95b711100 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -1127,7 +1127,14 @@ snd_pcm_kernel_readv(struct snd_pcm_substream *substream, return __snd_pcm_lib_xfer(substream, bufs, false, frames, true); } -int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime); +int snd_pcm_hw_limit_rates(struct snd_pcm_hardware *hw); + +static inline int +snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime) +{ + return snd_pcm_hw_limit_rates(&runtime->hw); +} + unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate); unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit); unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a, diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index a6a541511534..5dd2e5335900 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c @@ -474,32 +474,32 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int EXPORT_SYMBOL(snd_pcm_format_set_silence); /** - * snd_pcm_limit_hw_rates - determine rate_min/rate_max fields - * @runtime: the runtime instance + * snd_pcm_hw_limit_rates - determine rate_min/rate_max fields + * @hw: the pcm hw instance * * Determines the rate_min and rate_max fields from the rates bits of - * the given runtime->hw. + * the given hw. * * Return: Zero if successful. */ -int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime) +int snd_pcm_hw_limit_rates(struct snd_pcm_hardware *hw) { int i; for (i = 0; i < (int)snd_pcm_known_rates.count; i++) { - if (runtime->hw.rates & (1 << i)) { - runtime->hw.rate_min = snd_pcm_known_rates.list[i]; + if (hw->rates & (1 << i)) { + hw->rate_min = snd_pcm_known_rates.list[i]; break; } } for (i = (int)snd_pcm_known_rates.count - 1; i >= 0; i--) { - if (runtime->hw.rates & (1 << i)) { - runtime->hw.rate_max = snd_pcm_known_rates.list[i]; + if (hw->rates & (1 << i)) { + hw->rate_max = snd_pcm_known_rates.list[i]; break; } } return 0; } -EXPORT_SYMBOL(snd_pcm_limit_hw_rates); +EXPORT_SYMBOL(snd_pcm_hw_limit_rates); /** * snd_pcm_rate_to_rate_bit - converts sample rate to SNDRV_PCM_RATE_xxx bit From 5854a46486ad5b8d73766735fb0d77f05956b22c Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Wed, 4 Mar 2020 23:11:42 -0600 Subject: [PATCH 1248/4444] ASoC: pcm: Export parameter intersection logic The logic to calculate the subset of stream parameters supported by all DAIs associated with a PCM stream is nontrivial. Export a helper function so it can be used to set up simple codec2codec DAI links. Signed-off-by: Samuel Holland Link: https://lore.kernel.org/r/20200305051143.60691-3-samuel@sholland.org Signed-off-by: Mark Brown --- include/sound/soc.h | 3 +++ sound/soc/soc-pcm.c | 56 ++++++++++++++++++++++++++++++--------------- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 81e5d17be935..9543d9246ca4 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -471,6 +471,9 @@ bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd); void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream); void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream); +int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hardware *hw, int stream); + int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, unsigned int dai_fmt); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index e3a2c4f7757b..de4226357e2b 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -587,11 +587,18 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) soc_pcm_set_msb(substream, cpu_bits); } -static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) +/** + * snd_soc_runtime_calc_hw() - Calculate hw limits for a PCM stream + * @rtd: ASoC PCM runtime + * @hw: PCM hardware parameters (output) + * @stream: Direction of the PCM stream + * + * Calculates the subset of stream parameters supported by all DAIs + * associated with the PCM stream. + */ +int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hardware *hw, int stream) { - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_pcm_hardware *hw = &runtime->hw; - struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai; struct snd_soc_dai *cpu_dai; struct snd_soc_pcm_stream *codec_stream; @@ -602,7 +609,6 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) unsigned int cpu_rate_min = 0, cpu_rate_max = UINT_MAX; unsigned int rates = UINT_MAX, cpu_rates = UINT_MAX; u64 formats = ULLONG_MAX; - int stream = substream->stream; int i; /* first calculate min/max only for CPUs in the DAI link */ @@ -613,12 +619,8 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) * Otherwise, since the rate, channel, and format values will * zero in that case, we would have no usable settings left, * causing the resulting setup to fail. - * At least one CPU should match, otherwise we should have - * bailed out on a higher level, since there would be no - * CPU to support the transfer direction in that case. */ - if (!snd_soc_dai_stream_valid(cpu_dai, - substream->stream)) + if (!snd_soc_dai_stream_valid(cpu_dai, stream)) continue; cpu_stream = snd_soc_dai_get_pcm_stream(cpu_dai, stream); @@ -640,9 +642,6 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) * Otherwise, since the rate, channel, and format values will * zero in that case, we would have no usable settings left, * causing the resulting setup to fail. - * At least one CODEC should match, otherwise we should have - * bailed out on a higher level, since there would be no - * CODEC to support the transfer direction in that case. */ if (!snd_soc_dai_stream_valid(codec_dai, stream)) continue; @@ -657,6 +656,10 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) rates = snd_pcm_rate_mask_intersect(codec_stream->rates, rates); } + /* Verify both a valid CPU DAI and a valid CODEC DAI were found */ + if (!chan_min || !cpu_chan_min) + return -EINVAL; + /* * chan min/max cannot be enforced if there are multiple CODEC DAIs * connected to CPU DAI(s), use CPU DAI's directly and let @@ -670,18 +673,35 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) /* finally find a intersection between CODECs and CPUs */ hw->channels_min = max(chan_min, cpu_chan_min); hw->channels_max = min(chan_max, cpu_chan_max); - if (hw->formats) - hw->formats &= formats; - else - hw->formats = formats; + hw->formats = formats; hw->rates = snd_pcm_rate_mask_intersect(rates, cpu_rates); - snd_pcm_limit_hw_rates(runtime); + snd_pcm_hw_limit_rates(hw); hw->rate_min = max(hw->rate_min, cpu_rate_min); hw->rate_min = max(hw->rate_min, rate_min); hw->rate_max = min_not_zero(hw->rate_max, cpu_rate_max); hw->rate_max = min_not_zero(hw->rate_max, rate_max); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_runtime_calc_hw); + +static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) +{ + struct snd_pcm_hardware *hw = &substream->runtime->hw; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + u64 formats = hw->formats; + + /* + * At least one CPU and one CODEC should match. Otherwise, we should + * have bailed out on a higher level, since there would be no CPU or + * CODEC to support the transfer direction in that case. + */ + snd_soc_runtime_calc_hw(rtd, hw, substream->stream); + + if (formats) + hw->formats &= formats; } static int soc_pcm_components_open(struct snd_pcm_substream *substream) From 95cfc0a0aaf575207152dd7601e782702565a6f1 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Wed, 4 Mar 2020 23:11:43 -0600 Subject: [PATCH 1249/4444] ASoC: simple-card: Add support for codec2codec DAI links Following the example in cb2cf0de1174 ("ASoC: soc-core: care Codec <-> Codec case by non_legacy_dai_naming"), determine if a DAI link contains only codec DAIs by examining the non_legacy_dai_naming flag in each DAI's component. For now, we assume there is only one or a small set of valid PCM stream parameters, so num_params == 1 is good enough. We also assume that the same params are valid for all supported streams. params is set to the subset of parameters common among all DAIs, and then the existing code automatically chooses the highest quality of the remaining values when the link is brought up. Signed-off-by: Samuel Holland Link: https://lore.kernel.org/r/20200305051143.60691-4-samuel@sholland.org Signed-off-by: Mark Brown --- Documentation/sound/soc/codec-to-codec.rst | 9 +++- sound/soc/generic/simple-card-utils.c | 48 ++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/Documentation/sound/soc/codec-to-codec.rst b/Documentation/sound/soc/codec-to-codec.rst index 810109d7500d..4eaa9a0c41fc 100644 --- a/Documentation/sound/soc/codec-to-codec.rst +++ b/Documentation/sound/soc/codec-to-codec.rst @@ -104,5 +104,10 @@ Make sure to name your corresponding cpu and codec playback and capture dai names ending with "Playback" and "Capture" respectively as dapm core will link and power those dais based on the name. -Note that in current device tree there is no way to mark a dai_link -as codec to codec. However, it may change in future. +A dai_link in a "simple-audio-card" will automatically be detected as +codec to codec when all DAIs on the link belong to codec components. +The dai_link will be initialized with the subset of stream parameters +(channels, format, sample rate) supported by all DAIs on the link. Since +there is no way to provide these parameters in the device tree, this is +mostly useful for communication with simple fixed-function codecs, such +as a Bluetooth controller or cellular modem. diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 9b794775df53..320e648f7499 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -331,6 +331,50 @@ static int asoc_simple_init_dai(struct snd_soc_dai *dai, return 0; } +static int asoc_simple_init_dai_link_params(struct snd_soc_pcm_runtime *rtd, + struct simple_dai_props *dai_props) +{ + struct snd_soc_dai_link *dai_link = rtd->dai_link; + struct snd_soc_component *component; + struct snd_soc_pcm_stream *params; + struct snd_pcm_hardware hw; + int i, ret, stream; + + /* Only codecs should have non_legacy_dai_naming set. */ + for_each_rtd_components(rtd, i, component) { + if (!component->driver->non_legacy_dai_naming) + return 0; + } + + /* Assumes the capabilities are the same for all supported streams */ + for (stream = 0; stream < 2; stream++) { + ret = snd_soc_runtime_calc_hw(rtd, &hw, stream); + if (ret == 0) + break; + } + + if (ret < 0) { + dev_err(rtd->dev, "simple-card: no valid dai_link params\n"); + return ret; + } + + params = devm_kzalloc(rtd->dev, sizeof(*params), GFP_KERNEL); + if (!params) + return -ENOMEM; + + params->formats = hw.formats; + params->rates = hw.rates; + params->rate_min = hw.rate_min; + params->rate_max = hw.rate_max; + params->channels_min = hw.channels_min; + params->channels_max = hw.channels_max; + + dai_link->params = params; + dai_link->num_params = 1; + + return 0; +} + int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd) { struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); @@ -347,6 +391,10 @@ int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd) if (ret < 0) return ret; + ret = asoc_simple_init_dai_link_params(rtd, dai_props); + if (ret < 0) + return ret; + return 0; } EXPORT_SYMBOL_GPL(asoc_simple_dai_init); From 30fca26f8e2277ccd14fe3277a330b4f21cadca7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 6 Mar 2020 10:09:44 +0900 Subject: [PATCH 1250/4444] ASoC: soc-pcm: move dpcm_fe_dai_close() move dpcm_fe_dai_close() next to dpcm_fe_dai_open(). This is prepare for dpcm_fe_dai_open() cleanup Signed-off-by: Kuninori Morimoto Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87pndqp9uv.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index e3a2c4f7757b..3686dda097e2 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2978,6 +2978,26 @@ out: return ret; } +static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) +{ + struct snd_soc_pcm_runtime *fe = fe_substream->private_data; + struct snd_soc_dpcm *dpcm; + int stream = fe_substream->stream, ret; + + mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); + ret = dpcm_fe_dai_shutdown(fe_substream); + + /* mark FE's links ready to prune */ + for_each_dpcm_be(fe, stream, dpcm) + dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; + + dpcm_be_disconnect(fe, stream); + + fe->dpcm[stream].runtime = NULL; + mutex_unlock(&fe->card->mutex); + return ret; +} + static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) { struct snd_soc_pcm_runtime *fe = fe_substream->private_data; @@ -3017,26 +3037,6 @@ open_end: return ret; } -static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) -{ - struct snd_soc_pcm_runtime *fe = fe_substream->private_data; - struct snd_soc_dpcm *dpcm; - int stream = fe_substream->stream, ret; - - mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); - ret = dpcm_fe_dai_shutdown(fe_substream); - - /* mark FE's links ready to prune */ - for_each_dpcm_be(fe, stream, dpcm) - dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; - - dpcm_be_disconnect(fe, stream); - - fe->dpcm[stream].runtime = NULL; - mutex_unlock(&fe->card->mutex); - return ret; -} - /* create a new pcm */ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) { From 265694b67c13f00384bd0b97549b4681cbcc85af Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 6 Mar 2020 10:09:49 +0900 Subject: [PATCH 1251/4444] ASoC: soc-pcm: add dpcm_fe_dai_cleanup() dpcm_fe_dai_close() and error case of dpcm_fe_dai_open() need to do same cleanup operation. To avoid duplicate code, this patch adds dpcm_fe_dai_cleanup() and use it. Signed-off-by: Kuninori Morimoto Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87o8tap9uq.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 3686dda097e2..b405fb3a181b 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2978,14 +2978,11 @@ out: return ret; } -static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) +static void dpcm_fe_dai_cleanup(struct snd_pcm_substream *fe_substream) { struct snd_soc_pcm_runtime *fe = fe_substream->private_data; struct snd_soc_dpcm *dpcm; - int stream = fe_substream->stream, ret; - - mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); - ret = dpcm_fe_dai_shutdown(fe_substream); + int stream = fe_substream->stream; /* mark FE's links ready to prune */ for_each_dpcm_be(fe, stream, dpcm) @@ -2994,6 +2991,18 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) dpcm_be_disconnect(fe, stream); fe->dpcm[stream].runtime = NULL; +} + +static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) +{ + struct snd_soc_pcm_runtime *fe = fe_substream->private_data; + int ret; + + mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); + ret = dpcm_fe_dai_shutdown(fe_substream); + + dpcm_fe_dai_cleanup(fe_substream); + mutex_unlock(&fe->card->mutex); return ret; } @@ -3001,7 +3010,6 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) { struct snd_soc_pcm_runtime *fe = fe_substream->private_data; - struct snd_soc_dpcm *dpcm; struct snd_soc_dapm_widget_list *list; int ret; int stream = fe_substream->stream; @@ -3021,14 +3029,8 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) dpcm_process_paths(fe, stream, &list, 1); ret = dpcm_fe_dai_startup(fe_substream); - if (ret < 0) { - /* clean up all links */ - for_each_dpcm_be(fe, stream, dpcm) - dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; - - dpcm_be_disconnect(fe, stream); - fe->dpcm[stream].runtime = NULL; - } + if (ret < 0) + dpcm_fe_dai_cleanup(fe_substream); dpcm_clear_pending_state(fe, stream); dpcm_path_put(&list); From 0c9ba720f0be457443ba89b09a5198616cd3e811 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 6 Mar 2020 10:09:54 +0900 Subject: [PATCH 1252/4444] ASoC: soc-pcm: use snd_soc_dai_get_pcm_stream() at dpcm_set_fe_runtime() We already have snd_soc_dai_get_pcm_stream(), let's use it Signed-off-by: Kuninori Morimoto Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87mu8up9ul.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b405fb3a181b..3a30776858bf 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2022,7 +2022,6 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai; - struct snd_soc_dai_driver *cpu_dai_drv; int i; for_each_rtd_cpu_dai(rtd, i, cpu_dai) { @@ -2033,11 +2032,9 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) if (!snd_soc_dai_stream_valid(cpu_dai, substream->stream)) continue; - cpu_dai_drv = cpu_dai->driver; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dpcm_init_runtime_hw(runtime, &cpu_dai_drv->playback); - else - dpcm_init_runtime_hw(runtime, &cpu_dai_drv->capture); + dpcm_init_runtime_hw(runtime, + snd_soc_dai_get_pcm_stream(cpu_dai, + substream->stream)); } dpcm_runtime_merge_format(substream, &runtime->hw.formats); From 8a01fbf0ac115268293d8764850edc0628a58e4f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 6 Mar 2020 10:09:59 +0900 Subject: [PATCH 1253/4444] ASoC: soc-pcm: tidyup dulicate handing at dpcm_fe_dai_startup() error handling at dpcm_fe_dai_startup() has duplicate code. This patch tidyup it. Signed-off-by: Kuninori Morimoto Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87lfoep9ug.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 3a30776858bf..7d787e0966f3 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2162,17 +2162,13 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) snd_pcm_limit_hw_rates(runtime); ret = dpcm_apply_symmetry(fe_substream, stream); - if (ret < 0) { + if (ret < 0) dev_err(fe->dev, "ASoC: failed to apply dpcm symmetry %d\n", ret); - goto unwind; - } - - dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); - return 0; unwind: - dpcm_be_dai_startup_unwind(fe, stream); + if (ret < 0) + dpcm_be_dai_startup_unwind(fe, stream); be_err: dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); return ret; From 67ad877757cea329f74c1e169ec54131c3f223ce Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 6 Mar 2020 10:10:04 +0900 Subject: [PATCH 1254/4444] ASoC: soc-pcm: check DAI's activity more simply soc_pcm_hw_free() want to call snd_soc_dai_digital_mute() if it was last user of Playback or Capture. bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; int playback_active = dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK]; int capture_active = dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]; if ((playback && playback_active == 1) || (!playback && capture_active == 1)) snd_soc_dai_digital_mute(...) But it is same as int active = dai->stream_active[substream->stream]; if (active == 1) snd_soc_dai_digital_mute(...) This patch simplify the code. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87k13yp9ub.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 7d787e0966f3..af0e17bfeeab 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1202,7 +1202,6 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; - bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; int i; mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); @@ -1226,11 +1225,9 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) /* apply codec digital mute */ for_each_rtd_codec_dai(rtd, i, codec_dai) { - int playback_active = codec_dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK]; - int capture_active = codec_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]; + int active = codec_dai->stream_active[substream->stream]; - if ((playback && playback_active == 1) || - (!playback && capture_active == 1)) + if (active == 1) snd_soc_dai_digital_mute(codec_dai, 1, substream->stream); } From a9ee331b537a3dfe6778fa4e07c0801f33e474f5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 6 Mar 2020 10:10:17 +0900 Subject: [PATCH 1255/4444] ASoC: soc-pcm: Do Digital Mute for both CPU/Codec in same timing. Digital Mute for CPU is done at soc_pcm_close(), and Digital Mute for Codec is done at soc_pcm_hw_free(). It is just confusable. This patch do Digital Mute for both CPU/Codec in same timing. Then, it cares DAI activity Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87imjip9ty.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index af0e17bfeeab..90d26fccb0da 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -760,9 +760,6 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) snd_soc_runtime_deactivate(rtd, substream->stream); - for_each_rtd_cpu_dai(rtd, i, cpu_dai) - snd_soc_dai_digital_mute(cpu_dai, 1, substream->stream); - for_each_rtd_cpu_dai(rtd, i, cpu_dai) snd_soc_dai_shutdown(cpu_dai, substream); @@ -1232,6 +1229,14 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) substream->stream); } + for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + int active = cpu_dai->stream_active[substream->stream]; + + if (active == 1) + snd_soc_dai_digital_mute(cpu_dai, 1, + substream->stream); + } + /* free any machine hw params */ soc_rtd_hw_free(rtd, substream); From 9c0d16ac059148fc7647f5f9e90df6f34d3439f0 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 6 Mar 2020 22:52:29 +0900 Subject: [PATCH 1256/4444] ALSA: firewire: use KBUILD_MODNAME for struct driver.name instead of string KBUILD_MODNAME is available to name kernel modules according to its object name. This commit uses the macro instead of string for name field of struct driver since drivers in ALSA firewire stack have the same name of each object name. Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200306135229.11659-1-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob.c | 2 +- sound/firewire/digi00x/digi00x.c | 2 +- sound/firewire/fireface/ff.c | 2 +- sound/firewire/fireworks/fireworks.c | 2 +- sound/firewire/tascam/tascam.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index 976d8cb9a34f..2c8e3392a490 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c @@ -509,7 +509,7 @@ MODULE_DEVICE_TABLE(ieee1394, bebob_id_table); static struct fw_driver bebob_driver = { .driver = { .owner = THIS_MODULE, - .name = "snd-bebob", + .name = KBUILD_MODNAME, .bus = &fw_bus_type, }, .probe = bebob_probe, diff --git a/sound/firewire/digi00x/digi00x.c b/sound/firewire/digi00x/digi00x.c index 1f5fc0e7c024..c84b913a9fe0 100644 --- a/sound/firewire/digi00x/digi00x.c +++ b/sound/firewire/digi00x/digi00x.c @@ -192,7 +192,7 @@ MODULE_DEVICE_TABLE(ieee1394, snd_dg00x_id_table); static struct fw_driver dg00x_driver = { .driver = { .owner = THIS_MODULE, - .name = "snd-firewire-digi00x", + .name = KBUILD_MODNAME, .bus = &fw_bus_type, }, .probe = snd_dg00x_probe, diff --git a/sound/firewire/fireface/ff.c b/sound/firewire/fireface/ff.c index f5a016560eb8..b62a4fd22407 100644 --- a/sound/firewire/fireface/ff.c +++ b/sound/firewire/fireface/ff.c @@ -224,7 +224,7 @@ MODULE_DEVICE_TABLE(ieee1394, snd_ff_id_table); static struct fw_driver ff_driver = { .driver = { .owner = THIS_MODULE, - .name = "snd-fireface", + .name = KBUILD_MODNAME, .bus = &fw_bus_type, }, .probe = snd_ff_probe, diff --git a/sound/firewire/fireworks/fireworks.c b/sound/firewire/fireworks/fireworks.c index 134fc9ee26b9..b1cc013a3540 100644 --- a/sound/firewire/fireworks/fireworks.c +++ b/sound/firewire/fireworks/fireworks.c @@ -362,7 +362,7 @@ MODULE_DEVICE_TABLE(ieee1394, efw_id_table); static struct fw_driver efw_driver = { .driver = { .owner = THIS_MODULE, - .name = "snd-fireworks", + .name = KBUILD_MODNAME, .bus = &fw_bus_type, }, .probe = efw_probe, diff --git a/sound/firewire/tascam/tascam.c b/sound/firewire/tascam/tascam.c index addc464503bc..5dac0d9fc58e 100644 --- a/sound/firewire/tascam/tascam.c +++ b/sound/firewire/tascam/tascam.c @@ -224,7 +224,7 @@ MODULE_DEVICE_TABLE(ieee1394, snd_tscm_id_table); static struct fw_driver tscm_driver = { .driver = { .owner = THIS_MODULE, - .name = "snd-firewire-tascam", + .name = KBUILD_MODNAME, .bus = &fw_bus_type, }, .probe = snd_tscm_probe, From f9c23615c688270d2a383bd752f7a54a7137d596 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 27 Feb 2020 11:35:44 +0200 Subject: [PATCH 1257/4444] ALSA: dmaengine_pcm: No need to take runtime reference twice in pcm_pointer The runtime pointer has been taken in functional level so there is no need to take it again under the if () case. Fixes: 9d789dc047e3 ("ALSA: dmaengine_pcm: Consider DMA cache caused delay in pointer callback") Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20200227093544.27723-1-peter.ujfalusi@ti.com Signed-off-by: Mark Brown --- sound/core/pcm_dmaengine.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index 6852bb670b4e..9d4f48cfe47f 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c @@ -248,8 +248,6 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state); if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) { - struct snd_pcm_runtime *runtime = substream->runtime; - buf_size = snd_pcm_lib_buffer_bytes(substream); if (state.residue > 0 && state.residue <= buf_size) pos = buf_size - state.residue; From ece275032fe70692285270705784d7ba668883f5 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 07:25:30 -0800 Subject: [PATCH 1258/4444] ARM: dts: Configure interconnect target module for am3 tpcc We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty to avoid new boot time warnings. The legacy property will be removed in later patches together with the legacy platform data. Let's also correct the custom node name to use generic node name dma. Cc: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am33xx.dtsi | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi index 41dcfb37155a..3c478100bc68 100644 --- a/arch/arm/boot/dts/am33xx.dtsi +++ b/arch/arm/boot/dts/am33xx.dtsi @@ -193,21 +193,32 @@ reg = <0x48200000 0x1000>; }; - edma: edma@49000000 { - compatible = "ti,edma3-tpcc"; + target-module@49000000 { + compatible = "ti,sysc-omap4", "ti,sysc"; ti,hwmods = "tpcc"; - reg = <0x49000000 0x10000>; - reg-names = "edma3_cc"; - interrupts = <12 13 14>; - interrupt-names = "edma3_ccint", "edma3_mperr", - "edma3_ccerrint"; - dma-requests = <64>; - #dma-cells = <2>; + reg = <0x49000000 0x4>; + reg-names = "rev"; + clocks = <&l3_clkctrl AM3_L3_TPCC_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x49000000 0x10000>; - ti,tptcs = <&edma_tptc0 7>, <&edma_tptc1 5>, - <&edma_tptc2 0>; + edma: dma@0 { + compatible = "ti,edma3-tpcc"; + reg = <0 0x10000>; + reg-names = "edma3_cc"; + interrupts = <12 13 14>; + interrupt-names = "edma3_ccint", "edma3_mperr", + "edma3_ccerrint"; + dma-requests = <64>; + #dma-cells = <2>; - ti,edma-memcpy-channels = <20 21>; + ti,tptcs = <&edma_tptc0 7>, <&edma_tptc1 5>, + <&edma_tptc2 0>; + + ti,edma-memcpy-channels = <20 21>; + }; }; edma_tptc0: tptc@49800000 { From 9c1562ea71feb0b5fd700770bb935922d21c438e Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 07:25:30 -0800 Subject: [PATCH 1259/4444] ARM: dts: Configure interconnect target module for am3 tptc0 We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty to avoid new boot time warnings. The legacy property will be removed in later patches together with the legacy platform data. Let's also correct the custom node name to use generic node name dma. Cc: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am33xx.dtsi | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi index 3c478100bc68..63c34219fcf6 100644 --- a/arch/arm/boot/dts/am33xx.dtsi +++ b/arch/arm/boot/dts/am33xx.dtsi @@ -221,12 +221,28 @@ }; }; - edma_tptc0: tptc@49800000 { - compatible = "ti,edma3-tptc"; + target-module@49800000 { + compatible = "ti,sysc-omap4", "ti,sysc"; ti,hwmods = "tptc0"; - reg = <0x49800000 0x100000>; - interrupts = <112>; - interrupt-names = "edma3_tcerrint"; + reg = <0x49800000 0x4>, + <0x49800010 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-mask = ; + ti,sysc-midle = ; + ti,sysc-sidle = , + ; + clocks = <&l3_clkctrl AM3_L3_TPTC0_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x49800000 0x100000>; + + edma_tptc0: dma@0 { + compatible = "ti,edma3-tptc"; + reg = <0 0x100000>; + interrupts = <112>; + interrupt-names = "edma3_tcerrint"; + }; }; edma_tptc1: tptc@49900000 { From 1e666cb36072b67670bd4ef3e6008323c264bcdc Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 07:25:30 -0800 Subject: [PATCH 1260/4444] ARM: dts: Configure interconnect target module for am3 tptc1 We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty to avoid new boot time warnings. The legacy property will be removed in later patches together with the legacy platform data. Let's also correct the custom node name to use generic node name dma. Cc: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am33xx.dtsi | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi index 63c34219fcf6..40ed8e1bfbe6 100644 --- a/arch/arm/boot/dts/am33xx.dtsi +++ b/arch/arm/boot/dts/am33xx.dtsi @@ -245,12 +245,28 @@ }; }; - edma_tptc1: tptc@49900000 { - compatible = "ti,edma3-tptc"; + target-module@49900000 { + compatible = "ti,sysc-omap4", "ti,sysc"; ti,hwmods = "tptc1"; - reg = <0x49900000 0x100000>; - interrupts = <113>; - interrupt-names = "edma3_tcerrint"; + reg = <0x49900000 0x4>, + <0x49900010 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-mask = ; + ti,sysc-midle = ; + ti,sysc-sidle = , + ; + clocks = <&l3_clkctrl AM3_L3_TPTC1_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x49900000 0x100000>; + + edma_tptc1: dma@0 { + compatible = "ti,edma3-tptc"; + reg = <0 0x100000>; + interrupts = <113>; + interrupt-names = "edma3_tcerrint"; + }; }; edma_tptc2: tptc@49a00000 { From 551e01ad62ac3a6932d036631e6143b1363059f8 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 07:25:30 -0800 Subject: [PATCH 1261/4444] ARM: dts: Configure interconnect target module for am3 tptc2 We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty to avoid new boot time warnings. The legacy property will be removed in later patches together with the legacy platform data. Let's also correct the custom node name to use generic node name dma. Cc: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am33xx.dtsi | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi index 40ed8e1bfbe6..d8d93e58750e 100644 --- a/arch/arm/boot/dts/am33xx.dtsi +++ b/arch/arm/boot/dts/am33xx.dtsi @@ -269,12 +269,28 @@ }; }; - edma_tptc2: tptc@49a00000 { - compatible = "ti,edma3-tptc"; + target-module@49a00000 { + compatible = "ti,sysc-omap4", "ti,sysc"; ti,hwmods = "tptc2"; - reg = <0x49a00000 0x100000>; - interrupts = <114>; - interrupt-names = "edma3_tcerrint"; + reg = <0x49a00000 0x4>, + <0x49a00010 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-mask = ; + ti,sysc-midle = ; + ti,sysc-sidle = , + ; + clocks = <&l3_clkctrl AM3_L3_TPTC2_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x49a00000 0x100000>; + + edma_tptc2: dma@0 { + compatible = "ti,edma3-tptc"; + reg = <0 0x100000>; + interrupts = <114>; + interrupt-names = "edma3_tcerrint"; + }; }; target-module@47810000 { From cabc9d127c6f05f304c1eea459c64f7dab0fe2dc Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 07:25:30 -0800 Subject: [PATCH 1262/4444] ARM: dts: Configure interconnect target module for am4 tpcc We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty to avoid new boot time warnings. The legacy property will be removed in later patches together with the legacy platform data. Let's also correct the custom node name to use generic node name dma. Cc: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am4372.dtsi | 39 ++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index 3caddfe1e3e1..fd6b6cb5cf42 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -185,23 +185,34 @@ &pm_sram_data>; }; - edma: edma@49000000 { - compatible = "ti,edma3-tpcc"; + target-module@49000000 { + compatible = "ti,sysc-omap4", "ti,sysc"; ti,hwmods = "tpcc"; - reg = <0x49000000 0x10000>; - reg-names = "edma3_cc"; - interrupts = , - , - ; - interrupt-names = "edma3_ccint", "edma3_mperr", - "edma3_ccerrint"; - dma-requests = <64>; - #dma-cells = <2>; + reg = <0x49000000 0x4>; + reg-names = "rev"; + clocks = <&l3_clkctrl AM4_L3_TPCC_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x49000000 0x10000>; - ti,tptcs = <&edma_tptc0 7>, <&edma_tptc1 5>, - <&edma_tptc2 0>; + edma: dma@0 { + compatible = "ti,edma3-tpcc"; + reg = <0 0x10000>; + reg-names = "edma3_cc"; + interrupts = , + , + ; + interrupt-names = "edma3_ccint", "edma3_mperr", + "edma3_ccerrint"; + dma-requests = <64>; + #dma-cells = <2>; - ti,edma-memcpy-channels = <58 59>; + ti,tptcs = <&edma_tptc0 7>, <&edma_tptc1 5>, + <&edma_tptc2 0>; + + ti,edma-memcpy-channels = <58 59>; + }; }; edma_tptc0: tptc@49800000 { From 0ee89ca32d5b0db9d3e759f7d405d498217a0b67 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 07:25:30 -0800 Subject: [PATCH 1263/4444] ARM: dts: Configure interconnect target module for am4 tptc0 We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty to avoid new boot time warnings. The legacy property will be removed in later patches together with the legacy platform data. Let's also correct the custom node name to use generic node name dma. Cc: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am4372.dtsi | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index fd6b6cb5cf42..17c7a9ae7d95 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -215,12 +215,28 @@ }; }; - edma_tptc0: tptc@49800000 { - compatible = "ti,edma3-tptc"; + target-module@49800000 { + compatible = "ti,sysc-omap4", "ti,sysc"; ti,hwmods = "tptc0"; - reg = <0x49800000 0x100000>; - interrupts = ; - interrupt-names = "edma3_tcerrint"; + reg = <0x49800000 0x4>, + <0x49800010 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-mask = ; + ti,sysc-midle = ; + ti,sysc-sidle = , + ; + clocks = <&l3_clkctrl AM4_L3_TPTC0_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x49800000 0x100000>; + + edma_tptc0: dma@0 { + compatible = "ti,edma3-tptc"; + reg = <0 0x100000>; + interrupts = ; + interrupt-names = "edma3_tcerrint"; + }; }; edma_tptc1: tptc@49900000 { From de01821f2783d23774986535a13b3a8129c08d73 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 07:25:31 -0800 Subject: [PATCH 1264/4444] ARM: dts: Configure interconnect target module for am4 tptc1 We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty to avoid new boot time warnings. The legacy property will be removed in later patches together with the legacy platform data. Let's also correct the custom node name to use generic node name dma. Cc: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am4372.dtsi | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index 17c7a9ae7d95..3f76db2c260b 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -239,12 +239,28 @@ }; }; - edma_tptc1: tptc@49900000 { - compatible = "ti,edma3-tptc"; + target-module@49900000 { + compatible = "ti,sysc-omap4", "ti,sysc"; ti,hwmods = "tptc1"; - reg = <0x49900000 0x100000>; - interrupts = ; - interrupt-names = "edma3_tcerrint"; + reg = <0x49900000 0x4>, + <0x49900010 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-mask = ; + ti,sysc-midle = ; + ti,sysc-sidle = , + ; + clocks = <&l3_clkctrl AM4_L3_TPTC1_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x49900000 0x100000>; + + edma_tptc1: dma@0 { + compatible = "ti,edma3-tptc"; + reg = <0 0x100000>; + interrupts = ; + interrupt-names = "edma3_tcerrint"; + }; }; edma_tptc2: tptc@49a00000 { From 45701c402fe0c2fb8fb0ec7e7f41aa47fe1b583b Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 07:25:31 -0800 Subject: [PATCH 1265/4444] ARM: dts: Configure interconnect target module for am4 tptc2 We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty to avoid new boot time warnings. The legacy property will be removed in later patches together with the legacy platform data. Let's also correct the custom node name to use generic node name dma. Cc: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am4372.dtsi | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index 3f76db2c260b..228c2b5afa33 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -263,12 +263,28 @@ }; }; - edma_tptc2: tptc@49a00000 { - compatible = "ti,edma3-tptc"; + target-module@49a00000 { + compatible = "ti,sysc-omap4", "ti,sysc"; ti,hwmods = "tptc2"; - reg = <0x49a00000 0x100000>; - interrupts = ; - interrupt-names = "edma3_tcerrint"; + reg = <0x49a00000 0x4>, + <0x49a00010 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-mask = ; + ti,sysc-midle = ; + ti,sysc-sidle = , + ; + clocks = <&l3_clkctrl AM4_L3_TPTC2_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x49a00000 0x100000>; + + edma_tptc2: dma@0 { + compatible = "ti,edma3-tptc"; + reg = <0 0x100000>; + interrupts = ; + interrupt-names = "edma3_tcerrint"; + }; }; target-module@47810000 { From 13149bb878b31152daaf8ced098ad3575375a5f2 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 07:25:31 -0800 Subject: [PATCH 1266/4444] ARM: dts: Configure interconnect target module for dra7 tpcc We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty to avoid new boot time warnings. The legacy property will be removed in later patches together with the legacy platform data. Let's also correct the custom node name to use generic node name dma. Cc: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7.dtsi | 47 +++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 9f8758052053..9b664b735c68 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -331,27 +331,38 @@ #pinctrl-cells = <2>; }; - edma: edma@43300000 { - compatible = "ti,edma3-tpcc"; + target-module@43300000 { + compatible = "ti,sysc-omap4", "ti,sysc"; ti,hwmods = "tpcc"; - reg = <0x43300000 0x100000>; - reg-names = "edma3_cc"; - interrupts = , - , - ; - interrupt-names = "edma3_ccint", "edma3_mperr", - "edma3_ccerrint"; - dma-requests = <64>; - #dma-cells = <2>; + reg = <0x43300000 0x4>; + reg-names = "rev"; + clocks = <&l3main1_clkctrl DRA7_L3MAIN1_TPCC_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x43300000 0x100000>; - ti,tptcs = <&edma_tptc0 7>, <&edma_tptc1 0>; + edma: dma@0 { + compatible = "ti,edma3-tpcc"; + reg = <0 0x100000>; + reg-names = "edma3_cc"; + interrupts = , + , + ; + interrupt-names = "edma3_ccint", "edma3_mperr", + "edma3_ccerrint"; + dma-requests = <64>; + #dma-cells = <2>; - /* - * memcpy is disabled, can be enabled with: - * ti,edma-memcpy-channels = <20 21>; - * for example. Note that these channels need to be - * masked in the xbar as well. - */ + ti,tptcs = <&edma_tptc0 7>, <&edma_tptc1 0>; + + /* + * memcpy is disabled, can be enabled with: + * ti,edma-memcpy-channels = <20 21>; + * for example. Note that these channels need to be + * masked in the xbar as well. + */ + }; }; edma_tptc0: tptc@43400000 { From 103d26417492cf577aab0031990c16534eee90dc Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 07:25:31 -0800 Subject: [PATCH 1267/4444] ARM: dts: Configure interconnect target module for dra7 tptc0 We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty to avoid new boot time warnings. The legacy property will be removed in later patches together with the legacy platform data. Let's also correct the custom node name to use generic node name dma. Cc: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7.dtsi | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 9b664b735c68..bdab879e59ea 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -365,12 +365,23 @@ }; }; - edma_tptc0: tptc@43400000 { - compatible = "ti,edma3-tptc"; + target-module@43400000 { + compatible = "ti,sysc-omap4", "ti,sysc"; ti,hwmods = "tptc0"; - reg = <0x43400000 0x100000>; - interrupts = ; - interrupt-names = "edma3_tcerrint"; + reg = <0x43400000 0x4>; + reg-names = "rev"; + clocks = <&l3main1_clkctrl DRA7_L3MAIN1_TPTC0_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x43400000 0x100000>; + + edma_tptc0: dma@0 { + compatible = "ti,edma3-tptc"; + reg = <0 0x100000>; + interrupts = ; + interrupt-names = "edma3_tcerrint"; + }; }; edma_tptc1: tptc@43500000 { From 4286b6741e9bea0f021a0eaeb0ce3283847330b9 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 07:25:31 -0800 Subject: [PATCH 1268/4444] ARM: dts: Configure interconnect target module for dra7 tptc1 We can now probe devices with device tree only configuration using ti-sysc interconnect target module driver. Let's configure the module, but keep the legacy "ti,hwmods" peroperty to avoid new boot time warnings. The legacy property will be removed in later patches together with the legacy platform data. Let's also correct the custom node name to use generic node name dma. Cc: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7.dtsi | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index bdab879e59ea..878c79c1283c 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -384,12 +384,23 @@ }; }; - edma_tptc1: tptc@43500000 { - compatible = "ti,edma3-tptc"; + target-module@43500000 { + compatible = "ti,sysc-omap4", "ti,sysc"; ti,hwmods = "tptc1"; - reg = <0x43500000 0x100000>; - interrupts = ; - interrupt-names = "edma3_tcerrint"; + reg = <0x43500000 0x4>; + reg-names = "rev"; + clocks = <&l3main1_clkctrl DRA7_L3MAIN1_TPTC1_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x43500000 0x100000>; + + edma_tptc1: dma@0 { + compatible = "ti,edma3-tptc"; + reg = <0 0x100000>; + interrupts = ; + interrupt-names = "edma3_tcerrint"; + }; }; dmm@4e000000 { From b2fbe56c22b4e66648fefc53f534271d485ea582 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 07:25:31 -0800 Subject: [PATCH 1269/4444] ARM: OMAP2+: Drop legacy platform data for am3 and am4 edma We can now probe devices with ti-sysc interconnect driver and dts data. Let's drop the related platform data and custom ti,hwmods dts property. As we're just dropping data, and the early platform data init is based on the custom ti,hwmods property, we want to drop both the platform data and ti,hwmods property in a single patch. Cc: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am33xx.dtsi | 4 - arch/arm/boot/dts/am4372.dtsi | 4 - .../omap_hwmod_33xx_43xx_common_data.h | 8 -- .../omap_hwmod_33xx_43xx_interconnect_data.c | 32 -------- .../omap_hwmod_33xx_43xx_ipblock_data.c | 82 ------------------- arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 4 - arch/arm/mach-omap2/omap_hwmod_43xx_data.c | 4 - 7 files changed, 138 deletions(-) diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi index d8d93e58750e..5b4dc957c474 100644 --- a/arch/arm/boot/dts/am33xx.dtsi +++ b/arch/arm/boot/dts/am33xx.dtsi @@ -195,7 +195,6 @@ target-module@49000000 { compatible = "ti,sysc-omap4", "ti,sysc"; - ti,hwmods = "tpcc"; reg = <0x49000000 0x4>; reg-names = "rev"; clocks = <&l3_clkctrl AM3_L3_TPCC_CLKCTRL 0>; @@ -223,7 +222,6 @@ target-module@49800000 { compatible = "ti,sysc-omap4", "ti,sysc"; - ti,hwmods = "tptc0"; reg = <0x49800000 0x4>, <0x49800010 0x4>; reg-names = "rev", "sysc"; @@ -247,7 +245,6 @@ target-module@49900000 { compatible = "ti,sysc-omap4", "ti,sysc"; - ti,hwmods = "tptc1"; reg = <0x49900000 0x4>, <0x49900010 0x4>; reg-names = "rev", "sysc"; @@ -271,7 +268,6 @@ target-module@49a00000 { compatible = "ti,sysc-omap4", "ti,sysc"; - ti,hwmods = "tptc2"; reg = <0x49a00000 0x4>, <0x49a00010 0x4>; reg-names = "rev", "sysc"; diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index 228c2b5afa33..f9eb65457083 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -187,7 +187,6 @@ target-module@49000000 { compatible = "ti,sysc-omap4", "ti,sysc"; - ti,hwmods = "tpcc"; reg = <0x49000000 0x4>; reg-names = "rev"; clocks = <&l3_clkctrl AM4_L3_TPCC_CLKCTRL 0>; @@ -217,7 +216,6 @@ target-module@49800000 { compatible = "ti,sysc-omap4", "ti,sysc"; - ti,hwmods = "tptc0"; reg = <0x49800000 0x4>, <0x49800010 0x4>; reg-names = "rev", "sysc"; @@ -241,7 +239,6 @@ target-module@49900000 { compatible = "ti,sysc-omap4", "ti,sysc"; - ti,hwmods = "tptc1"; reg = <0x49900000 0x4>, <0x49900010 0x4>; reg-names = "rev", "sysc"; @@ -265,7 +262,6 @@ target-module@49a00000 { compatible = "ti,sysc-omap4", "ti,sysc"; - ti,hwmods = "tptc2"; reg = <0x49a00000 0x4>, <0x49a00010 0x4>; reg-names = "rev", "sysc"; diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h index 75aabbf5ff22..fa2ff41f84b9 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h @@ -29,10 +29,6 @@ extern struct omap_hwmod_ocp_if am33xx_l3_main__gfx; extern struct omap_hwmod_ocp_if am33xx_l4_wkup__rtc; extern struct omap_hwmod_ocp_if am33xx_l3_s__gpmc; extern struct omap_hwmod_ocp_if am33xx_l4_ls__timer2; -extern struct omap_hwmod_ocp_if am33xx_l3_main__tpcc; -extern struct omap_hwmod_ocp_if am33xx_l3_main__tptc0; -extern struct omap_hwmod_ocp_if am33xx_l3_main__tptc1; -extern struct omap_hwmod_ocp_if am33xx_l3_main__tptc2; extern struct omap_hwmod_ocp_if am33xx_l3_main__ocmc; extern struct omap_hwmod am33xx_l3_main_hwmod; @@ -50,10 +46,6 @@ extern struct omap_hwmod am33xx_gpmc_hwmod; extern struct omap_hwmod am33xx_rtc_hwmod; extern struct omap_hwmod am33xx_timer1_hwmod; extern struct omap_hwmod am33xx_timer2_hwmod; -extern struct omap_hwmod am33xx_tpcc_hwmod; -extern struct omap_hwmod am33xx_tptc0_hwmod; -extern struct omap_hwmod am33xx_tptc1_hwmod; -extern struct omap_hwmod am33xx_tptc2_hwmod; extern struct omap_hwmod_class am33xx_emif_hwmod_class; extern struct omap_hwmod_class am33xx_l4_hwmod_class; diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c index 4731946ee2ab..0ebbfbb4fb1c 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c @@ -114,38 +114,6 @@ struct omap_hwmod_ocp_if am33xx_l4_ls__timer2 = { .user = OCP_USER_MPU, }; -/* l3 main -> tpcc */ -struct omap_hwmod_ocp_if am33xx_l3_main__tpcc = { - .master = &am33xx_l3_main_hwmod, - .slave = &am33xx_tpcc_hwmod, - .clk = "l3_gclk", - .user = OCP_USER_MPU, -}; - -/* l3 main -> tpcc0 */ -struct omap_hwmod_ocp_if am33xx_l3_main__tptc0 = { - .master = &am33xx_l3_main_hwmod, - .slave = &am33xx_tptc0_hwmod, - .clk = "l3_gclk", - .user = OCP_USER_MPU, -}; - -/* l3 main -> tpcc1 */ -struct omap_hwmod_ocp_if am33xx_l3_main__tptc1 = { - .master = &am33xx_l3_main_hwmod, - .slave = &am33xx_tptc1_hwmod, - .clk = "l3_gclk", - .user = OCP_USER_MPU, -}; - -/* l3 main -> tpcc2 */ -struct omap_hwmod_ocp_if am33xx_l3_main__tptc2 = { - .master = &am33xx_l3_main_hwmod, - .slave = &am33xx_tptc2_hwmod, - .clk = "l3_gclk", - .user = OCP_USER_MPU, -}; - /* l3 main -> ocmc */ struct omap_hwmod_ocp_if am33xx_l3_main__ocmc = { .master = &am33xx_l3_main_hwmod, diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c index dc2a684d375d..dca5a3a7b97c 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c @@ -365,80 +365,6 @@ struct omap_hwmod am33xx_timer2_hwmod = { }, }; -/* tpcc */ -static struct omap_hwmod_class am33xx_tpcc_hwmod_class = { - .name = "tpcc", -}; - -struct omap_hwmod am33xx_tpcc_hwmod = { - .name = "tpcc", - .class = &am33xx_tpcc_hwmod_class, - .clkdm_name = "l3_clkdm", - .main_clk = "l3_gclk", - .prcm = { - .omap4 = { - .modulemode = MODULEMODE_SWCTRL, - }, - }, -}; - -static struct omap_hwmod_class_sysconfig am33xx_tptc_sysc = { - .rev_offs = 0x0, - .sysc_offs = 0x10, - .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | - SYSC_HAS_MIDLEMODE), - .idlemodes = (SIDLE_FORCE | SIDLE_SMART | MSTANDBY_FORCE), - .sysc_fields = &omap_hwmod_sysc_type2, -}; - -/* 'tptc' class */ -static struct omap_hwmod_class am33xx_tptc_hwmod_class = { - .name = "tptc", - .sysc = &am33xx_tptc_sysc, -}; - -/* tptc0 */ -struct omap_hwmod am33xx_tptc0_hwmod = { - .name = "tptc0", - .class = &am33xx_tptc_hwmod_class, - .clkdm_name = "l3_clkdm", - .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY, - .main_clk = "l3_gclk", - .prcm = { - .omap4 = { - .modulemode = MODULEMODE_SWCTRL, - }, - }, -}; - -/* tptc1 */ -struct omap_hwmod am33xx_tptc1_hwmod = { - .name = "tptc1", - .class = &am33xx_tptc_hwmod_class, - .clkdm_name = "l3_clkdm", - .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY), - .main_clk = "l3_gclk", - .prcm = { - .omap4 = { - .modulemode = MODULEMODE_SWCTRL, - }, - }, -}; - -/* tptc2 */ -struct omap_hwmod am33xx_tptc2_hwmod = { - .name = "tptc2", - .class = &am33xx_tptc_hwmod_class, - .clkdm_name = "l3_clkdm", - .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY), - .main_clk = "l3_gclk", - .prcm = { - .omap4 = { - .modulemode = MODULEMODE_SWCTRL, - }, - }, -}; - static void omap_hwmod_am33xx_clkctrl(void) { CLKCTRL(am33xx_timer2_hwmod, AM33XX_CM_PER_TIMER2_CLKCTRL_OFFSET); @@ -453,10 +379,6 @@ static void omap_hwmod_am33xx_clkctrl(void) CLKCTRL(am33xx_l4_ls_hwmod, AM33XX_CM_PER_L4LS_CLKCTRL_OFFSET); CLKCTRL(am33xx_l4_wkup_hwmod, AM33XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET); CLKCTRL(am33xx_l3_main_hwmod, AM33XX_CM_PER_L3_CLKCTRL_OFFSET); - CLKCTRL(am33xx_tpcc_hwmod, AM33XX_CM_PER_TPCC_CLKCTRL_OFFSET); - CLKCTRL(am33xx_tptc0_hwmod, AM33XX_CM_PER_TPTC0_CLKCTRL_OFFSET); - CLKCTRL(am33xx_tptc1_hwmod, AM33XX_CM_PER_TPTC1_CLKCTRL_OFFSET); - CLKCTRL(am33xx_tptc2_hwmod, AM33XX_CM_PER_TPTC2_CLKCTRL_OFFSET); CLKCTRL(am33xx_gfx_hwmod, AM33XX_CM_GFX_GFX_CLKCTRL_OFFSET); CLKCTRL(am33xx_mpu_hwmod , AM33XX_CM_MPU_MPU_CLKCTRL_OFFSET); CLKCTRL(am33xx_l3_instr_hwmod , AM33XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET); @@ -488,10 +410,6 @@ static void omap_hwmod_am43xx_clkctrl(void) CLKCTRL(am33xx_l4_ls_hwmod, AM43XX_CM_PER_L4LS_CLKCTRL_OFFSET); CLKCTRL(am33xx_l4_wkup_hwmod, AM43XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET); CLKCTRL(am33xx_l3_main_hwmod, AM43XX_CM_PER_L3_CLKCTRL_OFFSET); - CLKCTRL(am33xx_tpcc_hwmod, AM43XX_CM_PER_TPCC_CLKCTRL_OFFSET); - CLKCTRL(am33xx_tptc0_hwmod, AM43XX_CM_PER_TPTC0_CLKCTRL_OFFSET); - CLKCTRL(am33xx_tptc1_hwmod, AM43XX_CM_PER_TPTC1_CLKCTRL_OFFSET); - CLKCTRL(am33xx_tptc2_hwmod, AM43XX_CM_PER_TPTC2_CLKCTRL_OFFSET); CLKCTRL(am33xx_gfx_hwmod, AM43XX_CM_GFX_GFX_CLKCTRL_OFFSET); CLKCTRL(am33xx_mpu_hwmod , AM43XX_CM_MPU_MPU_CLKCTRL_OFFSET); CLKCTRL(am33xx_l3_instr_hwmod , AM43XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET); diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c index 1c258616b9a9..c64b735c8acc 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c @@ -294,11 +294,7 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = { &am33xx_l4_wkup__timer1, &am33xx_l4_wkup__rtc, &am33xx_l4_ls__timer2, - &am33xx_l3_main__tpcc, &am33xx_l3_s__gpmc, - &am33xx_l3_main__tptc0, - &am33xx_l3_main__tptc1, - &am33xx_l3_main__tptc2, &am33xx_l3_main__ocmc, NULL, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c index 7fd435363276..d2203f44af88 100644 --- a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c @@ -254,11 +254,7 @@ static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = { &am43xx_l4_wkup__smartreflex1, &am43xx_l4_wkup__timer1, &am33xx_l4_ls__timer2, - &am33xx_l3_main__tpcc, &am33xx_l3_s__gpmc, - &am33xx_l3_main__tptc0, - &am33xx_l3_main__tptc1, - &am33xx_l3_main__tptc2, &am33xx_l3_main__ocmc, &am43xx_l3_s__usbotgss0, &am43xx_l3_s__usbotgss1, From 104d56b3e3766931ff1a1d786d2fcce908daaaf7 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 07:25:31 -0800 Subject: [PATCH 1270/4444] ARM: OMAP2+: Drop legacy platform data for dra7 edma We can now probe devices with ti-sysc interconnect driver and dts data. Let's drop the related platform data and custom ti,hwmods dts property. As we're just dropping data, and the early platform data init is based on the custom ti,hwmods property, we want to drop both the platform data and ti,hwmods property in a single patch. Cc: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7.dtsi | 3 - arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 88 ----------------------- 2 files changed, 91 deletions(-) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 878c79c1283c..00a286426f16 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -333,7 +333,6 @@ target-module@43300000 { compatible = "ti,sysc-omap4", "ti,sysc"; - ti,hwmods = "tpcc"; reg = <0x43300000 0x4>; reg-names = "rev"; clocks = <&l3main1_clkctrl DRA7_L3MAIN1_TPCC_CLKCTRL 0>; @@ -367,7 +366,6 @@ target-module@43400000 { compatible = "ti,sysc-omap4", "ti,sysc"; - ti,hwmods = "tptc0"; reg = <0x43400000 0x4>; reg-names = "rev"; clocks = <&l3main1_clkctrl DRA7_L3MAIN1_TPTC0_CLKCTRL 0>; @@ -386,7 +384,6 @@ target-module@43500000 { compatible = "ti,sysc-omap4", "ti,sysc"; - ti,hwmods = "tptc1"; reg = <0x43500000 0x4>; reg-names = "rev"; clocks = <&l3main1_clkctrl DRA7_L3MAIN1_TPTC1_CLKCTRL 0>; diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c index 2f60333caaf1..e95668bdbc3f 100644 --- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c @@ -276,67 +276,6 @@ static struct omap_hwmod dra7xx_ctrl_module_wkup_hwmod = { }, }; -/* - * 'tpcc' class - * - */ -static struct omap_hwmod_class dra7xx_tpcc_hwmod_class = { - .name = "tpcc", -}; - -static struct omap_hwmod dra7xx_tpcc_hwmod = { - .name = "tpcc", - .class = &dra7xx_tpcc_hwmod_class, - .clkdm_name = "l3main1_clkdm", - .main_clk = "l3_iclk_div", - .prcm = { - .omap4 = { - .clkctrl_offs = DRA7XX_CM_L3MAIN1_TPCC_CLKCTRL_OFFSET, - .context_offs = DRA7XX_RM_L3MAIN1_TPCC_CONTEXT_OFFSET, - }, - }, -}; - -/* - * 'tptc' class - * - */ -static struct omap_hwmod_class dra7xx_tptc_hwmod_class = { - .name = "tptc", -}; - -/* tptc0 */ -static struct omap_hwmod dra7xx_tptc0_hwmod = { - .name = "tptc0", - .class = &dra7xx_tptc_hwmod_class, - .clkdm_name = "l3main1_clkdm", - .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY, - .main_clk = "l3_iclk_div", - .prcm = { - .omap4 = { - .clkctrl_offs = DRA7XX_CM_L3MAIN1_TPTC1_CLKCTRL_OFFSET, - .context_offs = DRA7XX_RM_L3MAIN1_TPTC1_CONTEXT_OFFSET, - .modulemode = MODULEMODE_HWCTRL, - }, - }, -}; - -/* tptc1 */ -static struct omap_hwmod dra7xx_tptc1_hwmod = { - .name = "tptc1", - .class = &dra7xx_tptc_hwmod_class, - .clkdm_name = "l3main1_clkdm", - .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY, - .main_clk = "l3_iclk_div", - .prcm = { - .omap4 = { - .clkctrl_offs = DRA7XX_CM_L3MAIN1_TPTC2_CLKCTRL_OFFSET, - .context_offs = DRA7XX_RM_L3MAIN1_TPTC2_CONTEXT_OFFSET, - .modulemode = MODULEMODE_HWCTRL, - }, - }, -}; - /* * 'gpmc' class * @@ -941,30 +880,6 @@ static struct omap_hwmod_ocp_if dra7xx_l4_wkup__ctrl_module_wkup = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; -/* l3_main_1 -> tpcc */ -static struct omap_hwmod_ocp_if dra7xx_l3_main_1__tpcc = { - .master = &dra7xx_l3_main_1_hwmod, - .slave = &dra7xx_tpcc_hwmod, - .clk = "l3_iclk_div", - .user = OCP_USER_MPU, -}; - -/* l3_main_1 -> tptc0 */ -static struct omap_hwmod_ocp_if dra7xx_l3_main_1__tptc0 = { - .master = &dra7xx_l3_main_1_hwmod, - .slave = &dra7xx_tptc0_hwmod, - .clk = "l3_iclk_div", - .user = OCP_USER_MPU, -}; - -/* l3_main_1 -> tptc1 */ -static struct omap_hwmod_ocp_if dra7xx_l3_main_1__tptc1 = { - .master = &dra7xx_l3_main_1_hwmod, - .slave = &dra7xx_tptc1_hwmod, - .clk = "l3_iclk_div", - .user = OCP_USER_MPU, -}; - /* l3_main_1 -> gpmc */ static struct omap_hwmod_ocp_if dra7xx_l3_main_1__gpmc = { .master = &dra7xx_l3_main_1_hwmod, @@ -1149,9 +1064,6 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = { &dra7xx_l3_main_1__bb2d, &dra7xx_l4_wkup__counter_32k, &dra7xx_l4_wkup__ctrl_module_wkup, - &dra7xx_l3_main_1__tpcc, - &dra7xx_l3_main_1__tptc0, - &dra7xx_l3_main_1__tptc1, &dra7xx_l3_main_1__gpmc, &dra7xx_l4_cfg__mpu, &dra7xx_l3_main_1__pciess1, From d902e7856d2a3b5da7acab90e5faec22e395e57a Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 6 Mar 2020 15:26:33 +0000 Subject: [PATCH 1271/4444] ASoC: wcd9335: fix address map representation slimbus addresses are 16 bit wide, masking page numbers to wcd register at offset of 12 will limit the number for pages. So it becomes impossible to write to page 0x10 registers. Remove masking 0x800 (slimbus address range) from register address and making use of window parameters in regmap config should fix it and also will represent the registers exactly inline with Datasheet. Remove this unnessary masking and make the registers be inline with datasheet. Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20200306152633.25836-1-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd9335.c | 18 +++++++++--------- sound/soc/codecs/wcd9335.h | 7 ++++--- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index f11ffa28683b..700cc1212770 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -4926,11 +4926,11 @@ static const struct regmap_range_cfg wcd9335_ranges[] = { .name = "WCD9335", .range_min = 0x0, .range_max = WCD9335_MAX_REGISTER, - .selector_reg = WCD9335_REG(0x0, 0), + .selector_reg = WCD9335_SEL_REGISTER, .selector_mask = 0xff, .selector_shift = 0, - .window_start = 0x0, - .window_len = 0x1000, + .window_start = 0x800, + .window_len = 0x100, }, }; @@ -4968,12 +4968,12 @@ static const struct regmap_range_cfg wcd9335_ifc_ranges[] = { { .name = "WCD9335-IFC-DEV", .range_min = 0x0, - .range_max = WCD9335_REG(0, 0x7ff), - .selector_reg = WCD9335_REG(0, 0x0), - .selector_mask = 0xff, + .range_max = WCD9335_MAX_REGISTER, + .selector_reg = WCD9335_SEL_REGISTER, + .selector_mask = 0xfff, .selector_shift = 0, - .window_start = 0x0, - .window_len = 0x1000, + .window_start = 0x800, + .window_len = 0x400, }, }; @@ -4981,7 +4981,7 @@ static struct regmap_config wcd9335_ifc_regmap_config = { .reg_bits = 16, .val_bits = 8, .can_multi_write = true, - .max_register = WCD9335_REG(0, 0x7FF), + .max_register = WCD9335_MAX_REGISTER, .ranges = wcd9335_ifc_ranges, .num_ranges = ARRAY_SIZE(wcd9335_ifc_ranges), }; diff --git a/sound/soc/codecs/wcd9335.h b/sound/soc/codecs/wcd9335.h index 4d9be2496c30..72060824c743 100644 --- a/sound/soc/codecs/wcd9335.h +++ b/sound/soc/codecs/wcd9335.h @@ -8,9 +8,9 @@ * in slimbus mode the reg base starts from 0x800 * in i2s/i2c mode the reg base is 0x0 */ -#define WCD9335_REG(pg, r) ((pg << 12) | (r) | 0x800) +#define WCD9335_REG(pg, r) ((pg << 8) | (r)) #define WCD9335_REG_OFFSET(r) (r & 0xFF) -#define WCD9335_PAGE_OFFSET(r) ((r >> 12) & 0xFF) +#define WCD9335_PAGE_OFFSET(r) ((r >> 8) & 0xFF) /* Page-0 Registers */ #define WCD9335_PAGE0_PAGE_REGISTER WCD9335_REG(0x00, 0x000) @@ -600,7 +600,8 @@ #define WCD9335_CDC_CLK_RST_CTRL_FS_CNT_ENABLE BIT(0) #define WCD9335_CDC_CLK_RST_CTRL_FS_CNT_DISABLE 0 #define WCD9335_CDC_TOP_TOP_CFG1 WCD9335_REG(0x0d, 0x082) -#define WCD9335_MAX_REGISTER WCD9335_REG(0x80, 0x0FF) +#define WCD9335_MAX_REGISTER 0xffff +#define WCD9335_SEL_REGISTER 0x800 /* SLIMBUS Slave Registers */ #define WCD9335_SLIM_PGD_PORT_INT_EN0 WCD9335_REG(0, 0x30) From 7e11f4c0c5ccaac5e8ee1b2e46b3c2cbc47d199e Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 5 Mar 2020 11:28:38 +0100 Subject: [PATCH 1272/4444] platform/chrome: Kconfig: Remove CONFIG_ prefix from MFD_CROS_EC section Remove the CONFIG_ prefix from the select statement for MFD_CROS_EC. Fixes: 2fa2b980e3fe1 ("mfd / platform: cros_ec: Rename config to a better name") Reported-by: Randy Dunlap Signed-off-by: Enric Balletbo i Serra Acked-by: Andy Shevchenko Acked-by: Randy Dunlap --- drivers/platform/chrome/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig index 15fc8b8a2db8..5ae6c49f553d 100644 --- a/drivers/platform/chrome/Kconfig +++ b/drivers/platform/chrome/Kconfig @@ -7,7 +7,7 @@ config MFD_CROS_EC tristate "Platform support for Chrome hardware (transitional)" select CHROME_PLATFORMS select CROS_EC - select CONFIG_MFD_CROS_EC_DEV + select MFD_CROS_EC_DEV depends on X86 || ARM || ARM64 || COMPILE_TEST help This is a transitional Kconfig option and will be removed after From 1dd5ddc125b4625c3beb8e644ae872445d739bbc Mon Sep 17 00:00:00 2001 From: "Sergei A. Trusov" Date: Thu, 5 Mar 2020 19:53:06 -0800 Subject: [PATCH 1273/4444] Input: goodix - fix touch coordinates on Cube I15-TC The touchscreen on the Cube I15-TC don't match the default display, with 0,0 touches being reported when touching at the top-right of the screen. Add a quirk to invert the x coordinate. Reported-and-tested-by: Arkadiy Signed-off-by: Sergei A. Trusov Reviewed-by: Bastien Nocera Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/goodix.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index 0403102e807e..37b35ab97beb 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -168,6 +168,22 @@ static const struct dmi_system_id nine_bytes_report[] = { {} }; +/* + * Those tablets have their x coordinate inverted + */ +static const struct dmi_system_id inverted_x_screen[] = { +#if defined(CONFIG_DMI) && defined(CONFIG_X86) + { + .ident = "Cube I15-TC", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Cube"), + DMI_MATCH(DMI_PRODUCT_NAME, "I15-TC") + }, + }, +#endif + {} +}; + /** * goodix_i2c_read - read data from a register of the i2c slave device. * @@ -780,6 +796,12 @@ static int goodix_configure_dev(struct goodix_ts_data *ts) "Non-standard 9-bytes report format quirk\n"); } + if (dmi_check_system(inverted_x_screen)) { + ts->prop.invert_x = true; + dev_dbg(&ts->client->dev, + "Applying 'inverted x screen' quirk\n"); + } + error = input_mt_init_slots(ts->input_dev, ts->max_touch_num, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); if (error) { From 061706716384f1633d3d5090b22a99f33f1fcf2f Mon Sep 17 00:00:00 2001 From: Johnny Chuang Date: Fri, 6 Mar 2020 10:05:20 -0800 Subject: [PATCH 1274/4444] Input: elants_i2c - report resolution information for touch major This patch supports reporting resolution for ABS_MT_TOUCH_MAJOR event. This information is needed in showing pressure/width radius. Signed-off-by: Johnny Chuang Reviewed-by: Harry Cutts Reviewed-by: Peter Hutterer Acked-by: Benjamin Tissoires Link: https://lore.kernel.org/r/1582766000-23023-1-git-send-email-johnny.chuang.emc@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/elants_i2c.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 491179967b29..14c577c16b16 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -1309,6 +1309,7 @@ static int elants_i2c_probe(struct i2c_client *client, input_set_abs_params(ts->input, ABS_MT_PRESSURE, 0, 255, 0, 0); input_abs_set_res(ts->input, ABS_MT_POSITION_X, ts->x_res); input_abs_set_res(ts->input, ABS_MT_POSITION_Y, ts->y_res); + input_abs_set_res(ts->input, ABS_MT_TOUCH_MAJOR, 1); error = input_register_device(ts->input); if (error) { From 5a65505a6988443b211d3bf3f5bb5b79907c33b9 Mon Sep 17 00:00:00 2001 From: Tobias Schramm Date: Wed, 4 Mar 2020 22:30:23 +0100 Subject: [PATCH 1275/4444] arm64: dts: rockchip: Add initial support for Pinebook Pro This commit adds initial dt support for the rk3399 based Pinebook Pro. Signed-off-by: Tobias Schramm Link: https://lore.kernel.org/r/20200304213023.689983-3-t.schramm@manjaro.org Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/Makefile | 1 + .../boot/dts/rockchip/rk3399-pinebook-pro.dts | 1096 +++++++++++++++++ 2 files changed, 1097 insertions(+) create mode 100644 arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index 60d9437096c7..ae7621309e92 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -28,6 +28,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopc-t4.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-m4.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-neo4.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-orangepi.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-pinebook-pro.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-puma-haikou.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-roc-pc.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-roc-pc-mezzanine.dtb diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts new file mode 100644 index 000000000000..5ea281b55fe2 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts @@ -0,0 +1,1096 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd. + * Copyright (c) 2018 Akash Gajjar + * Copyright (c) 2020 Tobias Schramm + */ + +/dts-v1/; +#include +#include +#include +#include +#include +#include "rk3399.dtsi" +#include "rk3399-opp.dtsi" + +/ { + model = "Pine64 Pinebook Pro"; + compatible = "pine64,pinebook-pro", "rockchip,rk3399"; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + backlight: edp-backlight { + compatible = "pwm-backlight"; + power-supply = <&vcc_12v>; + pwms = <&pwm0 0 740740 0>; + }; + + edp_panel: edp-panel { + compatible = "boe,nv140fhmn49"; + backlight = <&backlight>; + enable-gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&panel_en_gpio>; + power-supply = <&vcc3v3_panel>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + panel_in_edp: endpoint@0 { + reg = <0>; + remote-endpoint = <&edp_out_panel>; + }; + }; + }; + }; + + /* + * Use separate nodes for gpio-keys to allow for selective deactivation + * of wakeup sources via sysfs without disabling the whole key + */ + gpio-key-lid { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&lidbtn_gpio>; + + lid { + debounce-interval = <20>; + gpios = <&gpio1 RK_PA1 GPIO_ACTIVE_LOW>; + label = "Lid"; + linux,code = ; + linux,input-type = ; + wakeup-event-action = ; + wakeup-source; + }; + }; + + gpio-key-power { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&pwrbtn_gpio>; + + power { + debounce-interval = <20>; + gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>; + label = "Power"; + linux,code = ; + wakeup-source; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pwrled_gpio &slpled_gpio>; + + green-led { + color = ; + default-state = "on"; + function = LED_FUNCTION_POWER; + gpios = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; + label = "green:power"; + }; + + red-led { + color = ; + default-state = "off"; + function = LED_FUNCTION_STANDBY; + gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; + label = "red:standby"; + panic-indicator; + retain-state-suspended; + }; + }; + + /* Power sequence for SDIO WiFi module */ + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&rk808 1>; + clock-names = "ext_clock"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_enable_h_gpio>; + post-power-on-delay-ms = <100>; + power-off-delay-us = <500000>; + + /* WL_REG_ON on module */ + reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; + }; + + /* Audio components */ + es8316-sound { + compatible = "simple-audio-card"; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det_gpio>; + simple-audio-card,name = "rockchip,es8316-codec"; + simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; + + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Headphone", "Headphones", + "Speaker", "Speaker"; + simple-audio-card,routing = + "MIC1", "Mic Jack", + "Headphones", "HPOL", + "Headphones", "HPOR", + "Speaker Amplifier INL", "HPOL", + "Speaker Amplifier INR", "HPOR", + "Speaker", "Speaker Amplifier OUTL", + "Speaker", "Speaker Amplifier OUTR"; + + simple-audio-card,hp-det-gpio = <&gpio0 RK_PB0 GPIO_ACTIVE_LOW>; + simple-audio-card,aux-devs = <&speaker_amp>; + simple-audio-card,pin-switches = "Speaker"; + + simple-audio-card,cpu { + sound-dai = <&i2s1>; + }; + + simple-audio-card,codec { + sound-dai = <&es8316>; + }; + }; + + speaker_amp: speaker-amplifier { + compatible = "simple-audio-amplifier"; + enable-gpios = <&gpio4 RK_PD3 GPIO_ACTIVE_HIGH>; + sound-name-prefix = "Speaker Amplifier"; + VCC-supply = <&pa_5v>; + }; + + /* Power tree */ + /* Root power source */ + vcc_sysin: vcc-sysin { + compatible = "regulator-fixed"; + regulator-name = "vcc_sysin"; + regulator-always-on; + regulator-boot-on; + }; + + /* Regulators supplied by vcc_sysin */ + /* LCD backlight supply */ + vcc_12v: vcc-12v { + compatible = "regulator-fixed"; + regulator-name = "vcc_12v"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + vin-supply = <&vcc_sysin>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + /* Main 3.3 V supply */ + vcc3v3_sys: wifi_bat: vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_sysin>; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + /* 5 V USB power supply */ + vcc5v0_usb: pa_5v: vcc5v0-usb-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwr_5v_gpio>; + regulator-name = "vcc5v0_usb"; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc_sysin>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + /* RK3399 logic supply */ + vdd_log: vdd-log { + compatible = "pwm-regulator"; + pwms = <&pwm2 0 25000 1>; + regulator-name = "vdd_log"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1400000>; + vin-supply = <&vcc_sysin>; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + /* Regulators supplied by vcc3v3_sys */ + /* 0.9 V supply, always on */ + vcc_0v9: vcc-0v9 { + compatible = "regulator-fixed"; + regulator-name = "vcc_0v9"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + vin-supply = <&vcc3v3_sys>; + }; + + /* S3 1.8 V supply, switched by vcc1v8_s3 */ + vcca1v8_s3: vcc1v8-s3 { + compatible = "regulator-fixed"; + regulator-name = "vcca1v8_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vcc3v3_sys>; + }; + + /* micro SD card power */ + vcc3v0_sd: vcc3v0-sd { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_pwr_h_gpio>; + regulator-name = "vcc3v0_sd"; + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + vin-supply = <&vcc3v3_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + /* LCD panel power, called VCC3V3_S0 in schematic */ + vcc3v3_panel: vcc3v3-panel { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 RK_PC6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&lcdvcc_en_gpio>; + regulator-name = "vcc3v3_panel"; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <100000>; + vin-supply = <&vcc3v3_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + /* M.2 adapter power, switched by vcc1v8_s3 */ + vcc3v3_ssd: vcc3v3-ssd { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_ssd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc3v3_sys>; + }; + + /* Regulators supplied by vcc5v0_usb */ + /* USB 3 port power supply regulator */ + vcc5v0_otg: vcc5v0-otg { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en_gpio>; + regulator-name = "vcc5v0_otg"; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usb>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + /* Regulators supplied by vcc5v0_usb */ + /* Type C port power supply regulator */ + vbus_5vout: vbus_typec: vbus-5vout { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_typec0_en_gpio>; + regulator-name = "vbus_5vout"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usb>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + /* Regulators supplied by vcc_1v8 */ + /* Primary 0.9 V LDO */ + vcca0v9_s3: vcca0v9-s3 { + compatible = "regulator-fixed"; + regulator-name = "vcc0v9_s3"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc_1v8>; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + mains_charger: dc-charger { + compatible = "gpio-charger"; + charger-type = "mains"; + gpios = <&gpio4 RK_PD0 GPIO_ACTIVE_LOW>; + + /* Also triggered by USB charger */ + pinctrl-names = "default"; + pinctrl-0 = <&dc_det_gpio>; + }; +}; + +&cdn_dp { + status = "okay"; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_b>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_b>; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_l>; +}; + +&edp { + force-hpd; + pinctrl-names = "default"; + pinctrl-0 = <&edp_hpd>; + status = "okay"; + + ports { + edp_out: port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + edp_out_panel: endpoint@0 { + reg = <0>; + remote-endpoint = <&panel_in_edp>; + }; + }; + }; +}; + +&emmc_phy { + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_gpu>; + status = "okay"; +}; + +&hdmi_sound { + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-falling-time-ns = <4>; + i2c-scl-rising-time-ns = <168>; + status = "okay"; + + rk808: pmic@1b { + compatible = "rockchip,rk808"; + reg = <0x1b>; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + interrupt-parent = <&gpio3>; + interrupts = <10 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l_gpio>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc_sysin>; + vcc2-supply = <&vcc_sysin>; + vcc3-supply = <&vcc_sysin>; + vcc4-supply = <&vcc_sysin>; + vcc6-supply = <&vcc_sysin>; + vcc7-supply = <&vcc_sysin>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc_sysin>; + vcc10-supply = <&vcc_sysin>; + vcc11-supply = <&vcc_sysin>; + vcc12-supply = <&vcc3v3_sys>; + vcc13-supply = <&vcc_sysin>; + vcc14-supply = <&vcc_sysin>; + + regulators { + /* rk3399 center logic supply */ + vdd_center: DCDC_REG1 { + regulator-name = "vdd_center"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_l: DCDC_REG2 { + regulator-name = "vdd_cpu_l"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_1v8: vcc_wl: DCDC_REG4 { + regulator-name = "vcc_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + /* not used */ + LDO_REG1 { + }; + + /* not used */ + LDO_REG2 { + }; + + vcc1v8_pmupll: LDO_REG3 { + regulator-name = "vcc1v8_pmupll"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_sdio: LDO_REG4 { + regulator-name = "vcc_sdio"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3000000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcca3v0_codec: LDO_REG5 { + regulator-name = "vcca3v0_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v5: LDO_REG6 { + regulator-name = "vcc_1v5"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcca1v8_codec: LDO_REG7 { + regulator-name = "vcca1v8_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v0: LDO_REG8 { + regulator-name = "vcc_3v0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc3v3_s3: SWITCH_REG1 { + regulator-name = "vcc3v3_s3"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_s0: SWITCH_REG2 { + regulator-name = "vcc3v3_s0"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; + + vdd_cpu_b: regulator@40 { + compatible = "silergy,syr827"; + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&vsel1_gpio>; + regulator-name = "vdd_cpu_b"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-ramp-delay = <1000>; + vin-supply = <&vcc_1v8>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: regulator@41 { + compatible = "silergy,syr828"; + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&vsel2_gpio>; + regulator-name = "vdd_gpu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-ramp-delay = <1000>; + vin-supply = <&vcc_1v8>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c1 { + clock-frequency = <100000>; + i2c-scl-falling-time-ns = <4>; + i2c-scl-rising-time-ns = <168>; + status = "okay"; + + es8316: es8316@11 { + compatible = "everest,es8316"; + reg = <0x11>; + clocks = <&cru SCLK_I2S_8CH_OUT>; + clock-names = "mclk"; + #sound-dai-cells = <0>; + }; +}; + +&i2c3 { + i2c-scl-falling-time-ns = <15>; + i2c-scl-rising-time-ns = <450>; + status = "okay"; +}; + +&i2c4 { + i2c-scl-falling-time-ns = <20>; + i2c-scl-rising-time-ns = <600>; + status = "okay"; + + fusb0: fusb30x@22 { + compatible = "fcs,fusb302"; + reg = <0x22>; + fcs,int_n = <&gpio1 RK_PA2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&fusb0_int_gpio>; + vbus-supply = <&vbus_typec>; + + connector { + compatible = "usb-c-connector"; + data-role = "host"; + label = "USB-C"; + op-sink-microwatt = <1000000>; + power-role = "dual"; + sink-pdos = + ; + source-pdos = + ; + try-power-role = "sink"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usbc_hs: endpoint { + remote-endpoint = + <&u2phy0_typec_hs>; + }; + }; + + port@1 { + reg = <1>; + + usbc_ss: endpoint { + remote-endpoint = + <&tcphy0_typec_ss>; + }; + }; + + port@2 { + reg = <2>; + + usbc_dp: endpoint { + remote-endpoint = + <&tcphy0_typec_dp>; + }; + }; + }; + }; + }; +}; + +&i2s1 { + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_8ch_mclk_gpio>, <&i2s1_2ch_bus>; + rockchip,capture-channels = <8>; + rockchip,playback-channels = <8>; + status = "okay"; +}; + +&io_domains { + audio-supply = <&vcc_3v0>; + gpio1830-supply = <&vcc_3v0>; + sdmmc-supply = <&vcc_sdio>; + status = "okay"; +}; + +&pcie_phy { + status = "okay"; +}; + +&pcie0 { + bus-scan-delay-ms = <1000>; + ep-gpios = <&gpio2 RK_PD4 GPIO_ACTIVE_HIGH>; + max-link-speed = <2>; + num-lanes = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_clkreqn_cpm>; + vpcie0v9-supply = <&vcca0v9_s3>; + vpcie1v8-supply = <&vcca1v8_s3>; + vpcie3v3-supply = <&vcc3v3_ssd>; + status = "okay"; +}; + +&pinctrl { + buttons { + pwrbtn_gpio: pwrbtn-gpio { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + lidbtn_gpio: lidbtn-gpio { + rockchip,pins = <1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + dc-charger { + dc_det_gpio: dc-det-gpio { + rockchip,pins = <4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + es8316 { + hp_det_gpio: hp-det-gpio { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + fusb302x { + fusb0_int_gpio: fusb0-int-gpio { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + i2s1 { + i2s_8ch_mclk_gpio: i2s-8ch-mclk-gpio { + rockchip,pins = <4 RK_PA0 1 &pcfg_pull_none>; + }; + }; + + lcd-panel { + lcdvcc_en_gpio: lcdvcc-en-gpio { + rockchip,pins = <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + panel_en_gpio: panel-en-gpio { + rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + lcd_panel_reset_gpio: lcd-panel-reset-gpio { + rockchip,pins = <4 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + leds { + pwrled_gpio: pwrled_gpio { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + slpled_gpio: slpled_gpio { + rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int_l_gpio: pmic-int-l-gpio { + rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + vsel1_gpio: vsel1-gpio { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + vsel2_gpio: vsel2-gpio { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + sdcard { + sdmmc0_pwr_h_gpio: sdmmc0-pwr-h-gpio { + rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + }; + + sdio-pwrseq { + wifi_enable_h_gpio: wifi-enable-h-gpio { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb-typec { + vcc5v0_typec0_en_gpio: vcc5v0-typec0-en-gpio { + rockchip,pins = <1 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb2 { + pwr_5v_gpio: pwr-5v-gpio { + rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + vcc5v0_host_en_gpio: vcc5v0-host-en-gpio { + rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + wireless-bluetooth { + bt_wake_gpio: bt-wake-gpio { + rockchip,pins = <2 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + bt_host_wake_gpio: bt-host-wake-gpio { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + bt_reset_gpio: bt-reset-gpio { + rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pmu_io_domains { + pmu1830-supply = <&vcc_3v0>; + status = "okay"; +}; + +&pwm0 { + status = "okay"; +}; + +&pwm2 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcca1v8_s3>; + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; + disable-wp; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4>; + sd-uhs-sdr104; + vmmc-supply = <&vcc3v0_sd>; + vqmmc-supply = <&vcc_sdio>; + status = "okay"; +}; + +&sdio0 { + bus-width = <4>; + cap-sd-highspeed; + cap-sdio-irq; + keep-power-in-suspend; + mmc-pwrseq = <&sdio_pwrseq>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>; + sd-uhs-sdr104; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + mmc-hs200-1_8v; + non-removable; + status = "okay"; +}; + +&spi1 { + max-freq = <10000000>; + status = "okay"; + + spiflash: flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + m25p,fast-read; + spi-max-frequency = <10000000>; + }; +}; + +&tcphy0 { + status = "okay"; +}; + +&tcphy0_dp { + port { + tcphy0_typec_dp: endpoint { + remote-endpoint = <&usbc_dp>; + }; + }; +}; + +&tcphy0_usb3 { + port { + tcphy0_typec_ss: endpoint { + remote-endpoint = <&usbc_ss>; + }; + }; +}; + +&tcphy1 { + status = "okay"; +}; + +&tsadc { + /* tshut mode 0:CRU 1:GPIO */ + rockchip,hw-tshut-mode = <1>; + /* tshut polarity 0:LOW 1:HIGH */ + rockchip,hw-tshut-polarity = <1>; + status = "okay"; +}; + +&u2phy0 { + status = "okay"; + + u2phy0_otg: otg-port { + status = "okay"; + }; + + u2phy0_host: host-port { + phy-supply = <&vcc5v0_otg>; + status = "okay"; + }; + + port { + u2phy0_typec_hs: endpoint { + remote-endpoint = <&usbc_hs>; + }; + }; +}; + +&u2phy1 { + status = "okay"; + + u2phy1_otg: otg-port { + status = "okay"; + }; + + u2phy1_host: host-port { + phy-supply = <&vcc5v0_otg>; + status = "okay"; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>; + uart-has-rtscts; + status = "okay"; + + bluetooth { + compatible = "brcm,bcm4345c5"; + clocks = <&rk808 1>; + clock-names = "lpo"; + device-wakeup-gpios = <&gpio2 RK_PD3 GPIO_ACTIVE_HIGH>; + host-wakeup-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>; + max-speed = <1500000>; + pinctrl-names = "default"; + pinctrl-0 = <&bt_host_wake_gpio &bt_wake_gpio &bt_reset_gpio>; + shutdown-gpios = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>; + vbat-supply = <&wifi_bat>; + vddio-supply = <&vcc_wl>; + }; +}; + +&uart2 { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usbdrd3_0 { + status = "okay"; +}; + +&usbdrd_dwc3_0 { + dr_mode = "host"; + status = "okay"; +}; + +&usbdrd3_1 { + status = "okay"; +}; + +&usbdrd_dwc3_1 { + dr_mode = "host"; + status = "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; From d894992502474a6e84644012deb14a0280acbf96 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Tue, 3 Mar 2020 20:29:56 +0100 Subject: [PATCH 1276/4444] clk: rockchip: fix mmc get phase If the mmc clock has no rate, it can be assumed to be constant. In such case, there is no measurable phase shift. Just return 0 in this case instead of returning an error. Fixes: 2760878662a2 ("clk: Bail out when calculating phase fails during clk registration") Tested-by: Markus Reichl Signed-off-by: Jerome Brunet Link: https://lkml.kernel.org/r/20200303192956.64410-1-jbrunet@baylibre.com Signed-off-by: Stephen Boyd --- drivers/clk/rockchip/clk-mmc-phase.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c index 4abe7ff31f53..975454a3dd72 100644 --- a/drivers/clk/rockchip/clk-mmc-phase.c +++ b/drivers/clk/rockchip/clk-mmc-phase.c @@ -51,9 +51,9 @@ static int rockchip_mmc_get_phase(struct clk_hw *hw) u16 degrees; u32 delay_num = 0; - /* See the comment for rockchip_mmc_set_phase below */ + /* Constant signal, no measurable phase shift */ if (!rate) - return -EINVAL; + return 0; raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift); From 241eaabc3c315cdfea505725a43de848f498527f Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Fri, 6 Mar 2020 10:34:10 +0800 Subject: [PATCH 1277/4444] power: supply: Allow charger manager can be built as a module Allow charger manager can be built as a module like other charger drivers. Signed-off-by: Baolin Wang Signed-off-by: Sebastian Reichel --- drivers/power/supply/Kconfig | 2 +- include/linux/power/charger-manager.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index 9a5591ab90d0..195bc0462d3e 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -480,7 +480,7 @@ config CHARGER_GPIO called gpio-charger. config CHARGER_MANAGER - bool "Battery charger manager for multiple chargers" + tristate "Battery charger manager for multiple chargers" depends on REGULATOR select EXTCON help diff --git a/include/linux/power/charger-manager.h b/include/linux/power/charger-manager.h index ad19e68e1fc3..ae94dcebd936 100644 --- a/include/linux/power/charger-manager.h +++ b/include/linux/power/charger-manager.h @@ -248,7 +248,7 @@ struct charger_manager { u64 charging_end_time; }; -#ifdef CONFIG_CHARGER_MANAGER +#if IS_ENABLED(CONFIG_CHARGER_MANAGER) extern void cm_notify_event(struct power_supply *psy, enum cm_event_types type, char *msg); #else From ddb74e985f2d3db1ef5688121c8b1961f0c9d80d Mon Sep 17 00:00:00 2001 From: Ashish Chavan Date: Wed, 26 Feb 2020 23:22:23 +0530 Subject: [PATCH 1278/4444] power: supply: ab8500_charger: Fix typos in commit messages Trivial fix to spelling mistake in commit messages. Signed-off-by: Ashish Chavan Signed-off-by: Sebastian Reichel --- drivers/power/supply/ab8500_charger.c | 35 +++++++++++++++------------ 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c index f69550d64f09..9469fe182d02 100644 --- a/drivers/power/supply/ab8500_charger.c +++ b/drivers/power/supply/ab8500_charger.c @@ -404,7 +404,7 @@ disable_otp: } /** - * ab8500_power_supply_changed - a wrapper with local extentions for + * ab8500_power_supply_changed - a wrapper with local extensions for * power_supply_changed * @di: pointer to the ab8500_charger structure * @psy: pointer to power_supply_that have changed. @@ -683,7 +683,7 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, /* * Platform only supports USB 2.0. * This means that charging current from USB source - * is maximum 500 mA. Every occurence of USB_STAT_*_HOST_* + * is maximum 500 mA. Every occurrence of USB_STAT_*_HOST_* * should set USB_CH_IP_CUR_LVL_0P5. */ @@ -1379,13 +1379,13 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger, /* * Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts - * will be triggered everytime we enable the VDD ADC supply. + * will be triggered every time we enable the VDD ADC supply. * This will turn off charging for a short while. * It can be avoided by having the supply on when * there is a charger enabled. Normally the VDD ADC supply - * is enabled everytime a GPADC conversion is triggered. We will - * force it to be enabled from this driver to have - * the GPADC module independant of the AB8500 chargers + * is enabled every time a GPADC conversion is triggered. + * We will force it to be enabled from this driver to have + * the GPADC module independent of the AB8500 chargers */ if (!di->vddadc_en_ac) { ret = regulator_enable(di->regu); @@ -1455,7 +1455,7 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger, if (is_ab8500_1p1_or_earlier(di->parent)) { /* * For ABB revision 1.0 and 1.1 there is a bug in the - * watchdog logic. That means we have to continously + * watchdog logic. That means we have to continuously * kick the charger watchdog even when no charger is * connected. This is only valid once the AC charger * has been enabled. This is a bug that is not handled @@ -1552,13 +1552,13 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger, /* * Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts - * will be triggered everytime we enable the VDD ADC supply. + * will be triggered every time we enable the VDD ADC supply. * This will turn off charging for a short while. * It can be avoided by having the supply on when * there is a charger enabled. Normally the VDD ADC supply - * is enabled everytime a GPADC conversion is triggered. We will - * force it to be enabled from this driver to have - * the GPADC module independant of the AB8500 chargers + * is enabled every time a GPADC conversion is triggered. + * We will force it to be enabled from this driver to have + * the GPADC module independent of the AB8500 chargers */ if (!di->vddadc_en_usb) { ret = regulator_enable(di->regu); @@ -1582,7 +1582,10 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger, return -ENXIO; } - /* ChVoltLevel: max voltage upto which battery can be charged */ + /* + * ChVoltLevel: max voltage up to which battery can be + * charged + */ ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, AB8500_CH_VOLT_LVL_REG, (u8) volt_index); if (ret) { @@ -2014,7 +2017,7 @@ static void ab8500_charger_check_hw_failure_work(struct work_struct *work) * Work queue function for kicking the charger watchdog. * * For ABB revision 1.0 and 1.1 there is a bug in the watchdog - * logic. That means we have to continously kick the charger + * logic. That means we have to continuously kick the charger * watchdog even when no charger is connected. This is only * valid once the AC charger has been enabled. This is * a bug that is not handled by the algorithm and the @@ -2262,7 +2265,7 @@ static void ab8500_charger_usb_link_status_work(struct work_struct *work) * Some chargers that breaks the USB spec is * identified as invalid by AB8500 and it refuse * to start the charging process. but by jumping - * thru a few hoops it can be forced to start. + * through a few hoops it can be forced to start. */ if (is_ab8500(di->parent)) ret = abx500_get_register_interruptible(di->dev, AB8500_USB, @@ -3214,7 +3217,7 @@ static int ab8500_charger_resume(struct platform_device *pdev) /* * For ABB revision 1.0 and 1.1 there is a bug in the watchdog - * logic. That means we have to continously kick the charger + * logic. That means we have to continuously kick the charger * watchdog even when no charger is connected. This is only * valid once the AC charger has been enabled. This is * a bug that is not handled by the algorithm and the @@ -3483,7 +3486,7 @@ static int ab8500_charger_probe(struct platform_device *pdev) /* * For ABB revision 1.0 and 1.1 there is a bug in the watchdog - * logic. That means we have to continously kick the charger + * logic. That means we have to continuously kick the charger * watchdog even when no charger is connected. This is only * valid once the AC charger has been enabled. This is * a bug that is not handled by the algorithm and the From e42fe5b29ac07210297e75f36deefe54edbdbf80 Mon Sep 17 00:00:00 2001 From: Jeffery Miller Date: Tue, 25 Feb 2020 16:59:41 -0600 Subject: [PATCH 1279/4444] power: supply: axp288_fuel_gauge: Broaden vendor check for Intel Compute Sticks. The Intel Compute Stick `STK1A32SC` can have a system vendor of "Intel(R) Client Systems". Broaden the Intel Compute Stick DMI checks so that they match "Intel Corporation" as well as "Intel(R) Client Systems". This fixes an issue where the STK1A32SC compute sticks were still exposing a battery with the existing blacklist entry. Signed-off-by: Jeffery Miller Reviewed-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp288_fuel_gauge.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c index e1bc4e6e6f30..f40fa0e63b6e 100644 --- a/drivers/power/supply/axp288_fuel_gauge.c +++ b/drivers/power/supply/axp288_fuel_gauge.c @@ -706,14 +706,14 @@ static const struct dmi_system_id axp288_fuel_gauge_blacklist[] = { { /* Intel Cherry Trail Compute Stick, Windows version */ .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_SYS_VENDOR, "Intel"), DMI_MATCH(DMI_PRODUCT_NAME, "STK1AW32SC"), }, }, { /* Intel Cherry Trail Compute Stick, version without an OS */ .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_SYS_VENDOR, "Intel"), DMI_MATCH(DMI_PRODUCT_NAME, "STK1A32SC"), }, }, From 5cf9ffe70c2d37ca623589844bfd24cb7a5a3a88 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Sat, 14 Mar 2020 14:25:37 -0700 Subject: [PATCH 1280/4444] ARM: omap2plus_defconfig: Enable ext4 security for setcap Enable ext4 security for setcap. Signed-off-by: Tony Lindgren --- arch/arm/configs/omap2plus_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index c32c338f7704..ef5ac91e76b5 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -514,6 +514,7 @@ CONFIG_TI_PIPE3=y CONFIG_TWL4030_USB=m CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y +CONFIG_EXT4_FS_SECURITY=y CONFIG_FANOTIFY=y CONFIG_QUOTA=y CONFIG_QFMT_V2=y From 4086e48084702032dab023653ed2c74b42045496 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Fri, 6 Mar 2020 18:39:28 +0100 Subject: [PATCH 1281/4444] arm64: dts: qcom: apq8016-sbc: Remove wrong regulator supply As specified in the smd-rpm-regulator binding and confirmed by the pm8616 device specification, there is no vdd_l5. l5 vdd comes from vdd_l4_l5_l6. Fix that (though it does not cause any issue since the supply is not requested). Signed-off-by: Loic Poulain Link: https://lore.kernel.org/r/1583516368-29593-1-git-send-email-loic.poulain@linaro.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi index 037e26b3f8d5..06aab44d798c 100644 --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi @@ -562,7 +562,6 @@ &smd_rpm_regulators { vdd_l1_l2_l3-supply = <&pm8916_s3>; - vdd_l5-supply = <&pm8916_s3>; vdd_l4_l5_l6-supply = <&pm8916_s4>; vdd_l7-supply = <&pm8916_s4>; From 8d23a004047595a2ac4f01932a1492dc57b7fd55 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 5 Mar 2020 14:53:44 +0000 Subject: [PATCH 1282/4444] arm64: dts: qcom: db845c: add Low speed expansion i2c and spi nodes This patch adds support UART0, I2C0, I2C1 and SPI0 available on Low Speed expansion connector. Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20200305145344.14670-5-srinivas.kandagatla@linaro.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts index 6e60e81f8db7..8fc1766aa8b9 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts @@ -359,6 +359,18 @@ }; }; +&i2c11 { + /* On Low speed expansion */ + label = "LS-I2C1"; + status = "okay"; +}; + +&i2c14 { + /* On Low speed expansion */ + label = "LS-I2C0"; + status = "okay"; +}; + &mss_pil { status = "okay"; firmware-name = "qcom/sdm845/mba.mbn", "qcom/sdm845/modem.mbn"; @@ -438,6 +450,12 @@ cd-gpios = <&tlmm 126 GPIO_ACTIVE_LOW>; }; +&spi2 { + /* On Low speed expansion */ + label = "LS-SPI0"; + status = "okay"; +}; + &tlmm { pcie0_default_state: pcie0-default { clkreq { @@ -537,6 +555,11 @@ }; }; +&uart3 { + label = "LS-UART0"; + status = "disabled"; +}; + &uart6 { status = "okay"; @@ -552,6 +575,7 @@ }; &uart9 { + label = "LS-UART1"; status = "okay"; }; @@ -637,6 +661,16 @@ }; /* PINCTRL - additions to nodes defined in sdm845.dtsi */ +&qup_spi2_default { + drive-strength = <16>; +}; + +&qup_uart3_default{ + pinmux { + pins = "gpio41", "gpio42", "gpio43", "gpio44"; + function = "qup3"; + }; +}; &qup_uart6_default { pinmux { From 9c80662a74cd2a5d1113f5c69d027face963a556 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 23 Feb 2020 16:32:08 +0100 Subject: [PATCH 1283/4444] power: supply: axp288_charger: Add special handling for HP Pavilion x2 10 Some HP Pavilion x2 10 models use an AXP288 for charging and fuel-gauge. We use a native power_supply / PMIC driver in this case, because on most models with an AXP288 the ACPI AC / Battery code is either completely missing or relies on custom / proprietary ACPI OpRegions which Linux does not implement. The native drivers mostly work fine, but there are 2 problems: 1. These model uses a Type-C connector for charging which the AXP288 does not support. As long as a Type-A charger (which uses the USB data pins for charger type detection) is used everything is fine. But if a Type-C charger is used (such as the charger shipped with the device) then the charger is not recognized. So we end up slowly discharging the device even though a charger is connected, because we are limiting the current from the charger to 500mA. To make things worse this happens with the device's official charger. Looking at the ACPI tables HP has "solved" the problem of the AXP288 not being able to recognize Type-C chargers by simply always programming the input-current-limit at 3000mA and relying on a Vhold setting of 4.7V (normally 4.4V) to limit the current intake if the charger cannot handle this. 2. If no charger is connected when the machine boots then it boots with the vbus-path disabled. On other devices this is done when a 5V boost converter is active to avoid the PMIC trying to charge from the 5V boost output. This is done when an OTG host cable is inserted and the ID pin on the micro-B receptacle is pulled low, the ID pin has an ACPI event handler associated with it which re-enables the vbus-path when the ID pin is pulled high when the OTG cable is removed. The Type-C connector has no ID pin, there is no ID pin handler and there appears to be no 5V boost converter, so we end up not charging because the vbus-path is disabled, until we unplug the charger which automatically clears the vbus-path disable bit and then on the second plug-in of the adapter we start charging. The HP Pavilion x2 10 models with an AXP288 do have mostly working ACPI AC / Battery code which does not rely on custom / proprietary ACPI OpRegions. So one possible solution would be to blacklist the AXP288 native power_supply drivers and add the HP Pavilion x2 10 with AXP288 DMI ids to the list of devices which should use the ACPI AC / Battery code even though they have an AXP288 PMIC. This would require changes to 4 files: drivers/acpi/ac.c, drivers/power/supply/axp288_charger.c, drivers/acpi/battery.c and drivers/power/supply/axp288_fuel_gauge.c. Beside needing adding the same DMI matches to 4 different files, this approach also triggers problem 2. from above, but then when suspended, during suspend the machine will not wakeup because the vbus path is disabled by the AML code when not charging, so the Vbus low-to-high IRQ is not triggered, the CPU never wakes up and the device does not charge even though the user likely things it is charging, esp. since the charge status LED is directly coupled to an adapter being plugged in and does not reflect actual charging. This could be worked by enabling vbus-path explicitly from say the axp288_charger driver's suspend handler. So neither situation is ideal, in both cased we need to explicitly enable the vbus-path to work around different variants of problem 2 above, this requires a quirk in the axp288_charger code. If we go the route of using the ACPI AC / Battery drivers then we need modifications to 3 other drivers; and we need to partially disable the axp288_charger code, while at the same time keeping it around to enable vbus-path on suspend. OTOH we can copy the hardcoding of 3A input-current-limit (we never touch Vhold, so that would stay at 4.7V) to the axp288_charger code, which needs changes regardless, then we concentrate all special handling of this interesting device model in the axp288_charger code. That is what this commit does. Cc: stable@vger.kernel.org BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1791098 Signed-off-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp288_charger.c | 57 ++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/axp288_charger.c b/drivers/power/supply/axp288_charger.c index 1bbba6bba673..cf4c67b2d235 100644 --- a/drivers/power/supply/axp288_charger.c +++ b/drivers/power/supply/axp288_charger.c @@ -21,6 +21,7 @@ #include #include #include +#include #define PS_STAT_VBUS_TRIGGER BIT(0) #define PS_STAT_BAT_CHRG_DIR BIT(2) @@ -545,6 +546,49 @@ out: return IRQ_HANDLED; } +/* + * The HP Pavilion x2 10 series comes in a number of variants: + * Bay Trail SoC + AXP288 PMIC, DMI_BOARD_NAME: "815D" + * Cherry Trail SoC + AXP288 PMIC, DMI_BOARD_NAME: "813E" + * Cherry Trail SoC + TI PMIC, DMI_BOARD_NAME: "827C" or "82F4" + * + * The variants with the AXP288 PMIC are all kinds of special: + * + * 1. All variants use a Type-C connector which the AXP288 does not support, so + * when using a Type-C charger it is not recognized. Unlike most AXP288 devices, + * this model actually has mostly working ACPI AC / Battery code, the ACPI code + * "solves" this by simply setting the input_current_limit to 3A. + * There are still some issues with the ACPI code, so we use this native driver, + * and to solve the charging not working (500mA is not enough) issue we hardcode + * the 3A input_current_limit like the ACPI code does. + * + * 2. If no charger is connected the machine boots with the vbus-path disabled. + * Normally this is done when a 5V boost converter is active to avoid the PMIC + * trying to charge from the 5V boost converter's output. This is done when + * an OTG host cable is inserted and the ID pin on the micro-B receptacle is + * pulled low and the ID pin has an ACPI event handler associated with it + * which re-enables the vbus-path when the ID pin is pulled high when the + * OTG host cable is removed. The Type-C connector has no ID pin, there is + * no ID pin handler and there appears to be no 5V boost converter, so we + * end up not charging because the vbus-path is disabled, until we unplug + * the charger which automatically clears the vbus-path disable bit and then + * on the second plug-in of the adapter we start charging. To solve the not + * charging on first charger plugin we unconditionally enable the vbus-path at + * probe on this model, which is safe since there is no 5V boost converter. + */ +static const struct dmi_system_id axp288_hp_x2_dmi_ids[] = { + { + /* + * Bay Trail model has "Hewlett-Packard" as sys_vendor, Cherry + * Trail model has "HP", so we only match on product_name. + */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), + }, + }, + {} /* Terminating entry */ +}; + static void axp288_charger_extcon_evt_worker(struct work_struct *work) { struct axp288_chrg_info *info = @@ -568,7 +612,11 @@ static void axp288_charger_extcon_evt_worker(struct work_struct *work) } /* Determine cable/charger type */ - if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) { + if (dmi_check_system(axp288_hp_x2_dmi_ids)) { + /* See comment above axp288_hp_x2_dmi_ids declaration */ + dev_dbg(&info->pdev->dev, "HP X2 with Type-C, setting inlmt to 3A\n"); + current_limit = 3000000; + } else if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) { dev_dbg(&info->pdev->dev, "USB SDP charger is connected\n"); current_limit = 500000; } else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) { @@ -685,6 +733,13 @@ static int charger_init_hw_regs(struct axp288_chrg_info *info) return ret; } + if (dmi_check_system(axp288_hp_x2_dmi_ids)) { + /* See comment above axp288_hp_x2_dmi_ids declaration */ + ret = axp288_charger_vbus_path_select(info, true); + if (ret < 0) + return ret; + } + /* Read current charge voltage and current limit */ ret = regmap_read(info->regmap, AXP20X_CHRG_CTRL1, &val); if (ret < 0) { From 49d5b5683aae632e8bf3598e9779a3621ebc58bf Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 21 Jan 2020 11:37:18 +0100 Subject: [PATCH 1284/4444] ARM: orion5x: Drop unneeded select of PCI_DOMAINS_GENERIC Support for Marvell Orion SoCs depends on ARCH_MULTI_V5, and thus on ARCH_MULTIPLATFORM. As the latter selects GENERIC_CLOCKEVENTS and USE_OF, there is no need for ARCH_ORION5X and ARCH_ORION5X_DT to select any of them. Signed-off-by: Geert Uytterhoeven Cc: Jason Cooper Cc: Andrew Lunn Cc: Sebastian Hesselbarth Cc: Gregory Clement Signed-off-by: Gregory CLEMENT --- arch/arm/mach-orion5x/Kconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig index cf9cb3d2590e..e94a61901ffd 100644 --- a/arch/arm/mach-orion5x/Kconfig +++ b/arch/arm/mach-orion5x/Kconfig @@ -3,7 +3,6 @@ menuconfig ARCH_ORION5X bool "Marvell Orion" depends on MMU && ARCH_MULTI_V5 select CPU_FEROCEON - select GENERIC_CLOCKEVENTS select GPIOLIB select MVEBU_MBUS select FORCE_PCI @@ -18,7 +17,6 @@ if ARCH_ORION5X config ARCH_ORION5X_DT bool "Marvell Orion5x Flattened Device Tree" - select USE_OF select ORION_CLK select ORION_IRQCHIP select ORION_TIMER From cf8dcf2725a903d4a2f4655f37972cb8f4cdc516 Mon Sep 17 00:00:00 2001 From: Xu Wang Date: Mon, 24 Feb 2020 15:24:47 +0100 Subject: [PATCH 1285/4444] ARM: orion5x: ts78xx: Remove unneeded variable ret Remove unneeded variable ret used to store return value,just return 0. Signed-off-by: Xu Wang Signed-off-by: Gregory CLEMENT --- arch/arm/mach-orion5x/ts78xx-setup.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index fda9b75c3a33..a39764faf2a0 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c @@ -398,7 +398,6 @@ static int ts78xx_fpga_load_devices(void) static int ts78xx_fpga_unload_devices(void) { - int ret = 0; if (ts78xx_fpga.supports.ts_rtc.present == 1) ts78xx_ts_rtc_unload(); @@ -407,7 +406,7 @@ static int ts78xx_fpga_unload_devices(void) if (ts78xx_fpga.supports.ts_rng.present == 1) ts78xx_ts_rng_unload(); - return ret; + return 0; } static int ts78xx_fpga_load(void) From 12879bda3c2a974b7e4fe199a9c21f0c5f6bca04 Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Wed, 26 Feb 2020 10:23:26 +0800 Subject: [PATCH 1286/4444] csky: Fixup init_fpu compile warning with __init WARNING: vmlinux.o(.text+0x2366): Section mismatch in reference from the function csky_start_secondary() to the function .init.text:init_fpu() The function csky_start_secondary() references the function __init init_fpu(). This is often because csky_start_secondary lacks a __init annotation or the annotation of init_fpu is wrong. Reported-by: Lu Chongzhi Signed-off-by: Guo Ren --- arch/csky/abiv2/fpu.c | 5 ----- arch/csky/abiv2/inc/abi/fpu.h | 3 ++- arch/csky/kernel/smp.c | 3 +++ 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/csky/abiv2/fpu.c b/arch/csky/abiv2/fpu.c index 86d187d4e5af..5acc5c2e544e 100644 --- a/arch/csky/abiv2/fpu.c +++ b/arch/csky/abiv2/fpu.c @@ -10,11 +10,6 @@ #define MTCR_DIST 0xC0006420 #define MFCR_DIST 0xC0006020 -void __init init_fpu(void) -{ - mtcr("cr<1, 2>", 0); -} - /* * fpu_libc_helper() is to help libc to excute: * - mfcr %a, cr<1, 2> diff --git a/arch/csky/abiv2/inc/abi/fpu.h b/arch/csky/abiv2/inc/abi/fpu.h index 22ca3cf2794a..09e2700a3693 100644 --- a/arch/csky/abiv2/inc/abi/fpu.h +++ b/arch/csky/abiv2/inc/abi/fpu.h @@ -9,7 +9,8 @@ int fpu_libc_helper(struct pt_regs *regs); void fpu_fpe(struct pt_regs *regs); -void __init init_fpu(void); + +static inline void init_fpu(void) { mtcr("cr<1, 2>", 0); } void save_to_user_fp(struct user_fp *user_fp); void restore_from_user_fp(struct user_fp *user_fp); diff --git a/arch/csky/kernel/smp.c b/arch/csky/kernel/smp.c index 0bb0954d5570..df2e2174dbd0 100644 --- a/arch/csky/kernel/smp.c +++ b/arch/csky/kernel/smp.c @@ -22,6 +22,9 @@ #include #include #include +#ifdef CONFIG_CPU_HAS_FPU +#include +#endif struct ipi_data_struct { unsigned long bits ____cacheline_aligned; From bfe47f358ad298a1efb9b8f8299a81541d90df87 Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Tue, 17 Dec 2019 14:57:22 +0800 Subject: [PATCH 1287/4444] csky: Implement ptrace regs and stack API Needed for kprobes support. Copied and adapted from Patrick's patch, but it has been modified for csky's pt_regs. ref: https://lore.kernel.org/linux-riscv/1572919114-3886-2-git-send-email-vincent.chen@sifive.com/raw Signed-off-by: Guo Ren Cc: Patrick Staehlin --- arch/csky/Kconfig | 1 + arch/csky/include/asm/ptrace.h | 41 +++++++++++++ arch/csky/kernel/ptrace.c | 103 +++++++++++++++++++++++++++++++++ 3 files changed, 145 insertions(+) diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig index 047427f71d83..2dfd3fb07db9 100644 --- a/arch/csky/Kconfig +++ b/arch/csky/Kconfig @@ -48,6 +48,7 @@ config CSKY select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP select HAVE_DMA_CONTIGUOUS + select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select MAY_HAVE_SPARSE_IRQ diff --git a/arch/csky/include/asm/ptrace.h b/arch/csky/include/asm/ptrace.h index d0aba7b32417..f16ca256e007 100644 --- a/arch/csky/include/asm/ptrace.h +++ b/arch/csky/include/asm/ptrace.h @@ -7,6 +7,7 @@ #include #include #include +#include #ifndef __ASSEMBLY__ @@ -22,6 +23,18 @@ #define instruction_pointer(regs) ((regs)->pc) #define profile_pc(regs) instruction_pointer(regs) +static inline void instruction_pointer_set(struct pt_regs *regs, + unsigned long val) +{ + regs->pc = val; +} + +#if defined(__CSKYABIV2__) +#define MAX_REG_OFFSET offsetof(struct pt_regs, dcsr) +#else +#define MAX_REG_OFFSET offsetof(struct pt_regs, regs[9]) +#endif + static inline bool in_syscall(struct pt_regs const *regs) { return ((regs->sr >> 16) & 0xff) == VEC_TRAP0; @@ -37,5 +50,33 @@ static inline unsigned long regs_return_value(struct pt_regs *regs) return regs->a0; } +/* Valid only for Kernel mode traps. */ +static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) +{ + return regs->usp; +} + +extern int regs_query_register_offset(const char *name); +extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, + unsigned int n); + +/* + * regs_get_register() - get register value from its offset + * @regs: pt_regs from which register value is gotten + * @offset: offset of the register. + * + * regs_get_register returns the value of a register whose offset from @regs. + * The @offset is the offset of the register in struct pt_regs. + * If @offset is bigger than MAX_REG_OFFSET, this returns 0. + */ +static inline unsigned long regs_get_register(struct pt_regs *regs, + unsigned int offset) +{ + if (unlikely(offset > MAX_REG_OFFSET)) + return 0; + + return *(unsigned long *)((unsigned long)regs + offset); +} + #endif /* __ASSEMBLY__ */ #endif /* __ASM_CSKY_PTRACE_H */ diff --git a/arch/csky/kernel/ptrace.c b/arch/csky/kernel/ptrace.c index 313623a19ecb..21ac2608f205 100644 --- a/arch/csky/kernel/ptrace.c +++ b/arch/csky/kernel/ptrace.c @@ -193,6 +193,109 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) return &user_csky_view; } +struct pt_regs_offset { + const char *name; + int offset; +}; + +#define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)} +#define REG_OFFSET_END {.name = NULL, .offset = 0} + +static const struct pt_regs_offset regoffset_table[] = { + REG_OFFSET_NAME(tls), + REG_OFFSET_NAME(lr), + REG_OFFSET_NAME(pc), + REG_OFFSET_NAME(sr), + REG_OFFSET_NAME(usp), + REG_OFFSET_NAME(orig_a0), + REG_OFFSET_NAME(a0), + REG_OFFSET_NAME(a1), + REG_OFFSET_NAME(a2), + REG_OFFSET_NAME(a3), + REG_OFFSET_NAME(regs[0]), + REG_OFFSET_NAME(regs[1]), + REG_OFFSET_NAME(regs[2]), + REG_OFFSET_NAME(regs[3]), + REG_OFFSET_NAME(regs[4]), + REG_OFFSET_NAME(regs[5]), + REG_OFFSET_NAME(regs[6]), + REG_OFFSET_NAME(regs[7]), + REG_OFFSET_NAME(regs[8]), + REG_OFFSET_NAME(regs[9]), +#if defined(__CSKYABIV2__) + REG_OFFSET_NAME(exregs[0]), + REG_OFFSET_NAME(exregs[1]), + REG_OFFSET_NAME(exregs[2]), + REG_OFFSET_NAME(exregs[3]), + REG_OFFSET_NAME(exregs[4]), + REG_OFFSET_NAME(exregs[5]), + REG_OFFSET_NAME(exregs[6]), + REG_OFFSET_NAME(exregs[7]), + REG_OFFSET_NAME(exregs[8]), + REG_OFFSET_NAME(exregs[9]), + REG_OFFSET_NAME(exregs[10]), + REG_OFFSET_NAME(exregs[11]), + REG_OFFSET_NAME(exregs[12]), + REG_OFFSET_NAME(exregs[13]), + REG_OFFSET_NAME(exregs[14]), + REG_OFFSET_NAME(rhi), + REG_OFFSET_NAME(rlo), + REG_OFFSET_NAME(dcsr), +#endif + REG_OFFSET_END, +}; + +/** + * regs_query_register_offset() - query register offset from its name + * @name: the name of a register + * + * regs_query_register_offset() returns the offset of a register in struct + * pt_regs from its name. If the name is invalid, this returns -EINVAL; + */ +int regs_query_register_offset(const char *name) +{ + const struct pt_regs_offset *roff; + + for (roff = regoffset_table; roff->name != NULL; roff++) + if (!strcmp(roff->name, name)) + return roff->offset; + return -EINVAL; +} + +/** + * regs_within_kernel_stack() - check the address in the stack + * @regs: pt_regs which contains kernel stack pointer. + * @addr: address which is checked. + * + * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). + * If @addr is within the kernel stack, it returns true. If not, returns false. + */ +static bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) +{ + return (addr & ~(THREAD_SIZE - 1)) == + (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)); +} + +/** + * regs_get_kernel_stack_nth() - get Nth entry of the stack + * @regs: pt_regs which contains kernel stack pointer. + * @n: stack entry number. + * + * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which + * is specified by @regs. If the @n th entry is NOT in the kernel stack, + * this returns 0. + */ +unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) +{ + unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); + + addr += n; + if (regs_within_kernel_stack(regs, (unsigned long)addr)) + return *addr; + else + return 0; +} + void ptrace_disable(struct task_struct *child) { singlestep_disable(child); From 9866d141a0977ace974400bf1f793dfc163409ce Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Tue, 5 Nov 2019 09:58:33 +0800 Subject: [PATCH 1288/4444] csky: Add support for restartable sequence Copied and adapted from vincent's patch, but modified for csky. ref: https://lore.kernel.org/linux-riscv/1572919114-3886-3-git-send-email-vincent.chen@sifive.com/raw Add calls to rseq_signal_deliver(), rseq_handle_notify_resume() and rseq_syscall() to introduce RSEQ support. 1. Call the rseq_handle_notify_resume() function on return to userspace if TIF_NOTIFY_RESUME thread flag is set. 2. Call the rseq_signal_deliver() function to fixup on the pre-signal frame when a signal is delivered on top of a restartable sequence critical section. 3. Check that system calls are not invoked from within rseq critical sections by invoking rseq_signal() from ret_from_syscall(). With CONFIG_DEBUG_RSEQ, such behavior results in termination of the process with SIGSEGV. Signed-off-by: Guo Ren --- arch/csky/Kconfig | 1 + arch/csky/kernel/entry.S | 5 ++++- arch/csky/kernel/signal.c | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig index 2dfd3fb07db9..0e9b14367fa8 100644 --- a/arch/csky/Kconfig +++ b/arch/csky/Kconfig @@ -49,6 +49,7 @@ config CSKY select HAVE_PERF_USER_STACK_DUMP select HAVE_DMA_CONTIGUOUS select HAVE_REGS_AND_STACK_ACCESS_API + select HAVE_RSEQ select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select MAY_HAVE_SPARSE_IRQ diff --git a/arch/csky/kernel/entry.S b/arch/csky/kernel/entry.S index 007706328000..0bde1d9fd277 100644 --- a/arch/csky/kernel/entry.S +++ b/arch/csky/kernel/entry.S @@ -128,7 +128,10 @@ tlbop_end 1 ENTRY(csky_systemcall) SAVE_ALL TRAP0_SIZE zero_fp - +#ifdef CONFIG_RSEQ_DEBUG + mov a0, sp + jbsr rseq_syscall +#endif psrset ee, ie lrw r11, __NR_syscalls diff --git a/arch/csky/kernel/signal.c b/arch/csky/kernel/signal.c index 9b1b7c039ddf..3d6b728cbb72 100644 --- a/arch/csky/kernel/signal.c +++ b/arch/csky/kernel/signal.c @@ -175,6 +175,8 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) sigset_t *oldset = sigmask_to_save(); int ret; + rseq_signal_deliver(ksig, regs); + /* Are we from a system call? */ if (in_syscall(regs)) { /* Avoid additional syscall restarting via ret_from_exception */ @@ -258,5 +260,6 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + rseq_handle_notify_resume(NULL, regs); } } From 89a3927a775c0a7212e2e3c4e2d42cd48895bee0 Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Tue, 18 Feb 2020 20:27:39 +0800 Subject: [PATCH 1289/4444] csky: Implement ftrace with regs This patch implements FTRACE_WITH_REGS for csky, which allows a traced function's arguments (and some other registers) to be captured into a struct pt_regs, allowing these to be inspected and/or modified. Signed-off-by: Guo Ren --- arch/csky/Kconfig | 1 + arch/csky/abiv2/inc/abi/entry.h | 60 +++++++++++++++++++++++++++++++++ arch/csky/abiv2/mcount.S | 48 ++++++++++++++++++++++++++ arch/csky/include/asm/ftrace.h | 2 ++ arch/csky/kernel/asm-offsets.c | 1 + arch/csky/kernel/ftrace.c | 11 ++++++ 6 files changed, 123 insertions(+) diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig index 0e9b14367fa8..6cf169a15794 100644 --- a/arch/csky/Kconfig +++ b/arch/csky/Kconfig @@ -38,6 +38,7 @@ config CSKY select HAVE_ARCH_AUDITSYSCALL select HAVE_COPY_THREAD_TLS select HAVE_DYNAMIC_FTRACE + select HAVE_DYNAMIC_FTRACE_WITH_REGS select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FTRACE_MCOUNT_RECORD diff --git a/arch/csky/abiv2/inc/abi/entry.h b/arch/csky/abiv2/inc/abi/entry.h index 94a7a58765df..6a404393d0f4 100644 --- a/arch/csky/abiv2/inc/abi/entry.h +++ b/arch/csky/abiv2/inc/abi/entry.h @@ -100,6 +100,66 @@ rte .endm +.macro SAVE_REGS_FTRACE + subi sp, 152 + stw tls, (sp, 0) + stw lr, (sp, 4) + + mfcr lr, psr + stw lr, (sp, 12) + + addi lr, sp, 152 + stw lr, (sp, 16) + + stw a0, (sp, 20) + stw a0, (sp, 24) + stw a1, (sp, 28) + stw a2, (sp, 32) + stw a3, (sp, 36) + + addi sp, 40 + stm r4-r13, (sp) + + addi sp, 40 + stm r16-r30, (sp) +#ifdef CONFIG_CPU_HAS_HILO + mfhi lr + stw lr, (sp, 60) + mflo lr + stw lr, (sp, 64) + mfcr lr, cr14 + stw lr, (sp, 68) +#endif + subi sp, 80 +.endm + +.macro RESTORE_REGS_FTRACE + ldw tls, (sp, 0) + ldw a0, (sp, 16) + mtcr a0, ss0 + +#ifdef CONFIG_CPU_HAS_HILO + ldw a0, (sp, 140) + mthi a0 + ldw a0, (sp, 144) + mtlo a0 + ldw a0, (sp, 148) + mtcr a0, cr14 +#endif + + ldw a0, (sp, 24) + ldw a1, (sp, 28) + ldw a2, (sp, 32) + ldw a3, (sp, 36) + + addi sp, 40 + ldm r4-r13, (sp) + addi sp, 40 + ldm r16-r30, (sp) + addi sp, 72 + mfcr sp, ss0 +.endm + .macro SAVE_SWITCH_STACK subi sp, 64 stm r4-r11, (sp) diff --git a/arch/csky/abiv2/mcount.S b/arch/csky/abiv2/mcount.S index 326402e65f9e..9331c7ed5958 100644 --- a/arch/csky/abiv2/mcount.S +++ b/arch/csky/abiv2/mcount.S @@ -3,6 +3,8 @@ #include #include +#include +#include /* * csky-gcc with -pg will put the following asm after prologue: @@ -44,6 +46,22 @@ jmp t1 .endm +.macro mcount_enter_regs + subi sp, 8 + stw lr, (sp, 0) + stw r8, (sp, 4) + SAVE_REGS_FTRACE +.endm + +.macro mcount_exit_regs + RESTORE_REGS_FTRACE + ldw t1, (sp, 0) + ldw r8, (sp, 4) + ldw lr, (sp, 8) + addi sp, 12 + jmp t1 +.endm + .macro save_return_regs subi sp, 16 stw a0, (sp, 0) @@ -122,6 +140,8 @@ ENTRY(ftrace_caller) ldw a0, (sp, 16) subi a0, 4 ldw a1, (sp, 24) + lrw a2, function_trace_op + ldw a2, (a2, 0) nop GLOBAL(ftrace_call) @@ -157,3 +177,31 @@ ENTRY(return_to_handler) jmp lr END(return_to_handler) #endif + +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS +ENTRY(ftrace_regs_caller) + mcount_enter_regs + + lrw t1, PT_FRAME_SIZE + add t1, sp + + ldw a0, (t1, 0) + subi a0, 4 + ldw a1, (t1, 8) + lrw a2, function_trace_op + ldw a2, (a2, 0) + mov a3, sp + + nop +GLOBAL(ftrace_regs_call) + nop32_stub + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + nop +GLOBAL(ftrace_graph_regs_call) + nop32_stub +#endif + + mcount_exit_regs +ENDPROC(ftrace_regs_caller) +#endif /* CONFIG_DYNAMIC_FTRACE */ diff --git a/arch/csky/include/asm/ftrace.h b/arch/csky/include/asm/ftrace.h index ba35d93ecda2..fae72b0b1374 100644 --- a/arch/csky/include/asm/ftrace.h +++ b/arch/csky/include/asm/ftrace.h @@ -10,6 +10,8 @@ #define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR +#define ARCH_SUPPORTS_FTRACE_OPS 1 + #define MCOUNT_ADDR ((unsigned long)_mcount) #ifndef __ASSEMBLY__ diff --git a/arch/csky/kernel/asm-offsets.c b/arch/csky/kernel/asm-offsets.c index 9b48b1b1a61b..f8be348df9e4 100644 --- a/arch/csky/kernel/asm-offsets.c +++ b/arch/csky/kernel/asm-offsets.c @@ -72,6 +72,7 @@ int main(void) DEFINE(PT_RLO, offsetof(struct pt_regs, rlo)); #endif DEFINE(PT_USP, offsetof(struct pt_regs, usp)); + DEFINE(PT_FRAME_SIZE, sizeof(struct pt_regs)); /* offsets into the irq_cpustat_t struct */ DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, diff --git a/arch/csky/kernel/ftrace.c b/arch/csky/kernel/ftrace.c index 44f4880179b7..b4502cd2eabe 100644 --- a/arch/csky/kernel/ftrace.c +++ b/arch/csky/kernel/ftrace.c @@ -126,6 +126,9 @@ int ftrace_update_ftrace_func(ftrace_func_t func) { int ret = ftrace_modify_code((unsigned long)&ftrace_call, (unsigned long)func, true, true); + if (!ret) + ret = ftrace_modify_code((unsigned long)&ftrace_regs_call, + (unsigned long)func, true, true); return ret; } @@ -135,6 +138,14 @@ int __init ftrace_dyn_arch_init(void) } #endif /* CONFIG_DYNAMIC_FTRACE */ +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS +int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, + unsigned long addr) +{ + return ftrace_modify_code(rec->ip, addr, true, true); +} +#endif + #ifdef CONFIG_FUNCTION_GRAPH_TRACER void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, unsigned long frame_pointer) From b2a16610f2ba72468b4a7ac1e462af1e9c70bae8 Mon Sep 17 00:00:00 2001 From: "Claudiu.Beznea@microchip.com" Date: Tue, 21 Jan 2020 10:03:29 +0000 Subject: [PATCH 1290/4444] power: reset: at91-reset: introduce struct at91_reset Introduce struct at91_reset intended to keep all the at91 reset controller data. Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-reset.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index d94e3267c3b6..2df0610e5527 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -49,7 +49,13 @@ enum reset_type { RESET_TYPE_ULP2 = 8, }; -static void __iomem *at91_ramc_base[2], *at91_rstc_base; +struct at91_reset { + void __iomem *rstc_base; +}; + +static struct at91_reset reset; + +static void __iomem *at91_ramc_base[2]; static struct clk *sclk; /* @@ -76,7 +82,7 @@ static int at91sam9260_restart(struct notifier_block *this, unsigned long mode, "b .\n\t" : : "r" (at91_ramc_base[0]), - "r" (at91_rstc_base), + "r" (reset.rstc_base), "r" (1), "r" cpu_to_le32(AT91_SDRAMC_LPCB_POWER_DOWN), "r" cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)); @@ -119,7 +125,7 @@ static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode, : : "r" (at91_ramc_base[0]), "r" (at91_ramc_base[1]), - "r" (at91_rstc_base), + "r" (reset.rstc_base), "r" (1), "r" cpu_to_le32(AT91_DDRSDRC_LPCB_POWER_DOWN), "r" cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST) @@ -131,8 +137,8 @@ static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode, static int sama5d3_restart(struct notifier_block *this, unsigned long mode, void *cmd) { - writel(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST, - at91_rstc_base); + writel(cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST), + reset.rstc_base); return NOTIFY_DONE; } @@ -140,14 +146,16 @@ static int sama5d3_restart(struct notifier_block *this, unsigned long mode, static int samx7_restart(struct notifier_block *this, unsigned long mode, void *cmd) { - writel(AT91_RSTC_KEY | AT91_RSTC_PROCRST, at91_rstc_base); + writel(cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PROCRST), + reset.rstc_base); + return NOTIFY_DONE; } static void __init at91_reset_status(struct platform_device *pdev) { const char *reason; - u32 reg = readl(at91_rstc_base + AT91_RSTC_SR); + u32 reg = readl(reset.rstc_base + AT91_RSTC_SR); switch ((reg & AT91_RSTC_RSTTYP) >> 8) { case RESET_TYPE_GENERAL: @@ -208,8 +216,8 @@ static int __init at91_reset_probe(struct platform_device *pdev) struct device_node *np; int ret, idx = 0; - at91_rstc_base = of_iomap(pdev->dev.of_node, 0); - if (!at91_rstc_base) { + reset.rstc_base = of_iomap(pdev->dev.of_node, 0); + if (!reset.rstc_base) { dev_err(&pdev->dev, "Could not map reset controller address\n"); return -ENODEV; } From 4d9ce0f56aeeb46c8be0e8974646f163d3f6b72d Mon Sep 17 00:00:00 2001 From: "Claudiu.Beznea@microchip.com" Date: Tue, 21 Jan 2020 10:03:30 +0000 Subject: [PATCH 1291/4444] power: reset: at91-reset: add ramc_base[] to struct at91_reset Add ramc_base[] to struct at91_reset. Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-reset.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index 2df0610e5527..999d3a1653d2 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -51,11 +51,11 @@ enum reset_type { struct at91_reset { void __iomem *rstc_base; + void __iomem *ramc_base[2]; }; static struct at91_reset reset; -static void __iomem *at91_ramc_base[2]; static struct clk *sclk; /* @@ -81,7 +81,7 @@ static int at91sam9260_restart(struct notifier_block *this, unsigned long mode, "b .\n\t" : - : "r" (at91_ramc_base[0]), + : "r" (reset.ramc_base[0]), "r" (reset.rstc_base), "r" (1), "r" cpu_to_le32(AT91_SDRAMC_LPCB_POWER_DOWN), @@ -123,8 +123,8 @@ static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode, " b .\n\t" : - : "r" (at91_ramc_base[0]), - "r" (at91_ramc_base[1]), + : "r" (reset.ramc_base[0]), + "r" (reset.ramc_base[1]), "r" (reset.rstc_base), "r" (1), "r" cpu_to_le32(AT91_DDRSDRC_LPCB_POWER_DOWN), @@ -225,8 +225,8 @@ static int __init at91_reset_probe(struct platform_device *pdev) if (!of_device_is_compatible(pdev->dev.of_node, "atmel,sama5d3-rstc")) { /* we need to shutdown the ddr controller, so get ramc base */ for_each_matching_node(np, at91_ramc_of_match) { - at91_ramc_base[idx] = of_iomap(np, 0); - if (!at91_ramc_base[idx]) { + reset.ramc_base[idx] = of_iomap(np, 0); + if (!reset.ramc_base[idx]) { dev_err(&pdev->dev, "Could not map ram controller address\n"); of_node_put(np); return -ENODEV; From f9e6ce74cbf2a34f4d37bccbbfc7865e5b3e01dd Mon Sep 17 00:00:00 2001 From: "Claudiu.Beznea@microchip.com" Date: Tue, 21 Jan 2020 10:03:30 +0000 Subject: [PATCH 1292/4444] power: reset: at91-reset: add sclk to struct at91_reset Add sclk to struct at91_reset. Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-reset.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index 999d3a1653d2..1bc39bfda0aa 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -52,12 +52,11 @@ enum reset_type { struct at91_reset { void __iomem *rstc_base; void __iomem *ramc_base[2]; + struct clk *sclk; }; static struct at91_reset reset; -static struct clk *sclk; - /* * unless the SDRAM is cleanly shutdown before we hit the * reset register it can be left driving the data bus and @@ -238,11 +237,11 @@ static int __init at91_reset_probe(struct platform_device *pdev) match = of_match_node(at91_reset_of_match, pdev->dev.of_node); at91_restart_nb.notifier_call = match->data; - sclk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(sclk)) - return PTR_ERR(sclk); + reset.sclk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(reset.sclk)) + return PTR_ERR(reset.sclk); - ret = clk_prepare_enable(sclk); + ret = clk_prepare_enable(reset.sclk); if (ret) { dev_err(&pdev->dev, "Could not enable slow clock\n"); return ret; @@ -250,7 +249,7 @@ static int __init at91_reset_probe(struct platform_device *pdev) ret = register_restart_handler(&at91_restart_nb); if (ret) { - clk_disable_unprepare(sclk); + clk_disable_unprepare(reset.sclk); return ret; } @@ -262,7 +261,7 @@ static int __init at91_reset_probe(struct platform_device *pdev) static int __exit at91_reset_remove(struct platform_device *pdev) { unregister_restart_handler(&at91_restart_nb); - clk_disable_unprepare(sclk); + clk_disable_unprepare(reset.sclk); return 0; } From 1e3c4af9de26a0246cf00aba207c49846e80c37b Mon Sep 17 00:00:00 2001 From: "Claudiu.Beznea@microchip.com" Date: Tue, 21 Jan 2020 10:03:31 +0000 Subject: [PATCH 1293/4444] power: reset: at91-reset: add notifier block to struct at91_reset Add struct notifier_block to struct at91_reset. Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-reset.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index 1bc39bfda0aa..e8840193620d 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -53,6 +53,7 @@ struct at91_reset { void __iomem *rstc_base; void __iomem *ramc_base[2]; struct clk *sclk; + struct notifier_block nb; }; static struct at91_reset reset; @@ -205,10 +206,6 @@ static const struct of_device_id at91_reset_of_match[] = { }; MODULE_DEVICE_TABLE(of, at91_reset_of_match); -static struct notifier_block at91_restart_nb = { - .priority = 192, -}; - static int __init at91_reset_probe(struct platform_device *pdev) { const struct of_device_id *match; @@ -235,7 +232,8 @@ static int __init at91_reset_probe(struct platform_device *pdev) } match = of_match_node(at91_reset_of_match, pdev->dev.of_node); - at91_restart_nb.notifier_call = match->data; + reset.nb.notifier_call = match->data; + reset.nb.priority = 192; reset.sclk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(reset.sclk)) @@ -247,7 +245,7 @@ static int __init at91_reset_probe(struct platform_device *pdev) return ret; } - ret = register_restart_handler(&at91_restart_nb); + ret = register_restart_handler(&reset.nb); if (ret) { clk_disable_unprepare(reset.sclk); return ret; @@ -260,7 +258,7 @@ static int __init at91_reset_probe(struct platform_device *pdev) static int __exit at91_reset_remove(struct platform_device *pdev) { - unregister_restart_handler(&at91_restart_nb); + unregister_restart_handler(&reset.nb); clk_disable_unprepare(reset.sclk); return 0; From b7967b7919f0e3787d6e23424b5ad367fbb937e2 Mon Sep 17 00:00:00 2001 From: "Claudiu.Beznea@microchip.com" Date: Tue, 21 Jan 2020 10:03:31 +0000 Subject: [PATCH 1294/4444] power: reset: at91-reset: convert reset in pointer to struct at91_reset Convert reset in pointer to struct at91_reset. Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-reset.c | 50 +++++++++++++++++--------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index e8840193620d..4bb5eef4b258 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -56,7 +56,7 @@ struct at91_reset { struct notifier_block nb; }; -static struct at91_reset reset; +static struct at91_reset *reset; /* * unless the SDRAM is cleanly shutdown before we hit the @@ -81,8 +81,8 @@ static int at91sam9260_restart(struct notifier_block *this, unsigned long mode, "b .\n\t" : - : "r" (reset.ramc_base[0]), - "r" (reset.rstc_base), + : "r" (reset->ramc_base[0]), + "r" (reset->rstc_base), "r" (1), "r" cpu_to_le32(AT91_SDRAMC_LPCB_POWER_DOWN), "r" cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)); @@ -123,9 +123,9 @@ static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode, " b .\n\t" : - : "r" (reset.ramc_base[0]), - "r" (reset.ramc_base[1]), - "r" (reset.rstc_base), + : "r" (reset->ramc_base[0]), + "r" (reset->ramc_base[1]), + "r" (reset->rstc_base), "r" (1), "r" cpu_to_le32(AT91_DDRSDRC_LPCB_POWER_DOWN), "r" cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST) @@ -138,7 +138,7 @@ static int sama5d3_restart(struct notifier_block *this, unsigned long mode, void *cmd) { writel(cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST), - reset.rstc_base); + reset->rstc_base); return NOTIFY_DONE; } @@ -147,7 +147,7 @@ static int samx7_restart(struct notifier_block *this, unsigned long mode, void *cmd) { writel(cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PROCRST), - reset.rstc_base); + reset->rstc_base); return NOTIFY_DONE; } @@ -155,7 +155,7 @@ static int samx7_restart(struct notifier_block *this, unsigned long mode, static void __init at91_reset_status(struct platform_device *pdev) { const char *reason; - u32 reg = readl(reset.rstc_base + AT91_RSTC_SR); + u32 reg = readl(reset->rstc_base + AT91_RSTC_SR); switch ((reg & AT91_RSTC_RSTTYP) >> 8) { case RESET_TYPE_GENERAL: @@ -212,8 +212,12 @@ static int __init at91_reset_probe(struct platform_device *pdev) struct device_node *np; int ret, idx = 0; - reset.rstc_base = of_iomap(pdev->dev.of_node, 0); - if (!reset.rstc_base) { + reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL); + if (!reset) + return -ENOMEM; + + reset->rstc_base = of_iomap(pdev->dev.of_node, 0); + if (!reset->rstc_base) { dev_err(&pdev->dev, "Could not map reset controller address\n"); return -ENODEV; } @@ -221,8 +225,8 @@ static int __init at91_reset_probe(struct platform_device *pdev) if (!of_device_is_compatible(pdev->dev.of_node, "atmel,sama5d3-rstc")) { /* we need to shutdown the ddr controller, so get ramc base */ for_each_matching_node(np, at91_ramc_of_match) { - reset.ramc_base[idx] = of_iomap(np, 0); - if (!reset.ramc_base[idx]) { + reset->ramc_base[idx] = of_iomap(np, 0); + if (!reset->ramc_base[idx]) { dev_err(&pdev->dev, "Could not map ram controller address\n"); of_node_put(np); return -ENODEV; @@ -232,22 +236,22 @@ static int __init at91_reset_probe(struct platform_device *pdev) } match = of_match_node(at91_reset_of_match, pdev->dev.of_node); - reset.nb.notifier_call = match->data; - reset.nb.priority = 192; + reset->nb.notifier_call = match->data; + reset->nb.priority = 192; - reset.sclk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(reset.sclk)) - return PTR_ERR(reset.sclk); + reset->sclk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(reset->sclk)) + return PTR_ERR(reset->sclk); - ret = clk_prepare_enable(reset.sclk); + ret = clk_prepare_enable(reset->sclk); if (ret) { dev_err(&pdev->dev, "Could not enable slow clock\n"); return ret; } - ret = register_restart_handler(&reset.nb); + ret = register_restart_handler(&reset->nb); if (ret) { - clk_disable_unprepare(reset.sclk); + clk_disable_unprepare(reset->sclk); return ret; } @@ -258,8 +262,8 @@ static int __init at91_reset_probe(struct platform_device *pdev) static int __exit at91_reset_remove(struct platform_device *pdev) { - unregister_restart_handler(&reset.nb); - clk_disable_unprepare(reset.sclk); + unregister_restart_handler(&reset->nb); + clk_disable_unprepare(reset->sclk); return 0; } From 55f8e6fdefbe926e1729bba3a7608eed7d7f24f5 Mon Sep 17 00:00:00 2001 From: "Claudiu.Beznea@microchip.com" Date: Tue, 21 Jan 2020 10:03:32 +0000 Subject: [PATCH 1295/4444] power: reset: at91-reset: pass rstc base address to at91_reset_status() Add new argument to at91_reset_status() that is the pointer to reset controller base address. Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-reset.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index 4bb5eef4b258..bd05496c5ac7 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -152,10 +152,11 @@ static int samx7_restart(struct notifier_block *this, unsigned long mode, return NOTIFY_DONE; } -static void __init at91_reset_status(struct platform_device *pdev) +static void __init at91_reset_status(struct platform_device *pdev, + void __iomem *base) { const char *reason; - u32 reg = readl(reset->rstc_base + AT91_RSTC_SR); + u32 reg = readl(base + AT91_RSTC_SR); switch ((reg & AT91_RSTC_RSTTYP) >> 8) { case RESET_TYPE_GENERAL: @@ -255,7 +256,7 @@ static int __init at91_reset_probe(struct platform_device *pdev) return ret; } - at91_reset_status(pdev); + at91_reset_status(pdev, reset->rstc_base); return 0; } From 583ef884c8dc8e5ec9a7fde12d40ef7fdf18f5fb Mon Sep 17 00:00:00 2001 From: "Claudiu.Beznea@microchip.com" Date: Tue, 21 Jan 2020 10:03:32 +0000 Subject: [PATCH 1296/4444] power: reset: at91-reset: devm_kzalloc() for at91_reset data structure Allocate at91_reset data on probe and set it as platform data. Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-reset.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index bd05496c5ac7..7ba77555e9e1 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -56,8 +56,6 @@ struct at91_reset { struct notifier_block nb; }; -static struct at91_reset *reset; - /* * unless the SDRAM is cleanly shutdown before we hit the * reset register it can be left driving the data bus and @@ -66,6 +64,8 @@ static struct at91_reset *reset; static int at91sam9260_restart(struct notifier_block *this, unsigned long mode, void *cmd) { + struct at91_reset *reset = container_of(this, struct at91_reset, nb); + asm volatile( /* Align to cache lines */ ".balign 32\n\t" @@ -93,6 +93,8 @@ static int at91sam9260_restart(struct notifier_block *this, unsigned long mode, static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode, void *cmd) { + struct at91_reset *reset = container_of(this, struct at91_reset, nb); + asm volatile( /* * Test wether we have a second RAM controller to care @@ -137,6 +139,8 @@ static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode, static int sama5d3_restart(struct notifier_block *this, unsigned long mode, void *cmd) { + struct at91_reset *reset = container_of(this, struct at91_reset, nb); + writel(cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST), reset->rstc_base); @@ -146,6 +150,8 @@ static int sama5d3_restart(struct notifier_block *this, unsigned long mode, static int samx7_restart(struct notifier_block *this, unsigned long mode, void *cmd) { + struct at91_reset *reset = container_of(this, struct at91_reset, nb); + writel(cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PROCRST), reset->rstc_base); @@ -210,6 +216,7 @@ MODULE_DEVICE_TABLE(of, at91_reset_of_match); static int __init at91_reset_probe(struct platform_device *pdev) { const struct of_device_id *match; + struct at91_reset *reset; struct device_node *np; int ret, idx = 0; @@ -250,6 +257,8 @@ static int __init at91_reset_probe(struct platform_device *pdev) return ret; } + platform_set_drvdata(pdev, reset); + ret = register_restart_handler(&reset->nb); if (ret) { clk_disable_unprepare(reset->sclk); @@ -263,6 +272,8 @@ static int __init at91_reset_probe(struct platform_device *pdev) static int __exit at91_reset_remove(struct platform_device *pdev) { + struct at91_reset *reset = platform_get_drvdata(pdev); + unregister_restart_handler(&reset->nb); clk_disable_unprepare(reset->sclk); From a5bbad258a9ec41df4a158c828b9ef0af7955854 Mon Sep 17 00:00:00 2001 From: "Claudiu.Beznea@microchip.com" Date: Tue, 21 Jan 2020 10:03:32 +0000 Subject: [PATCH 1297/4444] power: reset: at91-reset: introduce struct at91_reset_data Introduce struct at91_reset_data to be able to provide per SoC data. At the moment this being only notifier callback. Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-reset.c | 50 ++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index 7ba77555e9e1..c653bd7ac29a 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -49,6 +49,11 @@ enum reset_type { RESET_TYPE_ULP2 = 8, }; +struct at91_reset_data { + int (*notifier_call)(struct notifier_block *this, unsigned long mode, + void *cmd); +}; + struct at91_reset { void __iomem *rstc_base; void __iomem *ramc_base[2]; @@ -203,18 +208,50 @@ static const struct of_device_id at91_ramc_of_match[] = { { /* sentinel */ } }; +static const struct at91_reset_data at91sam9260_reset_data = { + .notifier_call = at91sam9260_restart, +}; + +static const struct at91_reset_data at91sam9g45_reset_data = { + .notifier_call = at91sam9g45_restart, +}; + +static const struct at91_reset_data sama5d3_reset_data = { + .notifier_call = sama5d3_restart, +}; + +static const struct at91_reset_data samx7_reset_data = { + .notifier_call = samx7_restart, +}; + static const struct of_device_id at91_reset_of_match[] = { - { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9260_restart }, - { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart }, - { .compatible = "atmel,sama5d3-rstc", .data = sama5d3_restart }, - { .compatible = "atmel,samx7-rstc", .data = samx7_restart }, - { .compatible = "microchip,sam9x60-rstc", .data = samx7_restart }, + { + .compatible = "atmel,at91sam9260-rstc", + .data = &at91sam9260_reset_data + }, + { + .compatible = "atmel,at91sam9g45-rstc", + .data = &at91sam9g45_reset_data + }, + { + .compatible = "atmel,sama5d3-rstc", + .data = &sama5d3_reset_data + }, + { + .compatible = "atmel,samx7-rstc", + .data = &samx7_reset_data + }, + { + .compatible = "microchip,sam9x60-rstc", + .data = &samx7_reset_data + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, at91_reset_of_match); static int __init at91_reset_probe(struct platform_device *pdev) { + const struct at91_reset_data *reset_data; const struct of_device_id *match; struct at91_reset *reset; struct device_node *np; @@ -244,7 +281,8 @@ static int __init at91_reset_probe(struct platform_device *pdev) } match = of_match_node(at91_reset_of_match, pdev->dev.of_node); - reset->nb.notifier_call = match->data; + reset_data = match->data; + reset->nb.notifier_call = reset_data->notifier_call; reset->nb.priority = 192; reset->sclk = devm_clk_get(&pdev->dev, NULL); From 25b80b7d5a5b41cb52db441e37a04d71e7196f60 Mon Sep 17 00:00:00 2001 From: "Claudiu.Beznea@microchip.com" Date: Tue, 21 Jan 2020 10:03:33 +0000 Subject: [PATCH 1298/4444] power: reset: at91-reset: introduce args member in at91_reset_data Introduce args member in struct at91_reset_data. It stores the value that needs to be written in mode register so that the reboot actions to happen. With these changes samx7_restart() could be removed. Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-reset.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index c653bd7ac29a..dc48f6850796 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -52,6 +52,7 @@ enum reset_type { struct at91_reset_data { int (*notifier_call)(struct notifier_block *this, unsigned long mode, void *cmd); + u32 args; }; struct at91_reset { @@ -59,6 +60,7 @@ struct at91_reset { void __iomem *ramc_base[2]; struct clk *sclk; struct notifier_block nb; + u32 args; }; /* @@ -90,7 +92,7 @@ static int at91sam9260_restart(struct notifier_block *this, unsigned long mode, "r" (reset->rstc_base), "r" (1), "r" cpu_to_le32(AT91_SDRAMC_LPCB_POWER_DOWN), - "r" cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)); + "r" (reset->args)); return NOTIFY_DONE; } @@ -135,7 +137,7 @@ static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode, "r" (reset->rstc_base), "r" (1), "r" cpu_to_le32(AT91_DDRSDRC_LPCB_POWER_DOWN), - "r" cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST) + "r" (reset->args) : "r0"); return NOTIFY_DONE; @@ -146,19 +148,7 @@ static int sama5d3_restart(struct notifier_block *this, unsigned long mode, { struct at91_reset *reset = container_of(this, struct at91_reset, nb); - writel(cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST), - reset->rstc_base); - - return NOTIFY_DONE; -} - -static int samx7_restart(struct notifier_block *this, unsigned long mode, - void *cmd) -{ - struct at91_reset *reset = container_of(this, struct at91_reset, nb); - - writel(cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PROCRST), - reset->rstc_base); + writel(reset->args, reset->rstc_base); return NOTIFY_DONE; } @@ -210,18 +200,22 @@ static const struct of_device_id at91_ramc_of_match[] = { static const struct at91_reset_data at91sam9260_reset_data = { .notifier_call = at91sam9260_restart, + .args = AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST, }; static const struct at91_reset_data at91sam9g45_reset_data = { .notifier_call = at91sam9g45_restart, + .args = AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST, }; static const struct at91_reset_data sama5d3_reset_data = { .notifier_call = sama5d3_restart, + .args = AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST, }; static const struct at91_reset_data samx7_reset_data = { - .notifier_call = samx7_restart, + .notifier_call = sama5d3_restart, + .args = AT91_RSTC_KEY | AT91_RSTC_PROCRST, }; static const struct of_device_id at91_reset_of_match[] = { @@ -284,6 +278,7 @@ static int __init at91_reset_probe(struct platform_device *pdev) reset_data = match->data; reset->nb.notifier_call = reset_data->notifier_call; reset->nb.priority = 192; + reset->args = reset_data->args; reset->sclk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(reset->sclk)) From 7cb290d3dd559dff5028b9418a31ecb99988f640 Mon Sep 17 00:00:00 2001 From: "Claudiu.Beznea@microchip.com" Date: Tue, 21 Jan 2020 10:03:33 +0000 Subject: [PATCH 1299/4444] power: reset: at91-reset: use r4 as tmp argument Use r4 as temporary register. On ARM r0-r3 should be used to hold function arguments. Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-reset.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index dc48f6850796..3b1d566350f4 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -113,8 +113,8 @@ static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode, "beq 1f\n\t" /* Then, test that the RAM controller is enabled */ - "ldr r0, [%1]\n\t" - "cmp r0, #0\n\t" + "ldr r4, [%1]\n\t" + "cmp r4, #0\n\t" /* Align to cache lines */ ".balign 32\n\t" @@ -138,7 +138,7 @@ static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode, "r" (1), "r" cpu_to_le32(AT91_DDRSDRC_LPCB_POWER_DOWN), "r" (reset->args) - : "r0"); + : "r4"); return NOTIFY_DONE; } From 68a84a3e68a2238036dd6c7dbb677fe62a92d70a Mon Sep 17 00:00:00 2001 From: "Claudiu.Beznea@microchip.com" Date: Tue, 21 Jan 2020 10:03:34 +0000 Subject: [PATCH 1300/4444] power: reset: at91-reset: introduce ramc_lpr to struct at91_reset Introduce ramc_lpr to struct at91_reset. This will lead to the unification of at91sam9260_restart() and at91sam9g45_restart(). Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-reset.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index 3b1d566350f4..4e1961334e4d 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -61,6 +61,7 @@ struct at91_reset { struct clk *sclk; struct notifier_block nb; u32 args; + u32 ramc_lpr; }; /* @@ -81,7 +82,7 @@ static int at91sam9260_restart(struct notifier_block *this, unsigned long mode, "str %2, [%0, #" __stringify(AT91_SDRAMC_TR) "]\n\t" /* Power down SDRAM */ - "str %3, [%0, #" __stringify(AT91_SDRAMC_LPR) "]\n\t" + "str %3, [%0, %5]\n\t" /* Reset CPU */ "str %4, [%1, #" __stringify(AT91_RSTC_CR) "]\n\t" @@ -92,7 +93,8 @@ static int at91sam9260_restart(struct notifier_block *this, unsigned long mode, "r" (reset->rstc_base), "r" (1), "r" cpu_to_le32(AT91_SDRAMC_LPCB_POWER_DOWN), - "r" (reset->args)); + "r" (reset->args), + "r" (reset->ramc_lpr)); return NOTIFY_DONE; } @@ -122,11 +124,11 @@ static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode, /* Disable SDRAM0 accesses */ "1: str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t" /* Power down SDRAM0 */ - " str %4, [%0, #" __stringify(AT91_DDRSDRC_LPR) "]\n\t" + " str %4, [%0, %6]\n\t" /* Disable SDRAM1 accesses */ " strne %3, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t" /* Power down SDRAM1 */ - " strne %4, [%1, #" __stringify(AT91_DDRSDRC_LPR) "]\n\t" + " strne %4, [%1, %6]\n\t" /* Reset CPU */ " str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t" @@ -137,7 +139,8 @@ static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode, "r" (reset->rstc_base), "r" (1), "r" cpu_to_le32(AT91_DDRSDRC_LPCB_POWER_DOWN), - "r" (reset->args) + "r" (reset->args), + "r" (reset->ramc_lpr) : "r4"); return NOTIFY_DONE; @@ -193,8 +196,14 @@ static void __init at91_reset_status(struct platform_device *pdev, } static const struct of_device_id at91_ramc_of_match[] = { - { .compatible = "atmel,at91sam9260-sdramc", }, - { .compatible = "atmel,at91sam9g45-ddramc", }, + { + .compatible = "atmel,at91sam9260-sdramc", + .data = (void *)AT91_SDRAMC_LPR, + }, + { + .compatible = "atmel,at91sam9g45-ddramc", + .data = (void *)AT91_DDRSDRC_LPR, + }, { /* sentinel */ } }; @@ -263,7 +272,8 @@ static int __init at91_reset_probe(struct platform_device *pdev) if (!of_device_is_compatible(pdev->dev.of_node, "atmel,sama5d3-rstc")) { /* we need to shutdown the ddr controller, so get ramc base */ - for_each_matching_node(np, at91_ramc_of_match) { + for_each_matching_node_and_match(np, at91_ramc_of_match, &match) { + reset->ramc_lpr = (u32)match->data; reset->ramc_base[idx] = of_iomap(np, 0); if (!reset->ramc_base[idx]) { dev_err(&pdev->dev, "Could not map ram controller address\n"); From fcd0532fac2ac82cec6d7b43298c8ecfc93e1049 Mon Sep 17 00:00:00 2001 From: "Claudiu.Beznea@microchip.com" Date: Tue, 21 Jan 2020 10:03:37 +0000 Subject: [PATCH 1301/4444] power: reset: at91-reset: make at91sam9g45_restart() generic Make at91sam9g45_restart() generic. Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-reset.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index 4e1961334e4d..61433060d784 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -105,32 +105,23 @@ static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode, struct at91_reset *reset = container_of(this, struct at91_reset, nb); asm volatile( - /* - * Test wether we have a second RAM controller to care - * about. - * - * First, test that we can dereference the virtual address. - */ - "cmp %1, #0\n\t" - "beq 1f\n\t" - - /* Then, test that the RAM controller is enabled */ - "ldr r4, [%1]\n\t" - "cmp r4, #0\n\t" - /* Align to cache lines */ ".balign 32\n\t" /* Disable SDRAM0 accesses */ - "1: str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t" + " tst %0, #0\n\t" + " beq 1f\n\t" + " str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t" /* Power down SDRAM0 */ " str %4, [%0, %6]\n\t" /* Disable SDRAM1 accesses */ + "1: tst %1, #0\n\t" + " beq 2f\n\t" " strne %3, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t" /* Power down SDRAM1 */ " strne %4, [%1, %6]\n\t" /* Reset CPU */ - " str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t" + "2: str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t" " b .\n\t" : From 51aa7d45f905ca03d3c61d32a09537903a7ea707 Mon Sep 17 00:00:00 2001 From: "Claudiu.Beznea@microchip.com" Date: Tue, 21 Jan 2020 10:03:38 +0000 Subject: [PATCH 1302/4444] power: reset: at91-reset: keep only one reset function Keep only one reset function. With this, notifier_call member of struct at91_reset_data could be removed. Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-reset.c | 52 ++------------------------------ 1 file changed, 3 insertions(+), 49 deletions(-) diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index 61433060d784..9c1b69f76a01 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -50,8 +50,6 @@ enum reset_type { }; struct at91_reset_data { - int (*notifier_call)(struct notifier_block *this, unsigned long mode, - void *cmd); u32 args; }; @@ -69,38 +67,8 @@ struct at91_reset { * reset register it can be left driving the data bus and * killing the chance of a subsequent boot from NAND */ -static int at91sam9260_restart(struct notifier_block *this, unsigned long mode, - void *cmd) -{ - struct at91_reset *reset = container_of(this, struct at91_reset, nb); - - asm volatile( - /* Align to cache lines */ - ".balign 32\n\t" - - /* Disable SDRAM accesses */ - "str %2, [%0, #" __stringify(AT91_SDRAMC_TR) "]\n\t" - - /* Power down SDRAM */ - "str %3, [%0, %5]\n\t" - - /* Reset CPU */ - "str %4, [%1, #" __stringify(AT91_RSTC_CR) "]\n\t" - - "b .\n\t" - : - : "r" (reset->ramc_base[0]), - "r" (reset->rstc_base), - "r" (1), - "r" cpu_to_le32(AT91_SDRAMC_LPCB_POWER_DOWN), - "r" (reset->args), - "r" (reset->ramc_lpr)); - - return NOTIFY_DONE; -} - -static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode, - void *cmd) +static int at91_reset(struct notifier_block *this, unsigned long mode, + void *cmd) { struct at91_reset *reset = container_of(this, struct at91_reset, nb); @@ -137,16 +105,6 @@ static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode, return NOTIFY_DONE; } -static int sama5d3_restart(struct notifier_block *this, unsigned long mode, - void *cmd) -{ - struct at91_reset *reset = container_of(this, struct at91_reset, nb); - - writel(reset->args, reset->rstc_base); - - return NOTIFY_DONE; -} - static void __init at91_reset_status(struct platform_device *pdev, void __iomem *base) { @@ -199,22 +157,18 @@ static const struct of_device_id at91_ramc_of_match[] = { }; static const struct at91_reset_data at91sam9260_reset_data = { - .notifier_call = at91sam9260_restart, .args = AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST, }; static const struct at91_reset_data at91sam9g45_reset_data = { - .notifier_call = at91sam9g45_restart, .args = AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST, }; static const struct at91_reset_data sama5d3_reset_data = { - .notifier_call = sama5d3_restart, .args = AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST, }; static const struct at91_reset_data samx7_reset_data = { - .notifier_call = sama5d3_restart, .args = AT91_RSTC_KEY | AT91_RSTC_PROCRST, }; @@ -277,7 +231,7 @@ static int __init at91_reset_probe(struct platform_device *pdev) match = of_match_node(at91_reset_of_match, pdev->dev.of_node); reset_data = match->data; - reset->nb.notifier_call = reset_data->notifier_call; + reset->nb.notifier_call = at91_reset; reset->nb.priority = 192; reset->args = reset_data->args; From 766b0162e613a89a330382e566e29da57f5f0de5 Mon Sep 17 00:00:00 2001 From: "Claudiu.Beznea@microchip.com" Date: Tue, 21 Jan 2020 10:03:39 +0000 Subject: [PATCH 1303/4444] power: reset: at91-reset: get rid of at91_reset_data After refactoring struct at91_reset_data and struct at91_reset_data at91sam9260_reset_data are not needed anymore. Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-reset.c | 37 ++++++++------------------------ 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index 9c1b69f76a01..537ccb180568 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -49,10 +49,6 @@ enum reset_type { RESET_TYPE_ULP2 = 8, }; -struct at91_reset_data { - u32 args; -}; - struct at91_reset { void __iomem *rstc_base; void __iomem *ramc_base[2]; @@ -156,42 +152,29 @@ static const struct of_device_id at91_ramc_of_match[] = { { /* sentinel */ } }; -static const struct at91_reset_data at91sam9260_reset_data = { - .args = AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST, -}; - -static const struct at91_reset_data at91sam9g45_reset_data = { - .args = AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST, -}; - -static const struct at91_reset_data sama5d3_reset_data = { - .args = AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST, -}; - -static const struct at91_reset_data samx7_reset_data = { - .args = AT91_RSTC_KEY | AT91_RSTC_PROCRST, -}; - static const struct of_device_id at91_reset_of_match[] = { { .compatible = "atmel,at91sam9260-rstc", - .data = &at91sam9260_reset_data + .data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PERRST | + AT91_RSTC_PROCRST), }, { .compatible = "atmel,at91sam9g45-rstc", - .data = &at91sam9g45_reset_data + .data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PERRST | + AT91_RSTC_PROCRST) }, { .compatible = "atmel,sama5d3-rstc", - .data = &sama5d3_reset_data + .data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PERRST | + AT91_RSTC_PROCRST) }, { .compatible = "atmel,samx7-rstc", - .data = &samx7_reset_data + .data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PROCRST) }, { .compatible = "microchip,sam9x60-rstc", - .data = &samx7_reset_data + .data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PROCRST) }, { /* sentinel */ } }; @@ -199,7 +182,6 @@ MODULE_DEVICE_TABLE(of, at91_reset_of_match); static int __init at91_reset_probe(struct platform_device *pdev) { - const struct at91_reset_data *reset_data; const struct of_device_id *match; struct at91_reset *reset; struct device_node *np; @@ -230,10 +212,9 @@ static int __init at91_reset_probe(struct platform_device *pdev) } match = of_match_node(at91_reset_of_match, pdev->dev.of_node); - reset_data = match->data; reset->nb.notifier_call = at91_reset; reset->nb.priority = 192; - reset->args = reset_data->args; + reset->args = (u32)match->data; reset->sclk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(reset->sclk)) From e48bbb52a2aad8613291a9e4e757bbf995769015 Mon Sep 17 00:00:00 2001 From: "Claudiu.Beznea@microchip.com" Date: Tue, 21 Jan 2020 10:03:39 +0000 Subject: [PATCH 1304/4444] power: reset: at91-reset: handle nrst async for sam9x60 Handle NRST asynchronously for SAM9X60 to avoid problem with fast drop of VDDCORE on shutdown operations in the first 100 us after CPU is shutdown. Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-reset.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index 537ccb180568..3ff9d93a5226 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -35,6 +35,7 @@ #define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */ #define AT91_RSTC_URSTEN BIT(0) /* User Reset Enable */ +#define AT91_RSTC_URSTASYNC BIT(2) /* User Reset Asynchronous Control */ #define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */ #define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */ @@ -228,6 +229,13 @@ static int __init at91_reset_probe(struct platform_device *pdev) platform_set_drvdata(pdev, reset); + if (of_device_is_compatible(pdev->dev.of_node, "microchip,sam9x60-rstc")) { + u32 val = readl(reset->rstc_base + AT91_RSTC_MR); + + writel(AT91_RSTC_KEY | AT91_RSTC_URSTASYNC | val, + reset->rstc_base + AT91_RSTC_MR); + } + ret = register_restart_handler(&reset->nb); if (ret) { clk_disable_unprepare(reset->sclk); From fc51da4c15fa1e00cd1f855e14e8b05abbc555c7 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 4 Mar 2020 15:42:14 +0900 Subject: [PATCH 1305/4444] dt-bindings: clock: renesas: rcar-usb2-clock-sel: Fix clock[-name]s properties Since the hardware requires to enable both USB 2.0 host and peripheral functional clock, this patch fixes the documentation. Fortunately, no one has this device node for now, so that we don't need to think of backward compatibility. Fixes: 311accb64570 ("clk: renesas: rcar-usb2-clock-sel: Add R-Car USB 2.0 clock selector PHY") Signed-off-by: Yoshihiro Shimoda Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/1583304137-28482-2-git-send-email-yoshihiro.shimoda.uh@renesas.com Signed-off-by: Geert Uytterhoeven --- .../bindings/clock/renesas,rcar-usb2-clock-sel.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt b/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt index 83f6c6a7c41c..5c1903fc40b3 100644 --- a/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt +++ b/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt @@ -38,7 +38,8 @@ Required properties: - reg: offset and length of the USB 2.0 clock selector register block. - clocks: A list of phandles and specifier pairs. - clock-names: Name of the clocks. - - The functional clock must be "ehci_ohci" + - The functional clock of USB 2.0 host side must be "ehci_ohci" + - The functional clock of HS-USB side must be "hs-usb-if" - The USB_EXTAL clock pin must be "usb_extal" - The USB_XTAL clock pin must be "usb_xtal" - #clock-cells: Must be 0 @@ -49,7 +50,8 @@ Example (R-Car H3): compatible = "renesas,r8a7795-rcar-usb2-clock-sel", "renesas,rcar-gen3-usb2-clock-sel"; reg = <0 0xe6590630 0 0x02>; - clocks = <&cpg CPG_MOD 703>, <&usb_extal>, <&usb_xtal>; - clock-names = "ehci_ohci", "usb_extal", "usb_xtal"; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>, + <&usb_extal>, <&usb_xtal>; + clock-names = "ehci_ohci", "hs-usb-if", "usb_extal", "usb_xtal"; #clock-cells = <0>; }; From f70ae8ecf950fc49291eb4aeca43192b28ff342f Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 4 Mar 2020 15:42:15 +0900 Subject: [PATCH 1306/4444] dt-bindings: clock: renesas: rcar-usb2-clock-sel: Add power-domains and resets properties This patch adds missing required properties of power-domains and resets. Fortunately, no one has this device node for now, so that we don't need to think of backward compatibility. Fixes: 311accb64570 ("clk: renesas: rcar-usb2-clock-sel: Add R-Car USB 2.0 clock selector PHY") Signed-off-by: Yoshihiro Shimoda Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/1583304137-28482-3-git-send-email-yoshihiro.shimoda.uh@renesas.com Signed-off-by: Geert Uytterhoeven --- .../bindings/clock/renesas,rcar-usb2-clock-sel.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt b/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt index 5c1903fc40b3..4bf6f53bd95e 100644 --- a/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt +++ b/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt @@ -43,6 +43,12 @@ Required properties: - The USB_EXTAL clock pin must be "usb_extal" - The USB_XTAL clock pin must be "usb_xtal" - #clock-cells: Must be 0 +- power-domains: A phandle and symbolic PM domain specifier. + See power/renesas,rcar-sysc.yaml. +- resets: A list of phandles and specifier pairs. +- reset-names: Name of the resets. + - The reset of USB 2.0 host side must be "ehci_ohci" + - The reset of HS-USB side must be "hs-usb-if" Example (R-Car H3): @@ -54,4 +60,7 @@ Example (R-Car H3): <&usb_extal>, <&usb_xtal>; clock-names = "ehci_ohci", "hs-usb-if", "usb_extal", "usb_xtal"; #clock-cells = <0>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + resets = <&cpg 703>, <&cpg 704>; + reset-names = "ehci_ohci", "hs-usb-if"; }; From 80cf67dd010b4a187360bb8ce8a1974bdad8c076 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 4 Mar 2020 15:42:16 +0900 Subject: [PATCH 1307/4444] clk: renesas: rcar-usb2-clock-sel: Add multiple clocks management This hardware needs to enable clocks of both host and peripheral. So, this patch adds multiple clocks management. Signed-off-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/1583304137-28482-4-git-send-email-yoshihiro.shimoda.uh@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rcar-usb2-clock-sel.c | 27 +++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/clk/renesas/rcar-usb2-clock-sel.c b/drivers/clk/renesas/rcar-usb2-clock-sel.c index b97f5f9326cf..d5f47ab017b7 100644 --- a/drivers/clk/renesas/rcar-usb2-clock-sel.c +++ b/drivers/clk/renesas/rcar-usb2-clock-sel.c @@ -26,9 +26,15 @@ #define CLKSET0_PRIVATE BIT(0) #define CLKSET0_EXTAL_ONLY (CLKSET0_INTCLK_EN | CLKSET0_PRIVATE) +static const struct clk_bulk_data rcar_usb2_clocks[] = { + { .id = "ehci_ohci", }, + { .id = "hs-usb-if", }, +}; + struct usb2_clock_sel_priv { void __iomem *base; struct clk_hw hw; + struct clk_bulk_data clks[ARRAY_SIZE(rcar_usb2_clocks)]; bool extal; bool xtal; }; @@ -53,14 +59,25 @@ static void usb2_clock_sel_disable_extal_only(struct usb2_clock_sel_priv *priv) static int usb2_clock_sel_enable(struct clk_hw *hw) { - usb2_clock_sel_enable_extal_only(to_priv(hw)); + struct usb2_clock_sel_priv *priv = to_priv(hw); + int ret; + + ret = clk_bulk_prepare_enable(ARRAY_SIZE(priv->clks), priv->clks); + if (ret) + return ret; + + usb2_clock_sel_enable_extal_only(priv); return 0; } static void usb2_clock_sel_disable(struct clk_hw *hw) { - usb2_clock_sel_disable_extal_only(to_priv(hw)); + struct usb2_clock_sel_priv *priv = to_priv(hw); + + usb2_clock_sel_disable_extal_only(priv); + + clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clks), priv->clks); } /* @@ -119,6 +136,7 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) struct usb2_clock_sel_priv *priv; struct clk *clk; struct clk_init_data init; + int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -128,6 +146,11 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) if (IS_ERR(priv->base)) return PTR_ERR(priv->base); + memcpy(priv->clks, rcar_usb2_clocks, sizeof(priv->clks)); + ret = devm_clk_bulk_get(dev, ARRAY_SIZE(priv->clks), priv->clks); + if (ret < 0) + return ret; + pm_runtime_enable(dev); pm_runtime_get_sync(dev); From 1ab4f43927a452ef24cd47ef686f3e1cbac9ab61 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 4 Mar 2020 15:42:17 +0900 Subject: [PATCH 1308/4444] clk: renesas: rcar-usb2-clock-sel: Add reset_control This hardware needs to deassert resets of both host and peripheral. So, this patch adds reset control. Signed-off-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/1583304137-28482-5-git-send-email-yoshihiro.shimoda.uh@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/Kconfig | 1 + drivers/clk/renesas/rcar-usb2-clock-sel.c | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 879d96ead06b..ac2dd92ce2ef 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -161,6 +161,7 @@ config CLK_RCAR_GEN3_CPG config CLK_RCAR_USB2_CLOCK_SEL bool "Renesas R-Car USB2 clock selector support" depends on ARCH_RENESAS || COMPILE_TEST + select RESET_CONTROLLER help This is a driver for R-Car USB2 clock selector diff --git a/drivers/clk/renesas/rcar-usb2-clock-sel.c b/drivers/clk/renesas/rcar-usb2-clock-sel.c index d5f47ab017b7..d4c02986c34e 100644 --- a/drivers/clk/renesas/rcar-usb2-clock-sel.c +++ b/drivers/clk/renesas/rcar-usb2-clock-sel.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #define USB20_CLKSET0 0x00 @@ -35,6 +36,7 @@ struct usb2_clock_sel_priv { void __iomem *base; struct clk_hw hw; struct clk_bulk_data clks[ARRAY_SIZE(rcar_usb2_clocks)]; + struct reset_control *rsts; bool extal; bool xtal; }; @@ -62,10 +64,16 @@ static int usb2_clock_sel_enable(struct clk_hw *hw) struct usb2_clock_sel_priv *priv = to_priv(hw); int ret; - ret = clk_bulk_prepare_enable(ARRAY_SIZE(priv->clks), priv->clks); + ret = reset_control_deassert(priv->rsts); if (ret) return ret; + ret = clk_bulk_prepare_enable(ARRAY_SIZE(priv->clks), priv->clks); + if (ret) { + reset_control_assert(priv->rsts); + return ret; + } + usb2_clock_sel_enable_extal_only(priv); return 0; @@ -78,6 +86,7 @@ static void usb2_clock_sel_disable(struct clk_hw *hw) usb2_clock_sel_disable_extal_only(priv); clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clks), priv->clks); + reset_control_assert(priv->rsts); } /* @@ -151,6 +160,10 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) if (ret < 0) return ret; + priv->rsts = devm_reset_control_array_get(dev, true, false); + if (IS_ERR(priv->rsts)) + return PTR_ERR(priv->rsts); + pm_runtime_enable(dev); pm_runtime_get_sync(dev); From bc0ae0e737f5167348579612493e2754e2122dfb Mon Sep 17 00:00:00 2001 From: Asmaa Mnebhi Date: Mon, 2 Mar 2020 16:04:46 -0500 Subject: [PATCH 1309/4444] gpio: add driver for Mellanox BlueField 2 GPIO controller This patch adds support for the GPIO controller used by Mellanox BlueField 2 SOCs. Signed-off-by: Asmaa Mnebhi Link: https://lore.kernel.org/r/1680de9eb6d2b8855228dde9a2dd065f0dcbe1fb.1583182325.git.Asmaa@mellanox.com Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 7 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-mlxbf2.c | 335 +++++++++++++++++++++++++++++++++++++ 3 files changed, 343 insertions(+) create mode 100644 drivers/gpio/gpio-mlxbf2.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b8013cf90064..6234ccc90e7e 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1399,6 +1399,13 @@ config GPIO_MLXBF help Say Y here if you want GPIO support on Mellanox BlueField SoC. +config GPIO_MLXBF2 + tristate "Mellanox BlueField 2 SoC GPIO" + depends on (MELLANOX_PLATFORM && ARM64 && ACPI) || (64BIT && COMPILE_TEST) + select GPIO_GENERIC + help + Say Y here if you want GPIO support on Mellanox BlueField 2 SoC. + config GPIO_ML_IOH tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support" depends on X86 || COMPILE_TEST diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 0b571264ddbc..b2cfc21a97f3 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -93,6 +93,7 @@ obj-$(CONFIG_GPIO_MENZ127) += gpio-menz127.o obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o obj-$(CONFIG_GPIO_MLXBF) += gpio-mlxbf.o +obj-$(CONFIG_GPIO_MLXBF2) += gpio-mlxbf2.o obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o obj-$(CONFIG_GPIO_MOXTET) += gpio-moxtet.o diff --git a/drivers/gpio/gpio-mlxbf2.c b/drivers/gpio/gpio-mlxbf2.c new file mode 100644 index 000000000000..7b7085050219 --- /dev/null +++ b/drivers/gpio/gpio-mlxbf2.c @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * There are 3 YU GPIO blocks: + * gpio[0]: HOST_GPIO0->HOST_GPIO31 + * gpio[1]: HOST_GPIO32->HOST_GPIO63 + * gpio[2]: HOST_GPIO64->HOST_GPIO69 + */ +#define MLXBF2_GPIO_MAX_PINS_PER_BLOCK 32 + +/* + * arm_gpio_lock register: + * bit[31] lock status: active if set + * bit[15:0] set lock + * The lock is enabled only if 0xd42f is written to this field + */ +#define YU_ARM_GPIO_LOCK_ADDR 0x2801088 +#define YU_ARM_GPIO_LOCK_SIZE 0x8 +#define YU_LOCK_ACTIVE_BIT(val) (val >> 31) +#define YU_ARM_GPIO_LOCK_ACQUIRE 0xd42f +#define YU_ARM_GPIO_LOCK_RELEASE 0x0 + +/* + * gpio[x] block registers and their offset + */ +#define YU_GPIO_DATAIN 0x04 +#define YU_GPIO_MODE1 0x08 +#define YU_GPIO_MODE0 0x0c +#define YU_GPIO_DATASET 0x14 +#define YU_GPIO_DATACLEAR 0x18 +#define YU_GPIO_MODE1_CLEAR 0x50 +#define YU_GPIO_MODE0_SET 0x54 +#define YU_GPIO_MODE0_CLEAR 0x58 + +#ifdef CONFIG_PM +struct mlxbf2_gpio_context_save_regs { + u32 gpio_mode0; + u32 gpio_mode1; +}; +#endif + +/* BlueField-2 gpio block context structure. */ +struct mlxbf2_gpio_context { + struct gpio_chip gc; + + /* YU GPIO blocks address */ + void __iomem *gpio_io; + +#ifdef CONFIG_PM + struct mlxbf2_gpio_context_save_regs *csave_regs; +#endif +}; + +/* BlueField-2 gpio shared structure. */ +struct mlxbf2_gpio_param { + void __iomem *io; + struct resource *res; + struct mutex *lock; +}; + +static struct resource yu_arm_gpio_lock_res = { + .start = YU_ARM_GPIO_LOCK_ADDR, + .end = YU_ARM_GPIO_LOCK_ADDR + YU_ARM_GPIO_LOCK_SIZE - 1, + .name = "YU_ARM_GPIO_LOCK", +}; + +static DEFINE_MUTEX(yu_arm_gpio_lock_mutex); + +static struct mlxbf2_gpio_param yu_arm_gpio_lock_param = { + .res = &yu_arm_gpio_lock_res, + .lock = &yu_arm_gpio_lock_mutex, +}; + +/* Request memory region and map yu_arm_gpio_lock resource */ +static int mlxbf2_gpio_get_lock_res(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + resource_size_t size; + int ret = 0; + + mutex_lock(yu_arm_gpio_lock_param.lock); + + /* Check if the memory map already exists */ + if (yu_arm_gpio_lock_param.io) + goto exit; + + res = yu_arm_gpio_lock_param.res; + size = resource_size(res); + + if (!devm_request_mem_region(dev, res->start, size, res->name)) { + ret = -EFAULT; + goto exit; + } + + yu_arm_gpio_lock_param.io = devm_ioremap(dev, res->start, size); + if (IS_ERR(yu_arm_gpio_lock_param.io)) + ret = PTR_ERR(yu_arm_gpio_lock_param.io); + +exit: + mutex_unlock(yu_arm_gpio_lock_param.lock); + + return ret; +} + +/* + * Acquire the YU arm_gpio_lock to be able to change the direction + * mode. If the lock_active bit is already set, return an error. + */ +static int mlxbf2_gpio_lock_acquire(struct mlxbf2_gpio_context *gs) +{ + u32 arm_gpio_lock_val; + + spin_lock(&gs->gc.bgpio_lock); + mutex_lock(yu_arm_gpio_lock_param.lock); + + arm_gpio_lock_val = readl(yu_arm_gpio_lock_param.io); + + /* + * When lock active bit[31] is set, ModeX is write enabled + */ + if (YU_LOCK_ACTIVE_BIT(arm_gpio_lock_val)) { + mutex_unlock(yu_arm_gpio_lock_param.lock); + spin_unlock(&gs->gc.bgpio_lock); + return -EINVAL; + } + + writel(YU_ARM_GPIO_LOCK_ACQUIRE, yu_arm_gpio_lock_param.io); + + return 0; +} + +/* + * Release the YU arm_gpio_lock after changing the direction mode. + */ +static void mlxbf2_gpio_lock_release(struct mlxbf2_gpio_context *gs) +{ + writel(YU_ARM_GPIO_LOCK_RELEASE, yu_arm_gpio_lock_param.io); + mutex_unlock(yu_arm_gpio_lock_param.lock); + spin_unlock(&gs->gc.bgpio_lock); +} + +/* + * mode0 and mode1 are both locked by the gpio_lock field. + * + * Together, mode0 and mode1 define the gpio Mode dependeing also + * on Reg_DataOut. + * + * {mode1,mode0}:{Reg_DataOut=0,Reg_DataOut=1}->{DataOut=0,DataOut=1} + * + * {0,0}:Reg_DataOut{0,1}->{Z,Z} Input PAD + * {0,1}:Reg_DataOut{0,1}->{0,1} Full drive Output PAD + * {1,0}:Reg_DataOut{0,1}->{0,Z} 0-set PAD to low, 1-float + * {1,1}:Reg_DataOut{0,1}->{Z,1} 0-float, 1-set PAD to high + */ + +/* + * Set input direction: + * {mode1,mode0} = {0,0} + */ +static int mlxbf2_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) +{ + struct mlxbf2_gpio_context *gs = gpiochip_get_data(chip); + int ret; + + /* + * Although the arm_gpio_lock was set in the probe function, check again + * if it is still enabled to be able to write to the ModeX registers. + */ + ret = mlxbf2_gpio_lock_acquire(gs); + if (ret < 0) + return ret; + + writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE0_CLEAR); + writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE1_CLEAR); + + mlxbf2_gpio_lock_release(gs); + + return ret; +} + +/* + * Set output direction: + * {mode1,mode0} = {0,1} + */ +static int mlxbf2_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, + int value) +{ + struct mlxbf2_gpio_context *gs = gpiochip_get_data(chip); + int ret = 0; + + /* + * Although the arm_gpio_lock was set in the probe function, + * check again it is still enabled to be able to write to the + * ModeX registers. + */ + ret = mlxbf2_gpio_lock_acquire(gs); + if (ret < 0) + return ret; + + writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE1_CLEAR); + writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE0_SET); + + mlxbf2_gpio_lock_release(gs); + + return ret; +} + +/* BlueField-2 GPIO driver initialization routine. */ +static int +mlxbf2_gpio_probe(struct platform_device *pdev) +{ + struct mlxbf2_gpio_context *gs; + struct device *dev = &pdev->dev; + struct gpio_chip *gc; + struct resource *res; + unsigned int npins; + int ret; + + gs = devm_kzalloc(dev, sizeof(*gs), GFP_KERNEL); + if (!gs) + return -ENOMEM; + + /* YU GPIO block address */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + gs->gpio_io = devm_ioremap(dev, res->start, resource_size(res)); + if (!gs->gpio_io) + return -ENOMEM; + + ret = mlxbf2_gpio_get_lock_res(pdev); + if (ret) { + dev_err(dev, "Failed to get yu_arm_gpio_lock resource\n"); + return ret; + } + + if (device_property_read_u32(dev, "npins", &npins)) + npins = MLXBF2_GPIO_MAX_PINS_PER_BLOCK; + + gc = &gs->gc; + + ret = bgpio_init(gc, dev, 4, + gs->gpio_io + YU_GPIO_DATAIN, + gs->gpio_io + YU_GPIO_DATASET, + gs->gpio_io + YU_GPIO_DATACLEAR, + NULL, + NULL, + 0); + + gc->direction_input = mlxbf2_gpio_direction_input; + gc->direction_output = mlxbf2_gpio_direction_output; + gc->ngpio = npins; + gc->owner = THIS_MODULE; + + platform_set_drvdata(pdev, gs); + + ret = devm_gpiochip_add_data(dev, &gs->gc, gs); + if (ret) { + dev_err(dev, "Failed adding memory mapped gpiochip\n"); + return ret; + } + + return 0; +} + +#ifdef CONFIG_PM +static int mlxbf2_gpio_suspend(struct platform_device *pdev, + pm_message_t state) +{ + struct mlxbf2_gpio_context *gs = platform_get_drvdata(pdev); + + gs->csave_regs->gpio_mode0 = readl(gs->gpio_io + + YU_GPIO_MODE0); + gs->csave_regs->gpio_mode1 = readl(gs->gpio_io + + YU_GPIO_MODE1); + + return 0; +} + +static int mlxbf2_gpio_resume(struct platform_device *pdev) +{ + struct mlxbf2_gpio_context *gs = platform_get_drvdata(pdev); + + writel(gs->csave_regs->gpio_mode0, gs->gpio_io + + YU_GPIO_MODE0); + writel(gs->csave_regs->gpio_mode1, gs->gpio_io + + YU_GPIO_MODE1); + + return 0; +} +#endif + +static const struct acpi_device_id mlxbf2_gpio_acpi_match[] = { + { "MLNXBF22", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, mlxbf2_gpio_acpi_match); + +static struct platform_driver mlxbf2_gpio_driver = { + .driver = { + .name = "mlxbf2_gpio", + .acpi_match_table = ACPI_PTR(mlxbf2_gpio_acpi_match), + }, + .probe = mlxbf2_gpio_probe, +#ifdef CONFIG_PM + .suspend = mlxbf2_gpio_suspend, + .resume = mlxbf2_gpio_resume, +#endif +}; + +module_platform_driver(mlxbf2_gpio_driver); + +MODULE_DESCRIPTION("Mellanox BlueField-2 GPIO Driver"); +MODULE_AUTHOR("Mellanox Technologies"); +MODULE_LICENSE("GPL v2"); From 55be2f50336f67800513b46c5ba6270e4ed0e784 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 14:54:30 -0800 Subject: [PATCH 1310/4444] ARM: OMAP2+: Handle errors for cpu_pm We need to check for errors when calling cpu_pm_enter() and cpu_cluster_pm_enter(). And we need to bail out on errors as otherwise we can enter a deeper idle state when not desired. I'm not aware of the lack of error handling causing issues yet, but we need this at least for blocking deeper idle states when a GPIO instance has pending interrupts. Cc: Dave Gerlach Cc: Grygorii Strashko Cc: Keerthy Cc: Ladislav Michl Cc: Russell King Cc: Tero Kristo Signed-off-by: Tony Lindgren Link: https://lore.kernel.org/r/20200304225433.37336-2-tony@atomide.com Signed-off-by: Linus Walleij --- arch/arm/mach-omap2/cpuidle34xx.c | 9 +++++++-- arch/arm/mach-omap2/cpuidle44xx.c | 26 +++++++++++++++++--------- arch/arm/mach-omap2/pm34xx.c | 8 ++++++-- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 532a3e4b98c6..090a8aafb25e 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -109,6 +109,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, int index) { struct omap3_idle_statedata *cx = &omap3_idle_data[index]; + int error; if (omap_irq_pending() || need_resched()) goto return_sleep_time; @@ -125,8 +126,11 @@ static int omap3_enter_idle(struct cpuidle_device *dev, * Call idle CPU PM enter notifier chain so that * VFP context is saved. */ - if (cx->mpu_state == PWRDM_POWER_OFF) - cpu_pm_enter(); + if (cx->mpu_state == PWRDM_POWER_OFF) { + error = cpu_pm_enter(); + if (error) + goto out_clkdm_set; + } /* Execute ARM wfi */ omap_sram_idle(); @@ -139,6 +143,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, pwrdm_read_prev_pwrst(mpu_pd) == PWRDM_POWER_OFF) cpu_pm_exit(); +out_clkdm_set: /* Re-allow idle for C1 */ if (cx->flags & OMAP_CPUIDLE_CX_NO_CLKDM_IDLE) clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]); diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c index fe75d4fa6073..6f5f89711f25 100644 --- a/arch/arm/mach-omap2/cpuidle44xx.c +++ b/arch/arm/mach-omap2/cpuidle44xx.c @@ -122,6 +122,7 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, { struct idle_statedata *cx = state_ptr + index; u32 mpuss_can_lose_context = 0; + int error; /* * CPU0 has to wait and stay ON until CPU1 is OFF state. @@ -159,7 +160,9 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, * Call idle CPU PM enter notifier chain so that * VFP and per CPU interrupt context is saved. */ - cpu_pm_enter(); + error = cpu_pm_enter(); + if (error) + goto cpu_pm_out; if (dev->cpu == 0) { pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state); @@ -169,13 +172,17 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, * Call idle CPU cluster PM enter notifier chain * to save GIC and wakeupgen context. */ - if (mpuss_can_lose_context) - cpu_cluster_pm_enter(); + if (mpuss_can_lose_context) { + error = cpu_cluster_pm_enter(); + if (error) + goto cpu_cluster_pm_out; + } } omap4_enter_lowpower(dev->cpu, cx->cpu_state); cpu_done[dev->cpu] = true; +cpu_cluster_pm_out: /* Wakeup CPU1 only if it is not offlined */ if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) { @@ -197,12 +204,6 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, } } - /* - * Call idle CPU PM exit notifier chain to restore - * VFP and per CPU IRQ context. - */ - cpu_pm_exit(); - /* * Call idle CPU cluster PM exit notifier chain * to restore GIC and wakeupgen context. @@ -210,6 +211,13 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, if (dev->cpu == 0 && mpuss_can_lose_context) cpu_cluster_pm_exit(); + /* + * Call idle CPU PM exit notifier chain to restore + * VFP and per CPU IRQ context. + */ + cpu_pm_exit(); + +cpu_pm_out: tick_broadcast_exit(); fail: diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index e66e9948636c..6df395fff971 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -191,6 +191,7 @@ void omap_sram_idle(void) int per_next_state = PWRDM_POWER_ON; int core_next_state = PWRDM_POWER_ON; u32 sdrc_pwr = 0; + int error; mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm); switch (mpu_next_state) { @@ -219,8 +220,11 @@ void omap_sram_idle(void) pwrdm_pre_transition(NULL); /* PER */ - if (per_next_state == PWRDM_POWER_OFF) - cpu_cluster_pm_enter(); + if (per_next_state == PWRDM_POWER_OFF) { + error = cpu_cluster_pm_enter(); + if (error) + return; + } /* CORE */ if (core_next_state < PWRDM_POWER_ON) { From 43582265be8c5c29f4f420ce08a29d48f560c86e Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 14:54:31 -0800 Subject: [PATCH 1311/4444] gpio: omap: Block idle on pending gpio interrupts With the SoC cpuidle handling fixed for cpu_pm, we can now start to return NOTIFY_BAD if there there are pending gpio interrupts. This way the deeper SoC idle states can get blocked, and gpio latency is improved in some cases. Note that this will not help with the latency if the SoC has already entered a deeper idle state. Note that this patch depends on cpu_pm properly handling the errors returned by notifiers. For omap variants, this is fixed with patch "ARM: OMAP2+: Handle errors for cpu_pm". Cc: Dave Gerlach Cc: Grygorii Strashko Cc: Keerthy Cc: Ladislav Michl Cc: Russell King Cc: Tero Kristo Signed-off-by: Tony Lindgren Link: https://lore.kernel.org/r/20200304225433.37336-3-tony@atomide.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 3bd8adaeed9e..3d50cb25aa24 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1237,26 +1237,35 @@ static int gpio_omap_cpu_notifier(struct notifier_block *nb, { struct gpio_bank *bank; unsigned long flags; + int ret = NOTIFY_OK; + u32 isr, mask; bank = container_of(nb, struct gpio_bank, nb); raw_spin_lock_irqsave(&bank->lock, flags); + if (bank->is_suspended) + goto out_unlock; + switch (cmd) { case CPU_CLUSTER_PM_ENTER: - if (bank->is_suspended) + mask = omap_get_gpio_irqbank_mask(bank); + isr = readl_relaxed(bank->base + bank->regs->irqstatus) & mask; + if (isr) { + ret = NOTIFY_BAD; break; + } omap_gpio_idle(bank, true); break; case CPU_CLUSTER_PM_ENTER_FAILED: case CPU_CLUSTER_PM_EXIT: - if (bank->is_suspended) - break; omap_gpio_unidle(bank); break; } + +out_unlock: raw_spin_unlock_irqrestore(&bank->lock, flags); - return NOTIFY_OK; + return ret; } static const struct omap_gpio_reg_offs omap2_gpio_regs = { From 579ced8fdb00b8e94304a83e3cc419f6f8eab08e Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 14:54:32 -0800 Subject: [PATCH 1312/4444] Revert "gpio: omap: Fix lost edge wake-up interrupts" This reverts commit a522f1d0c381c42f3ace13b8bbeeccabdd6d2e5c. With cpu_pm handling fixed for omaps, and with gpio-omap now returning notify error on pending interrupts, we can drop the old workaround for seeing if there may be pending edge interrupts. Depends-on: ARM: OMAP2+: Handle errors for cpu_pm Depends-on: gpio: omap: Block idle on pending gpio interrupts Cc: Aaro Koskinen Cc: Grygorii Strashko Cc: Keerthy Cc: Ladislav Michl Cc: Peter Ujfalusi Cc: Russell King Cc: Tero Kristo Signed-off-by: Tony Lindgren Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20200304225433.37336-4-tony@atomide.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 3d50cb25aa24..b8e2ecc3eade 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1102,23 +1102,13 @@ static void omap_gpio_idle(struct gpio_bank *bank, bool may_lose_context) { struct device *dev = bank->chip.parent; void __iomem *base = bank->base; - u32 mask, nowake; + u32 nowake; bank->saved_datain = readl_relaxed(base + bank->regs->datain); if (!bank->enabled_non_wakeup_gpios) goto update_gpio_context_count; - /* Check for pending EDGE_FALLING, ignore EDGE_BOTH */ - mask = bank->enabled_non_wakeup_gpios & bank->context.fallingdetect; - mask &= ~bank->context.risingdetect; - bank->saved_datain |= mask; - - /* Check for pending EDGE_RISING, ignore EDGE_BOTH */ - mask = bank->enabled_non_wakeup_gpios & bank->context.risingdetect; - mask &= ~bank->context.fallingdetect; - bank->saved_datain &= ~mask; - if (!may_lose_context) goto update_gpio_context_count; From 43d8b6362378913bafbc54690474131568458c42 Mon Sep 17 00:00:00 2001 From: Martin Devera Date: Thu, 16 Jan 2020 14:54:31 +0100 Subject: [PATCH 1313/4444] mtd: rawnand: Ensure nand_soft_waitrdy wait period is enough The used way to compute jiffies timeout brokes when jiffie difference is 1. Assume that nand_soft_waitrdy is called with timeout_ms==1. Jiffies are 1000 for example (assume something more like 1000.99 - just before incrementing to 1001). We compute timeout_ms = 1000+msecs_to_jiffies(1) = 1001. nand_read_data_op is called for the first time and returns 0. During the call jiffies changes to 1001 thus "while loop" ends here (wrongly). Notice that routine was called with expected timeout 1ms but actual timeout used was something between 0...1ms. Fixes STM32MP1 FMC2 NAND controller which sometimes failed exactly in this way. Signed-off-by: Martin Devera Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200116135431.17480-1-devik@eaxlabs.cz --- drivers/mtd/nand/raw/nand_base.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index f64e3b6605c6..8ad4af99eea4 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -683,7 +683,12 @@ int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms) if (ret) return ret; - timeout_ms = jiffies + msecs_to_jiffies(timeout_ms); + /* + * +1 below is necessary because if we are now in the last fraction + * of jiffy and msecs_to_jiffies is 1 then we will wait only that + * small jiffy fraction - possibly leading to false timeout + */ + timeout_ms = jiffies + msecs_to_jiffies(timeout_ms) + 1; do { ret = nand_read_data_op(chip, &status, sizeof(status), true); if (ret) From 009264605cdf1b12962c3a46f75818d05452e890 Mon Sep 17 00:00:00 2001 From: Christophe Kerello Date: Thu, 23 Jan 2020 09:22:48 +0100 Subject: [PATCH 1314/4444] mtd: rawnand: free the nand_device object This patch releases the resources allocated in nanddev_init function. Fixes: a7ab085d7c16 ("mtd: rawnand: Initialize the nand_device object") Signed-off-by: Christophe Kerello Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/1579767768-32295-1-git-send-email-christophe.kerello@st.com --- drivers/mtd/nand/raw/nand_base.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 8ad4af99eea4..a3ed6c54963e 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -5912,6 +5912,8 @@ void nand_cleanup(struct nand_chip *chip) chip->ecc.algo == NAND_ECC_BCH) nand_bch_free((struct nand_bch_control *)chip->ecc.priv); + nanddev_cleanup(&chip->base); + /* Free bad block table memory */ kfree(chip->bbt); kfree(chip->data_buf); From 9afbe7c0140f663586edb6e823b616bd7076c00a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 27 Jan 2020 21:39:34 +0900 Subject: [PATCH 1315/4444] mtd: rawnand: denali: deassert write protect pin If the write protect signal from this IP is connected to the NAND device, this IP can handle the WP# pin via the WRITE_PROTECT register. The Denali NAND Flash Memory Controller User's Guide describes this register like follows: When the controller is in reset, the WP# pin is always asserted to the device. Once the reset is removed, the WP# is de-asserted. The software will then have to come and program this bit to assert/de-assert the same. 1 - Write protect de-assert 0 - Write protect assert The default value is 1, so the write protect is de-asserted after the reset is removed. The driver can write to the device unless someone has explicitly cleared register before booting the kernel. The boot ROM of some UniPhier SoCs (LD4, Pro4, sLD8, Pro5) is the case; the boot ROM clears the WRITE_PROTECT register when the system is booting from the NAND device, so the NAND device becomes read-only. Set it to 1 in the driver in order to allow the write access to the device. Signed-off-by: Masahiro Yamada Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200127123934.11847-1-yamada.masahiro@socionext.com --- drivers/mtd/nand/raw/denali.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index fafd0a0aa8e2..6a6c919b2569 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -1317,6 +1317,7 @@ int denali_init(struct denali_controller *denali) iowrite32(CHIP_EN_DONT_CARE__FLAG, denali->reg + CHIP_ENABLE_DONT_CARE); iowrite32(ECC_ENABLE__FLAG, denali->reg + ECC_ENABLE); iowrite32(0xffff, denali->reg + SPARE_AREA_MARKER); + iowrite32(WRITE_PROTECT__FLAG, denali->reg + WRITE_PROTECT); denali_clear_irq_all(denali); From a91f8170df832967dc75d5bd594c496999882e22 Mon Sep 17 00:00:00 2001 From: Yoshio Furuyama Date: Fri, 7 Feb 2020 13:59:21 +0900 Subject: [PATCH 1316/4444] mtd: spinand: toshiba: Add comment about Kioxia ID Add a comment above NAND_MFR_TOSHIBA and SPINAND_MFR_TOSHIBA definitions that Toshiba and Kioxia ID are the same. Since its independence from Toshiba Group, Toshiba memory Co has become Kioxia Co. Signed-off-by: Yoshio Furuyama Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/1581051561-7302-1-git-send-email-ytc-mb-yfuruyama7@kioxia.com --- drivers/mtd/nand/raw/internals.h | 1 + drivers/mtd/nand/spi/toshiba.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index cba6fe7dd8c4..9d0caadf940e 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -30,6 +30,7 @@ #define NAND_MFR_SAMSUNG 0xec #define NAND_MFR_SANDISK 0x45 #define NAND_MFR_STMICRO 0x20 +/* Kioxia is new name of Toshiba memory. */ #define NAND_MFR_TOSHIBA 0x98 #define NAND_MFR_WINBOND 0xef diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c index 0db5ee4e82af..833e8f64e0a0 100644 --- a/drivers/mtd/nand/spi/toshiba.c +++ b/drivers/mtd/nand/spi/toshiba.c @@ -10,6 +10,7 @@ #include #include +/* Kioxia is new name of Toshiba memory. */ #define SPINAND_MFR_TOSHIBA 0x98 #define TOSH_STATUS_ECC_HAS_BITFLIPS_T (3 << 4) From f1541773af49ecd1edae29c8ac0775253a0b0760 Mon Sep 17 00:00:00 2001 From: Chuanhong Guo Date: Sat, 8 Feb 2020 15:43:50 +0800 Subject: [PATCH 1317/4444] mtd: spinand: rework detect procedure for different READ_ID operation Currently there are 3 different variants of read_id implementation: 1. opcode only. Found in GD5FxGQ4xF. 2. opcode + 1 addr byte. Found in GD5GxGQ4xA/E 3. opcode + 1 dummy byte. Found in other currently supported chips. Original implementation was for variant 1 and let detect function of chips with variant 2 and 3 to ignore the first byte. This isn't robust: 1. For chips of variant 2, if SPI master doesn't keep MOSI low during read, chip will get a random id offset, and the entire id buffer will shift by that offset, causing detect failure. 2. For chips of variant 1, if it happens to get a devid that equals to manufacture id of variant 2 or 3 chips, it'll get incorrectly detected. This patch reworks detect procedure to address problems above. New logic do detection for all variants separatedly, in 1-2-3 order. Since all current detect methods do exactly the same id matching procedure, unify them into core.c and remove detect method from manufacture_ops. Tested on GD5F1GQ4UAYIG and W25N01GVZEIG. Signed-off-by: Chuanhong Guo Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200208074439.146296-1-gch981213@gmail.com --- drivers/mtd/nand/spi/core.c | 86 ++++++++++++++++++++++--------- drivers/mtd/nand/spi/gigadevice.c | 45 +++++----------- drivers/mtd/nand/spi/macronix.c | 30 +++-------- drivers/mtd/nand/spi/micron.c | 26 ++-------- drivers/mtd/nand/spi/paragon.c | 28 +++------- drivers/mtd/nand/spi/toshiba.c | 45 ++++++---------- drivers/mtd/nand/spi/winbond.c | 34 +++--------- include/linux/mtd/spinand.h | 66 ++++++++++++++++-------- 8 files changed, 157 insertions(+), 203 deletions(-) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 89f6beefb01c..a9e9cbad942f 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -370,10 +371,11 @@ out: return status & STATUS_BUSY ? -ETIMEDOUT : 0; } -static int spinand_read_id_op(struct spinand_device *spinand, u8 *buf) +static int spinand_read_id_op(struct spinand_device *spinand, u8 naddr, + u8 ndummy, u8 *buf) { - struct spi_mem_op op = SPINAND_READID_OP(0, spinand->scratchbuf, - SPINAND_MAX_ID_LEN); + struct spi_mem_op op = SPINAND_READID_OP( + naddr, ndummy, spinand->scratchbuf, SPINAND_MAX_ID_LEN); int ret; ret = spi_mem_exec_op(spinand->spimem, &op); @@ -762,24 +764,62 @@ static const struct spinand_manufacturer *spinand_manufacturers[] = { &winbond_spinand_manufacturer, }; -static int spinand_manufacturer_detect(struct spinand_device *spinand) +static int spinand_manufacturer_match(struct spinand_device *spinand, + enum spinand_readid_method rdid_method) { + u8 *id = spinand->id.data; unsigned int i; int ret; for (i = 0; i < ARRAY_SIZE(spinand_manufacturers); i++) { - ret = spinand_manufacturers[i]->ops->detect(spinand); - if (ret > 0) { - spinand->manufacturer = spinand_manufacturers[i]; - return 0; - } else if (ret < 0) { - return ret; - } - } + const struct spinand_manufacturer *manufacturer = + spinand_manufacturers[i]; + if (id[0] != manufacturer->id) + continue; + + ret = spinand_match_and_init(spinand, + manufacturer->chips, + manufacturer->nchips, + rdid_method); + if (ret < 0) + continue; + + spinand->manufacturer = manufacturer; + return 0; + } return -ENOTSUPP; } +static int spinand_id_detect(struct spinand_device *spinand) +{ + u8 *id = spinand->id.data; + int ret; + + ret = spinand_read_id_op(spinand, 0, 0, id); + if (ret) + return ret; + ret = spinand_manufacturer_match(spinand, SPINAND_READID_METHOD_OPCODE); + if (!ret) + return 0; + + ret = spinand_read_id_op(spinand, 1, 0, id); + if (ret) + return ret; + ret = spinand_manufacturer_match(spinand, + SPINAND_READID_METHOD_OPCODE_ADDR); + if (!ret) + return 0; + + ret = spinand_read_id_op(spinand, 0, 1, id); + if (ret) + return ret; + ret = spinand_manufacturer_match(spinand, + SPINAND_READID_METHOD_OPCODE_DUMMY); + + return ret; +} + static int spinand_manufacturer_init(struct spinand_device *spinand) { if (spinand->manufacturer->ops->init) @@ -835,9 +875,9 @@ spinand_select_op_variant(struct spinand_device *spinand, * @spinand: SPI NAND object * @table: SPI NAND device description table * @table_size: size of the device description table + * @rdid_method: read id method to match * - * Should be used by SPI NAND manufacturer drivers when they want to find a - * match between a device ID retrieved through the READ_ID command and an + * Match between a device ID retrieved through the READ_ID command and an * entry in the SPI NAND description table. If a match is found, the spinand * object will be initialized with information provided by the matching * spinand_info entry. @@ -846,8 +886,10 @@ spinand_select_op_variant(struct spinand_device *spinand, */ int spinand_match_and_init(struct spinand_device *spinand, const struct spinand_info *table, - unsigned int table_size, u16 devid) + unsigned int table_size, + enum spinand_readid_method rdid_method) { + u8 *id = spinand->id.data; struct nand_device *nand = spinand_to_nand(spinand); unsigned int i; @@ -855,13 +897,17 @@ int spinand_match_and_init(struct spinand_device *spinand, const struct spinand_info *info = &table[i]; const struct spi_mem_op *op; - if (devid != info->devid) + if (rdid_method != info->devid.method) + continue; + + if (memcmp(id + 1, info->devid.id, info->devid.len)) continue; nand->memorg = table[i].memorg; nand->eccreq = table[i].eccreq; spinand->eccinfo = table[i].eccinfo; spinand->flags = table[i].flags; + spinand->id.len = 1 + table[i].devid.len; spinand->select_target = table[i].select_target; op = spinand_select_op_variant(spinand, @@ -898,13 +944,7 @@ static int spinand_detect(struct spinand_device *spinand) if (ret) return ret; - ret = spinand_read_id_op(spinand, spinand->id.data); - if (ret) - return ret; - - spinand->id.len = SPINAND_MAX_ID_LEN; - - ret = spinand_manufacturer_detect(spinand); + ret = spinand_id_detect(spinand); if (ret) { dev_err(dev, "unknown raw ID %*phN\n", SPINAND_MAX_ID_LEN, spinand->id.data); diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c index e99d425aa93f..d219c970042a 100644 --- a/drivers/mtd/nand/spi/gigadevice.c +++ b/drivers/mtd/nand/spi/gigadevice.c @@ -195,7 +195,8 @@ static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand, } static const struct spinand_info gigadevice_spinand_table[] = { - SPINAND_INFO("GD5F1GQ4xA", 0xF1, + SPINAND_INFO("GD5F1GQ4xA", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf1), NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -204,7 +205,8 @@ static const struct spinand_info gigadevice_spinand_table[] = { 0, SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, gd5fxgq4xa_ecc_get_status)), - SPINAND_INFO("GD5F2GQ4xA", 0xF2, + SPINAND_INFO("GD5F2GQ4xA", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf2), NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -213,7 +215,8 @@ static const struct spinand_info gigadevice_spinand_table[] = { 0, SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, gd5fxgq4xa_ecc_get_status)), - SPINAND_INFO("GD5F4GQ4xA", 0xF4, + SPINAND_INFO("GD5F4GQ4xA", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf4), NAND_MEMORG(1, 2048, 64, 64, 4096, 80, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -222,7 +225,8 @@ static const struct spinand_info gigadevice_spinand_table[] = { 0, SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, gd5fxgq4xa_ecc_get_status)), - SPINAND_INFO("GD5F1GQ4UExxG", 0xd1, + SPINAND_INFO("GD5F1GQ4UExxG", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd1), NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -231,7 +235,8 @@ static const struct spinand_info gigadevice_spinand_table[] = { 0, SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout, gd5fxgq4uexxg_ecc_get_status)), - SPINAND_INFO("GD5F1GQ4UFxxG", 0xb148, + SPINAND_INFO("GD5F1GQ4UFxxG", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb1, 0x48), NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f, @@ -242,39 +247,13 @@ static const struct spinand_info gigadevice_spinand_table[] = { gd5fxgq4ufxxg_ecc_get_status)), }; -static int gigadevice_spinand_detect(struct spinand_device *spinand) -{ - u8 *id = spinand->id.data; - u16 did; - int ret; - - /* - * Earlier GDF5-series devices (A,E) return [0][MID][DID] - * Later (F) devices return [MID][DID1][DID2] - */ - - if (id[0] == SPINAND_MFR_GIGADEVICE) - did = (id[1] << 8) + id[2]; - else if (id[0] == 0 && id[1] == SPINAND_MFR_GIGADEVICE) - did = id[2]; - else - return 0; - - ret = spinand_match_and_init(spinand, gigadevice_spinand_table, - ARRAY_SIZE(gigadevice_spinand_table), - did); - if (ret) - return ret; - - return 1; -} - static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = { - .detect = gigadevice_spinand_detect, }; const struct spinand_manufacturer gigadevice_spinand_manufacturer = { .id = SPINAND_MFR_GIGADEVICE, .name = "GigaDevice", + .chips = gigadevice_spinand_table, + .nchips = ARRAY_SIZE(gigadevice_spinand_table), .ops = &gigadevice_spinand_manuf_ops, }; diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c index 21def3f8fb36..0f900f3aa21a 100644 --- a/drivers/mtd/nand/spi/macronix.c +++ b/drivers/mtd/nand/spi/macronix.c @@ -99,7 +99,8 @@ static int mx35lf1ge4ab_ecc_get_status(struct spinand_device *spinand, } static const struct spinand_info macronix_spinand_table[] = { - SPINAND_INFO("MX35LF1GE4AB", 0x12, + SPINAND_INFO("MX35LF1GE4AB", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x12), NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), NAND_ECCREQ(4, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -108,7 +109,8 @@ static const struct spinand_info macronix_spinand_table[] = { SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, mx35lf1ge4ab_ecc_get_status)), - SPINAND_INFO("MX35LF2GE4AB", 0x22, + SPINAND_INFO("MX35LF2GE4AB", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x22), NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1), NAND_ECCREQ(4, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -118,33 +120,13 @@ static const struct spinand_info macronix_spinand_table[] = { SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)), }; -static int macronix_spinand_detect(struct spinand_device *spinand) -{ - u8 *id = spinand->id.data; - int ret; - - /* - * Macronix SPI NAND read ID needs a dummy byte, so the first byte in - * raw_id is garbage. - */ - if (id[1] != SPINAND_MFR_MACRONIX) - return 0; - - ret = spinand_match_and_init(spinand, macronix_spinand_table, - ARRAY_SIZE(macronix_spinand_table), - id[2]); - if (ret) - return ret; - - return 1; -} - static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = { - .detect = macronix_spinand_detect, }; const struct spinand_manufacturer macronix_spinand_manufacturer = { .id = SPINAND_MFR_MACRONIX, .name = "Macronix", + .chips = macronix_spinand_table, + .nchips = ARRAY_SIZE(macronix_spinand_table), .ops = ¯onix_spinand_manuf_ops, }; diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c index 7d7b1f7fcf71..f56f81325e10 100644 --- a/drivers/mtd/nand/spi/micron.c +++ b/drivers/mtd/nand/spi/micron.c @@ -91,7 +91,8 @@ static int mt29f2g01abagd_ecc_get_status(struct spinand_device *spinand, } static const struct spinand_info micron_spinand_table[] = { - SPINAND_INFO("MT29F2G01ABAGD", 0x24, + SPINAND_INFO("MT29F2G01ABAGD", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24), NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -102,32 +103,13 @@ static const struct spinand_info micron_spinand_table[] = { mt29f2g01abagd_ecc_get_status)), }; -static int micron_spinand_detect(struct spinand_device *spinand) -{ - u8 *id = spinand->id.data; - int ret; - - /* - * Micron SPI NAND read ID need a dummy byte, - * so the first byte in raw_id is dummy. - */ - if (id[1] != SPINAND_MFR_MICRON) - return 0; - - ret = spinand_match_and_init(spinand, micron_spinand_table, - ARRAY_SIZE(micron_spinand_table), id[2]); - if (ret) - return ret; - - return 1; -} - static const struct spinand_manufacturer_ops micron_spinand_manuf_ops = { - .detect = micron_spinand_detect, }; const struct spinand_manufacturer micron_spinand_manufacturer = { .id = SPINAND_MFR_MICRON, .name = "Micron", + .chips = micron_spinand_table, + .nchips = ARRAY_SIZE(micron_spinand_table), .ops = µn_spinand_manuf_ops, }; diff --git a/drivers/mtd/nand/spi/paragon.c b/drivers/mtd/nand/spi/paragon.c index 52307681cbd0..519ade513c1f 100644 --- a/drivers/mtd/nand/spi/paragon.c +++ b/drivers/mtd/nand/spi/paragon.c @@ -97,7 +97,8 @@ static const struct mtd_ooblayout_ops pn26g0xa_ooblayout = { static const struct spinand_info paragon_spinand_table[] = { - SPINAND_INFO("PN26G01A", 0xe1, + SPINAND_INFO("PN26G01A", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xe1), NAND_MEMORG(1, 2048, 128, 64, 1024, 21, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -106,7 +107,8 @@ static const struct spinand_info paragon_spinand_table[] = { 0, SPINAND_ECCINFO(&pn26g0xa_ooblayout, pn26g0xa_ecc_get_status)), - SPINAND_INFO("PN26G02A", 0xe2, + SPINAND_INFO("PN26G02A", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xe2), NAND_MEMORG(1, 2048, 128, 64, 2048, 41, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -117,31 +119,13 @@ static const struct spinand_info paragon_spinand_table[] = { pn26g0xa_ecc_get_status)), }; -static int paragon_spinand_detect(struct spinand_device *spinand) -{ - u8 *id = spinand->id.data; - int ret; - - /* Read ID returns [0][MID][DID] */ - - if (id[1] != SPINAND_MFR_PARAGON) - return 0; - - ret = spinand_match_and_init(spinand, paragon_spinand_table, - ARRAY_SIZE(paragon_spinand_table), - id[2]); - if (ret) - return ret; - - return 1; -} - static const struct spinand_manufacturer_ops paragon_spinand_manuf_ops = { - .detect = paragon_spinand_detect, }; const struct spinand_manufacturer paragon_spinand_manufacturer = { .id = SPINAND_MFR_PARAGON, .name = "Paragon", + .chips = paragon_spinand_table, + .nchips = ARRAY_SIZE(paragon_spinand_table), .ops = ¶gon_spinand_manuf_ops, }; diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c index 833e8f64e0a0..d34773191700 100644 --- a/drivers/mtd/nand/spi/toshiba.c +++ b/drivers/mtd/nand/spi/toshiba.c @@ -96,7 +96,8 @@ static int tc58cxgxsx_ecc_get_status(struct spinand_device *spinand, static const struct spinand_info toshiba_spinand_table[] = { /* 3.3V 1Gb */ - SPINAND_INFO("TC58CVG0S3", 0xC2, + SPINAND_INFO("TC58CVG0S3", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xC2), NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -106,7 +107,8 @@ static const struct spinand_info toshiba_spinand_table[] = { SPINAND_ECCINFO(&tc58cxgxsx_ooblayout, tc58cxgxsx_ecc_get_status)), /* 3.3V 2Gb */ - SPINAND_INFO("TC58CVG1S3", 0xCB, + SPINAND_INFO("TC58CVG1S3", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCB), NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -116,7 +118,8 @@ static const struct spinand_info toshiba_spinand_table[] = { SPINAND_ECCINFO(&tc58cxgxsx_ooblayout, tc58cxgxsx_ecc_get_status)), /* 3.3V 4Gb */ - SPINAND_INFO("TC58CVG2S0", 0xCD, + SPINAND_INFO("TC58CVG2S0", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCD), NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -126,7 +129,8 @@ static const struct spinand_info toshiba_spinand_table[] = { SPINAND_ECCINFO(&tc58cxgxsx_ooblayout, tc58cxgxsx_ecc_get_status)), /* 3.3V 4Gb */ - SPINAND_INFO("TC58CVG2S0", 0xED, + SPINAND_INFO("TC58CVG2S0", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xED), NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -136,7 +140,8 @@ static const struct spinand_info toshiba_spinand_table[] = { SPINAND_ECCINFO(&tc58cxgxsx_ooblayout, tc58cxgxsx_ecc_get_status)), /* 1.8V 1Gb */ - SPINAND_INFO("TC58CYG0S3", 0xB2, + SPINAND_INFO("TC58CYG0S3", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xB2), NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -146,7 +151,8 @@ static const struct spinand_info toshiba_spinand_table[] = { SPINAND_ECCINFO(&tc58cxgxsx_ooblayout, tc58cxgxsx_ecc_get_status)), /* 1.8V 2Gb */ - SPINAND_INFO("TC58CYG1S3", 0xBB, + SPINAND_INFO("TC58CYG1S3", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBB), NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -156,7 +162,8 @@ static const struct spinand_info toshiba_spinand_table[] = { SPINAND_ECCINFO(&tc58cxgxsx_ooblayout, tc58cxgxsx_ecc_get_status)), /* 1.8V 4Gb */ - SPINAND_INFO("TC58CYG2S0", 0xBD, + SPINAND_INFO("TC58CYG2S0", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBD), NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -167,33 +174,13 @@ static const struct spinand_info toshiba_spinand_table[] = { tc58cxgxsx_ecc_get_status)), }; -static int toshiba_spinand_detect(struct spinand_device *spinand) -{ - u8 *id = spinand->id.data; - int ret; - - /* - * Toshiba SPI NAND read ID needs a dummy byte, - * so the first byte in id is garbage. - */ - if (id[1] != SPINAND_MFR_TOSHIBA) - return 0; - - ret = spinand_match_and_init(spinand, toshiba_spinand_table, - ARRAY_SIZE(toshiba_spinand_table), - id[2]); - if (ret) - return ret; - - return 1; -} - static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = { - .detect = toshiba_spinand_detect, }; const struct spinand_manufacturer toshiba_spinand_manufacturer = { .id = SPINAND_MFR_TOSHIBA, .name = "Toshiba", + .chips = toshiba_spinand_table, + .nchips = ARRAY_SIZE(toshiba_spinand_table), .ops = &toshiba_spinand_manuf_ops, }; diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c index a6c17e0cace8..76684428354e 100644 --- a/drivers/mtd/nand/spi/winbond.c +++ b/drivers/mtd/nand/spi/winbond.c @@ -75,7 +75,8 @@ static int w25m02gv_select_target(struct spinand_device *spinand, } static const struct spinand_info winbond_spinand_table[] = { - SPINAND_INFO("W25M02GV", 0xAB, + SPINAND_INFO("W25M02GV", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab), NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2), NAND_ECCREQ(1, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -84,7 +85,8 @@ static const struct spinand_info winbond_spinand_table[] = { 0, SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL), SPINAND_SELECT_TARGET(w25m02gv_select_target)), - SPINAND_INFO("W25N01GV", 0xAA, + SPINAND_INFO("W25N01GV", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa), NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), NAND_ECCREQ(1, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, @@ -94,31 +96,6 @@ static const struct spinand_info winbond_spinand_table[] = { SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)), }; -/** - * winbond_spinand_detect - initialize device related part in spinand_device - * struct if it is a Winbond device. - * @spinand: SPI NAND device structure - */ -static int winbond_spinand_detect(struct spinand_device *spinand) -{ - u8 *id = spinand->id.data; - int ret; - - /* - * Winbond SPI NAND read ID need a dummy byte, - * so the first byte in raw_id is dummy. - */ - if (id[1] != SPINAND_MFR_WINBOND) - return 0; - - ret = spinand_match_and_init(spinand, winbond_spinand_table, - ARRAY_SIZE(winbond_spinand_table), id[2]); - if (ret) - return ret; - - return 1; -} - static int winbond_spinand_init(struct spinand_device *spinand) { struct nand_device *nand = spinand_to_nand(spinand); @@ -138,12 +115,13 @@ static int winbond_spinand_init(struct spinand_device *spinand) } static const struct spinand_manufacturer_ops winbond_spinand_manuf_ops = { - .detect = winbond_spinand_detect, .init = winbond_spinand_init, }; const struct spinand_manufacturer winbond_spinand_manufacturer = { .id = SPINAND_MFR_WINBOND, .name = "Winbond", + .chips = winbond_spinand_table, + .nchips = ARRAY_SIZE(winbond_spinand_table), .ops = &winbond_spinand_manuf_ops, }; diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index 4ea558bd3c46..f4c4ae87181b 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -32,9 +32,9 @@ SPI_MEM_OP_NO_DUMMY, \ SPI_MEM_OP_NO_DATA) -#define SPINAND_READID_OP(ndummy, buf, len) \ +#define SPINAND_READID_OP(naddr, ndummy, buf, len) \ SPI_MEM_OP(SPI_MEM_OP_CMD(0x9f, 1), \ - SPI_MEM_OP_NO_ADDR, \ + SPI_MEM_OP_ADDR(naddr, 0, 1), \ SPI_MEM_OP_DUMMY(ndummy, 1), \ SPI_MEM_OP_DATA_IN(len, buf, 1)) @@ -176,37 +176,46 @@ struct spinand_device; * @data: buffer containing the id bytes. Currently 4 bytes large, but can * be extended if required * @len: ID length - * - * struct_spinand_id->data contains all bytes returned after a READ_ID command, - * including dummy bytes if the chip does not emit ID bytes right after the - * READ_ID command. The responsibility to extract real ID bytes is left to - * struct_manufacurer_ops->detect(). */ struct spinand_id { u8 data[SPINAND_MAX_ID_LEN]; int len; }; +enum spinand_readid_method { + SPINAND_READID_METHOD_OPCODE, + SPINAND_READID_METHOD_OPCODE_ADDR, + SPINAND_READID_METHOD_OPCODE_DUMMY, +}; + +/** + * struct spinand_devid - SPI NAND device id structure + * @id: device id of current chip + * @len: number of bytes in device id + * @method: method to read chip id + * There are 3 possible variants: + * SPINAND_READID_METHOD_OPCODE: chip id is returned immediately + * after read_id opcode. + * SPINAND_READID_METHOD_OPCODE_ADDR: chip id is returned after + * read_id opcode + 1-byte address. + * SPINAND_READID_METHOD_OPCODE_DUMMY: chip id is returned after + * read_id opcode + 1 dummy byte. + */ +struct spinand_devid { + const u8 *id; + const u8 len; + const enum spinand_readid_method method; +}; + /** * struct manufacurer_ops - SPI NAND manufacturer specific operations - * @detect: detect a SPI NAND device. Every time a SPI NAND device is probed - * the core calls the struct_manufacurer_ops->detect() hook of each - * registered manufacturer until one of them return 1. Note that - * the first thing to check in this hook is that the manufacturer ID - * in struct_spinand_device->id matches the manufacturer whose - * ->detect() hook has been called. Should return 1 if there's a - * match, 0 if the manufacturer ID does not match and a negative - * error code otherwise. When true is returned, the core assumes - * that properties of the NAND chip (spinand->base.memorg and - * spinand->base.eccreq) have been filled * @init: initialize a SPI NAND device * @cleanup: cleanup a SPI NAND device * * Each SPI NAND manufacturer driver should implement this interface so that - * NAND chips coming from this vendor can be detected and initialized properly. + * NAND chips coming from this vendor can be initialized properly. */ struct spinand_manufacturer_ops { - int (*detect)(struct spinand_device *spinand); int (*init)(struct spinand_device *spinand); void (*cleanup)(struct spinand_device *spinand); }; @@ -215,11 +224,16 @@ struct spinand_manufacturer_ops { * struct spinand_manufacturer - SPI NAND manufacturer instance * @id: manufacturer ID * @name: manufacturer name + * @devid_len: number of bytes in device ID + * @chips: supported SPI NANDs under current manufacturer + * @nchips: number of SPI NANDs available in chips array * @ops: manufacturer operations */ struct spinand_manufacturer { u8 id; char *name; + const struct spinand_info *chips; + const size_t nchips; const struct spinand_manufacturer_ops *ops; }; @@ -291,7 +305,7 @@ struct spinand_ecc_info { */ struct spinand_info { const char *model; - u16 devid; + struct spinand_devid devid; u32 flags; struct nand_memory_organization memorg; struct nand_ecc_req eccreq; @@ -305,6 +319,13 @@ struct spinand_info { unsigned int target); }; +#define SPINAND_ID(__method, ...) \ + { \ + .id = (const u8[]){ __VA_ARGS__ }, \ + .len = sizeof((u8[]){ __VA_ARGS__ }), \ + .method = __method, \ + } + #define SPINAND_INFO_OP_VARIANTS(__read, __write, __update) \ { \ .read_cache = __read, \ @@ -451,9 +472,10 @@ static inline void spinand_set_of_node(struct spinand_device *spinand, nanddev_set_of_node(&spinand->base, np); } -int spinand_match_and_init(struct spinand_device *dev, +int spinand_match_and_init(struct spinand_device *spinand, const struct spinand_info *table, - unsigned int table_size, u16 devid); + unsigned int table_size, + enum spinand_readid_method rdid_method); int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val); int spinand_select_target(struct spinand_device *spinand, unsigned int target); From c4b7dd35d35936964c71db42e1d94994ee6ea411 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Tue, 11 Feb 2020 14:31:51 -0300 Subject: [PATCH 1318/4444] mtd: rawnand: ingenic: Use devm_platform_ioremap_resource() Use devm_platform_ioremap_resource() instead of platform_get_resource() + devm_ioremap_resource(). Signed-off-by: Paul Cercueil Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200211173151.27587-1-paul@crapouillou.net --- drivers/mtd/nand/raw/ingenic/ingenic_ecc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mtd/nand/raw/ingenic/ingenic_ecc.c b/drivers/mtd/nand/raw/ingenic/ingenic_ecc.c index c954189606f6..8e22cd6ec71f 100644 --- a/drivers/mtd/nand/raw/ingenic/ingenic_ecc.c +++ b/drivers/mtd/nand/raw/ingenic/ingenic_ecc.c @@ -124,7 +124,6 @@ int ingenic_ecc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct ingenic_ecc *ecc; - struct resource *res; ecc = devm_kzalloc(dev, sizeof(*ecc), GFP_KERNEL); if (!ecc) @@ -134,8 +133,7 @@ int ingenic_ecc_probe(struct platform_device *pdev) if (!ecc->ops) return -EINVAL; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ecc->base = devm_ioremap_resource(dev, res); + ecc->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(ecc->base)) return PTR_ERR(ecc->base); From 91a1abfb752357fe5d0783bd69db0d91f358e3eb Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 12 Feb 2020 01:39:16 +0100 Subject: [PATCH 1319/4444] mtd: rawnand: ams-delta: Write protect device during probe Initialise NWP GPIO pin as asserted to protect the device from hazard during setup of other GPIO pins. Signed-off-by: Janusz Krzysztofik Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200212003929.6682-2-jmkrzyszt@gmail.com --- drivers/mtd/nand/raw/ams-delta.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 8312182088c1..2501cfe00f43 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -251,8 +251,8 @@ static int ams_delta_init(struct platform_device *pdev) platform_set_drvdata(pdev, priv); - /* Set chip enabled, but */ - priv->gpiod_nwp = devm_gpiod_get(&pdev->dev, "nwp", GPIOD_OUT_HIGH); + /* Set chip enabled but write protected */ + priv->gpiod_nwp = devm_gpiod_get(&pdev->dev, "nwp", GPIOD_OUT_LOW); if (IS_ERR(priv->gpiod_nwp)) { err = PTR_ERR(priv->gpiod_nwp); dev_err(&pdev->dev, "NWP GPIO request failed (%d)\n", err); @@ -309,6 +309,17 @@ static int ams_delta_init(struct platform_device *pdev) nand_controller_init(&priv->base); this->controller = &priv->base; + /* + * FIXME: We should release write protection only after nand_scan() to + * be on the safe side but we can't do that until we have a generic way + * to assert/deassert WP from the core. Even if the core shouldn't + * write things in the nand_scan() path, it should have control on this + * pin just in case we ever need to disable write protection during + * chip detection/initialization. + */ + /* Release write protection */ + gpiod_set_value(priv->gpiod_nwp, 1); + /* Scan to find existence of the device */ err = nand_scan(this, 1); if (err) @@ -336,6 +347,9 @@ static int ams_delta_cleanup(struct platform_device *pdev) struct ams_delta_nand *priv = platform_get_drvdata(pdev); struct mtd_info *mtd = nand_to_mtd(&priv->nand_chip); + /* Apply write protection */ + gpiod_set_value(priv->gpiod_nwp, 0); + /* Unregister device */ nand_release(mtd_to_nand(mtd)); From 1698ea32133a884d6def357f90265e59799242e9 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 12 Feb 2020 01:39:17 +0100 Subject: [PATCH 1320/4444] mtd: rawnand: ams-delta: Use struct gpio_nand_platdata In order to be able to move the hardcoded Amstrad Delta partition info from the driver code to the board file, reuse gpio_nand_platdata structure owned by "gpio-nand" driver and try to obtain information on device partitions from device platform data. Signed-off-by: Janusz Krzysztofik Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200212003929.6682-3-jmkrzyszt@gmail.com --- drivers/mtd/nand/raw/ams-delta.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 2501cfe00f43..fbab7cc14607 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -220,12 +221,20 @@ static const struct nand_controller_ops ams_delta_ops = { */ static int ams_delta_init(struct platform_device *pdev) { + struct gpio_nand_platdata *pdata = dev_get_platdata(&pdev->dev); + const struct mtd_partition *partitions = partition_info; + int num_partitions = ARRAY_SIZE(partition_info); struct ams_delta_nand *priv; struct nand_chip *this; struct mtd_info *mtd; struct gpio_descs *data_gpiods; int err = 0; + if (pdata) { + partitions = pdata->parts; + num_partitions = pdata->num_parts; + } + /* Allocate memory for MTD device structure and private data */ priv = devm_kzalloc(&pdev->dev, sizeof(struct ams_delta_nand), GFP_KERNEL); @@ -326,8 +335,7 @@ static int ams_delta_init(struct platform_device *pdev) return err; /* Register the partitions */ - err = mtd_device_register(mtd, partition_info, - ARRAY_SIZE(partition_info)); + err = mtd_device_register(mtd, partitions, num_partitions); if (err) goto err_nand_cleanup; From 38c30b3c96a572926346b7c5221fb3953bfb0d5e Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 12 Feb 2020 01:39:18 +0100 Subject: [PATCH 1321/4444] ARM: OMAP1: ams-delta: Provide board specific partition info Now as the Amstrad Delta NAND driver supports fetching information on MTD partitions from device platform data, add partition info to the NAND device configuration. Signed-off-by: Janusz Krzysztofik Acked-by: Tony Lindgren Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200212003929.6682-4-jmkrzyszt@gmail.com --- arch/arm/mach-omap1/board-ams-delta.c | 35 +++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index a2aa7a12b374..f4d2ef97099e 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include #include @@ -294,9 +296,42 @@ struct modem_private_data { static struct modem_private_data modem_priv; +/* + * Define partitions for flash device + */ + +static struct mtd_partition partition_info[] = { + { .name = "Kernel", + .offset = 0, + .size = 3 * SZ_1M + SZ_512K }, + { .name = "u-boot", + .offset = 3 * SZ_1M + SZ_512K, + .size = SZ_256K }, + { .name = "u-boot params", + .offset = 3 * SZ_1M + SZ_512K + SZ_256K, + .size = SZ_256K }, + { .name = "Amstrad LDR", + .offset = 4 * SZ_1M, + .size = SZ_256K }, + { .name = "File system", + .offset = 4 * SZ_1M + 1 * SZ_256K, + .size = 27 * SZ_1M }, + { .name = "PBL reserved", + .offset = 32 * SZ_1M - 3 * SZ_256K, + .size = 3 * SZ_256K }, +}; + +static struct gpio_nand_platdata nand_platdata = { + .parts = partition_info, + .num_parts = ARRAY_SIZE(partition_info), +}; + static struct platform_device ams_delta_nand_device = { .name = "ams-delta-nand", .id = -1, + .dev = { + .platform_data = &nand_platdata, + }, }; #define OMAP_GPIO_LABEL "gpio-0-15" From d7ffe387cc12a5dbfdeeabae85b168dc407ac285 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 12 Feb 2020 01:39:19 +0100 Subject: [PATCH 1322/4444] mtd: rawnand: ams-delta: Drop board specific partition info Now as we support fetching partition info from device platform data and the Amstrad Delta board file provides that info, drop it from the driver code. v2: rebase on top of gpio_nand_platdata extension Signed-off-by: Janusz Krzysztofik Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200212003929.6682-5-jmkrzyszt@gmail.com --- drivers/mtd/nand/raw/ams-delta.c | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index fbab7cc14607..25f121adea6f 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -42,31 +42,6 @@ struct ams_delta_nand { bool data_in; }; -/* - * Define partitions for flash devices - */ - -static const struct mtd_partition partition_info[] = { - { .name = "Kernel", - .offset = 0, - .size = 3 * SZ_1M + SZ_512K }, - { .name = "u-boot", - .offset = 3 * SZ_1M + SZ_512K, - .size = SZ_256K }, - { .name = "u-boot params", - .offset = 3 * SZ_1M + SZ_512K + SZ_256K, - .size = SZ_256K }, - { .name = "Amstrad LDR", - .offset = 4 * SZ_1M, - .size = SZ_256K }, - { .name = "File system", - .offset = 4 * SZ_1M + 1 * SZ_256K, - .size = 27 * SZ_1M }, - { .name = "PBL reserved", - .offset = 32 * SZ_1M - 3 * SZ_256K, - .size = 3 * SZ_256K }, -}; - static void ams_delta_write_commit(struct ams_delta_nand *priv) { gpiod_set_value(priv->gpiod_nwe, 0); @@ -222,8 +197,8 @@ static const struct nand_controller_ops ams_delta_ops = { static int ams_delta_init(struct platform_device *pdev) { struct gpio_nand_platdata *pdata = dev_get_platdata(&pdev->dev); - const struct mtd_partition *partitions = partition_info; - int num_partitions = ARRAY_SIZE(partition_info); + const struct mtd_partition *partitions = NULL; + int num_partitions = 0; struct ams_delta_nand *priv; struct nand_chip *this; struct mtd_info *mtd; From 2cef3d4cf4498e260f5bc2d5fab850e4a52be382 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 12 Feb 2020 01:39:20 +0100 Subject: [PATCH 1323/4444] mtd: rawnand: ams-delta: Enable OF partition info support Provide MTD layer with device OF node info required by OF partition parser. Signed-off-by: Janusz Krzysztofik Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200212003929.6682-6-jmkrzyszt@gmail.com --- drivers/mtd/nand/raw/ams-delta.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 25f121adea6f..fb96f6a3b0b3 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -222,6 +222,7 @@ static int ams_delta_init(struct platform_device *pdev) mtd->dev.parent = &pdev->dev; nand_set_controller_data(this, priv); + nand_set_flash_node(this, pdev->dev.of_node); priv->gpiod_rdy = devm_gpiod_get_optional(&pdev->dev, "rdy", GPIOD_IN); if (IS_ERR(priv->gpiod_rdy)) { From 241008ed0bb5955e52e06d7270e87c974bbaadd6 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 12 Feb 2020 01:39:21 +0100 Subject: [PATCH 1324/4444] mtd: rawnand: ams-delta: Push inversion handling to gpiolib Let platforms take care of declaring correct GPIO pin polarity so we can just ask a GPIO line to be asserted or deasserted and gpiolib deals with the rest depending on how the platform is configured. Inspired by similar changes to regulator drivers by Linus Walleij , thanks! Signed-off-by: Janusz Krzysztofik Acked-by: Tony Lindgren Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200212003929.6682-7-jmkrzyszt@gmail.com --- arch/arm/mach-omap1/board-ams-delta.c | 12 ++++++++---- drivers/mtd/nand/raw/ams-delta.c | 22 +++++++++++----------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index f4d2ef97099e..8d32894ecd2e 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -341,10 +341,14 @@ static struct gpiod_lookup_table ams_delta_nand_gpio_table = { .table = { GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_NAND_RB, "rdy", 0), - GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NCE, "nce", 0), - GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NRE, "nre", 0), - GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWP, "nwp", 0), - GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWE, "nwe", 0), + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NCE, "nce", + GPIO_ACTIVE_LOW), + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NRE, "nre", + GPIO_ACTIVE_LOW), + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWP, "nwp", + GPIO_ACTIVE_LOW), + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWE, "nwe", + GPIO_ACTIVE_LOW), GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_ALE, "ale", 0), GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_CLE, "cle", 0), GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 0, "data", 0, 0), diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index fb96f6a3b0b3..c7aeb940accd 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -44,9 +44,9 @@ struct ams_delta_nand { static void ams_delta_write_commit(struct ams_delta_nand *priv) { - gpiod_set_value(priv->gpiod_nwe, 0); - ndelay(40); gpiod_set_value(priv->gpiod_nwe, 1); + ndelay(40); + gpiod_set_value(priv->gpiod_nwe, 0); } static void ams_delta_io_write(struct ams_delta_nand *priv, u8 byte) @@ -81,13 +81,13 @@ static u8 ams_delta_io_read(struct ams_delta_nand *priv) struct gpio_descs *data_gpiods = priv->data_gpiods; DECLARE_BITMAP(values, BITS_PER_TYPE(res)) = { 0, }; - gpiod_set_value(priv->gpiod_nre, 0); + gpiod_set_value(priv->gpiod_nre, 1); ndelay(40); gpiod_get_raw_array_value(data_gpiods->ndescs, data_gpiods->desc, data_gpiods->info, values); - gpiod_set_value(priv->gpiod_nre, 1); + gpiod_set_value(priv->gpiod_nre, 0); res = values[0]; return res; @@ -129,7 +129,7 @@ static void ams_delta_read_buf(struct ams_delta_nand *priv, u8 *buf, int len) static void ams_delta_ctrl_cs(struct ams_delta_nand *priv, bool assert) { - gpiod_set_value(priv->gpiod_nce, assert ? 0 : 1); + gpiod_set_value(priv->gpiod_nce, assert); } static int ams_delta_exec_op(struct nand_chip *this, @@ -237,28 +237,28 @@ static int ams_delta_init(struct platform_device *pdev) platform_set_drvdata(pdev, priv); /* Set chip enabled but write protected */ - priv->gpiod_nwp = devm_gpiod_get(&pdev->dev, "nwp", GPIOD_OUT_LOW); + priv->gpiod_nwp = devm_gpiod_get(&pdev->dev, "nwp", GPIOD_OUT_HIGH); if (IS_ERR(priv->gpiod_nwp)) { err = PTR_ERR(priv->gpiod_nwp); dev_err(&pdev->dev, "NWP GPIO request failed (%d)\n", err); return err; } - priv->gpiod_nce = devm_gpiod_get(&pdev->dev, "nce", GPIOD_OUT_HIGH); + priv->gpiod_nce = devm_gpiod_get(&pdev->dev, "nce", GPIOD_OUT_LOW); if (IS_ERR(priv->gpiod_nce)) { err = PTR_ERR(priv->gpiod_nce); dev_err(&pdev->dev, "NCE GPIO request failed (%d)\n", err); return err; } - priv->gpiod_nre = devm_gpiod_get(&pdev->dev, "nre", GPIOD_OUT_HIGH); + priv->gpiod_nre = devm_gpiod_get(&pdev->dev, "nre", GPIOD_OUT_LOW); if (IS_ERR(priv->gpiod_nre)) { err = PTR_ERR(priv->gpiod_nre); dev_err(&pdev->dev, "NRE GPIO request failed (%d)\n", err); return err; } - priv->gpiod_nwe = devm_gpiod_get(&pdev->dev, "nwe", GPIOD_OUT_HIGH); + priv->gpiod_nwe = devm_gpiod_get(&pdev->dev, "nwe", GPIOD_OUT_LOW); if (IS_ERR(priv->gpiod_nwe)) { err = PTR_ERR(priv->gpiod_nwe); dev_err(&pdev->dev, "NWE GPIO request failed (%d)\n", err); @@ -303,7 +303,7 @@ static int ams_delta_init(struct platform_device *pdev) * chip detection/initialization. */ /* Release write protection */ - gpiod_set_value(priv->gpiod_nwp, 1); + gpiod_set_value(priv->gpiod_nwp, 0); /* Scan to find existence of the device */ err = nand_scan(this, 1); @@ -332,7 +332,7 @@ static int ams_delta_cleanup(struct platform_device *pdev) struct mtd_info *mtd = nand_to_mtd(&priv->nand_chip); /* Apply write protection */ - gpiod_set_value(priv->gpiod_nwp, 0); + gpiod_set_value(priv->gpiod_nwp, 1); /* Unregister device */ nand_release(mtd_to_nand(mtd)); From ccada49b050f44df9499859f09b822b8aebc3a4d Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 12 Feb 2020 01:39:22 +0100 Subject: [PATCH 1325/4444] mtd: rawnand: ams-delta: Don't hardcode read/write pulse widths Instead of forcing Amstrad Delta specific read/write pulse widths, use variables initialised from respective fields of chip SDR timings. Signed-off-by: Janusz Krzysztofik Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200212003929.6682-8-jmkrzyszt@gmail.com --- drivers/mtd/nand/raw/ams-delta.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index c7aeb940accd..11689218d23a 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -40,12 +40,14 @@ struct ams_delta_nand { struct gpio_desc *gpiod_cle; struct gpio_descs *data_gpiods; bool data_in; + unsigned int tRP; + unsigned int tWP; }; static void ams_delta_write_commit(struct ams_delta_nand *priv) { gpiod_set_value(priv->gpiod_nwe, 1); - ndelay(40); + ndelay(priv->tWP); gpiod_set_value(priv->gpiod_nwe, 0); } @@ -82,7 +84,7 @@ static u8 ams_delta_io_read(struct ams_delta_nand *priv) DECLARE_BITMAP(values, BITS_PER_TYPE(res)) = { 0, }; gpiod_set_value(priv->gpiod_nre, 1); - ndelay(40); + ndelay(priv->tRP); gpiod_get_raw_array_value(data_gpiods->ndescs, data_gpiods->desc, data_gpiods->info, values); @@ -187,8 +189,31 @@ static int ams_delta_exec_op(struct nand_chip *this, return ret; } +static int ams_delta_setup_data_interface(struct nand_chip *this, int csline, + const struct nand_data_interface *cf) +{ + struct ams_delta_nand *priv = nand_get_controller_data(this); + const struct nand_sdr_timings *sdr = nand_get_sdr_timings(cf); + struct device *dev = &nand_to_mtd(this)->dev; + + if (IS_ERR(sdr)) + return PTR_ERR(sdr); + + if (csline == NAND_DATA_IFACE_CHECK_ONLY) + return 0; + + priv->tRP = DIV_ROUND_UP(sdr->tRP_min, 1000); + dev_dbg(dev, "using %u ns read pulse width\n", priv->tRP); + + priv->tWP = DIV_ROUND_UP(sdr->tWP_min, 1000); + dev_dbg(dev, "using %u ns write pulse width\n", priv->tWP); + + return 0; +} + static const struct nand_controller_ops ams_delta_ops = { .exec_op = ams_delta_exec_op, + .setup_data_interface = ams_delta_setup_data_interface, }; /* From 586a746b326c35d2c0b2773dba61ffa1d4818711 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 12 Feb 2020 01:39:23 +0100 Subject: [PATCH 1326/4444] mtd: rawnand: ams-delta: Make read pulses optional Allow platforms to omit NRE pin from device configuration by requesting that pin as optional. In that case, also don't apply read pulse width from chip SDR timings. There should be no need for further code adjustments as gpiolib can handle NULL GPIO descriptor pointers. Signed-off-by: Janusz Krzysztofik Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200212003929.6682-9-jmkrzyszt@gmail.com --- drivers/mtd/nand/raw/ams-delta.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 11689218d23a..c481d73e3dcb 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -202,8 +202,10 @@ static int ams_delta_setup_data_interface(struct nand_chip *this, int csline, if (csline == NAND_DATA_IFACE_CHECK_ONLY) return 0; - priv->tRP = DIV_ROUND_UP(sdr->tRP_min, 1000); - dev_dbg(dev, "using %u ns read pulse width\n", priv->tRP); + if (priv->gpiod_nre) { + priv->tRP = DIV_ROUND_UP(sdr->tRP_min, 1000); + dev_dbg(dev, "using %u ns read pulse width\n", priv->tRP); + } priv->tWP = DIV_ROUND_UP(sdr->tWP_min, 1000); dev_dbg(dev, "using %u ns write pulse width\n", priv->tWP); @@ -276,7 +278,8 @@ static int ams_delta_init(struct platform_device *pdev) return err; } - priv->gpiod_nre = devm_gpiod_get(&pdev->dev, "nre", GPIOD_OUT_LOW); + priv->gpiod_nre = devm_gpiod_get_optional(&pdev->dev, "nre", + GPIOD_OUT_LOW); if (IS_ERR(priv->gpiod_nre)) { err = PTR_ERR(priv->gpiod_nre); dev_err(&pdev->dev, "NRE GPIO request failed (%d)\n", err); From ea5ea9fa6db23ff5b194e84fad32e3bae5c7f357 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 12 Feb 2020 01:39:24 +0100 Subject: [PATCH 1327/4444] mtd: rawnand: ams-delta: Handle more GPIO pins as optional In order to make the driver more useful on platforms other than Amstrad Delta, allow GPIO descriptor pointers of possibly non-critical NWP and NCE pins to be initialised as NULL. Signed-off-by: Janusz Krzysztofik Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200212003929.6682-10-jmkrzyszt@gmail.com --- drivers/mtd/nand/raw/ams-delta.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index c481d73e3dcb..0c88e94e9b71 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -264,14 +264,16 @@ static int ams_delta_init(struct platform_device *pdev) platform_set_drvdata(pdev, priv); /* Set chip enabled but write protected */ - priv->gpiod_nwp = devm_gpiod_get(&pdev->dev, "nwp", GPIOD_OUT_HIGH); + priv->gpiod_nwp = devm_gpiod_get_optional(&pdev->dev, "nwp", + GPIOD_OUT_HIGH); if (IS_ERR(priv->gpiod_nwp)) { err = PTR_ERR(priv->gpiod_nwp); dev_err(&pdev->dev, "NWP GPIO request failed (%d)\n", err); return err; } - priv->gpiod_nce = devm_gpiod_get(&pdev->dev, "nce", GPIOD_OUT_LOW); + priv->gpiod_nce = devm_gpiod_get_optional(&pdev->dev, "nce", + GPIOD_OUT_LOW); if (IS_ERR(priv->gpiod_nce)) { err = PTR_ERR(priv->gpiod_nce); dev_err(&pdev->dev, "NCE GPIO request failed (%d)\n", err); From dceeb0f0e61071b1d990459dbd6a53f590cdaf77 Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Thu, 9 Jan 2020 11:06:03 -0800 Subject: [PATCH 1328/4444] include: linux: firmware: Correct config dependency of zynqmp_eemi_ops zynqmp_eemi_ops will be compiled only when CONFIG_ZYNQMP_FIRMWARE is enabled. So check for CONFIG_ZYNQMP_FIRMWARE instead of checking for CONFIG_ARCH_ZYNQMP. Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Signed-off-by: Michal Simek --- include/linux/firmware/xlnx-zynqmp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h index 2cd12ebd6826..ed1aace0cbbc 100644 --- a/include/linux/firmware/xlnx-zynqmp.h +++ b/include/linux/firmware/xlnx-zynqmp.h @@ -320,7 +320,7 @@ struct zynqmp_eemi_ops { int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 *ret_payload); -#if IS_REACHABLE(CONFIG_ARCH_ZYNQMP) +#if IS_REACHABLE(CONFIG_ZYNQMP_FIRMWARE) const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void); #else static inline struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void) From 4b9cbf5084e2ed72181a544b48bdcea91463061b Mon Sep 17 00:00:00 2001 From: Tejas Patel Date: Tue, 25 Feb 2020 16:04:20 -0800 Subject: [PATCH 1329/4444] arm64: zynqmp: Make zynqmp_firmware driver optional Make zynqmp_firmware driver as optional to disable it, if user don't want to use default zynqmp firmware interface. Signed-off-by: Tejas Patel Signed-off-by: Jolly Shah Signed-off-by: Michal Simek --- arch/arm64/Kconfig.platforms | 1 - drivers/firmware/xilinx/Kconfig | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index b2b504ea6fd6..563c93d56c56 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -301,7 +301,6 @@ config ARCH_ZX config ARCH_ZYNQMP bool "Xilinx ZynqMP Family" - select ZYNQMP_FIRMWARE help This enables support for Xilinx ZynqMP Family diff --git a/drivers/firmware/xilinx/Kconfig b/drivers/firmware/xilinx/Kconfig index bd33bbf70daf..9a9bd190888e 100644 --- a/drivers/firmware/xilinx/Kconfig +++ b/drivers/firmware/xilinx/Kconfig @@ -6,6 +6,8 @@ menu "Zynq MPSoC Firmware Drivers" config ZYNQMP_FIRMWARE bool "Enable Xilinx Zynq MPSoC firmware interface" + depends on ARCH_ZYNQMP + default y if ARCH_ZYNQMP select MFD_CORE help Firmware interface driver is used by different From 9401d5aa328e64617d87abd59af1c91cace4c3e4 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Fri, 6 Mar 2020 23:29:27 +0100 Subject: [PATCH 1330/4444] ASoC: jz4740-i2s: Fix divider written at incorrect offset in register The 4-bit divider value was written at offset 8, while the jz4740 programming manual locates it at offset 0. Fixes: 26b0aad80a86 ("ASoC: jz4740: Add dynamic sampling rate support to jz4740-i2s") Signed-off-by: Paul Cercueil Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20200306222931.39664-2-paul@crapouillou.net Signed-off-by: Mark Brown --- sound/soc/jz4740/jz4740-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index 9d5405881209..434737b2b2b2 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c @@ -83,7 +83,7 @@ #define JZ_AIC_I2S_STATUS_BUSY BIT(2) #define JZ_AIC_CLK_DIV_MASK 0xf -#define I2SDIV_DV_SHIFT 8 +#define I2SDIV_DV_SHIFT 0 #define I2SDIV_DV_MASK (0xf << I2SDIV_DV_SHIFT) #define I2SDIV_IDV_SHIFT 8 #define I2SDIV_IDV_MASK (0xf << I2SDIV_IDV_SHIFT) From 40a92dbcbc32d7dfbf186dfb1e27ee55d1df2f64 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 9 Mar 2020 13:02:37 +0900 Subject: [PATCH 1331/4444] ASoC: simple-card-utils: use for_each_pcm_streams() We already have for_each_pcm_streams() macro. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/875zfei3aa.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card-utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 320e648f7499..abbdf1054f6f 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -347,7 +347,7 @@ static int asoc_simple_init_dai_link_params(struct snd_soc_pcm_runtime *rtd, } /* Assumes the capabilities are the same for all supported streams */ - for (stream = 0; stream < 2; stream++) { + for_each_pcm_streams(stream) { ret = snd_soc_runtime_calc_hw(rtd, &hw, stream); if (ret == 0) break; From ab985be95da1d68a0cdba1ed702961aae047bf89 Mon Sep 17 00:00:00 2001 From: Ravulapati Vishnu vardhan rao Date: Mon, 9 Mar 2020 16:20:10 +0530 Subject: [PATCH 1332/4444] ASoC: amd: Adding TDM support in hw_params. TDM related settings for ACP registers in hw_params. When TDM mode is enabled, Hw_params needs to read and write from/to respective TX/RX (ACP_(I2S/BT)TDM_(TX/RX)FRMT) registers. Signed-off-by: Ravulapati Vishnu vardhan rao Link: https://lore.kernel.org/r/1583751029-2850-1-git-send-email-Vishnuvardhanrao.Ravulapati@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/raven/acp3x-i2s.c | 44 ++++++++++----------------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/sound/soc/amd/raven/acp3x-i2s.c b/sound/soc/amd/raven/acp3x-i2s.c index 91a388184e52..3a3c47e820ab 100644 --- a/sound/soc/amd/raven/acp3x-i2s.c +++ b/sound/soc/amd/raven/acp3x-i2s.c @@ -42,7 +42,7 @@ static int acp3x_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask, u32 rx_mask, int slots, int slot_width) { struct i2s_dev_data *adata; - u32 val, reg_val, frmt_reg, frm_len; + u32 frm_len; u16 slot_len; adata = snd_soc_dai_get_drvdata(cpu_dai); @@ -64,36 +64,7 @@ static int acp3x_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai, default: return -EINVAL; } - - /* Enable I2S/BT channels TDM, respective TX/RX frame lengths.*/ - frm_len = FRM_LEN | (slots << 15) | (slot_len << 18); - if (adata->substream_type == SNDRV_PCM_STREAM_PLAYBACK) { - switch (adata->i2s_instance) { - case I2S_BT_INSTANCE: - reg_val = mmACP_BTTDM_ITER; - frmt_reg = mmACP_BTTDM_TXFRMT; - break; - case I2S_SP_INSTANCE: - default: - reg_val = mmACP_I2STDM_ITER; - frmt_reg = mmACP_I2STDM_TXFRMT; - } - } else { - switch (adata->i2s_instance) { - case I2S_BT_INSTANCE: - reg_val = mmACP_BTTDM_IRER; - frmt_reg = mmACP_BTTDM_RXFRMT; - break; - case I2S_SP_INSTANCE: - default: - reg_val = mmACP_I2STDM_IRER; - frmt_reg = mmACP_I2STDM_RXFRMT; - } - } - val = rv_readl(adata->acp3x_base + reg_val); - rv_writel(val | 0x2, adata->acp3x_base + reg_val); - rv_writel(frm_len, adata->acp3x_base + frmt_reg); adata->tdm_fmt = frm_len; return 0; } @@ -105,12 +76,14 @@ static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *prtd; struct snd_soc_card *card; struct acp3x_platform_info *pinfo; + struct i2s_dev_data *adata; u32 val; - u32 reg_val; + u32 reg_val, frmt_reg; prtd = substream->private_data; rtd = substream->runtime->private_data; card = prtd->card; + adata = snd_soc_dai_get_drvdata(dai); pinfo = snd_soc_card_get_drvdata(card); if (pinfo) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -141,21 +114,30 @@ static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream, switch (rtd->i2s_instance) { case I2S_BT_INSTANCE: reg_val = mmACP_BTTDM_ITER; + frmt_reg = mmACP_BTTDM_TXFRMT; break; case I2S_SP_INSTANCE: default: reg_val = mmACP_I2STDM_ITER; + frmt_reg = mmACP_I2STDM_TXFRMT; } } else { switch (rtd->i2s_instance) { case I2S_BT_INSTANCE: reg_val = mmACP_BTTDM_IRER; + frmt_reg = mmACP_BTTDM_RXFRMT; break; case I2S_SP_INSTANCE: default: reg_val = mmACP_I2STDM_IRER; + frmt_reg = mmACP_I2STDM_RXFRMT; } } + if (adata->tdm_mode) { + val = rv_readl(rtd->acp3x_base + reg_val); + rv_writel(val | 0x2, rtd->acp3x_base + reg_val); + rv_writel(adata->tdm_fmt, rtd->acp3x_base + frmt_reg); + } val = rv_readl(rtd->acp3x_base + reg_val); val = val | (rtd->xfer_resolution << 3); rv_writel(val, rtd->acp3x_base + reg_val); From a42d9ba15cbf3e84307906db65fc598a8b73e2f1 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Fri, 6 Mar 2020 23:29:28 +0100 Subject: [PATCH 1333/4444] ASoC: jz4740-i2s: Add local dev variable in probe function Make the code cleaner by using a "struct device *dev" variable instead of dereferencing it everytime from within the struct platform_device. Signed-off-by: Paul Cercueil Link: https://lore.kernel.org/r/20200306222931.39664-3-paul@crapouillou.net Signed-off-by: Mark Brown --- sound/soc/jz4740/jz4740-i2s.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index 9d5405881209..2572aba843e3 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c @@ -492,45 +492,45 @@ MODULE_DEVICE_TABLE(of, jz4740_of_matches); static int jz4740_i2s_dev_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct jz4740_i2s *i2s; struct resource *mem; int ret; - i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); + i2s = devm_kzalloc(dev, sizeof(*i2s), GFP_KERNEL); if (!i2s) return -ENOMEM; - i2s->version = - (enum jz47xx_i2s_version)of_device_get_match_data(&pdev->dev); + i2s->version = (enum jz47xx_i2s_version)of_device_get_match_data(dev); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2s->base = devm_ioremap_resource(&pdev->dev, mem); + i2s->base = devm_ioremap_resource(dev, mem); if (IS_ERR(i2s->base)) return PTR_ERR(i2s->base); i2s->phys_base = mem->start; - i2s->clk_aic = devm_clk_get(&pdev->dev, "aic"); + i2s->clk_aic = devm_clk_get(dev, "aic"); if (IS_ERR(i2s->clk_aic)) return PTR_ERR(i2s->clk_aic); - i2s->clk_i2s = devm_clk_get(&pdev->dev, "i2s"); + i2s->clk_i2s = devm_clk_get(dev, "i2s"); if (IS_ERR(i2s->clk_i2s)) return PTR_ERR(i2s->clk_i2s); platform_set_drvdata(pdev, i2s); if (i2s->version == JZ_I2S_JZ4780) - ret = devm_snd_soc_register_component(&pdev->dev, + ret = devm_snd_soc_register_component(dev, &jz4740_i2s_component, &jz4780_i2s_dai, 1); else - ret = devm_snd_soc_register_component(&pdev->dev, + ret = devm_snd_soc_register_component(dev, &jz4740_i2s_component, &jz4740_i2s_dai, 1); if (ret) return ret; - return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, + return devm_snd_dmaengine_pcm_register(dev, NULL, SND_DMAENGINE_PCM_FLAG_COMPAT); } From 62f9ed5f8768d2425461737d77b83f888b525c06 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Fri, 6 Mar 2020 23:29:29 +0100 Subject: [PATCH 1334/4444] ASoC: jz4740-i2s: Avoid passing enum as match data Instead of passing an enum as match data, and checking its value in the probe to register one or the other dai, pass a pointer to a struct i2s_soc_info, which contains all the information relative to one SoC. Signed-off-by: Paul Cercueil Link: https://lore.kernel.org/r/20200306222931.39664-4-paul@crapouillou.net Signed-off-by: Mark Brown --- sound/soc/jz4740/jz4740-i2s.c | 36 ++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index 2572aba843e3..d1512d483cda 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c @@ -93,6 +93,11 @@ enum jz47xx_i2s_version { JZ_I2S_JZ4780, }; +struct i2s_soc_info { + enum jz47xx_i2s_version version; + struct snd_soc_dai_driver *dai; +}; + struct jz4740_i2s { struct resource *mem; void __iomem *base; @@ -104,7 +109,7 @@ struct jz4740_i2s { struct snd_dmaengine_dai_dma_data playback_dma_data; struct snd_dmaengine_dai_dma_data capture_dma_data; - enum jz47xx_i2s_version version; + const struct i2s_soc_info *soc_info; }; static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s, @@ -284,7 +289,7 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK; ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET; - if (i2s->version >= JZ_I2S_JZ4780) { + if (i2s->soc_info->version >= JZ_I2S_JZ4780) { div_reg &= ~I2SDIV_IDV_MASK; div_reg |= (div - 1) << I2SDIV_IDV_SHIFT; } else { @@ -398,7 +403,7 @@ static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai) snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, &i2s->capture_dma_data); - if (i2s->version >= JZ_I2S_JZ4780) { + if (i2s->soc_info->version >= JZ_I2S_JZ4780) { conf = (7 << JZ4780_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | (8 << JZ4780_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | JZ_AIC_CONF_OVERFLOW_PLAY_LAST | @@ -457,6 +462,11 @@ static struct snd_soc_dai_driver jz4740_i2s_dai = { .ops = &jz4740_i2s_dai_ops, }; +static const struct i2s_soc_info jz4740_i2s_soc_info = { + .version = JZ_I2S_JZ4740, + .dai = &jz4740_i2s_dai, +}; + static struct snd_soc_dai_driver jz4780_i2s_dai = { .probe = jz4740_i2s_dai_probe, .remove = jz4740_i2s_dai_remove, @@ -475,6 +485,11 @@ static struct snd_soc_dai_driver jz4780_i2s_dai = { .ops = &jz4740_i2s_dai_ops, }; +static const struct i2s_soc_info jz4780_i2s_soc_info = { + .version = JZ_I2S_JZ4780, + .dai = &jz4780_i2s_dai, +}; + static const struct snd_soc_component_driver jz4740_i2s_component = { .name = "jz4740-i2s", .suspend = jz4740_i2s_suspend, @@ -483,8 +498,8 @@ static const struct snd_soc_component_driver jz4740_i2s_component = { #ifdef CONFIG_OF static const struct of_device_id jz4740_of_matches[] = { - { .compatible = "ingenic,jz4740-i2s", .data = (void *)JZ_I2S_JZ4740 }, - { .compatible = "ingenic,jz4780-i2s", .data = (void *)JZ_I2S_JZ4780 }, + { .compatible = "ingenic,jz4740-i2s", .data = &jz4740_i2s_soc_info }, + { .compatible = "ingenic,jz4780-i2s", .data = &jz4780_i2s_soc_info }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, jz4740_of_matches); @@ -501,7 +516,7 @@ static int jz4740_i2s_dev_probe(struct platform_device *pdev) if (!i2s) return -ENOMEM; - i2s->version = (enum jz47xx_i2s_version)of_device_get_match_data(dev); + i2s->soc_info = device_get_match_data(dev); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); i2s->base = devm_ioremap_resource(dev, mem); @@ -520,13 +535,8 @@ static int jz4740_i2s_dev_probe(struct platform_device *pdev) platform_set_drvdata(pdev, i2s); - if (i2s->version == JZ_I2S_JZ4780) - ret = devm_snd_soc_register_component(dev, - &jz4740_i2s_component, &jz4780_i2s_dai, 1); - else - ret = devm_snd_soc_register_component(dev, - &jz4740_i2s_component, &jz4740_i2s_dai, 1); - + ret = devm_snd_soc_register_component(dev, &jz4740_i2s_component, + i2s->soc_info->dai, 1); if (ret) return ret; From b00f80fcfaa098f987dde99585e73e8ed7edae51 Mon Sep 17 00:00:00 2001 From: Boqun Feng Date: Mon, 10 Feb 2020 11:39:51 +0800 Subject: [PATCH 1335/4444] PCI: hv: Move hypercall related definitions into tlfs header Currently HVCALL_RETARGET_INTERRUPT and HV_PARTITION_ID_SELF are defined in pci-hyperv.c. However, similar to other hypercall related definitions, it makes more sense to put them in the tlfs header file. Besides, these definitions are arch-dependent, so for the support of virtual PCI on non-x86 archs in the future, move them into arch-specific tlfs header file. Signed-off-by: Boqun Feng (Microsoft) Signed-off-by: Lorenzo Pieralisi Reviewed-by: Andrew Murray Reviewed-by: Dexuan Cui --- arch/x86/include/asm/hyperv-tlfs.h | 3 +++ drivers/pci/controller/pci-hyperv.c | 6 ------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h index 92abc1e42bfc..dffed0e10a68 100644 --- a/arch/x86/include/asm/hyperv-tlfs.h +++ b/arch/x86/include/asm/hyperv-tlfs.h @@ -376,6 +376,7 @@ struct hv_tsc_emulation_status { #define HVCALL_SEND_IPI_EX 0x0015 #define HVCALL_POST_MESSAGE 0x005c #define HVCALL_SIGNAL_EVENT 0x005d +#define HVCALL_RETARGET_INTERRUPT 0x007e #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0 @@ -405,6 +406,8 @@ enum HV_GENERIC_SET_FORMAT { HV_GENERIC_SET_ALL, }; +#define HV_PARTITION_ID_SELF ((u64)-1) + #define HV_HYPERCALL_RESULT_MASK GENMASK_ULL(15, 0) #define HV_HYPERCALL_FAST_BIT BIT(16) #define HV_HYPERCALL_VARHEAD_OFFSET 17 diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index 88fd39254e0c..c64c7ffdd653 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -435,12 +435,6 @@ struct pci_eject_response { static int pci_ring_size = (4 * PAGE_SIZE); -/* - * Definitions or interrupt steering hypercall. - */ -#define HV_PARTITION_ID_SELF ((u64)-1) -#define HVCALL_RETARGET_INTERRUPT 0x7e - struct hv_interrupt_entry { u32 source; /* 1 for MSI(-X) */ u32 reserved1; From 61bfd920abbf2c8c9c3b10bb335475e707247573 Mon Sep 17 00:00:00 2001 From: Boqun Feng Date: Mon, 10 Feb 2020 11:39:52 +0800 Subject: [PATCH 1336/4444] PCI: hv: Move retarget related structures into tlfs header Currently, retarget_msi_interrupt and other structures it relys on are defined in pci-hyperv.c. However, those structures are actually defined in Hypervisor Top-Level Functional Specification [1] and may be different in sizes of fields or layout from architecture to architecture. Let's move those definitions into x86's tlfs header file to support virtual PCI on non-x86 architectures in the future. Note that "__packed" attribute is added to these structures during the movement for the same reason as we use the attribute for other TLFS structures in the header file: make sure the structures meet the specification and avoid anything unexpected from the compilers. Additionally, rename struct retarget_msi_interrupt to hv_retarget_msi_interrupt for the consistent naming convention, also mirroring the name in TLFS. [1]: https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs Signed-off-by: Boqun Feng (Microsoft) Signed-off-by: Lorenzo Pieralisi Reviewed-by: Dexuan Cui --- arch/x86/include/asm/hyperv-tlfs.h | 31 ++++++++++++++++++++++++++ drivers/pci/controller/pci-hyperv.c | 34 ++--------------------------- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h index dffed0e10a68..a0b6a88d2f05 100644 --- a/arch/x86/include/asm/hyperv-tlfs.h +++ b/arch/x86/include/asm/hyperv-tlfs.h @@ -912,4 +912,35 @@ struct hv_tlb_flush_ex { struct hv_partition_assist_pg { u32 tlb_lock_count; }; + +struct hv_interrupt_entry { + u32 source; /* 1 for MSI(-X) */ + u32 reserved1; + u32 address; + u32 data; +} __packed; + +/* + * flags for hv_device_interrupt_target.flags + */ +#define HV_DEVICE_INTERRUPT_TARGET_MULTICAST 1 +#define HV_DEVICE_INTERRUPT_TARGET_PROCESSOR_SET 2 + +struct hv_device_interrupt_target { + u32 vector; + u32 flags; + union { + u64 vp_mask; + struct hv_vpset vp_set; + }; +} __packed; + +/* HvRetargetDeviceInterrupt hypercall */ +struct hv_retarget_device_interrupt { + u64 partition_id; /* use "self" */ + u64 device_id; + struct hv_interrupt_entry int_entry; + u64 reserved2; + struct hv_device_interrupt_target int_target; +} __packed __aligned(8); #endif diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index c64c7ffdd653..9c6ec289839c 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -435,36 +435,6 @@ struct pci_eject_response { static int pci_ring_size = (4 * PAGE_SIZE); -struct hv_interrupt_entry { - u32 source; /* 1 for MSI(-X) */ - u32 reserved1; - u32 address; - u32 data; -}; - -/* - * flags for hv_device_interrupt_target.flags - */ -#define HV_DEVICE_INTERRUPT_TARGET_MULTICAST 1 -#define HV_DEVICE_INTERRUPT_TARGET_PROCESSOR_SET 2 - -struct hv_device_interrupt_target { - u32 vector; - u32 flags; - union { - u64 vp_mask; - struct hv_vpset vp_set; - }; -}; - -struct retarget_msi_interrupt { - u64 partition_id; /* use "self" */ - u64 device_id; - struct hv_interrupt_entry int_entry; - u64 reserved2; - struct hv_device_interrupt_target int_target; -} __packed __aligned(8); - /* * Driver specific state. */ @@ -511,7 +481,7 @@ struct hv_pcibus_device { struct workqueue_struct *wq; /* hypercall arg, must not cross page boundary */ - struct retarget_msi_interrupt retarget_msi_interrupt_params; + struct hv_retarget_device_interrupt retarget_msi_interrupt_params; /* * Don't put anything here: retarget_msi_interrupt_params must be last @@ -1221,7 +1191,7 @@ static void hv_irq_unmask(struct irq_data *data) { struct msi_desc *msi_desc = irq_data_get_msi_desc(data); struct irq_cfg *cfg = irqd_cfg(data); - struct retarget_msi_interrupt *params; + struct hv_retarget_device_interrupt *params; struct hv_pcibus_device *hbus; struct cpumask *dest; cpumask_var_t tmp; From 1cf106d93245f436c10e73cd3d4b885067d4bbcc Mon Sep 17 00:00:00 2001 From: Boqun Feng Date: Mon, 10 Feb 2020 11:39:53 +0800 Subject: [PATCH 1337/4444] PCI: hv: Introduce hv_msi_entry Add a new structure (hv_msi_entry), which is also defined in the TLFS, to describe the msi entry for HVCALL_RETARGET_INTERRUPT. The structure is needed because its layout may be different from architecture to architecture. Also add a new generic interface hv_set_msi_entry_from_desc() to allow different archs to set the msi entry from msi_desc. No functional change, only preparation for the future support of virtual PCI on non-x86 architectures. Signed-off-by: Boqun Feng (Microsoft) Signed-off-by: Lorenzo Pieralisi Reviewed-by: Dexuan Cui --- arch/x86/include/asm/hyperv-tlfs.h | 11 +++++++++-- arch/x86/include/asm/mshyperv.h | 8 ++++++++ drivers/pci/controller/pci-hyperv.c | 3 +-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h index a0b6a88d2f05..29336574d0bc 100644 --- a/arch/x86/include/asm/hyperv-tlfs.h +++ b/arch/x86/include/asm/hyperv-tlfs.h @@ -913,11 +913,18 @@ struct hv_partition_assist_pg { u32 tlb_lock_count; }; +union hv_msi_entry { + u64 as_uint64; + struct { + u32 address; + u32 data; + } __packed; +}; + struct hv_interrupt_entry { u32 source; /* 1 for MSI(-X) */ u32 reserved1; - u32 address; - u32 data; + union hv_msi_entry msi_entry; } __packed; /* diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 6b79515abb82..81fc30240122 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -240,6 +241,13 @@ bool hv_vcpu_is_preempted(int vcpu); static inline void hv_apic_init(void) {} #endif +static inline void hv_set_msi_entry_from_desc(union hv_msi_entry *msi_entry, + struct msi_desc *msi_desc) +{ + msi_entry->address = msi_desc->msg.address_lo; + msi_entry->data = msi_desc->msg.data; +} + #else /* CONFIG_HYPERV */ static inline void hyperv_init(void) {} static inline void hyperv_setup_mmu_ops(void) {} diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index 9c6ec289839c..e15022ff63e3 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -1213,8 +1213,7 @@ static void hv_irq_unmask(struct irq_data *data) memset(params, 0, sizeof(*params)); params->partition_id = HV_PARTITION_ID_SELF; params->int_entry.source = 1; /* MSI(-X) */ - params->int_entry.address = msi_desc->msg.address_lo; - params->int_entry.data = msi_desc->msg.data; + hv_set_msi_entry_from_desc(¶ms->int_entry.msi_entry, msi_desc); params->device_id = (hbus->hdev->dev_instance.b[5] << 24) | (hbus->hdev->dev_instance.b[4] << 16) | (hbus->hdev->dev_instance.b[7] << 8) | From 32507b8681198c987fad8ac66e55ad4e15dfae4a Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Sun, 8 Mar 2020 14:58:49 +0100 Subject: [PATCH 1338/4444] arm64: dts: allwinner: h6: Move ext. oscillator to board DTs It turns out that not all H6 boards have external 32kHz oscillator. Currently the only one known such H6 board is Tanix TX6. Move external oscillator node from common H6 dtsi to board specific dts files where present. Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- .../boot/dts/allwinner/sun50i-h6-beelink-gs1.dts | 11 +++++++++++ .../arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts | 11 +++++++++++ arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi | 11 +++++++++++ arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts | 11 +++++++++++ arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 8 -------- 5 files changed, 44 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts index df6d872c34e2..8f09d209359b 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts @@ -32,6 +32,13 @@ }; }; + ext_osc32k: ext_osc32k_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + clock-output-names = "ext_osc32k"; + }; + leds { compatible = "gpio-leds"; @@ -275,6 +282,10 @@ vcc-pm-supply = <®_aldo1>; }; +&rtc { + clocks = <&ext_osc32k>; +}; + &spdif { status = "okay"; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts index 1e0abd9d047f..47f579610dcc 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts @@ -32,6 +32,13 @@ }; }; + ext_osc32k: ext_osc32k_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + clock-output-names = "ext_osc32k"; + }; + leds { compatible = "gpio-leds"; @@ -285,6 +292,10 @@ status = "okay"; }; +&rtc { + clocks = <&ext_osc32k>; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_ph_pins>; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi index 37f4c57597d4..37fc3f3697f7 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi @@ -20,6 +20,13 @@ stdout-path = "serial0:115200n8"; }; + ext_osc32k: ext_osc32k_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + clock-output-names = "ext_osc32k"; + }; + leds { compatible = "gpio-leds"; @@ -197,6 +204,10 @@ status = "okay"; }; +&rtc { + clocks = <&ext_osc32k>; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_ph_pins>; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts index 3c9dd0d69754..b0642d841933 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts @@ -21,6 +21,13 @@ stdout-path = "serial0:115200n8"; }; + ext_osc32k: ext_osc32k_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + clock-output-names = "ext_osc32k"; + }; + hdmi_connector: connector { compatible = "hdmi-connector"; type = "a"; @@ -279,6 +286,10 @@ vcc-pm-supply = <®_aldo1>; }; +&rtc { + clocks = <&ext_osc32k>; +}; + /* * The CS pin is shared with the MMC2 CMD pin, so we cannot have the SPI * flash and eMMC at the same time, as one of them would fail probing. diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index 967249e58811..b9ab7d8fa8af 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -62,13 +62,6 @@ clock-output-names = "osc24M"; }; - ext_osc32k: ext_osc32k_clk { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <32768>; - clock-output-names = "ext_osc32k"; - }; - pmu { compatible = "arm,cortex-a53-pmu"; interrupts = , @@ -854,7 +847,6 @@ interrupts = , ; clock-output-names = "osc32k", "osc32k-out", "iosc"; - clocks = <&ext_osc32k>; #clock-cells = <1>; }; From 7ee32a17e0d65fbaa55b032f3bb52232b09fb447 Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Sun, 8 Mar 2020 17:48:39 +0100 Subject: [PATCH 1339/4444] arm64: dts: allwinner: h6: orangepi-one-plus: Enable ethernet OrangePi One Plus has gigabit ethernet. Add nodes for it. Signed-off-by: Marcus Cooper [patch split and commit message] Signed-off-by: Jernej Skrabec Reviewed-by: Christopher Obbard Tested-by: Christopher Obbard Signed-off-by: Maxime Ripard --- .../allwinner/sun50i-h6-orangepi-one-plus.dts | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-one-plus.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-one-plus.dts index 83aab7368889..fceb298bfd53 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-one-plus.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-one-plus.dts @@ -7,4 +7,37 @@ / { model = "OrangePi One Plus"; compatible = "xunlong,orangepi-one-plus", "allwinner,sun50i-h6"; + + aliases { + ethernet0 = &emac; + }; + + reg_gmac_3v3: gmac-3v3 { + compatible = "regulator-fixed"; + regulator-name = "vcc-gmac-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <100000>; + enable-active-high; + gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* PD6 */ + vin-supply = <®_aldo2>; + }; +}; + +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&ext_rgmii_pins>; + phy-mode = "rgmii"; + phy-handle = <&ext_rgmii_phy>; + phy-supply = <®_gmac_3v3>; + allwinner,rx-delay-ps = <200>; + allwinner,tx-delay-ps = <200>; + status = "okay"; +}; + +&mdio { + ext_rgmii_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; }; From 2345b744f4f911713dcada64ea16a614f5be9328 Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Sun, 8 Mar 2020 17:48:40 +0100 Subject: [PATCH 1340/4444] arm64: dts: allwinner: h6: orangepi: Enable HDMI Both, OrangePi One Plus and OrangePi Lite 2 have HDMI output. Enable it in common DTSI. Signed-off-by: Marcus Cooper [patch split and commit message] Signed-off-by: Jernej Skrabec Reviewed-by: Christopher Obbard Tested-by: Christopher Obbard Signed-off-by: Maxime Ripard --- .../dts/allwinner/sun50i-h6-orangepi.dtsi | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi index 37fc3f3697f7..9287976c4a50 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi @@ -20,6 +20,18 @@ stdout-path = "serial0:115200n8"; }; + connector { + compatible = "hdmi-connector"; + type = "a"; + ddc-en-gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */ + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; + ext_osc32k: ext_osc32k_clk { #clock-cells = <0>; compatible = "fixed-clock"; @@ -52,6 +64,10 @@ }; }; +&de { + status = "okay"; +}; + &ehci0 { status = "okay"; }; @@ -65,6 +81,16 @@ status = "okay"; }; +&hdmi { + status = "okay"; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + &mmc0 { vmmc-supply = <®_cldo1>; cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; From 80f132d737091055ea79a59e03d1880aaf4203e3 Mon Sep 17 00:00:00 2001 From: Joyce Ooi Date: Mon, 9 Mar 2020 11:36:49 +0800 Subject: [PATCH 1341/4444] arm64: dts: increase the QSPI reg address for Stratix10 and Agilex This patch increases the reg addresses for QSPI boot and QSPI rootfs for Stratix10 and Agilex to cater for the increased size of kernel Image. Signed-off-by: Joyce Ooi Signed-off-by: Dinh Nguyen --- arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts | 6 +++--- arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts index fb11ef05d556..f6c4a15079d3 100644 --- a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts +++ b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts @@ -178,12 +178,12 @@ qspi_boot: partition@0 { label = "Boot and fpga data"; - reg = <0x0 0x034B0000>; + reg = <0x0 0x03FE0000>; }; - qspi_rootfs: partition@4000000 { + qspi_rootfs: partition@3FE0000 { label = "Root Filesystem - JFFS2"; - reg = <0x034B0000 0x0EB50000>; + reg = <0x03FE0000 0x0C020000>; }; }; }; diff --git a/arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts b/arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts index e794a12ba7c5..51d948323bfd 100644 --- a/arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts +++ b/arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts @@ -121,12 +121,12 @@ qspi_boot: partition@0 { label = "Boot and fpga data"; - reg = <0x0 0x034B0000>; + reg = <0x0 0x03FE0000>; }; - qspi_rootfs: partition@34B0000 { + qspi_rootfs: partition@3FE0000 { label = "Root Filesystem - JFFS2"; - reg = <0x034B0000 0x0EB50000>; + reg = <0x03FE0000 0x0C020000>; }; }; }; From efde2659b0fe835732047357b2902cca14f054d9 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 14 Jan 2020 17:37:51 -0800 Subject: [PATCH 1342/4444] drivers: qcom: rpmh-rsc: Use rcuidle tracepoints for rpmh This tracepoint is hit now that we call into the rpmh code from the cpu idle path. Let's move this to be an rcuidle tracepoint so that we avoid the RCU idle splat below ============================= WARNING: suspicious RCU usage 5.4.10 #68 Tainted: G S ----------------------------- drivers/soc/qcom/trace-rpmh.h:72 suspicious rcu_dereference_check() usage! other info that might help us debug this: RCU used illegally from idle CPU! rcu_scheduler_active = 2, debug_locks = 1 RCU used illegally from extended quiescent state! 5 locks held by swapper/2/0: #0: ffffff81745d6ee8 (&(&genpd->slock)->rlock){+.+.}, at: genpd_lock_spin+0x1c/0x2c #1: ffffff81745da6e8 (&(&genpd->slock)->rlock/1){....}, at: genpd_lock_nested_spin+0x24/0x34 #2: ffffff8174f2ca20 (&(&genpd->slock)->rlock/2){....}, at: genpd_lock_nested_spin+0x24/0x34 #3: ffffff8174f2c300 (&(&drv->client.cache_lock)->rlock){....}, at: rpmh_flush+0x48/0x24c #4: ffffff8174f2c150 (&(&tcs->lock)->rlock){+.+.}, at: rpmh_rsc_write_ctrl_data+0x74/0x270 stack backtrace: CPU: 2 PID: 0 Comm: swapper/2 Tainted: G S 5.4.10 #68 Call trace: dump_backtrace+0x0/0x174 show_stack+0x20/0x2c dump_stack+0xc8/0x124 lockdep_rcu_suspicious+0xe4/0x104 __tcs_buffer_write+0x230/0x2d0 rpmh_rsc_write_ctrl_data+0x210/0x270 rpmh_flush+0x84/0x24c rpmh_domain_power_off+0x78/0x98 _genpd_power_off+0x40/0xc0 genpd_power_off+0x168/0x208 genpd_power_off+0x1e0/0x208 genpd_power_off+0x1e0/0x208 genpd_runtime_suspend+0x1ac/0x220 __rpm_callback+0x70/0xfc rpm_callback+0x34/0x8c rpm_suspend+0x218/0x4a4 __pm_runtime_suspend+0x88/0xac psci_enter_domain_idle_state+0x3c/0xb4 cpuidle_enter_state+0xb8/0x284 cpuidle_enter+0x38/0x4c call_cpuidle+0x3c/0x68 do_idle+0x194/0x260 cpu_startup_entry+0x24/0x28 secondary_start_kernel+0x150/0x15c Acked-by: Ulf Hansson Reviewed-by: Douglas Anderson Tested-by: Sai Prakash Ranjan Fixes: a65a397f2451 ("cpuidle: psci: Add support for PM domains by using genpd") Reported-by: Sai Prakash Ranjan Cc: Ulf Hansson Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20200115013751.249588-1-swboyd@chromium.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rpmh-rsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index e278fc11fe5c..b71822131f59 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -277,7 +277,7 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id, write_tcs_cmd(drv, RSC_DRV_CMD_MSGID, tcs_id, j, msgid); write_tcs_cmd(drv, RSC_DRV_CMD_ADDR, tcs_id, j, cmd->addr); write_tcs_cmd(drv, RSC_DRV_CMD_DATA, tcs_id, j, cmd->data); - trace_rpmh_send_msg(drv, tcs_id, j, msgid, cmd); + trace_rpmh_send_msg_rcuidle(drv, tcs_id, j, msgid, cmd); } write_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id, cmd_complete); From cc41a5273d69391995cbf104cac326fac9780dd1 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 9 Mar 2020 11:51:23 -0700 Subject: [PATCH 1343/4444] soc: qcom: socinfo: Use seq_putc() if possible This is a single character that we're printing out. Use seq_putc() for that to simplify the code. Cc: Vaishali Thakkar Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20200309185123.65265-1-swboyd@chromium.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 7864b75ce569..ebb49aee179b 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -277,7 +277,7 @@ static int show_image_##type(struct seq_file *seq, void *p) \ { \ struct smem_image_version *image_version = seq->private; \ seq_puts(seq, image_version->type); \ - seq_puts(seq, "\n"); \ + seq_putc(seq, '\n'); \ return 0; \ } \ static int open_image_##type(struct inode *inode, struct file *file) \ From 3bbf9e2f8624432d1f436bf13ddce1cf9db5238d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 9 Mar 2020 19:58:55 +0100 Subject: [PATCH 1344/4444] ALSA: pcm: oss: Simplify plugin frame size calculations Both snd_pcm_plug_client_size() and snd_pcm_plug_slave_size() do the almost same calculations of calling src_frames() and dst_frames() in the chain, but just to the different directions with each other. This patch simplifies those functions. Now they return -EINVAL for the invalid direction, but practically seen, there is no functional changes at all. Link: https://lore.kernel.org/r/20200309185855.15693-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/oss/pcm_plugin.c | 120 +++++++++++++++++------------------- 1 file changed, 56 insertions(+), 64 deletions(-) diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index c9401832967c..58642fecd15c 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c @@ -196,82 +196,74 @@ int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin) return 0; } +static snd_pcm_sframes_t calc_dst_frames(struct snd_pcm_substream *plug, + snd_pcm_sframes_t frames) +{ + struct snd_pcm_plugin *plugin, *plugin_next; + + plugin = snd_pcm_plug_first(plug); + while (plugin && frames > 0) { + plugin_next = plugin->next; + if (plugin->dst_frames) { + frames = plugin->dst_frames(plugin, frames); + if (frames < 0) + return frames; + } + if (frames > plugin->buf_frames) + frames = plugin->buf_frames; + plugin = plugin_next; + } + return frames; +} + +static snd_pcm_sframes_t calc_src_frames(struct snd_pcm_substream *plug, + snd_pcm_sframes_t frames) +{ + struct snd_pcm_plugin *plugin, *plugin_prev; + + plugin = snd_pcm_plug_last(plug); + while (plugin && frames > 0) { + if (frames > plugin->buf_frames) + frames = plugin->buf_frames; + plugin_prev = plugin->prev; + if (plugin->src_frames) { + frames = plugin->src_frames(plugin, frames); + if (frames < 0) + return frames; + } + plugin = plugin_prev; + } + return frames; +} + snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t drv_frames) { - struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next; - int stream; - if (snd_BUG_ON(!plug)) return -ENXIO; - if (drv_frames == 0) - return 0; - stream = snd_pcm_plug_stream(plug); - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - plugin = snd_pcm_plug_last(plug); - while (plugin && drv_frames > 0) { - if (drv_frames > plugin->buf_frames) - drv_frames = plugin->buf_frames; - plugin_prev = plugin->prev; - if (plugin->src_frames) - drv_frames = plugin->src_frames(plugin, drv_frames); - plugin = plugin_prev; - } - } else if (stream == SNDRV_PCM_STREAM_CAPTURE) { - plugin = snd_pcm_plug_first(plug); - while (plugin && drv_frames > 0) { - plugin_next = plugin->next; - if (plugin->dst_frames) - drv_frames = plugin->dst_frames(plugin, drv_frames); - if (drv_frames > plugin->buf_frames) - drv_frames = plugin->buf_frames; - plugin = plugin_next; - } - } else + switch (snd_pcm_plug_stream(plug)) { + case SNDRV_PCM_STREAM_PLAYBACK: + return calc_src_frames(plug, drv_frames); + case SNDRV_PCM_STREAM_CAPTURE: + return calc_dst_frames(plug, drv_frames); + default: snd_BUG(); - return drv_frames; + return -EINVAL; + } } snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t clt_frames) { - struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next; - snd_pcm_sframes_t frames; - int stream; - if (snd_BUG_ON(!plug)) return -ENXIO; - if (clt_frames == 0) - return 0; - frames = clt_frames; - stream = snd_pcm_plug_stream(plug); - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - plugin = snd_pcm_plug_first(plug); - while (plugin && frames > 0) { - plugin_next = plugin->next; - if (plugin->dst_frames) { - frames = plugin->dst_frames(plugin, frames); - if (frames < 0) - return frames; - } - if (frames > plugin->buf_frames) - frames = plugin->buf_frames; - plugin = plugin_next; - } - } else if (stream == SNDRV_PCM_STREAM_CAPTURE) { - plugin = snd_pcm_plug_last(plug); - while (plugin) { - if (frames > plugin->buf_frames) - frames = plugin->buf_frames; - plugin_prev = plugin->prev; - if (plugin->src_frames) { - frames = plugin->src_frames(plugin, frames); - if (frames < 0) - return frames; - } - plugin = plugin_prev; - } - } else + switch (snd_pcm_plug_stream(plug)) { + case SNDRV_PCM_STREAM_PLAYBACK: + return calc_dst_frames(plug, clt_frames); + case SNDRV_PCM_STREAM_CAPTURE: + return calc_src_frames(plug, clt_frames); + default: snd_BUG(); - return frames; + return -EINVAL; + } } static int snd_pcm_plug_formats(const struct snd_mask *mask, From 93d3ae352bb5cda928570cfa2247d9c529605bef Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 17 Feb 2020 16:55:06 +0100 Subject: [PATCH 1345/4444] ARM: bcm2835_defconfig: add support for Raspberry Pi4 Add drivers needed to boot Raspberry Pi4 board. Signed-off-by: Marek Szyprowski Link: https://lore.kernel.org/r/20200217155506.5245-1-m.szyprowski@samsung.com Signed-off-by: Nicolas Saenz Julienne --- arch/arm/configs/bcm2835_defconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig index 519ff58e67b3..38437541ea76 100644 --- a/arch/arm/configs/bcm2835_defconfig +++ b/arch/arm/configs/bcm2835_defconfig @@ -72,6 +72,7 @@ CONFIG_BLK_DEV_SD=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SCAN_ASYNC=y CONFIG_NETDEVICES=y +CONFIG_BCMGENET=y CONFIG_USB_LAN78XX=y CONFIG_USB_USBNET=y CONFIG_USB_NET_SMSC95XX=y @@ -96,9 +97,13 @@ CONFIG_SPI_BCM2835AUX=y CONFIG_GPIO_SYSFS=y CONFIG_SENSORS_RASPBERRYPI_HWMON=m CONFIG_THERMAL=y +CONFIG_BCM2711_THERMAL=y CONFIG_BCM2835_THERMAL=y CONFIG_WATCHDOG=y CONFIG_BCM2835_WDT=y +CONFIG_MFD_SYSCON=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_GPIO=y CONFIG_MEDIA_SUPPORT=y CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_DRM=y From 3498d9c05f804414c4645a2c0bba0187630fe5f0 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sat, 7 Mar 2020 21:54:45 -0800 Subject: [PATCH 1346/4444] arm64: dts: qcom: msm8998-mtp: Disable funnel 4 and 5 Disable Coresight funnel 4 and 5, for now, as these causes the MTP to crash when clock late_initcall disables unused clocks. Reviewed-by: Jeffrey Hugo Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20200308055445.1992189-1-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/msm8998-mtp.dtsi | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/msm8998-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8998-mtp.dtsi index 0e0b9bc12945..8a14b2bf7bca 100644 --- a/arch/arm64/boot/dts/qcom/msm8998-mtp.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8998-mtp.dtsi @@ -95,11 +95,15 @@ }; &funnel4 { - status = "okay"; + // FIXME: Figure out why clock late_initcall crashes the board with + // this enabled. + // status = "okay"; }; &funnel5 { - status = "okay"; + // FIXME: Figure out why clock late_initcall crashes the board with + // this enabled. + // status = "okay"; }; &pm8005_lsid1 { From cd87c180b301e8eb7eee916fe6bb972962fe6904 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sat, 8 Feb 2020 14:02:55 +0100 Subject: [PATCH 1347/4444] ARM: dts: bcm2711-rpi-4-b: Add SoC GPIO labels This adds the labels for all the SoC GPIOs on the Raspberry Pi 4. Signed-off-by: Stefan Wahren Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/1581166975-22949-5-git-send-email-stefan.wahren@i2se.com Signed-off-by: Nicolas Saenz Julienne --- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 73 +++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts index 1b5a835f66bd..cb3385262705 100644 --- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts +++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts @@ -71,6 +71,79 @@ }; }; +&gpio { + /* + * Parts taken from rpi_SCH_4b_4p0_reduced.pdf and + * the official GPU firmware DT blob. + * + * Legend: + * "FOO" = GPIO line named "FOO" on the schematic + * "FOO_N" = GPIO line named "FOO" on schematic, active low + */ + gpio-line-names = "ID_SDA", + "ID_SCL", + "SDA1", + "SCL1", + "GPIO_GCLK", + "GPIO5", + "GPIO6", + "SPI_CE1_N", + "SPI_CE0_N", + "SPI_MISO", + "SPI_MOSI", + "SPI_SCLK", + "GPIO12", + "GPIO13", + /* Serial port */ + "TXD1", + "RXD1", + "GPIO16", + "GPIO17", + "GPIO18", + "GPIO19", + "GPIO20", + "GPIO21", + "GPIO22", + "GPIO23", + "GPIO24", + "GPIO25", + "GPIO26", + "GPIO27", + "RGMII_MDIO", + "RGMIO_MDC", + /* Used by BT module */ + "CTS0", + "RTS0", + "TXD0", + "RXD0", + /* Used by Wifi */ + "SD1_CLK", + "SD1_CMD", + "SD1_DATA0", + "SD1_DATA1", + "SD1_DATA2", + "SD1_DATA3", + /* Shared with SPI flash */ + "PWM0_MISO", + "PWM1_MOSI", + "STATUS_LED_G_CLK", + "SPIFLASH_CE_N", + "SDA0", + "SCL0", + "RGMII_RXCLK", + "RGMII_RXCTL", + "RGMII_RXD0", + "RGMII_RXD1", + "RGMII_RXD2", + "RGMII_RXD3", + "RGMII_TXCLK", + "RGMII_TXCTL", + "RGMII_TXD0", + "RGMII_TXD1", + "RGMII_TXD2", + "RGMII_TXD3"; +}; + &pwm1 { pinctrl-names = "default"; pinctrl-0 = <&pwm1_0_gpio40 &pwm1_1_gpio41>; From 3ae09e2608c3bbd619605e35fd3f7b5f547aea3f Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Fri, 14 Feb 2020 19:31:11 +0100 Subject: [PATCH 1348/4444] ARM: qcom_defconfig: Enable QRTR This option is useful on msm8974, so enable it. Signed-off-by: Luca Weiss Link: https://lore.kernel.org/r/20200214183111.50919-1-luca@z3ntu.xyz Signed-off-by: Bjorn Andersson --- arch/arm/configs/qcom_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/qcom_defconfig b/arch/arm/configs/qcom_defconfig index a00765b7225f..c882167e1496 100644 --- a/arch/arm/configs/qcom_defconfig +++ b/arch/arm/configs/qcom_defconfig @@ -50,6 +50,8 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_XFRM_MODE_TUNNEL is not set # CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_IPV6 is not set +CONFIG_QRTR=m +CONFIG_QRTR_SMD=m CONFIG_BT=m CONFIG_BT_HCIUART=m CONFIG_BT_HCIUART_BCM=y From 3d2cbb64483691c8f8cf88e17d7d581d9402ac4b Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Wed, 4 Mar 2020 14:24:37 +0100 Subject: [PATCH 1349/4444] ARM: dts: bcm2711: Move emmc2 into its own bus Depending on bcm2711's revision its emmc2 controller might have different DMA constraints. Raspberry Pi 4's firmware will take care of updating those, but only if a certain alias is found in the device tree. So, move emmc2 into its own bus, so as not to pollute other devices with dma-ranges changes and create the emmc2bus alias. Based in Phil ELwell's downstream implementation. Signed-off-by: Nicolas Saenz Julienne Link: https://lore.kernel.org/r/20200304132437.20164-1-nsaenzjulienne@suse.de --- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 1 + arch/arm/boot/dts/bcm2711.dtsi | 25 ++++++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts index cb3385262705..e738de379b8d 100644 --- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts +++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts @@ -20,6 +20,7 @@ }; aliases { + emmc2bus = &emmc2bus; ethernet0 = &genet; }; diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi index d1e684d0acfd..a91cf68e3c4c 100644 --- a/arch/arm/boot/dts/bcm2711.dtsi +++ b/arch/arm/boot/dts/bcm2711.dtsi @@ -241,17 +241,32 @@ status = "disabled"; }; + hvs@7e400000 { + interrupts = ; + }; + }; + + /* + * emmc2 has different DMA constraints based on SoC revisions. It was + * moved into its own bus, so as for RPi4's firmware to update them. + * The firmware will find whether the emmc2bus alias is defined, and if + * so, it'll edit the dma-ranges property below accordingly. + */ + emmc2bus: emmc2bus { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <1>; + + ranges = <0x0 0x7e000000 0x0 0xfe000000 0x01800000>; + dma-ranges = <0x0 0xc0000000 0x0 0x00000000 0x40000000>; + emmc2: emmc2@7e340000 { compatible = "brcm,bcm2711-emmc2"; - reg = <0x7e340000 0x100>; + reg = <0x0 0x7e340000 0x100>; interrupts = ; clocks = <&clocks BCM2711_CLOCK_EMMC2>; status = "disabled"; }; - - hvs@7e400000 { - interrupts = ; - }; }; arm-pmu { From dad4e7fda4bdc1a6357db500a7bab8843c08e521 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Fri, 14 Feb 2020 18:12:32 -0800 Subject: [PATCH 1350/4444] clk: qcom: clk-rpmh: Wait for completion when enabling clocks The current implementation always uses rpmh_write_async, which doesn't wait for completion. That's fine for disable requests since there's no immediate need for the clocks and they can be disabled in the background. However, for enable requests we need to ensure the clocks are actually enabled before returning to the client. Otherwise, clients can end up accessing their HW before the necessary clocks are enabled, which can lead to bus errors. Use the synchronous version of this API (rpmh_write) for enable requests in the active set to ensure completion. Completion isn't required for sleep/wake sets, since they don't take effect until after we enter sleep. All rpmh requests are automatically flushed prior to entering sleep. Fixes: 9c7e47025a6b ("clk: qcom: clk-rpmh: Add QCOM RPMh clock driver") Signed-off-by: Mike Tipton Link: https://lkml.kernel.org/r/20200215021232.1149-1-mdtipton@codeaurora.org Reviewed-by: Bjorn Andersson [sboyd@kernel.org: Reorg code a bit for readability, rename to 'wait' to make local variable not conflict with completion.h mechanism] Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-rpmh.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c index 12bd8715dece..bfc29aec3a78 100644 --- a/drivers/clk/qcom/clk-rpmh.c +++ b/drivers/clk/qcom/clk-rpmh.c @@ -143,12 +143,22 @@ static inline bool has_state_changed(struct clk_rpmh *c, u32 state) != (c->aggr_state & BIT(state)); } +static int clk_rpmh_send(struct clk_rpmh *c, enum rpmh_state state, + struct tcs_cmd *cmd, bool wait) +{ + if (wait) + return rpmh_write(c->dev, state, cmd, 1); + + return rpmh_write_async(c->dev, state, cmd, 1); +} + static int clk_rpmh_send_aggregate_command(struct clk_rpmh *c) { struct tcs_cmd cmd = { 0 }; u32 cmd_state, on_val; enum rpmh_state state = RPMH_SLEEP_STATE; int ret; + bool wait; cmd.addr = c->res_addr; cmd_state = c->aggr_state; @@ -159,7 +169,8 @@ static int clk_rpmh_send_aggregate_command(struct clk_rpmh *c) if (cmd_state & BIT(state)) cmd.data = on_val; - ret = rpmh_write_async(c->dev, state, &cmd, 1); + wait = cmd_state && state == RPMH_ACTIVE_ONLY_STATE; + ret = clk_rpmh_send(c, state, &cmd, wait); if (ret) { dev_err(c->dev, "set %s state of %s failed: (%d)\n", !state ? "sleep" : @@ -267,7 +278,7 @@ static int clk_rpmh_bcm_send_cmd(struct clk_rpmh *c, bool enable) cmd.addr = c->res_addr; cmd.data = BCM_TCS_CMD(1, enable, 0, cmd_state); - ret = rpmh_write_async(c->dev, RPMH_ACTIVE_ONLY_STATE, &cmd, 1); + ret = clk_rpmh_send(c, RPMH_ACTIVE_ONLY_STATE, &cmd, enable); if (ret) { dev_err(c->dev, "set active state of %s failed: (%d)\n", c->res_name, ret); From 7d61e773c3ed8a4aea866eb287cc0191f9f35779 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 31 Oct 2019 12:29:50 +0100 Subject: [PATCH 1351/4444] clk: qcom: smd: Add support for MSM8976 rpm clocks Add rpm smd clocks, PMIC and bus clocks which are required on MSM8976, MSM8956 (and APQ variants) for clients to vote on. Signed-off-by: AngeloGioacchino Del Regno Link: https://lkml.kernel.org/r/20191031112951.35850-2-kholk11@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-smd-rpm.c | 50 ++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 0bbfef9fa6de..52f63ad787ba 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -525,6 +525,55 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8974 = { .num_clks = ARRAY_SIZE(msm8974_clks), }; + +/* msm8976 */ +DEFINE_CLK_SMD_RPM(msm8976, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8976, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); +DEFINE_CLK_SMD_RPM(msm8976, mmssnoc_ahb_clk, mmssnoc_ahb_a_clk, + QCOM_SMD_RPM_BUS_CLK, 2); +DEFINE_CLK_SMD_RPM(msm8976, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8976, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); +DEFINE_CLK_SMD_RPM_QDSS(msm8976, qdss_clk, qdss_a_clk, + QCOM_SMD_RPM_MISC_CLK, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8976, bb_clk1, bb_clk1_a, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8976, bb_clk2, bb_clk2_a, 2); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8976, rf_clk2, rf_clk2_a, 5); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8976, div_clk2, div_clk2_a, 12); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8976, bb_clk1_pin, bb_clk1_a_pin, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8976, bb_clk2_pin, bb_clk2_a_pin, 2); + +static struct clk_smd_rpm *msm8976_clks[] = { + [RPM_SMD_PCNOC_CLK] = &msm8976_pcnoc_clk, + [RPM_SMD_PCNOC_A_CLK] = &msm8976_pcnoc_a_clk, + [RPM_SMD_SNOC_CLK] = &msm8976_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8976_snoc_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8976_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8976_bimc_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8976_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8976_qdss_a_clk, + [RPM_SMD_BB_CLK1] = &msm8976_bb_clk1, + [RPM_SMD_BB_CLK1_A] = &msm8976_bb_clk1_a, + [RPM_SMD_BB_CLK2] = &msm8976_bb_clk2, + [RPM_SMD_BB_CLK2_A] = &msm8976_bb_clk2_a, + [RPM_SMD_RF_CLK2] = &msm8976_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &msm8976_rf_clk2_a, + [RPM_SMD_BB_CLK1_PIN] = &msm8976_bb_clk1_pin, + [RPM_SMD_BB_CLK1_A_PIN] = &msm8976_bb_clk1_a_pin, + [RPM_SMD_BB_CLK2_PIN] = &msm8976_bb_clk2_pin, + [RPM_SMD_BB_CLK2_A_PIN] = &msm8976_bb_clk2_a_pin, + [RPM_SMD_MMSSNOC_AHB_CLK] = &msm8976_mmssnoc_ahb_clk, + [RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8976_mmssnoc_ahb_a_clk, + [RPM_SMD_DIV_CLK2] = &msm8976_div_clk2, + [RPM_SMD_DIV_A_CLK2] = &msm8976_div_clk2_a, + [RPM_SMD_IPA_CLK] = &msm8976_ipa_clk, + [RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk, +}; + +static const struct rpm_smd_clk_desc rpm_clk_msm8976 = { + .clks = msm8976_clks, + .num_clks = ARRAY_SIZE(msm8976_clks), +}; + /* msm8996 */ DEFINE_CLK_SMD_RPM(msm8996, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); DEFINE_CLK_SMD_RPM(msm8996, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); @@ -720,6 +769,7 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8998 = { static const struct of_device_id rpm_smd_clk_match_table[] = { { .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 }, { .compatible = "qcom,rpmcc-msm8974", .data = &rpm_clk_msm8974 }, + { .compatible = "qcom,rpmcc-msm8976", .data = &rpm_clk_msm8976 }, { .compatible = "qcom,rpmcc-msm8996", .data = &rpm_clk_msm8996 }, { .compatible = "qcom,rpmcc-msm8998", .data = &rpm_clk_msm8998 }, { .compatible = "qcom,rpmcc-qcs404", .data = &rpm_clk_qcs404 }, From cd5d5d8dec5e08e3e6ded9fa8366750a203b1d2a Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 31 Oct 2019 12:29:51 +0100 Subject: [PATCH 1352/4444] dt-bindings: clock: rpmcc: Document msm8976 compatible Support for MSM8976 was added to the clk-smd-rpm driver: let's document here the newly added compatible string. Signed-off-by: AngeloGioacchino Del Regno Link: https://lkml.kernel.org/r/20191031112951.35850-3-kholk11@gmail.com Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/qcom,rpmcc.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt index 944719bd586f..356cabcd844d 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt +++ b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt @@ -14,6 +14,7 @@ Required properties : "qcom,rpmcc-apq8060", "qcom,rpmcc" "qcom,rpmcc-msm8916", "qcom,rpmcc" "qcom,rpmcc-msm8974", "qcom,rpmcc" + "qcom,rpmcc-msm8976", "qcom,rpmcc" "qcom,rpmcc-apq8064", "qcom,rpmcc" "qcom,rpmcc-msm8996", "qcom,rpmcc" "qcom,rpmcc-msm8998", "qcom,rpmcc" From aec54ec0c845b05dce00bf0f45d617fbb380cf0c Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 17 Jan 2020 17:08:45 -0600 Subject: [PATCH 1353/4444] ARM: dts: at91: Kill off "simple-panel" compatibles "simple-panel" is a Linux driver and has never been an accepted upstream compatible string, so remove it. Cc: Nicolas Ferre Cc: Alexandre Belloni Cc: Ludovic Desroches Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20200117230845.25190-1-robh@kernel.org Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/at91-dvk_su60_somc_lcm.dtsi | 2 +- arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts | 2 +- arch/arm/boot/dts/at91sam9n12ek.dts | 2 +- arch/arm/boot/dts/at91sam9x5dm.dtsi | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/at91-dvk_su60_somc_lcm.dtsi b/arch/arm/boot/dts/at91-dvk_su60_somc_lcm.dtsi index df0f0cc575c1..bea920b192b6 100644 --- a/arch/arm/boot/dts/at91-dvk_su60_somc_lcm.dtsi +++ b/arch/arm/boot/dts/at91-dvk_su60_somc_lcm.dtsi @@ -17,7 +17,7 @@ }; panel: panel { - compatible = "winstar,wf70gtiagdng0", "innolux,at070tn92", "simple-panel"; + compatible = "winstar,wf70gtiagdng0", "innolux,at070tn92"; backlight = <&backlight>; power-supply = <&vcc_lcd_reg>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts b/arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts index af4969485c88..4d7cee569ff2 100644 --- a/arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts +++ b/arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts @@ -136,7 +136,7 @@ panel: panel { /* Actually Ampire 800480R2 */ - compatible = "foxlink,fl500wvr00-a0t", "simple-panel"; + compatible = "foxlink,fl500wvr00-a0t"; backlight = <&backlight>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts index ea5cef0b0974..d36e162a8817 100644 --- a/arch/arm/boot/dts/at91sam9n12ek.dts +++ b/arch/arm/boot/dts/at91sam9n12ek.dts @@ -238,7 +238,7 @@ }; panel: panel { - compatible = "qiaodian,qd43003c0-40", "simple-panel"; + compatible = "qiaodian,qd43003c0-40"; backlight = <&backlight>; power-supply = <&panel_reg>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/at91sam9x5dm.dtsi b/arch/arm/boot/dts/at91sam9x5dm.dtsi index 7f00c1f57b90..a9278038af3b 100644 --- a/arch/arm/boot/dts/at91sam9x5dm.dtsi +++ b/arch/arm/boot/dts/at91sam9x5dm.dtsi @@ -27,7 +27,7 @@ }; panel: panel { - compatible = "foxlink,fl500wvr00-a0t", "simple-panel"; + compatible = "foxlink,fl500wvr00-a0t"; backlight = <&backlight>; power-supply = <&panel_reg>; #address-cells = <1>; From 278af803475ec9dbdc2e8dfd87aa48c4660fd4c9 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Tue, 11 Feb 2020 08:07:14 +0000 Subject: [PATCH 1354/4444] ARM: dts: at91: sam9x60: add watchdog node Add node for watchdog timer. Signed-off-by: Eugen Hristev Link: https://lore.kernel.org/r/1581408369-14469-1-git-send-email-eugen.hristev@microchip.com Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/sam9x60.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/sam9x60.dtsi b/arch/arm/boot/dts/sam9x60.dtsi index 326b39328b58..6763423d64b8 100644 --- a/arch/arm/boot/dts/sam9x60.dtsi +++ b/arch/arm/boot/dts/sam9x60.dtsi @@ -686,6 +686,14 @@ interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; clocks = <&clk32k 0>; }; + + watchdog: watchdog@ffffff80 { + compatible = "microchip,sam9x60-wdt"; + reg = <0xffffff80 0x24>; + interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; + clocks = <&clk32k 0>; + status = "disabled"; + }; }; }; }; From 4d8353bd0da268faee34fa53853209022eb9f040 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Tue, 11 Feb 2020 08:07:14 +0000 Subject: [PATCH 1355/4444] ARM: dts: at91: sam9x60ek: enable watchdog node Enable node for watchdog timer Signed-off-by: Eugen Hristev Link: https://lore.kernel.org/r/1581408369-14469-2-git-send-email-eugen.hristev@microchip.com Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/at91-sam9x60ek.dts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/at91-sam9x60ek.dts b/arch/arm/boot/dts/at91-sam9x60ek.dts index 9f30132d7d7b..b484745bf2d4 100644 --- a/arch/arm/boot/dts/at91-sam9x60ek.dts +++ b/arch/arm/boot/dts/at91-sam9x60ek.dts @@ -645,3 +645,8 @@ &usb2 { status = "okay"; }; + +&watchdog { + status = "okay"; +}; + From bb502976653a833e76b997519d43cfeb599c8d40 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sun, 29 Dec 2019 21:44:20 +0100 Subject: [PATCH 1356/4444] ARM: dts: at91: sama5d2: use correct rtc compatible Use the sama5d2 specific compatible string for the RTC. Link: https://lore.kernel.org/r/20191229204421.337612-8-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/sama5d2.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi index 2012b7407c60..ab550d69db91 100644 --- a/arch/arm/boot/dts/sama5d2.dtsi +++ b/arch/arm/boot/dts/sama5d2.dtsi @@ -695,7 +695,7 @@ }; rtc: rtc@f80480b0 { - compatible = "atmel,at91rm9200-rtc"; + compatible = "atmel,sama5d2-rtc"; reg = <0xf80480b0 0x30>; interrupts = <74 IRQ_TYPE_LEVEL_HIGH 7>; clocks = <&clk32k>; From 761f6ed85417147cf02e65c37354c1d8ea767dd7 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sun, 29 Dec 2019 21:44:21 +0100 Subject: [PATCH 1357/4444] ARM: dts: at91: sama5d4: use correct rtc compatible Use the sama5d4 specific compatible string for the RTC. Link: https://lore.kernel.org/r/20191229204421.337612-9-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/sama5d4.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sama5d4.dtsi b/arch/arm/boot/dts/sama5d4.dtsi index 6ab27a7b388d..e9a8f82a6eda 100644 --- a/arch/arm/boot/dts/sama5d4.dtsi +++ b/arch/arm/boot/dts/sama5d4.dtsi @@ -884,7 +884,7 @@ }; rtc@fc0686b0 { - compatible = "atmel,at91rm9200-rtc"; + compatible = "atmel,sama5d4-rtc"; reg = <0xfc0686b0 0x30>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; clocks = <&clk32k>; From a4bd8da893a375165197df8315d69ec95aa7e51a Mon Sep 17 00:00:00 2001 From: Kamel Bouhara Date: Tue, 25 Feb 2020 17:50:10 +0200 Subject: [PATCH 1358/4444] ARM: dts: at91: sama5d3: add i2c gpio pinctrl Add the i2c gpio pinctrls to support the i2c bus recovery Signed-off-by: Kamel Bouhara [codrin.ciubotariu@microchip.com: removed gpio pull-ups] Signed-off-by: Codrin Ciubotariu Acked-by: Ludovic Desroches Link: https://lore.kernel.org/r/20200225155012.22764-2-codrin.ciubotariu@microchip.com Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/sama5d3.dtsi | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi index 203d40be70a5..f11b018e9173 100644 --- a/arch/arm/boot/dts/sama5d3.dtsi +++ b/arch/arm/boot/dts/sama5d3.dtsi @@ -159,8 +159,11 @@ dmas = <&dma0 2 AT91_DMA_CFG_PER_ID(7)>, <&dma0 2 AT91_DMA_CFG_PER_ID(8)>; dma-names = "tx", "rx"; - pinctrl-names = "default"; + pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c0>; + pinctrl-1 = <&pinctrl_i2c0_gpio>; + sda-gpios = <&pioA 30 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioA 31 GPIO_ACTIVE_HIGH>; #address-cells = <1>; #size-cells = <0>; clocks = <&twi0_clk>; @@ -174,8 +177,11 @@ dmas = <&dma0 2 AT91_DMA_CFG_PER_ID(9)>, <&dma0 2 AT91_DMA_CFG_PER_ID(10)>; dma-names = "tx", "rx"; - pinctrl-names = "default"; + pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c1>; + pinctrl-1 = <&pinctrl_i2c1_gpio>; + sda-gpios = <&pioC 26 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioC 27 GPIO_ACTIVE_HIGH>; #address-cells = <1>; #size-cells = <0>; clocks = <&twi1_clk>; @@ -357,8 +363,11 @@ dmas = <&dma1 2 AT91_DMA_CFG_PER_ID(11)>, <&dma1 2 AT91_DMA_CFG_PER_ID(12)>; dma-names = "tx", "rx"; - pinctrl-names = "default"; + pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c2>; + pinctrl-1 = <&pinctrl_i2c2_gpio>; + sda-gpios = <&pioA 18 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioA 19 GPIO_ACTIVE_HIGH>; #address-cells = <1>; #size-cells = <0>; clocks = <&twi2_clk>; @@ -639,6 +648,12 @@ ; /* PA31 periph A TWCK0 pin, conflicts with UTXD1, ISI_HSYNC */ }; + + pinctrl_i2c0_gpio: i2c0-gpio { + atmel,pins = + ; + }; }; i2c1 { @@ -647,6 +662,12 @@ ; /* PC27 periph B TWCK1 pin, conflicts with SPI1_NPCS2, ISI_D10 */ }; + + pinctrl_i2c1_gpio: i2c1-gpio { + atmel,pins = + ; + }; }; i2c2 { @@ -655,6 +676,12 @@ ; /* TWCK2 pin, conflicts with LCDDAT19, ISI_D3 */ }; + + pinctrl_i2c2_gpio: i2c2-gpio { + atmel,pins = + ; + }; }; isi { From 8fb82f050cf696989cceb09fc503e69f406d28de Mon Sep 17 00:00:00 2001 From: Kamel Bouhara Date: Tue, 25 Feb 2020 17:50:11 +0200 Subject: [PATCH 1359/4444] ARM: dts: at91: sama5d4: add i2c gpio pinctrl Add the i2c gpio pinctrls so the i2c bus recovery option can be enabled Signed-off-by: Kamel Bouhara [codrin.ciubotariu@microchip.com: removed gpio pull-ups] Signed-off-by: Codrin Ciubotariu Acked-by: Ludovic Desroches Link: https://lore.kernel.org/r/20200225155012.22764-3-codrin.ciubotariu@microchip.com Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/sama5d4.dtsi | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/sama5d4.dtsi b/arch/arm/boot/dts/sama5d4.dtsi index e9a8f82a6eda..c9c0316b5b0e 100644 --- a/arch/arm/boot/dts/sama5d4.dtsi +++ b/arch/arm/boot/dts/sama5d4.dtsi @@ -458,8 +458,11 @@ (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(3))>; dma-names = "tx", "rx"; - pinctrl-names = "default"; + pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c0>; + pinctrl-1 = <&pinctrl_i2c0_gpio>; + sda-gpios = <&pioA 30 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioA 31 GPIO_ACTIVE_HIGH>; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 32>; @@ -477,8 +480,11 @@ (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(5))>; dma-names = "tx", "rx"; - pinctrl-names = "default"; + pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c1>; + pinctrl-1 = <&pinctrl_i2c1_gpio>; + sda-gpios = <&pioE 29 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioE 30 GPIO_ACTIVE_HIGH>; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 33>; @@ -519,8 +525,11 @@ (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(7))>; dma-names = "tx", "rx"; - pinctrl-names = "default"; + pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c2>; + pinctrl-1 = <&pinctrl_i2c2_gpio>; + sda-gpios = <&pioB 29 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioB 30 GPIO_ACTIVE_HIGH>; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 34>; @@ -1122,6 +1131,12 @@ ; }; + + pinctrl_i2c0_gpio: i2c0-gpio { + atmel,pins = + ; + }; }; i2c1 { @@ -1130,6 +1145,12 @@ ; /* TWCK1, conflicts with UART0 TX and DIBN */ }; + + pinctrl_i2c1_gpio: i2c1-gpio { + atmel,pins = + ; + }; }; i2c2 { @@ -1138,6 +1159,12 @@ ; /* TWCK2, conflicts with RF0 */ }; + + pinctrl_i2c2_gpio: i2c2-gpio { + atmel,pins = + ; + }; }; isi { From 455fec938bbbe64210da0a10f0aaa7d97c8b31b0 Mon Sep 17 00:00:00 2001 From: Kamel Bouhara Date: Tue, 25 Feb 2020 17:50:12 +0200 Subject: [PATCH 1360/4444] ARM: dts: at91: sama5d2: add i2c gpio pinctrl Add the i2c gpio pinctrls to support the i2c bus recovery Signed-off-by: Kamel Bouhara [codrin.ciubotariu@microchip.com: removed gpio pull-ups] Signed-off-by: Codrin Ciubotariu Acked-by: Ludovic Desroches Link: https://lore.kernel.org/r/20200225155012.22764-4-codrin.ciubotariu@microchip.com Signed-off-by: Alexandre Belloni --- arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts | 33 +++++++++++++++++++-- arch/arm/boot/dts/at91-sama5d2_xplained.dts | 33 +++++++++++++++++++-- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts b/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts index ba7f3e646c26..1c24ac8019ba 100644 --- a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts +++ b/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts @@ -180,8 +180,11 @@ i2c0: i2c@f8028000 { dmas = <0>, <0>; - pinctrl-names = "default"; + pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c0_default>; + pinctrl-1 = <&pinctrl_i2c0_gpio>; + sda-gpios = <&pioA PIN_PD21 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioA PIN_PD22 GPIO_ACTIVE_HIGH>; status = "okay"; }; @@ -198,8 +201,11 @@ #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 19>; - pinctrl-names = "default"; + pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_flx0_default>; + pinctrl-1 = <&pinctrl_flx0_gpio>; + sda-gpios = <&pioA PIN_PB28 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioA PIN_PB29 GPIO_ACTIVE_HIGH>; atmel,fifo-size = <16>; status = "okay"; }; @@ -226,8 +232,11 @@ i2c1: i2c@fc028000 { dmas = <0>, <0>; - pinctrl-names = "default"; + pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c1_default>; + pinctrl-1 = <&pinctrl_i2c1_gpio>; + sda-gpios = <&pioA PIN_PC6 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioA PIN_PC7 GPIO_ACTIVE_HIGH>; status = "okay"; at24@50 { @@ -244,18 +253,36 @@ bias-disable; }; + pinctrl_flx0_gpio: flx0_gpio { + pinmux = , + ; + bias-disable; + }; + pinctrl_i2c0_default: i2c0_default { pinmux = , ; bias-disable; }; + pinctrl_i2c0_gpio: i2c0_gpio { + pinmux = , + ; + bias-disable; + }; + pinctrl_i2c1_default: i2c1_default { pinmux = , ; bias-disable; }; + pinctrl_i2c1_gpio: i2c1_gpio { + pinmux = , + ; + bias-disable; + }; + pinctrl_key_gpio_default: key_gpio_default { pinmux = ; bias-pull-up; diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts index 9d0a7fbea725..055ee53e4773 100644 --- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts @@ -129,8 +129,11 @@ i2c0: i2c@f8028000 { dmas = <0>, <0>; - pinctrl-names = "default"; + pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c0_default>; + pinctrl-1 = <&pinctrl_i2c0_gpio>; + sda-gpios = <&pioA PIN_PD21 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioA PIN_PD22 GPIO_ACTIVE_HIGH>; i2c-sda-hold-time-ns = <350>; status = "okay"; @@ -331,8 +334,11 @@ #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 23>; - pinctrl-names = "default"; + pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_flx4_default>; + pinctrl-1 = <&pinctrl_flx4_gpio>; + sda-gpios = <&pioA PIN_PD12 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioA PIN_PD13 GPIO_ACTIVE_HIGH>; atmel,fifo-size = <16>; i2c-analog-filter; i2c-digital-filter; @@ -343,11 +349,14 @@ i2c1: i2c@fc028000 { dmas = <0>, <0>; - pinctrl-names = "default"; + pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c1_default>; i2c-analog-filter; i2c-digital-filter; i2c-digital-filter-width-ns = <35>; + pinctrl-1 = <&pinctrl_i2c1_gpio>; + sda-gpios = <&pioA PIN_PD4 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioA PIN_PD5 GPIO_ACTIVE_HIGH>; status = "okay"; at24@54 { @@ -441,18 +450,36 @@ bias-disable; }; + pinctrl_flx4_gpio: flx4_gpio { + pinmux = , + ; + bias-disable; + }; + pinctrl_i2c0_default: i2c0_default { pinmux = , ; bias-disable; }; + pinctrl_i2c0_gpio: i2c0_gpio { + pinmux = , + ; + bias-disable; + }; + pinctrl_i2c1_default: i2c1_default { pinmux = , ; bias-disable; }; + pinctrl_i2c1_gpio: i2c1_gpio { + pinmux = , + ; + bias-disable; + }; + pinctrl_i2s0_default: i2s0_default { pinmux = , , From 06320cedc8971c2994c323de91b5b424fdfc5a19 Mon Sep 17 00:00:00 2001 From: Sean V Kelley Date: Thu, 20 Feb 2020 11:29:30 -0800 Subject: [PATCH 1361/4444] Documentation: PCI: Add background on Boot Interrupts Improve understanding of the PCI quirks for this legacy PCI interrupt behavior to the benefit of developers and users alike. Link: https://lore.kernel.org/r/20200220192930.64820-3-sean.v.kelley@linux.intel.com Signed-off-by: Sean V Kelley Signed-off-by: Bjorn Helgaas Reviewed-by: Thomas Gleixner --- Documentation/PCI/boot-interrupts.rst | 155 ++++++++++++++++++++++++++ Documentation/PCI/index.rst | 1 + 2 files changed, 156 insertions(+) create mode 100644 Documentation/PCI/boot-interrupts.rst diff --git a/Documentation/PCI/boot-interrupts.rst b/Documentation/PCI/boot-interrupts.rst new file mode 100644 index 000000000000..d078ef3eb192 --- /dev/null +++ b/Documentation/PCI/boot-interrupts.rst @@ -0,0 +1,155 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=============== +Boot Interrupts +=============== + +:Author: - Sean V Kelley + +Overview +======== + +On PCI Express, interrupts are represented with either MSI or inbound +interrupt messages (Assert_INTx/Deassert_INTx). The integrated IO-APIC in a +given Core IO converts the legacy interrupt messages from PCI Express to +MSI interrupts. If the IO-APIC is disabled (via the mask bits in the +IO-APIC table entries), the messages are routed to the legacy PCH. This +in-band interrupt mechanism was traditionally necessary for systems that +did not support the IO-APIC and for boot. Intel in the past has used the +term "boot interrupts" to describe this mechanism. Further, the PCI Express +protocol describes this in-band legacy wire-interrupt INTx mechanism for +I/O devices to signal PCI-style level interrupts. The subsequent paragraphs +describe problems with the Core IO handling of INTx message routing to the +PCH and mitigation within BIOS and the OS. + + +Issue +===== + +When in-band legacy INTx messages are forwarded to the PCH, they in turn +trigger a new interrupt for which the OS likely lacks a handler. When an +interrupt goes unhandled over time, they are tracked by the Linux kernel as +Spurious Interrupts. The IRQ will be disabled by the Linux kernel after it +reaches a specific count with the error "nobody cared". This disabled IRQ +now prevents valid usage by an existing interrupt which may happen to share +the IRQ line. + + irq 19: nobody cared (try booting with the "irqpoll" option) + CPU: 0 PID: 2988 Comm: irq/34-nipalk Tainted: 4.14.87-rt49-02410-g4a640ec-dirty #1 + Hardware name: National Instruments NI PXIe-8880/NI PXIe-8880, BIOS 2.1.5f1 01/09/2020 + Call Trace: + + ? dump_stack+0x46/0x5e + ? __report_bad_irq+0x2e/0xb0 + ? note_interrupt+0x242/0x290 + ? nNIKAL100_memoryRead16+0x8/0x10 [nikal] + ? handle_irq_event_percpu+0x55/0x70 + ? handle_irq_event+0x4f/0x80 + ? handle_fasteoi_irq+0x81/0x180 + ? handle_irq+0x1c/0x30 + ? do_IRQ+0x41/0xd0 + ? common_interrupt+0x84/0x84 + + + handlers: + irq_default_primary_handler threaded usb_hcd_irq + Disabling IRQ #19 + + +Conditions +========== + +The use of threaded interrupts is the most likely condition to trigger +this problem today. Threaded interrupts may not be reenabled after the IRQ +handler wakes. These "one shot" conditions mean that the threaded interrupt +needs to keep the interrupt line masked until the threaded handler has run. +Especially when dealing with high data rate interrupts, the thread needs to +run to completion; otherwise some handlers will end up in stack overflows +since the interrupt of the issuing device is still active. + +Affected Chipsets +================= + +The legacy interrupt forwarding mechanism exists today in a number of +devices including but not limited to chipsets from AMD/ATI, Broadcom, and +Intel. Changes made through the mitigations below have been applied to +drivers/pci/quirks.c + +Starting with ICX there are no longer any IO-APICs in the Core IO's +devices. IO-APIC is only in the PCH. Devices connected to the Core IO's +PCIe Root Ports will use native MSI/MSI-X mechanisms. + +Mitigations +=========== + +The mitigations take the form of PCI quirks. The preference has been to +first identify and make use of a means to disable the routing to the PCH. +In such a case a quirk to disable boot interrupt generation can be +added.[1] + + Intel® 6300ESB I/O Controller Hub + Alternate Base Address Register: + BIE: Boot Interrupt Enable + 0 = Boot interrupt is enabled. + 1 = Boot interrupt is disabled. + + Intel® Sandy Bridge through Sky Lake based Xeon servers: + Coherent Interface Protocol Interrupt Control + dis_intx_route2pch/dis_intx_route2ich/dis_intx_route2dmi2: + When this bit is set. Local INTx messages received from the + Intel® Quick Data DMA/PCI Express ports are not routed to legacy + PCH - they are either converted into MSI via the integrated IO-APIC + (if the IO-APIC mask bit is clear in the appropriate entries) + or cause no further action (when mask bit is set) + +In the absence of a way to directly disable the routing, another approach +has been to make use of PCI Interrupt pin to INTx routing tables for +purposes of redirecting the interrupt handler to the rerouted interrupt +line by default. Therefore, on chipsets where this INTx routing cannot be +disabled, the Linux kernel will reroute the valid interrupt to its legacy +interrupt. This redirection of the handler will prevent the occurrence of +the spurious interrupt detection which would ordinarily disable the IRQ +line due to excessive unhandled counts.[2] + +The config option X86_REROUTE_FOR_BROKEN_BOOT_IRQS exists to enable (or +disable) the redirection of the interrupt handler to the PCH interrupt +line. The option can be overridden by either pci=ioapicreroute or +pci=noioapicreroute.[3] + + +More Documentation +================== + +There is an overview of the legacy interrupt handling in several datasheets +(6300ESB and 6700PXH below). While largely the same, it provides insight +into the evolution of its handling with chipsets. + +Example of disabling of the boot interrupt +------------------------------------------ + +Intel® 6300ESB I/O Controller Hub (Document # 300641-004US) + 5.7.3 Boot Interrupt + https://www.intel.com/content/dam/doc/datasheet/6300esb-io-controller-hub-datasheet.pdf + +Intel® Xeon® Processor E5-1600/2400/2600/4600 v3 Product Families +Datasheet - Volume 2: Registers (Document # 330784-003) + 6.6.41 cipintrc Coherent Interface Protocol Interrupt Control + https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e5-v3-datasheet-vol-2.pdf + +Example of handler rerouting +---------------------------- + +Intel® 6700PXH 64-bit PCI Hub (Document # 302628) + 2.15.2 PCI Express Legacy INTx Support and Boot Interrupt + https://www.intel.com/content/dam/doc/datasheet/6700pxh-64-bit-pci-hub-datasheet.pdf + + +If you have any legacy PCI interrupt questions that aren't answered, email me. + +Cheers, + Sean V Kelley + sean.v.kelley@linux.intel.com + +[1] https://lore.kernel.org/r/12131949181903-git-send-email-sassmann@suse.de/ +[2] https://lore.kernel.org/r/12131949182094-git-send-email-sassmann@suse.de/ +[3] https://lore.kernel.org/r/487C8EA7.6020205@suse.de/ diff --git a/Documentation/PCI/index.rst b/Documentation/PCI/index.rst index 6768305e4c26..8f66feaafd4f 100644 --- a/Documentation/PCI/index.rst +++ b/Documentation/PCI/index.rst @@ -16,3 +16,4 @@ Linux PCI Bus Subsystem pci-error-recovery pcieaer-howto endpoint/index + boot-interrupts From 57d98e8e75bd6137a4e993913464c07802593d03 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 24 Feb 2020 10:19:59 +0530 Subject: [PATCH 1362/4444] clk: qcom: clk-alpha-pll: Use common names for defines The PLL run and standby modes are similar across the PLLs, thus rename them to common names and update the use of these. Signed-off-by: Taniya Das Signed-off-by: Venkata Narendra Kumar Gutta Signed-off-by: Vinod Koul Link: https://lkml.kernel.org/r/20200224045003.3783838-2-vkoul@kernel.org Reviewed-by: Bryan O'Donoghue Tested-by: Bryan O'Donoghue Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-alpha-pll.c | 40 ++++++++++++++------------------ 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 6d946770a80f..0bdf6e45fac9 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -134,15 +134,10 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); #define PLL_HUAYRA_N_MASK 0xff #define PLL_HUAYRA_ALPHA_WIDTH 16 -#define FABIA_OPMODE_STANDBY 0x0 -#define FABIA_OPMODE_RUN 0x1 - -#define FABIA_PLL_OUT_MASK 0x7 -#define FABIA_PLL_RATE_MARGIN 500 - -#define TRION_PLL_STANDBY 0x0 -#define TRION_PLL_RUN 0x1 -#define TRION_PLL_OUT_MASK 0x7 +#define PLL_STANDBY 0x0 +#define PLL_RUN 0x1 +#define PLL_OUT_MASK 0x7 +#define PLL_RATE_MARGIN 500 #define pll_alpha_width(p) \ ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \ @@ -766,7 +761,7 @@ static int trion_pll_is_enabled(struct clk_alpha_pll *pll, if (ret) return 0; - return ((opmode_regval & TRION_PLL_RUN) && (mode_regval & PLL_OUTCTRL)); + return ((opmode_regval & PLL_RUN) && (mode_regval & PLL_OUTCTRL)); } static int clk_trion_pll_is_enabled(struct clk_hw *hw) @@ -796,7 +791,7 @@ static int clk_trion_pll_enable(struct clk_hw *hw) } /* Set operation mode to RUN */ - regmap_write(regmap, PLL_OPMODE(pll), TRION_PLL_RUN); + regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN); ret = wait_for_pll_enable_lock(pll); if (ret) @@ -804,7 +799,7 @@ static int clk_trion_pll_enable(struct clk_hw *hw) /* Enable the PLL outputs */ ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), - TRION_PLL_OUT_MASK, TRION_PLL_OUT_MASK); + PLL_OUT_MASK, PLL_OUT_MASK); if (ret) return ret; @@ -837,12 +832,12 @@ static void clk_trion_pll_disable(struct clk_hw *hw) /* Disable the PLL outputs */ ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), - TRION_PLL_OUT_MASK, 0); + PLL_OUT_MASK, 0); if (ret) return; /* Place the PLL mode in STANDBY */ - regmap_write(regmap, PLL_OPMODE(pll), TRION_PLL_STANDBY); + regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); } @@ -1089,14 +1084,14 @@ static int alpha_pll_fabia_enable(struct clk_hw *hw) return ret; /* Skip If PLL is already running */ - if ((opmode_val & FABIA_OPMODE_RUN) && (val & PLL_OUTCTRL)) + if ((opmode_val & PLL_RUN) && (val & PLL_OUTCTRL)) return 0; ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); if (ret) return ret; - ret = regmap_write(regmap, PLL_OPMODE(pll), FABIA_OPMODE_STANDBY); + ret = regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); if (ret) return ret; @@ -1105,7 +1100,7 @@ static int alpha_pll_fabia_enable(struct clk_hw *hw) if (ret) return ret; - ret = regmap_write(regmap, PLL_OPMODE(pll), FABIA_OPMODE_RUN); + ret = regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN); if (ret) return ret; @@ -1114,7 +1109,7 @@ static int alpha_pll_fabia_enable(struct clk_hw *hw) return ret; ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), - FABIA_PLL_OUT_MASK, FABIA_PLL_OUT_MASK); + PLL_OUT_MASK, PLL_OUT_MASK); if (ret) return ret; @@ -1144,13 +1139,12 @@ static void alpha_pll_fabia_disable(struct clk_hw *hw) return; /* Disable main outputs */ - ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), FABIA_PLL_OUT_MASK, - 0); + ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, 0); if (ret) return; /* Place the PLL in STANDBY */ - regmap_write(regmap, PLL_OPMODE(pll), FABIA_OPMODE_STANDBY); + regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); } static unsigned long alpha_pll_fabia_recalc_rate(struct clk_hw *hw, @@ -1171,7 +1165,7 @@ static int alpha_pll_fabia_set_rate(struct clk_hw *hw, unsigned long rate, struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); u32 l, alpha_width = pll_alpha_width(pll); u64 a; - unsigned long rrate, max = rate + FABIA_PLL_RATE_MARGIN; + unsigned long rrate, max = rate + PLL_RATE_MARGIN; rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); @@ -1230,7 +1224,7 @@ static int alpha_pll_fabia_prepare(struct clk_hw *hw) * Due to a limited number of bits for fractional rate programming, the * rounded up rate could be marginally higher than the requested rate. */ - if (rrate > (cal_freq + FABIA_PLL_RATE_MARGIN) || rrate < cal_freq) + if (rrate > (cal_freq + PLL_RATE_MARGIN) || rrate < cal_freq) return -EINVAL; /* Setup PLL for calibration frequency */ From ee4adbbc9087eb22bca631fb6efb93c62f1761b1 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 24 Feb 2020 10:20:00 +0530 Subject: [PATCH 1363/4444] clk: qcom: clk-alpha-pll: Refactor trion PLL Remove duplicate function for calculating the round rate of PLL and also update the trion pll ops to use the common function. Signed-off-by: Taniya Das Signed-off-by: Venkata Narendra Kumar Gutta Signed-off-by: Vinod Koul Link: https://lkml.kernel.org/r/20200224045003.3783838-3-vkoul@kernel.org Reviewed-by: Bryan O'Donoghue Tested-by: Bryan O'Donoghue Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-alpha-pll.c | 33 ++++++-------------------------- 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 0bdf6e45fac9..0adec585eb4f 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -845,33 +845,12 @@ static unsigned long clk_trion_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); - struct regmap *regmap = pll->clkr.regmap; - u32 l, frac; - u64 prate = parent_rate; + u32 l, frac, alpha_width = pll_alpha_width(pll); - regmap_read(regmap, PLL_L_VAL(pll), &l); - regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac); + regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); + regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &frac); - return alpha_pll_calc_rate(prate, l, frac, ALPHA_REG_16BIT_WIDTH); -} - -static long clk_trion_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); - unsigned long min_freq, max_freq; - u32 l; - u64 a; - - rate = alpha_pll_round_rate(rate, *prate, - &l, &a, ALPHA_REG_16BIT_WIDTH); - if (!pll->vco_table || alpha_pll_find_vco(pll, rate)) - return rate; - - min_freq = pll->vco_table[0].min_freq; - max_freq = pll->vco_table[pll->num_vco - 1].max_freq; - - return clamp(rate, min_freq, max_freq); + return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width); } const struct clk_ops clk_alpha_pll_fixed_ops = { @@ -917,7 +896,7 @@ const struct clk_ops clk_trion_fixed_pll_ops = { .disable = clk_trion_pll_disable, .is_enabled = clk_trion_pll_is_enabled, .recalc_rate = clk_trion_pll_recalc_rate, - .round_rate = clk_trion_pll_round_rate, + .round_rate = clk_alpha_pll_round_rate, }; EXPORT_SYMBOL_GPL(clk_trion_fixed_pll_ops); @@ -1173,7 +1152,7 @@ static int alpha_pll_fabia_set_rate(struct clk_hw *hw, unsigned long rate, * Due to limited number of bits for fractional rate programming, the * rounded up rate could be marginally higher than the requested rate. */ - if (rrate > max || rrate < rate) { + if (rrate > (rate + PLL_RATE_MARGIN) || rrate < rate) { pr_err("%s: Rounded rate %lu not within range [%lu, %lu)\n", clk_hw_get_name(hw), rrate, rate, max); return -EINVAL; From 59128c20a6a98ee454e5ad23fe28dc84d23b6234 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 24 Feb 2020 10:20:01 +0530 Subject: [PATCH 1364/4444] clk: qcom: clk-alpha-pll: Add support for controlling Lucid PLLs Add programming sequence support for managing the Lucid PLLs. Signed-off-by: Taniya Das Signed-off-by: Venkata Narendra Kumar Gutta Signed-off-by: Vinod Koul Link: https://lkml.kernel.org/r/20200224045003.3783838-4-vkoul@kernel.org Reviewed-by: Bryan O'Donoghue Tested-by: Bryan O'Donoghue Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-alpha-pll.c | 193 +++++++++++++++++++++++++++++++ drivers/clk/qcom/clk-alpha-pll.h | 12 ++ 2 files changed, 205 insertions(+) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 0adec585eb4f..9b2dfa08acb2 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -52,6 +52,7 @@ #define PLL_CONFIG_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U1]) #define PLL_TEST_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL]) #define PLL_TEST_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U]) +#define PLL_TEST_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U1]) #define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS]) #define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE]) #define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC]) @@ -116,6 +117,22 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { [PLL_OFF_ALPHA_VAL] = 0x40, [PLL_OFF_CAL_VAL] = 0x44, }, + [CLK_ALPHA_PLL_TYPE_LUCID] = { + [PLL_OFF_L_VAL] = 0x04, + [PLL_OFF_CAL_L_VAL] = 0x08, + [PLL_OFF_USER_CTL] = 0x0c, + [PLL_OFF_USER_CTL_U] = 0x10, + [PLL_OFF_USER_CTL_U1] = 0x14, + [PLL_OFF_CONFIG_CTL] = 0x18, + [PLL_OFF_CONFIG_CTL_U] = 0x1c, + [PLL_OFF_CONFIG_CTL_U1] = 0x20, + [PLL_OFF_TEST_CTL] = 0x24, + [PLL_OFF_TEST_CTL_U] = 0x28, + [PLL_OFF_TEST_CTL_U1] = 0x2c, + [PLL_OFF_STATUS] = 0x30, + [PLL_OFF_OPMODE] = 0x38, + [PLL_OFF_ALPHA_VAL] = 0x40, + }, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); @@ -139,6 +156,10 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); #define PLL_OUT_MASK 0x7 #define PLL_RATE_MARGIN 500 +/* LUCID PLL specific settings and offsets */ +#define LUCID_PLL_CAL_VAL 0x44 +#define LUCID_PCAL_DONE BIT(26) + #define pll_alpha_width(p) \ ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \ ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH) @@ -1370,3 +1391,175 @@ const struct clk_ops clk_alpha_pll_postdiv_fabia_ops = { .set_rate = clk_alpha_pll_postdiv_fabia_set_rate, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_fabia_ops); + +/** + * clk_lucid_pll_configure - configure the lucid pll + * + * @pll: clk alpha pll + * @regmap: register map + * @config: configuration to apply for pll + */ +void clk_lucid_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, + const struct alpha_pll_config *config) +{ + if (config->l) + regmap_write(regmap, PLL_L_VAL(pll), config->l); + + regmap_write(regmap, PLL_CAL_L_VAL(pll), LUCID_PLL_CAL_VAL); + + if (config->alpha) + regmap_write(regmap, PLL_ALPHA_VAL(pll), config->alpha); + + if (config->config_ctl_val) + regmap_write(regmap, PLL_CONFIG_CTL(pll), + config->config_ctl_val); + + if (config->config_ctl_hi_val) + regmap_write(regmap, PLL_CONFIG_CTL_U(pll), + config->config_ctl_hi_val); + + if (config->config_ctl_hi1_val) + regmap_write(regmap, PLL_CONFIG_CTL_U1(pll), + config->config_ctl_hi1_val); + + if (config->user_ctl_val) + regmap_write(regmap, PLL_USER_CTL(pll), + config->user_ctl_val); + + if (config->user_ctl_hi_val) + regmap_write(regmap, PLL_USER_CTL_U(pll), + config->user_ctl_hi_val); + + if (config->user_ctl_hi1_val) + regmap_write(regmap, PLL_USER_CTL_U1(pll), + config->user_ctl_hi1_val); + + if (config->test_ctl_val) + regmap_write(regmap, PLL_TEST_CTL(pll), + config->test_ctl_val); + + if (config->test_ctl_hi_val) + regmap_write(regmap, PLL_TEST_CTL_U(pll), + config->test_ctl_hi_val); + + if (config->test_ctl_hi1_val) + regmap_write(regmap, PLL_TEST_CTL_U1(pll), + config->test_ctl_hi1_val); + + regmap_update_bits(regmap, PLL_MODE(pll), PLL_UPDATE_BYPASS, + PLL_UPDATE_BYPASS); + + /* Disable PLL output */ + regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); + + /* Set operation mode to OFF */ + regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); + + /* Place the PLL in STANDBY mode */ + regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); +} +EXPORT_SYMBOL_GPL(clk_lucid_pll_configure); + +/* + * The Lucid PLL requires a power-on self-calibration which happens when the + * PLL comes out of reset. Calibrate in case it is not completed. + */ +static int alpha_pll_lucid_prepare(struct clk_hw *hw) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 regval; + int ret; + + /* Return early if calibration is not needed. */ + regmap_read(pll->clkr.regmap, PLL_STATUS(pll), ®val); + if (regval & LUCID_PCAL_DONE) + return 0; + + /* On/off to calibrate */ + ret = clk_trion_pll_enable(hw); + if (!ret) + clk_trion_pll_disable(hw); + + return ret; +} + +static int alpha_pll_lucid_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long prate) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + unsigned long rrate; + u32 regval, l, alpha_width = pll_alpha_width(pll); + u64 a; + int ret; + + rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); + + /* + * Due to a limited number of bits for fractional rate programming, the + * rounded up rate could be marginally higher than the requested rate. + */ + if (rrate > (rate + PLL_RATE_MARGIN) || rrate < rate) { + pr_err("Call set rate on the PLL with rounded rates!\n"); + return -EINVAL; + } + + regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); + regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); + + /* Latch the PLL input */ + ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), + PLL_UPDATE, PLL_UPDATE); + if (ret) + return ret; + + /* Wait for 2 reference cycles before checking the ACK bit. */ + udelay(1); + regmap_read(pll->clkr.regmap, PLL_MODE(pll), ®val); + if (!(regval & ALPHA_PLL_ACK_LATCH)) { + pr_err("Lucid PLL latch failed. Output may be unstable!\n"); + return -EINVAL; + } + + /* Return the latch input to 0 */ + ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), + PLL_UPDATE, 0); + if (ret) + return ret; + + if (clk_hw_is_enabled(hw)) { + ret = wait_for_pll_enable_lock(pll); + if (ret) + return ret; + } + + /* Wait for PLL output to stabilize */ + udelay(100); + return 0; +} + +const struct clk_ops clk_alpha_pll_lucid_ops = { + .prepare = alpha_pll_lucid_prepare, + .enable = clk_trion_pll_enable, + .disable = clk_trion_pll_disable, + .is_enabled = clk_trion_pll_is_enabled, + .recalc_rate = clk_trion_pll_recalc_rate, + .round_rate = clk_alpha_pll_round_rate, + .set_rate = alpha_pll_lucid_set_rate, +}; +EXPORT_SYMBOL_GPL(clk_alpha_pll_lucid_ops); + +const struct clk_ops clk_alpha_pll_fixed_lucid_ops = { + .enable = clk_trion_pll_enable, + .disable = clk_trion_pll_disable, + .is_enabled = clk_trion_pll_is_enabled, + .recalc_rate = clk_trion_pll_recalc_rate, + .round_rate = clk_alpha_pll_round_rate, +}; +EXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_lucid_ops); + +const struct clk_ops clk_alpha_pll_postdiv_lucid_ops = { + .recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate, + .round_rate = clk_alpha_pll_postdiv_fabia_round_rate, + .set_rate = clk_alpha_pll_postdiv_fabia_set_rate, +}; +EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_lucid_ops); diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index fbc1f67c7a26..704674a153b6 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -14,6 +14,7 @@ enum { CLK_ALPHA_PLL_TYPE_BRAMMO, CLK_ALPHA_PLL_TYPE_FABIA, CLK_ALPHA_PLL_TYPE_TRION, + CLK_ALPHA_PLL_TYPE_LUCID, CLK_ALPHA_PLL_TYPE_MAX, }; @@ -30,6 +31,7 @@ enum { PLL_OFF_CONFIG_CTL_U1, PLL_OFF_TEST_CTL, PLL_OFF_TEST_CTL_U, + PLL_OFF_TEST_CTL_U1, PLL_OFF_STATUS, PLL_OFF_OPMODE, PLL_OFF_FRAC, @@ -94,10 +96,13 @@ struct alpha_pll_config { u32 alpha_hi; u32 config_ctl_val; u32 config_ctl_hi_val; + u32 config_ctl_hi1_val; u32 user_ctl_val; u32 user_ctl_hi_val; + u32 user_ctl_hi1_val; u32 test_ctl_val; u32 test_ctl_hi_val; + u32 test_ctl_hi1_val; u32 main_output_mask; u32 aux_output_mask; u32 aux2_output_mask; @@ -123,10 +128,17 @@ extern const struct clk_ops clk_alpha_pll_fabia_ops; extern const struct clk_ops clk_alpha_pll_fixed_fabia_ops; extern const struct clk_ops clk_alpha_pll_postdiv_fabia_ops; +extern const struct clk_ops clk_alpha_pll_lucid_ops; +extern const struct clk_ops clk_alpha_pll_fixed_lucid_ops; +extern const struct clk_ops clk_alpha_pll_postdiv_lucid_ops; + void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); +void clk_lucid_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, + const struct alpha_pll_config *config); + extern const struct clk_ops clk_trion_fixed_pll_ops; extern const struct clk_ops clk_trion_pll_postdiv_ops; From 98394efb48f51560fda86ed12f5d4e391629755f Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 24 Feb 2020 10:20:02 +0530 Subject: [PATCH 1365/4444] dt-bindings: clock: Add SM8250 GCC clock bindings Add device tree bindings for global clock controller on SM8250 SoCs. Signed-off-by: Taniya Das Signed-off-by: Venkata Narendra Kumar Gutta Signed-off-by: Vinod Koul Link: https://lkml.kernel.org/r/20200224045003.3783838-5-vkoul@kernel.org Reviewed-by: Rob Herring Reviewed-by: Bryan O'Donoghue Tested-by: Bryan O'Donoghue Signed-off-by: Stephen Boyd --- .../bindings/clock/qcom,gcc-sm8250.yaml | 72 +++++ include/dt-bindings/clock/qcom,gcc-sm8250.h | 271 ++++++++++++++++++ 2 files changed, 343 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,gcc-sm8250.yaml create mode 100644 include/dt-bindings/clock/qcom,gcc-sm8250.h diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8250.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8250.yaml new file mode 100644 index 000000000000..2c40a8aa9815 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8250.yaml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,gcc-sm8250.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Global Clock & Reset Controller Binding for SM8250 + +maintainers: + - Stephen Boyd + - Taniya Das + +description: | + Qualcomm global clock control module which supports the clocks, resets and + power domains on SM8250. + + See also: + - dt-bindings/clock/qcom,gcc-sm8250.h + +properties: + compatible: + const: qcom,gcc-sm8250 + + clocks: + items: + - description: Board XO source + - description: Sleep clock source + + clock-names: + items: + - const: bi_tcxo + - const: sleep_clk + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + + '#power-domain-cells': + const: 1 + + reg: + maxItems: 1 + + protected-clocks: + description: + Protected clock specifier list as per common clock binding. + +required: + - compatible + - clocks + - clock-names + - reg + - '#clock-cells' + - '#reset-cells' + - '#power-domain-cells' + +examples: + - | + #include + clock-controller@100000 { + compatible = "qcom,gcc-sm8250"; + reg = <0 0x00100000 0 0x1f0000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&sleep_clk>; + clock-names = "bi_tcxo", "sleep_clk"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; +... diff --git a/include/dt-bindings/clock/qcom,gcc-sm8250.h b/include/dt-bindings/clock/qcom,gcc-sm8250.h new file mode 100644 index 000000000000..7b7abe327e37 --- /dev/null +++ b/include/dt-bindings/clock/qcom,gcc-sm8250.h @@ -0,0 +1,271 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_GCC_SM8250_H +#define _DT_BINDINGS_CLK_QCOM_GCC_SM8250_H + +/* GCC clocks */ +#define GPLL0 0 +#define GPLL0_OUT_EVEN 1 +#define GPLL4 2 +#define GPLL9 3 +#define GCC_AGGRE_NOC_PCIE_TBU_CLK 4 +#define GCC_AGGRE_UFS_CARD_AXI_CLK 5 +#define GCC_AGGRE_UFS_PHY_AXI_CLK 6 +#define GCC_AGGRE_USB3_PRIM_AXI_CLK 7 +#define GCC_AGGRE_USB3_SEC_AXI_CLK 8 +#define GCC_BOOT_ROM_AHB_CLK 9 +#define GCC_CAMERA_AHB_CLK 10 +#define GCC_CAMERA_HF_AXI_CLK 11 +#define GCC_CAMERA_SF_AXI_CLK 12 +#define GCC_CAMERA_XO_CLK 13 +#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK 14 +#define GCC_CFG_NOC_USB3_SEC_AXI_CLK 15 +#define GCC_CPUSS_AHB_CLK 16 +#define GCC_CPUSS_AHB_CLK_SRC 17 +#define GCC_CPUSS_AHB_POSTDIV_CLK_SRC 18 +#define GCC_CPUSS_DVM_BUS_CLK 19 +#define GCC_CPUSS_RBCPR_CLK 20 +#define GCC_DDRSS_GPU_AXI_CLK 21 +#define GCC_DDRSS_PCIE_SF_TBU_CLK 22 +#define GCC_DISP_AHB_CLK 23 +#define GCC_DISP_HF_AXI_CLK 24 +#define GCC_DISP_SF_AXI_CLK 25 +#define GCC_DISP_XO_CLK 26 +#define GCC_GP1_CLK 27 +#define GCC_GP1_CLK_SRC 28 +#define GCC_GP2_CLK 29 +#define GCC_GP2_CLK_SRC 30 +#define GCC_GP3_CLK 31 +#define GCC_GP3_CLK_SRC 32 +#define GCC_GPU_CFG_AHB_CLK 33 +#define GCC_GPU_GPLL0_CLK_SRC 34 +#define GCC_GPU_GPLL0_DIV_CLK_SRC 35 +#define GCC_GPU_IREF_EN 36 +#define GCC_GPU_MEMNOC_GFX_CLK 37 +#define GCC_GPU_SNOC_DVM_GFX_CLK 38 +#define GCC_NPU_AXI_CLK 39 +#define GCC_NPU_BWMON_AXI_CLK 40 +#define GCC_NPU_BWMON_CFG_AHB_CLK 41 +#define GCC_NPU_CFG_AHB_CLK 42 +#define GCC_NPU_DMA_CLK 43 +#define GCC_NPU_GPLL0_CLK_SRC 44 +#define GCC_NPU_GPLL0_DIV_CLK_SRC 45 +#define GCC_PCIE0_PHY_REFGEN_CLK 46 +#define GCC_PCIE1_PHY_REFGEN_CLK 47 +#define GCC_PCIE2_PHY_REFGEN_CLK 48 +#define GCC_PCIE_0_AUX_CLK 49 +#define GCC_PCIE_0_AUX_CLK_SRC 50 +#define GCC_PCIE_0_CFG_AHB_CLK 51 +#define GCC_PCIE_0_MSTR_AXI_CLK 52 +#define GCC_PCIE_0_PIPE_CLK 53 +#define GCC_PCIE_0_SLV_AXI_CLK 54 +#define GCC_PCIE_0_SLV_Q2A_AXI_CLK 55 +#define GCC_PCIE_1_AUX_CLK 56 +#define GCC_PCIE_1_AUX_CLK_SRC 57 +#define GCC_PCIE_1_CFG_AHB_CLK 58 +#define GCC_PCIE_1_MSTR_AXI_CLK 59 +#define GCC_PCIE_1_PIPE_CLK 60 +#define GCC_PCIE_1_SLV_AXI_CLK 61 +#define GCC_PCIE_1_SLV_Q2A_AXI_CLK 62 +#define GCC_PCIE_2_AUX_CLK 63 +#define GCC_PCIE_2_AUX_CLK_SRC 64 +#define GCC_PCIE_2_CFG_AHB_CLK 65 +#define GCC_PCIE_2_MSTR_AXI_CLK 66 +#define GCC_PCIE_2_PIPE_CLK 67 +#define GCC_PCIE_2_SLV_AXI_CLK 68 +#define GCC_PCIE_2_SLV_Q2A_AXI_CLK 69 +#define GCC_PCIE_MDM_CLKREF_EN 70 +#define GCC_PCIE_PHY_AUX_CLK 71 +#define GCC_PCIE_PHY_REFGEN_CLK_SRC 72 +#define GCC_PCIE_WIFI_CLKREF_EN 73 +#define GCC_PCIE_WIGIG_CLKREF_EN 74 +#define GCC_PDM2_CLK 75 +#define GCC_PDM2_CLK_SRC 76 +#define GCC_PDM_AHB_CLK 77 +#define GCC_PDM_XO4_CLK 78 +#define GCC_PRNG_AHB_CLK 79 +#define GCC_QMIP_CAMERA_NRT_AHB_CLK 80 +#define GCC_QMIP_CAMERA_RT_AHB_CLK 81 +#define GCC_QMIP_DISP_AHB_CLK 82 +#define GCC_QMIP_VIDEO_CVP_AHB_CLK 83 +#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK 84 +#define GCC_QUPV3_WRAP0_CORE_2X_CLK 85 +#define GCC_QUPV3_WRAP0_CORE_CLK 86 +#define GCC_QUPV3_WRAP0_S0_CLK 87 +#define GCC_QUPV3_WRAP0_S0_CLK_SRC 88 +#define GCC_QUPV3_WRAP0_S1_CLK 89 +#define GCC_QUPV3_WRAP0_S1_CLK_SRC 90 +#define GCC_QUPV3_WRAP0_S2_CLK 91 +#define GCC_QUPV3_WRAP0_S2_CLK_SRC 92 +#define GCC_QUPV3_WRAP0_S3_CLK 93 +#define GCC_QUPV3_WRAP0_S3_CLK_SRC 94 +#define GCC_QUPV3_WRAP0_S4_CLK 95 +#define GCC_QUPV3_WRAP0_S4_CLK_SRC 96 +#define GCC_QUPV3_WRAP0_S5_CLK 97 +#define GCC_QUPV3_WRAP0_S5_CLK_SRC 98 +#define GCC_QUPV3_WRAP0_S6_CLK 99 +#define GCC_QUPV3_WRAP0_S6_CLK_SRC 100 +#define GCC_QUPV3_WRAP0_S7_CLK 101 +#define GCC_QUPV3_WRAP0_S7_CLK_SRC 102 +#define GCC_QUPV3_WRAP1_CORE_2X_CLK 103 +#define GCC_QUPV3_WRAP1_CORE_CLK 104 +#define GCC_QUPV3_WRAP1_S0_CLK 105 +#define GCC_QUPV3_WRAP1_S0_CLK_SRC 106 +#define GCC_QUPV3_WRAP1_S1_CLK 107 +#define GCC_QUPV3_WRAP1_S1_CLK_SRC 108 +#define GCC_QUPV3_WRAP1_S2_CLK 109 +#define GCC_QUPV3_WRAP1_S2_CLK_SRC 110 +#define GCC_QUPV3_WRAP1_S3_CLK 111 +#define GCC_QUPV3_WRAP1_S3_CLK_SRC 112 +#define GCC_QUPV3_WRAP1_S4_CLK 113 +#define GCC_QUPV3_WRAP1_S4_CLK_SRC 114 +#define GCC_QUPV3_WRAP1_S5_CLK 115 +#define GCC_QUPV3_WRAP1_S5_CLK_SRC 116 +#define GCC_QUPV3_WRAP2_CORE_2X_CLK 117 +#define GCC_QUPV3_WRAP2_CORE_CLK 118 +#define GCC_QUPV3_WRAP2_S0_CLK 119 +#define GCC_QUPV3_WRAP2_S0_CLK_SRC 120 +#define GCC_QUPV3_WRAP2_S1_CLK 121 +#define GCC_QUPV3_WRAP2_S1_CLK_SRC 122 +#define GCC_QUPV3_WRAP2_S2_CLK 123 +#define GCC_QUPV3_WRAP2_S2_CLK_SRC 124 +#define GCC_QUPV3_WRAP2_S3_CLK 125 +#define GCC_QUPV3_WRAP2_S3_CLK_SRC 126 +#define GCC_QUPV3_WRAP2_S4_CLK 127 +#define GCC_QUPV3_WRAP2_S4_CLK_SRC 128 +#define GCC_QUPV3_WRAP2_S5_CLK 129 +#define GCC_QUPV3_WRAP2_S5_CLK_SRC 130 +#define GCC_QUPV3_WRAP_0_M_AHB_CLK 131 +#define GCC_QUPV3_WRAP_0_S_AHB_CLK 132 +#define GCC_QUPV3_WRAP_1_M_AHB_CLK 133 +#define GCC_QUPV3_WRAP_1_S_AHB_CLK 134 +#define GCC_QUPV3_WRAP_2_M_AHB_CLK 135 +#define GCC_QUPV3_WRAP_2_S_AHB_CLK 136 +#define GCC_SDCC2_AHB_CLK 137 +#define GCC_SDCC2_APPS_CLK 138 +#define GCC_SDCC2_APPS_CLK_SRC 139 +#define GCC_SDCC4_AHB_CLK 140 +#define GCC_SDCC4_APPS_CLK 141 +#define GCC_SDCC4_APPS_CLK_SRC 142 +#define GCC_SYS_NOC_CPUSS_AHB_CLK 143 +#define GCC_TSIF_AHB_CLK 144 +#define GCC_TSIF_INACTIVITY_TIMERS_CLK 145 +#define GCC_TSIF_REF_CLK 146 +#define GCC_TSIF_REF_CLK_SRC 147 +#define GCC_UFS_1X_CLKREF_EN 148 +#define GCC_UFS_CARD_AHB_CLK 149 +#define GCC_UFS_CARD_AXI_CLK 150 +#define GCC_UFS_CARD_AXI_CLK_SRC 151 +#define GCC_UFS_CARD_ICE_CORE_CLK 152 +#define GCC_UFS_CARD_ICE_CORE_CLK_SRC 153 +#define GCC_UFS_CARD_PHY_AUX_CLK 154 +#define GCC_UFS_CARD_PHY_AUX_CLK_SRC 155 +#define GCC_UFS_CARD_RX_SYMBOL_0_CLK 156 +#define GCC_UFS_CARD_RX_SYMBOL_1_CLK 157 +#define GCC_UFS_CARD_TX_SYMBOL_0_CLK 158 +#define GCC_UFS_CARD_UNIPRO_CORE_CLK 159 +#define GCC_UFS_CARD_UNIPRO_CORE_CLK_SRC 160 +#define GCC_UFS_PHY_AHB_CLK 161 +#define GCC_UFS_PHY_AXI_CLK 162 +#define GCC_UFS_PHY_AXI_CLK_SRC 163 +#define GCC_UFS_PHY_ICE_CORE_CLK 164 +#define GCC_UFS_PHY_ICE_CORE_CLK_SRC 165 +#define GCC_UFS_PHY_PHY_AUX_CLK 166 +#define GCC_UFS_PHY_PHY_AUX_CLK_SRC 167 +#define GCC_UFS_PHY_RX_SYMBOL_0_CLK 168 +#define GCC_UFS_PHY_RX_SYMBOL_1_CLK 169 +#define GCC_UFS_PHY_TX_SYMBOL_0_CLK 170 +#define GCC_UFS_PHY_UNIPRO_CORE_CLK 171 +#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC 172 +#define GCC_USB30_PRIM_MASTER_CLK 173 +#define GCC_USB30_PRIM_MASTER_CLK_SRC 174 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK 175 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC 176 +#define GCC_USB30_PRIM_MOCK_UTMI_POSTDIV_CLK_SRC 177 +#define GCC_USB30_PRIM_SLEEP_CLK 178 +#define GCC_USB30_SEC_MASTER_CLK 179 +#define GCC_USB30_SEC_MASTER_CLK_SRC 180 +#define GCC_USB30_SEC_MOCK_UTMI_CLK 181 +#define GCC_USB30_SEC_MOCK_UTMI_CLK_SRC 182 +#define GCC_USB30_SEC_MOCK_UTMI_POSTDIV_CLK_SRC 183 +#define GCC_USB30_SEC_SLEEP_CLK 184 +#define GCC_USB3_PRIM_PHY_AUX_CLK 185 +#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC 186 +#define GCC_USB3_PRIM_PHY_COM_AUX_CLK 187 +#define GCC_USB3_PRIM_PHY_PIPE_CLK 188 +#define GCC_USB3_PRIM_PHY_PIPE_CLK_SRC 189 +#define GCC_USB3_SEC_CLKREF_EN 190 +#define GCC_USB3_SEC_PHY_AUX_CLK 191 +#define GCC_USB3_SEC_PHY_AUX_CLK_SRC 192 +#define GCC_USB3_SEC_PHY_COM_AUX_CLK 193 +#define GCC_USB3_SEC_PHY_PIPE_CLK 194 +#define GCC_USB3_SEC_PHY_PIPE_CLK_SRC 195 +#define GCC_VIDEO_AHB_CLK 196 +#define GCC_VIDEO_AXI0_CLK 197 +#define GCC_VIDEO_AXI1_CLK 198 +#define GCC_VIDEO_XO_CLK 199 + +/* GCC resets */ +#define GCC_GPU_BCR 0 +#define GCC_MMSS_BCR 1 +#define GCC_NPU_BWMON_BCR 2 +#define GCC_NPU_BCR 3 +#define GCC_PCIE_0_BCR 4 +#define GCC_PCIE_0_LINK_DOWN_BCR 5 +#define GCC_PCIE_0_NOCSR_COM_PHY_BCR 6 +#define GCC_PCIE_0_PHY_BCR 7 +#define GCC_PCIE_0_PHY_NOCSR_COM_PHY_BCR 8 +#define GCC_PCIE_1_BCR 9 +#define GCC_PCIE_1_LINK_DOWN_BCR 10 +#define GCC_PCIE_1_NOCSR_COM_PHY_BCR 11 +#define GCC_PCIE_1_PHY_BCR 12 +#define GCC_PCIE_1_PHY_NOCSR_COM_PHY_BCR 13 +#define GCC_PCIE_2_BCR 14 +#define GCC_PCIE_2_LINK_DOWN_BCR 15 +#define GCC_PCIE_2_NOCSR_COM_PHY_BCR 16 +#define GCC_PCIE_2_PHY_BCR 17 +#define GCC_PCIE_2_PHY_NOCSR_COM_PHY_BCR 18 +#define GCC_PCIE_PHY_BCR 19 +#define GCC_PCIE_PHY_CFG_AHB_BCR 20 +#define GCC_PCIE_PHY_COM_BCR 21 +#define GCC_PDM_BCR 22 +#define GCC_PRNG_BCR 23 +#define GCC_QUPV3_WRAPPER_0_BCR 24 +#define GCC_QUPV3_WRAPPER_1_BCR 25 +#define GCC_QUPV3_WRAPPER_2_BCR 26 +#define GCC_QUSB2PHY_PRIM_BCR 27 +#define GCC_QUSB2PHY_SEC_BCR 28 +#define GCC_SDCC2_BCR 29 +#define GCC_SDCC4_BCR 30 +#define GCC_TSIF_BCR 31 +#define GCC_UFS_CARD_BCR 32 +#define GCC_UFS_PHY_BCR 33 +#define GCC_USB30_PRIM_BCR 34 +#define GCC_USB30_SEC_BCR 35 +#define GCC_USB3_DP_PHY_PRIM_BCR 36 +#define GCC_USB3_DP_PHY_SEC_BCR 37 +#define GCC_USB3_PHY_PRIM_BCR 38 +#define GCC_USB3_PHY_SEC_BCR 39 +#define GCC_USB3PHY_PHY_PRIM_BCR 40 +#define GCC_USB3PHY_PHY_SEC_BCR 41 +#define GCC_USB_PHY_CFG_AHB2PHY_BCR 42 +#define GCC_VIDEO_AXI0_CLK_ARES 43 +#define GCC_VIDEO_AXI1_CLK_ARES 44 + +/* GCC power domains */ +#define PCIE_0_GDSC 0 +#define PCIE_1_GDSC 1 +#define PCIE_2_GDSC 2 +#define UFS_CARD_GDSC 3 +#define UFS_PHY_GDSC 4 +#define USB30_PRIM_GDSC 5 +#define USB30_SEC_GDSC 6 +#define HLOS1_VOTE_MMNOC_MMU_TBU_HF0_GDSC 7 +#define HLOS1_VOTE_MMNOC_MMU_TBU_HF1_GDSC 8 +#define HLOS1_VOTE_MMNOC_MMU_TBU_SF0_GDSC 9 +#define HLOS1_VOTE_MMNOC_MMU_TBU_SF1_GDSC 10 + +#endif From 3e5770921a8846ed1071257398eb7cd369399412 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 24 Feb 2020 10:20:03 +0530 Subject: [PATCH 1366/4444] clk: qcom: gcc: Add global clock controller driver for SM8250 Add the clocks supported in global clock controller, which clock the peripherals like BLSPs, SDCC, USB, MDSS etc. Register all the clocks to the clock framework for the clients to be able to request for them. Signed-off-by: Taniya Das Signed-off-by: Venkata Narendra Kumar Gutta Signed-off-by: Vinod Koul Link: https://lkml.kernel.org/r/20200224045003.3783838-6-vkoul@kernel.org Reviewed-by: Bryan O'Donoghue Tested-by: Bryan O'Donoghue Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 7 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/gcc-sm8250.c | 3690 +++++++++++++++++++++++++++++++++ 3 files changed, 3698 insertions(+) create mode 100644 drivers/clk/qcom/gcc-sm8250.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 15cdcdc9b3b8..af406a7c4aca 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -366,6 +366,13 @@ config SM_GCC_8150 Say Y if you want to use peripheral devices such as UART, SPI, I2C, USB, SD/UFS, PCIe etc. +config SM_GCC_8250 + tristate "SM8250 Global Clock Controller" + help + Support for the global clock controller on SM8250 devices. + Say Y if you want to use peripheral devices such as UART, + SPI, I2C, USB, SD/UFS, PCIe etc. + config SPMI_PMIC_CLKDIV tristate "SPMI PMIC clkdiv Support" depends on SPMI || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 656a87e629d4..bd6556b829c0 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -59,6 +59,7 @@ obj-$(CONFIG_SDM_GPUCC_845) += gpucc-sdm845.o obj-$(CONFIG_SDM_LPASSCC_845) += lpasscc-sdm845.o obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o +obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o obj-$(CONFIG_QCOM_HFPLL) += hfpll.o diff --git a/drivers/clk/qcom/gcc-sm8250.c b/drivers/clk/qcom/gcc-sm8250.c new file mode 100644 index 000000000000..6cb6617b8d88 --- /dev/null +++ b/drivers/clk/qcom/gcc-sm8250.c @@ -0,0 +1,3690 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + P_BI_TCXO, + P_AUD_REF_CLK, + P_CORE_BI_PLL_TEST_SE, + P_GPLL0_OUT_EVEN, + P_GPLL0_OUT_MAIN, + P_GPLL4_OUT_MAIN, + P_GPLL9_OUT_MAIN, + P_SLEEP_CLK, +}; + +static struct clk_alpha_pll gpll0 = { + .offset = 0x0, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpll0", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_gpll0_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll0_out_even = { + .offset = 0x0, + .post_div_shift = 8, + .post_div_table = post_div_table_gpll0_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_gpll0_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll0_out_even", + .parent_data = &(const struct clk_parent_data){ + .hw = &gpll0.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_lucid_ops, + }, +}; + +static struct clk_alpha_pll gpll4 = { + .offset = 0x76000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gpll4", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll9 = { + .offset = 0x1c000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gpll9", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_ops, + }, + }, +}; + +static const struct parent_map gcc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_0[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_even.clkr.hw }, +}; + +static const struct clk_parent_data gcc_parent_data_0_ao[] = { + { .fw_name = "bi_tcxo_ao" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_SLEEP_CLK, 5 }, + { P_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_1[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0.clkr.hw }, + { .fw_name = "sleep_clk" }, + { .hw = &gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_SLEEP_CLK, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_2[] = { + { .fw_name = "bi_tcxo" }, + { .fw_name = "sleep_clk" }, +}; + +static const struct parent_map gcc_parent_map_3[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data gcc_parent_data_3[] = { + { .fw_name = "bi_tcxo" }, +}; + +static const struct parent_map gcc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL9_OUT_MAIN, 2 }, + { P_GPLL4_OUT_MAIN, 5 }, + { P_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_4[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll9.clkr.hw }, + { .hw = &gpll4.clkr.hw }, + { .hw = &gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_5[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_AUD_REF_CLK, 2 }, + { P_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_5[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0.clkr.hw }, + { .fw_name = "aud_ref_clk" }, + { .hw = &gpll0_out_even.clkr.hw }, +}; + +static const struct freq_tbl ftbl_gcc_cpuss_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_cpuss_ahb_clk_src = { + .cmd_rcgr = 0x48010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_cpuss_ahb_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_cpuss_ahb_clk_src", + .parent_data = gcc_parent_data_0_ao, + .num_parents = 3, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_gp1_clk_src = { + .cmd_rcgr = 0x64004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp1_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_gp2_clk_src = { + .cmd_rcgr = 0x65004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp2_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_gp3_clk_src = { + .cmd_rcgr = 0x66004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp3_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pcie_0_aux_clk_src[] = { + F(9600000, P_BI_TCXO, 2, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pcie_0_aux_clk_src = { + .cmd_rcgr = 0x6b038, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_aux_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_1_aux_clk_src = { + .cmd_rcgr = 0x8d038, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_1_aux_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_2_aux_clk_src = { + .cmd_rcgr = 0x6038, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_2_aux_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pcie_phy_refgen_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pcie_phy_refgen_clk_src = { + .cmd_rcgr = 0x6f014, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pcie_phy_refgen_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_phy_refgen_clk_src", + .parent_data = gcc_parent_data_0_ao, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = { + F(9600000, P_BI_TCXO, 2, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(60000000, P_GPLL0_OUT_MAIN, 10, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pdm2_clk_src = { + .cmd_rcgr = 0x33010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pdm2_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_pdm2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = { + F(7372800, P_GPLL0_OUT_EVEN, 1, 384, 15625), + F(14745600, P_GPLL0_OUT_EVEN, 1, 768, 15625), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(29491200, P_GPLL0_OUT_EVEN, 1, 1536, 15625), + F(32000000, P_GPLL0_OUT_EVEN, 1, 8, 75), + F(48000000, P_GPLL0_OUT_EVEN, 1, 4, 25), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(64000000, P_GPLL0_OUT_EVEN, 1, 16, 75), + F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0), + F(80000000, P_GPLL0_OUT_EVEN, 1, 4, 15), + F(96000000, P_GPLL0_OUT_EVEN, 1, 8, 25), + F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), + F(102400000, P_GPLL0_OUT_EVEN, 1, 128, 375), + F(112000000, P_GPLL0_OUT_EVEN, 1, 28, 75), + F(117964800, P_GPLL0_OUT_EVEN, 1, 6144, 15625), + F(120000000, P_GPLL0_OUT_EVEN, 2.5, 0, 0), + { } +}; + +static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = { + .name = "gcc_qupv3_wrap0_s0_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = { + .cmd_rcgr = 0x17010, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = { + .name = "gcc_qupv3_wrap0_s1_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = { + .cmd_rcgr = 0x17140, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init, +}; + +static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s2_clk_src[] = { + F(7372800, P_GPLL0_OUT_EVEN, 1, 384, 15625), + F(14745600, P_GPLL0_OUT_EVEN, 1, 768, 15625), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(29491200, P_GPLL0_OUT_EVEN, 1, 1536, 15625), + F(32000000, P_GPLL0_OUT_EVEN, 1, 8, 75), + F(48000000, P_GPLL0_OUT_EVEN, 1, 4, 25), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(64000000, P_GPLL0_OUT_EVEN, 1, 16, 75), + F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0), + F(80000000, P_GPLL0_OUT_EVEN, 1, 4, 15), + F(96000000, P_GPLL0_OUT_EVEN, 1, 8, 25), + F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), + { } +}; + +static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = { + .name = "gcc_qupv3_wrap0_s2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = { + .cmd_rcgr = 0x17270, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = { + .name = "gcc_qupv3_wrap0_s3_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = { + .cmd_rcgr = 0x173a0, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = { + .name = "gcc_qupv3_wrap0_s4_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = { + .cmd_rcgr = 0x174d0, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = { + .name = "gcc_qupv3_wrap0_s5_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = { + .cmd_rcgr = 0x17600, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s6_clk_src_init = { + .name = "gcc_qupv3_wrap0_s6_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s6_clk_src = { + .cmd_rcgr = 0x17730, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s6_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s7_clk_src_init = { + .name = "gcc_qupv3_wrap0_s7_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s7_clk_src = { + .cmd_rcgr = 0x17860, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s7_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s0_clk_src_init = { + .name = "gcc_qupv3_wrap1_s0_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = { + .cmd_rcgr = 0x18010, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s0_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s1_clk_src_init = { + .name = "gcc_qupv3_wrap1_s1_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = { + .cmd_rcgr = 0x18140, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s1_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s2_clk_src_init = { + .name = "gcc_qupv3_wrap1_s2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = { + .cmd_rcgr = 0x18270, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s2_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s3_clk_src_init = { + .name = "gcc_qupv3_wrap1_s3_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = { + .cmd_rcgr = 0x183a0, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s3_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s4_clk_src_init = { + .name = "gcc_qupv3_wrap1_s4_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = { + .cmd_rcgr = 0x184d0, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s4_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s5_clk_src_init = { + .name = "gcc_qupv3_wrap1_s5_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s5_clk_src = { + .cmd_rcgr = 0x18600, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s5_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap2_s0_clk_src_init = { + .name = "gcc_qupv3_wrap2_s0_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap2_s0_clk_src = { + .cmd_rcgr = 0x1e010, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap2_s0_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap2_s1_clk_src_init = { + .name = "gcc_qupv3_wrap2_s1_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap2_s1_clk_src = { + .cmd_rcgr = 0x1e140, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap2_s1_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap2_s2_clk_src_init = { + .name = "gcc_qupv3_wrap2_s2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap2_s2_clk_src = { + .cmd_rcgr = 0x1e270, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap2_s2_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap2_s3_clk_src_init = { + .name = "gcc_qupv3_wrap2_s3_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap2_s3_clk_src = { + .cmd_rcgr = 0x1e3a0, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap2_s3_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap2_s4_clk_src_init = { + .name = "gcc_qupv3_wrap2_s4_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap2_s4_clk_src = { + .cmd_rcgr = 0x1e4d0, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap2_s4_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap2_s5_clk_src_init = { + .name = "gcc_qupv3_wrap2_s5_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap2_s5_clk_src = { + .cmd_rcgr = 0x1e600, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap2_s5_clk_src_init, +}; + +static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = { + F(400000, P_BI_TCXO, 12, 1, 4), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), + F(202000000, P_GPLL9_OUT_MAIN, 4, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { + .cmd_rcgr = 0x1400c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_sdcc2_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_apps_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc4_apps_clk_src[] = { + F(400000, P_BI_TCXO, 12, 1, 4), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc4_apps_clk_src = { + .cmd_rcgr = 0x1600c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_sdcc4_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc4_apps_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_tsif_ref_clk_src[] = { + F(105495, P_BI_TCXO, 2, 1, 91), + { } +}; + +static struct clk_rcg2 gcc_tsif_ref_clk_src = { + .cmd_rcgr = 0x36010, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_5, + .freq_tbl = ftbl_gcc_tsif_ref_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_tsif_ref_clk_src", + .parent_data = gcc_parent_data_5, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_card_axi_clk_src[] = { + F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_card_axi_clk_src = { + .cmd_rcgr = 0x75024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_card_axi_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_card_axi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_card_ice_core_clk_src[] = { + F(37500000, P_GPLL0_OUT_EVEN, 8, 0, 0), + F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0), + F(150000000, P_GPLL0_OUT_MAIN, 4, 0, 0), + F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_card_ice_core_clk_src = { + .cmd_rcgr = 0x7506c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_card_ice_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_card_ice_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_card_phy_aux_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_card_phy_aux_clk_src = { + .cmd_rcgr = 0x750a0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_ufs_card_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_card_phy_aux_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = 1, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_card_unipro_core_clk_src[] = { + F(37500000, P_GPLL0_OUT_EVEN, 8, 0, 0), + F(75000000, P_GPLL0_OUT_MAIN, 8, 0, 0), + F(150000000, P_GPLL0_OUT_MAIN, 4, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_card_unipro_core_clk_src = { + .cmd_rcgr = 0x75084, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_card_unipro_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_card_unipro_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_axi_clk_src[] = { + F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0), + F(37500000, P_GPLL0_OUT_EVEN, 8, 0, 0), + F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0), + F(150000000, P_GPLL0_OUT_MAIN, 4, 0, 0), + F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_axi_clk_src = { + .cmd_rcgr = 0x77024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_phy_axi_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_axi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_ufs_phy_ice_core_clk_src = { + .cmd_rcgr = 0x7706c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_card_ice_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_ice_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_ufs_phy_phy_aux_clk_src = { + .cmd_rcgr = 0x770a0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_phy_aux_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = 1, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_ufs_phy_unipro_core_clk_src = { + .cmd_rcgr = 0x77084, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_card_ice_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_unipro_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = { + F(33333333, P_GPLL0_OUT_EVEN, 9, 0, 0), + F(66666667, P_GPLL0_OUT_EVEN, 4.5, 0, 0), + F(133333333, P_GPLL0_OUT_MAIN, 4.5, 0, 0), + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + F(240000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb30_prim_master_clk_src = { + .cmd_rcgr = 0xf020, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_master_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = { + .cmd_rcgr = 0xf038, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_card_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_mock_utmi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_usb30_sec_master_clk_src = { + .cmd_rcgr = 0x10020, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_sec_master_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_usb30_sec_mock_utmi_clk_src = { + .cmd_rcgr = 0x10038, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_card_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_sec_mock_utmi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = { + .cmd_rcgr = 0xf064, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_ufs_card_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_aux_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_usb3_sec_phy_aux_clk_src = { + .cmd_rcgr = 0x10064, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_ufs_card_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_sec_phy_aux_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_regmap_div gcc_cpuss_ahb_postdiv_clk_src = { + .reg = 0x48028, + .shift = 0, + .width = 4, + .clkr.hw.init = &(struct clk_init_data) { + .name = "gcc_cpuss_ahb_postdiv_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_cpuss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gcc_usb30_prim_mock_utmi_postdiv_clk_src = { + .reg = 0xf050, + .shift = 0, + .width = 2, + .clkr.hw.init = &(struct clk_init_data) { + .name = "gcc_usb30_prim_mock_utmi_postdiv_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_usb30_prim_mock_utmi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gcc_usb30_sec_mock_utmi_postdiv_clk_src = { + .reg = 0x10050, + .shift = 0, + .width = 2, + .clkr.hw.init = &(struct clk_init_data) { + .name = "gcc_usb30_sec_mock_utmi_postdiv_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_usb30_sec_mock_utmi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch gcc_aggre_noc_pcie_tbu_clk = { + .halt_reg = 0x9000c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9000c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre_noc_pcie_tbu_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_ufs_card_axi_clk = { + .halt_reg = 0x750cc, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x750cc, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x750cc, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre_ufs_card_axi_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_ufs_card_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_ufs_phy_axi_clk = { + .halt_reg = 0x770cc, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x770cc, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x770cc, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre_ufs_phy_axi_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_ufs_phy_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_usb3_prim_axi_clk = { + .halt_reg = 0xf080, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0xf080, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre_usb3_prim_axi_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_usb3_sec_axi_clk = { + .halt_reg = 0x10080, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x10080, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre_usb3_sec_axi_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_usb30_sec_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_boot_rom_ahb_clk = { + .halt_reg = 0x38004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x38004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "gcc_boot_rom_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_hf_axi_clk = { + .halt_reg = 0xb02c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0xb02c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camera_hf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_sf_axi_clk = { + .halt_reg = 0xb030, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0xb030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camera_sf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_xo_clk = { + .halt_reg = 0xb040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camera_xo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cfg_noc_usb3_prim_axi_clk = { + .halt_reg = 0xf07c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0xf07c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cfg_noc_usb3_prim_axi_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cfg_noc_usb3_sec_axi_clk = { + .halt_reg = 0x1007c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x1007c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cfg_noc_usb3_sec_axi_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_usb30_sec_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cpuss_ahb_clk = { + .halt_reg = 0x48000, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(21), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cpuss_ahb_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_cpuss_ahb_postdiv_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cpuss_rbcpr_clk = { + .halt_reg = 0x48004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x48004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cpuss_rbcpr_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ddrss_gpu_axi_clk = { + .halt_reg = 0x71154, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x71154, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ddrss_gpu_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ddrss_pcie_sf_tbu_clk = { + .halt_reg = 0x8d058, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x8d058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ddrss_pcie_sf_tbu_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_hf_axi_clk = { + .halt_reg = 0xb034, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0xb034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_hf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_sf_axi_clk = { + .halt_reg = 0xb038, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0xb038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_sf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_xo_clk = { + .halt_reg = 0xb044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb044, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_xo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp1_clk = { + .halt_reg = 0x64000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x64000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp1_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_gp1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp2_clk = { + .halt_reg = 0x65000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x65000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp2_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_gp2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp3_clk = { + .halt_reg = 0x66000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x66000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp3_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_gp3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_gpll0_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(15), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_gpll0_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &gpll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(16), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_gpll0_div_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &gpll0_out_even.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_iref_en = { + .halt_reg = 0x8c014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_iref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_memnoc_gfx_clk = { + .halt_reg = 0x7100c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7100c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_memnoc_gfx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_snoc_dvm_gfx_clk = { + .halt_reg = 0x71018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x71018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_snoc_dvm_gfx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_npu_axi_clk = { + .halt_reg = 0x4d008, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x4d008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_npu_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_npu_bwmon_axi_clk = { + .halt_reg = 0x73008, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x73008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_npu_bwmon_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_npu_bwmon_cfg_ahb_clk = { + .halt_reg = 0x73004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x73004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_npu_bwmon_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_npu_cfg_ahb_clk = { + .halt_reg = 0x4d004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x4d004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x4d004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_npu_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_npu_dma_clk = { + .halt_reg = 0x4d00c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x4d00c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_npu_dma_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_npu_gpll0_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(18), + .hw.init = &(struct clk_init_data){ + .name = "gcc_npu_gpll0_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &gpll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_npu_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(19), + .hw.init = &(struct clk_init_data){ + .name = "gcc_npu_gpll0_div_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &gpll0_out_even.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie0_phy_refgen_clk = { + .halt_reg = 0x6f02c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6f02c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie0_phy_refgen_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_pcie_phy_refgen_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie1_phy_refgen_clk = { + .halt_reg = 0x6f030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6f030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie1_phy_refgen_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_pcie_phy_refgen_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie2_phy_refgen_clk = { + .halt_reg = 0x6f034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6f034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie2_phy_refgen_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_pcie_phy_refgen_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_aux_clk = { + .halt_reg = 0x6b028, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(3), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_aux_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_pcie_0_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_cfg_ahb_clk = { + .halt_reg = 0x6b024, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x6b024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(2), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_mstr_axi_clk = { + .halt_reg = 0x6b01c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_pipe_clk = { + .halt_reg = 0x6b02c, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_pipe_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_slv_axi_clk = { + .halt_reg = 0x6b014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x6b014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_slv_q2a_axi_clk = { + .halt_reg = 0x6b010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(5), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_aux_clk = { + .halt_reg = 0x8d028, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(29), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_1_aux_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_pcie_1_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_cfg_ahb_clk = { + .halt_reg = 0x8d024, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x8d024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(28), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_1_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_mstr_axi_clk = { + .halt_reg = 0x8d01c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(27), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_1_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_pipe_clk = { + .halt_reg = 0x8d02c, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(30), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_1_pipe_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_slv_axi_clk = { + .halt_reg = 0x8d014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x8d014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(26), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_1_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_slv_q2a_axi_clk = { + .halt_reg = 0x8d010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(25), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_1_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_aux_clk = { + .halt_reg = 0x6028, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(14), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_2_aux_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_pcie_2_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_cfg_ahb_clk = { + .halt_reg = 0x6024, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x6024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(13), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_2_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_mstr_axi_clk = { + .halt_reg = 0x601c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(12), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_2_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_pipe_clk = { + .halt_reg = 0x602c, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(15), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_2_pipe_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_slv_axi_clk = { + .halt_reg = 0x6014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x6014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_2_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_slv_q2a_axi_clk = { + .halt_reg = 0x6010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_2_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_mdm_clkref_en = { + .halt_reg = 0x8c00c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c00c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_mdm_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_phy_aux_clk = { + .halt_reg = 0x6f004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6f004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_phy_aux_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_pcie_0_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_wifi_clkref_en = { + .halt_reg = 0x8c004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_wifi_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_wigig_clkref_en = { + .halt_reg = 0x8c008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_wigig_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm2_clk = { + .halt_reg = 0x3300c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x3300c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm2_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_pdm2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_ahb_clk = { + .halt_reg = 0x33004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x33004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x33004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_xo4_clk = { + .halt_reg = 0x33008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x33008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm_xo4_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_prng_ahb_clk = { + .halt_reg = 0x34004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(13), + .hw.init = &(struct clk_init_data){ + .name = "gcc_prng_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_camera_nrt_ahb_clk = { + .halt_reg = 0xb018, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xb018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_camera_nrt_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_camera_rt_ahb_clk = { + .halt_reg = 0xb01c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xb01c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb01c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_camera_rt_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_disp_ahb_clk = { + .halt_reg = 0xb020, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xb020, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_disp_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_video_cvp_ahb_clk = { + .halt_reg = 0xb010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xb010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_video_cvp_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_video_vcodec_ahb_clk = { + .halt_reg = 0xb014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xb014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_video_vcodec_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_2x_clk = { + .halt_reg = 0x23008, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_core_2x_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_clk = { + .halt_reg = 0x23000, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(8), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s0_clk = { + .halt_reg = 0x1700c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s0_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap0_s0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s1_clk = { + .halt_reg = 0x1713c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s1_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap0_s1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s2_clk = { + .halt_reg = 0x1726c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(12), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s2_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap0_s2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s3_clk = { + .halt_reg = 0x1739c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(13), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s3_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap0_s3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s4_clk = { + .halt_reg = 0x174cc, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(14), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s4_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap0_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s5_clk = { + .halt_reg = 0x175fc, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(15), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s5_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap0_s5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s6_clk = { + .halt_reg = 0x1772c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(16), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s6_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap0_s6_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s7_clk = { + .halt_reg = 0x1785c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(17), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s7_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap0_s7_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_core_2x_clk = { + .halt_reg = 0x23140, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(18), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_core_2x_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_core_clk = { + .halt_reg = 0x23138, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(19), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s0_clk = { + .halt_reg = 0x1800c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(22), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s0_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap1_s0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s1_clk = { + .halt_reg = 0x1813c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(23), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s1_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap1_s1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s2_clk = { + .halt_reg = 0x1826c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(24), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s2_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap1_s2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s3_clk = { + .halt_reg = 0x1839c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(25), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s3_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap1_s3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s4_clk = { + .halt_reg = 0x184cc, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(26), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s4_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap1_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s5_clk = { + .halt_reg = 0x185fc, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(27), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s5_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap1_s5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_core_2x_clk = { + .halt_reg = 0x23278, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(3), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap2_core_2x_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_core_clk = { + .halt_reg = 0x23270, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap2_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_s0_clk = { + .halt_reg = 0x1e00c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap2_s0_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap2_s0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_s1_clk = { + .halt_reg = 0x1e13c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(5), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap2_s1_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap2_s1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_s2_clk = { + .halt_reg = 0x1e26c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(6), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap2_s2_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap2_s2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_s3_clk = { + .halt_reg = 0x1e39c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(7), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap2_s3_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap2_s3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_s4_clk = { + .halt_reg = 0x1e4cc, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(8), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap2_s4_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap2_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_s5_clk = { + .halt_reg = 0x1e5fc, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap2_s5_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap2_s5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_m_ahb_clk = { + .halt_reg = 0x17004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(6), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_0_m_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_s_ahb_clk = { + .halt_reg = 0x17008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(7), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_0_s_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_1_m_ahb_clk = { + .halt_reg = 0x18004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(20), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_1_m_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_1_s_ahb_clk = { + .halt_reg = 0x18008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x18008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(21), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_1_s_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_2_m_ahb_clk = { + .halt_reg = 0x1e004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(2), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_2_m_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_2_s_ahb_clk = { + .halt_reg = 0x1e008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1e008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_2_s_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_ahb_clk = { + .halt_reg = 0x14008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x14008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_apps_clk = { + .halt_reg = 0x14004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x14004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_apps_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_sdcc2_apps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc4_ahb_clk = { + .halt_reg = 0x16008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x16008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc4_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc4_apps_clk = { + .halt_reg = 0x16004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x16004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc4_apps_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_sdcc4_apps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_tsif_ahb_clk = { + .halt_reg = 0x36004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x36004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_tsif_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_tsif_inactivity_timers_clk = { + .halt_reg = 0x3600c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x3600c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_tsif_inactivity_timers_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_tsif_ref_clk = { + .halt_reg = 0x36008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x36008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_tsif_ref_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_tsif_ref_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_1x_clkref_en = { + .halt_reg = 0x8c000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_1x_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_ahb_clk = { + .halt_reg = 0x75018, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x75018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x75018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_card_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_axi_clk = { + .halt_reg = 0x75010, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x75010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x75010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_card_axi_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_ufs_card_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_ice_core_clk = { + .halt_reg = 0x75064, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x75064, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x75064, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_card_ice_core_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_ufs_card_ice_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_phy_aux_clk = { + .halt_reg = 0x7509c, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x7509c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7509c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_card_phy_aux_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_ufs_card_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_rx_symbol_0_clk = { + .halt_reg = 0x75020, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x75020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_card_rx_symbol_0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_rx_symbol_1_clk = { + .halt_reg = 0x750b8, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x750b8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_card_rx_symbol_1_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_tx_symbol_0_clk = { + .halt_reg = 0x7501c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7501c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_card_tx_symbol_0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_unipro_core_clk = { + .halt_reg = 0x7505c, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x7505c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7505c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_card_unipro_core_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_ufs_card_unipro_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_ahb_clk = { + .halt_reg = 0x77018, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x77018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_axi_clk = { + .halt_reg = 0x77010, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x77010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_axi_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_ufs_phy_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_ice_core_clk = { + .halt_reg = 0x77064, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x77064, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77064, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_ice_core_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_ufs_phy_ice_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_phy_aux_clk = { + .halt_reg = 0x7709c, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x7709c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7709c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_phy_aux_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_ufs_phy_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_rx_symbol_0_clk = { + .halt_reg = 0x77020, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x77020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_rx_symbol_0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_rx_symbol_1_clk = { + .halt_reg = 0x770b8, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x770b8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_rx_symbol_1_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_tx_symbol_0_clk = { + .halt_reg = 0x7701c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7701c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_tx_symbol_0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_unipro_core_clk = { + .halt_reg = 0x7705c, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x7705c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7705c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_unipro_core_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_ufs_phy_unipro_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_master_clk = { + .halt_reg = 0xf010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0xf010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_master_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_mock_utmi_clk = { + .halt_reg = 0xf01c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf01c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_mock_utmi_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = + &gcc_usb30_prim_mock_utmi_postdiv_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_sleep_clk = { + .halt_reg = 0xf018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_sec_master_clk = { + .halt_reg = 0x10010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x10010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_sec_master_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_usb30_sec_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_sec_mock_utmi_clk = { + .halt_reg = 0x1001c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1001c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_sec_mock_utmi_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = + &gcc_usb30_sec_mock_utmi_postdiv_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_sec_sleep_clk = { + .halt_reg = 0x10018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_sec_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_aux_clk = { + .halt_reg = 0xf054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_aux_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_usb3_prim_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_com_aux_clk = { + .halt_reg = 0xf058, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_com_aux_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_usb3_prim_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_pipe_clk = { + .halt_reg = 0xf05c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0xf05c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_pipe_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_sec_clkref_en = { + .halt_reg = 0x8c010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_sec_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_sec_phy_aux_clk = { + .halt_reg = 0x10054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_sec_phy_aux_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_usb3_sec_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_sec_phy_com_aux_clk = { + .halt_reg = 0x10058, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_sec_phy_com_aux_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_usb3_sec_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_sec_phy_pipe_clk = { + .halt_reg = 0x1005c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x1005c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_sec_phy_pipe_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_axi0_clk = { + .halt_reg = 0xb024, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0xb024, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_axi0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_axi1_clk = { + .halt_reg = 0xb028, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0xb028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_axi1_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_xo_clk = { + .halt_reg = 0xb03c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb03c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_xo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc pcie_0_gdsc = { + .gdscr = 0x6b004, + .pd = { + .name = "pcie_0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc pcie_1_gdsc = { + .gdscr = 0x8d004, + .pd = { + .name = "pcie_1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc pcie_2_gdsc = { + .gdscr = 0x6004, + .pd = { + .name = "pcie_2_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc ufs_card_gdsc = { + .gdscr = 0x75004, + .pd = { + .name = "ufs_card_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc ufs_phy_gdsc = { + .gdscr = 0x77004, + .pd = { + .name = "ufs_phy_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc usb30_prim_gdsc = { + .gdscr = 0xf004, + .pd = { + .name = "usb30_prim_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc usb30_sec_gdsc = { + .gdscr = 0x10004, + .pd = { + .name = "usb30_sec_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc = { + .gdscr = 0x7d050, + .pd = { + .name = "hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE, +}; + +static struct gdsc hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc = { + .gdscr = 0x7d058, + .pd = { + .name = "hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE, +}; + +static struct gdsc hlos1_vote_mmnoc_mmu_tbu_sf0_gdsc = { + .gdscr = 0x7d054, + .pd = { + .name = "hlos1_vote_mmnoc_mmu_tbu_sf0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE, +}; + +static struct gdsc hlos1_vote_mmnoc_mmu_tbu_sf1_gdsc = { + .gdscr = 0x7d06c, + .pd = { + .name = "hlos1_vote_mmnoc_mmu_tbu_sf1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE, +}; + +static struct clk_regmap *gcc_sm8250_clocks[] = { + [GCC_AGGRE_NOC_PCIE_TBU_CLK] = &gcc_aggre_noc_pcie_tbu_clk.clkr, + [GCC_AGGRE_UFS_CARD_AXI_CLK] = &gcc_aggre_ufs_card_axi_clk.clkr, + [GCC_AGGRE_UFS_PHY_AXI_CLK] = &gcc_aggre_ufs_phy_axi_clk.clkr, + [GCC_AGGRE_USB3_PRIM_AXI_CLK] = &gcc_aggre_usb3_prim_axi_clk.clkr, + [GCC_AGGRE_USB3_SEC_AXI_CLK] = &gcc_aggre_usb3_sec_axi_clk.clkr, + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, + [GCC_CAMERA_HF_AXI_CLK] = &gcc_camera_hf_axi_clk.clkr, + [GCC_CAMERA_SF_AXI_CLK] = &gcc_camera_sf_axi_clk.clkr, + [GCC_CAMERA_XO_CLK] = &gcc_camera_xo_clk.clkr, + [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr, + [GCC_CFG_NOC_USB3_SEC_AXI_CLK] = &gcc_cfg_noc_usb3_sec_axi_clk.clkr, + [GCC_CPUSS_AHB_CLK] = &gcc_cpuss_ahb_clk.clkr, + [GCC_CPUSS_AHB_CLK_SRC] = &gcc_cpuss_ahb_clk_src.clkr, + [GCC_CPUSS_AHB_POSTDIV_CLK_SRC] = &gcc_cpuss_ahb_postdiv_clk_src.clkr, + [GCC_CPUSS_RBCPR_CLK] = &gcc_cpuss_rbcpr_clk.clkr, + [GCC_DDRSS_GPU_AXI_CLK] = &gcc_ddrss_gpu_axi_clk.clkr, + [GCC_DDRSS_PCIE_SF_TBU_CLK] = &gcc_ddrss_pcie_sf_tbu_clk.clkr, + [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr, + [GCC_DISP_SF_AXI_CLK] = &gcc_disp_sf_axi_clk.clkr, + [GCC_DISP_XO_CLK] = &gcc_disp_xo_clk.clkr, + [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, + [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr, + [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, + [GCC_GP2_CLK_SRC] = &gcc_gp2_clk_src.clkr, + [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, + [GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr, + [GCC_GPU_GPLL0_CLK_SRC] = &gcc_gpu_gpll0_clk_src.clkr, + [GCC_GPU_GPLL0_DIV_CLK_SRC] = &gcc_gpu_gpll0_div_clk_src.clkr, + [GCC_GPU_IREF_EN] = &gcc_gpu_iref_en.clkr, + [GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr, + [GCC_GPU_SNOC_DVM_GFX_CLK] = &gcc_gpu_snoc_dvm_gfx_clk.clkr, + [GCC_NPU_AXI_CLK] = &gcc_npu_axi_clk.clkr, + [GCC_NPU_BWMON_AXI_CLK] = &gcc_npu_bwmon_axi_clk.clkr, + [GCC_NPU_BWMON_CFG_AHB_CLK] = &gcc_npu_bwmon_cfg_ahb_clk.clkr, + [GCC_NPU_CFG_AHB_CLK] = &gcc_npu_cfg_ahb_clk.clkr, + [GCC_NPU_DMA_CLK] = &gcc_npu_dma_clk.clkr, + [GCC_NPU_GPLL0_CLK_SRC] = &gcc_npu_gpll0_clk_src.clkr, + [GCC_NPU_GPLL0_DIV_CLK_SRC] = &gcc_npu_gpll0_div_clk_src.clkr, + [GCC_PCIE0_PHY_REFGEN_CLK] = &gcc_pcie0_phy_refgen_clk.clkr, + [GCC_PCIE1_PHY_REFGEN_CLK] = &gcc_pcie1_phy_refgen_clk.clkr, + [GCC_PCIE2_PHY_REFGEN_CLK] = &gcc_pcie2_phy_refgen_clk.clkr, + [GCC_PCIE_0_AUX_CLK] = &gcc_pcie_0_aux_clk.clkr, + [GCC_PCIE_0_AUX_CLK_SRC] = &gcc_pcie_0_aux_clk_src.clkr, + [GCC_PCIE_0_CFG_AHB_CLK] = &gcc_pcie_0_cfg_ahb_clk.clkr, + [GCC_PCIE_0_MSTR_AXI_CLK] = &gcc_pcie_0_mstr_axi_clk.clkr, + [GCC_PCIE_0_PIPE_CLK] = &gcc_pcie_0_pipe_clk.clkr, + [GCC_PCIE_0_SLV_AXI_CLK] = &gcc_pcie_0_slv_axi_clk.clkr, + [GCC_PCIE_0_SLV_Q2A_AXI_CLK] = &gcc_pcie_0_slv_q2a_axi_clk.clkr, + [GCC_PCIE_1_AUX_CLK] = &gcc_pcie_1_aux_clk.clkr, + [GCC_PCIE_1_AUX_CLK_SRC] = &gcc_pcie_1_aux_clk_src.clkr, + [GCC_PCIE_1_CFG_AHB_CLK] = &gcc_pcie_1_cfg_ahb_clk.clkr, + [GCC_PCIE_1_MSTR_AXI_CLK] = &gcc_pcie_1_mstr_axi_clk.clkr, + [GCC_PCIE_1_PIPE_CLK] = &gcc_pcie_1_pipe_clk.clkr, + [GCC_PCIE_1_SLV_AXI_CLK] = &gcc_pcie_1_slv_axi_clk.clkr, + [GCC_PCIE_1_SLV_Q2A_AXI_CLK] = &gcc_pcie_1_slv_q2a_axi_clk.clkr, + [GCC_PCIE_2_AUX_CLK] = &gcc_pcie_2_aux_clk.clkr, + [GCC_PCIE_2_AUX_CLK_SRC] = &gcc_pcie_2_aux_clk_src.clkr, + [GCC_PCIE_2_CFG_AHB_CLK] = &gcc_pcie_2_cfg_ahb_clk.clkr, + [GCC_PCIE_2_MSTR_AXI_CLK] = &gcc_pcie_2_mstr_axi_clk.clkr, + [GCC_PCIE_2_PIPE_CLK] = &gcc_pcie_2_pipe_clk.clkr, + [GCC_PCIE_2_SLV_AXI_CLK] = &gcc_pcie_2_slv_axi_clk.clkr, + [GCC_PCIE_2_SLV_Q2A_AXI_CLK] = &gcc_pcie_2_slv_q2a_axi_clk.clkr, + [GCC_PCIE_MDM_CLKREF_EN] = &gcc_pcie_mdm_clkref_en.clkr, + [GCC_PCIE_PHY_AUX_CLK] = &gcc_pcie_phy_aux_clk.clkr, + [GCC_PCIE_PHY_REFGEN_CLK_SRC] = &gcc_pcie_phy_refgen_clk_src.clkr, + [GCC_PCIE_WIFI_CLKREF_EN] = &gcc_pcie_wifi_clkref_en.clkr, + [GCC_PCIE_WIGIG_CLKREF_EN] = &gcc_pcie_wigig_clkref_en.clkr, + [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr, + [GCC_PDM2_CLK_SRC] = &gcc_pdm2_clk_src.clkr, + [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr, + [GCC_PDM_XO4_CLK] = &gcc_pdm_xo4_clk.clkr, + [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr, + [GCC_QMIP_CAMERA_NRT_AHB_CLK] = &gcc_qmip_camera_nrt_ahb_clk.clkr, + [GCC_QMIP_CAMERA_RT_AHB_CLK] = &gcc_qmip_camera_rt_ahb_clk.clkr, + [GCC_QMIP_DISP_AHB_CLK] = &gcc_qmip_disp_ahb_clk.clkr, + [GCC_QMIP_VIDEO_CVP_AHB_CLK] = &gcc_qmip_video_cvp_ahb_clk.clkr, + [GCC_QMIP_VIDEO_VCODEC_AHB_CLK] = &gcc_qmip_video_vcodec_ahb_clk.clkr, + [GCC_QUPV3_WRAP0_CORE_2X_CLK] = &gcc_qupv3_wrap0_core_2x_clk.clkr, + [GCC_QUPV3_WRAP0_CORE_CLK] = &gcc_qupv3_wrap0_core_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK] = &gcc_qupv3_wrap0_s0_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK_SRC] = &gcc_qupv3_wrap0_s0_clk_src.clkr, + [GCC_QUPV3_WRAP0_S1_CLK] = &gcc_qupv3_wrap0_s1_clk.clkr, + [GCC_QUPV3_WRAP0_S1_CLK_SRC] = &gcc_qupv3_wrap0_s1_clk_src.clkr, + [GCC_QUPV3_WRAP0_S2_CLK] = &gcc_qupv3_wrap0_s2_clk.clkr, + [GCC_QUPV3_WRAP0_S2_CLK_SRC] = &gcc_qupv3_wrap0_s2_clk_src.clkr, + [GCC_QUPV3_WRAP0_S3_CLK] = &gcc_qupv3_wrap0_s3_clk.clkr, + [GCC_QUPV3_WRAP0_S3_CLK_SRC] = &gcc_qupv3_wrap0_s3_clk_src.clkr, + [GCC_QUPV3_WRAP0_S4_CLK] = &gcc_qupv3_wrap0_s4_clk.clkr, + [GCC_QUPV3_WRAP0_S4_CLK_SRC] = &gcc_qupv3_wrap0_s4_clk_src.clkr, + [GCC_QUPV3_WRAP0_S5_CLK] = &gcc_qupv3_wrap0_s5_clk.clkr, + [GCC_QUPV3_WRAP0_S5_CLK_SRC] = &gcc_qupv3_wrap0_s5_clk_src.clkr, + [GCC_QUPV3_WRAP0_S6_CLK] = &gcc_qupv3_wrap0_s6_clk.clkr, + [GCC_QUPV3_WRAP0_S6_CLK_SRC] = &gcc_qupv3_wrap0_s6_clk_src.clkr, + [GCC_QUPV3_WRAP0_S7_CLK] = &gcc_qupv3_wrap0_s7_clk.clkr, + [GCC_QUPV3_WRAP0_S7_CLK_SRC] = &gcc_qupv3_wrap0_s7_clk_src.clkr, + [GCC_QUPV3_WRAP1_CORE_2X_CLK] = &gcc_qupv3_wrap1_core_2x_clk.clkr, + [GCC_QUPV3_WRAP1_CORE_CLK] = &gcc_qupv3_wrap1_core_clk.clkr, + [GCC_QUPV3_WRAP1_S0_CLK] = &gcc_qupv3_wrap1_s0_clk.clkr, + [GCC_QUPV3_WRAP1_S0_CLK_SRC] = &gcc_qupv3_wrap1_s0_clk_src.clkr, + [GCC_QUPV3_WRAP1_S1_CLK] = &gcc_qupv3_wrap1_s1_clk.clkr, + [GCC_QUPV3_WRAP1_S1_CLK_SRC] = &gcc_qupv3_wrap1_s1_clk_src.clkr, + [GCC_QUPV3_WRAP1_S2_CLK] = &gcc_qupv3_wrap1_s2_clk.clkr, + [GCC_QUPV3_WRAP1_S2_CLK_SRC] = &gcc_qupv3_wrap1_s2_clk_src.clkr, + [GCC_QUPV3_WRAP1_S3_CLK] = &gcc_qupv3_wrap1_s3_clk.clkr, + [GCC_QUPV3_WRAP1_S3_CLK_SRC] = &gcc_qupv3_wrap1_s3_clk_src.clkr, + [GCC_QUPV3_WRAP1_S4_CLK] = &gcc_qupv3_wrap1_s4_clk.clkr, + [GCC_QUPV3_WRAP1_S4_CLK_SRC] = &gcc_qupv3_wrap1_s4_clk_src.clkr, + [GCC_QUPV3_WRAP1_S5_CLK] = &gcc_qupv3_wrap1_s5_clk.clkr, + [GCC_QUPV3_WRAP1_S5_CLK_SRC] = &gcc_qupv3_wrap1_s5_clk_src.clkr, + [GCC_QUPV3_WRAP2_CORE_2X_CLK] = &gcc_qupv3_wrap2_core_2x_clk.clkr, + [GCC_QUPV3_WRAP2_CORE_CLK] = &gcc_qupv3_wrap2_core_clk.clkr, + [GCC_QUPV3_WRAP2_S0_CLK] = &gcc_qupv3_wrap2_s0_clk.clkr, + [GCC_QUPV3_WRAP2_S0_CLK_SRC] = &gcc_qupv3_wrap2_s0_clk_src.clkr, + [GCC_QUPV3_WRAP2_S1_CLK] = &gcc_qupv3_wrap2_s1_clk.clkr, + [GCC_QUPV3_WRAP2_S1_CLK_SRC] = &gcc_qupv3_wrap2_s1_clk_src.clkr, + [GCC_QUPV3_WRAP2_S2_CLK] = &gcc_qupv3_wrap2_s2_clk.clkr, + [GCC_QUPV3_WRAP2_S2_CLK_SRC] = &gcc_qupv3_wrap2_s2_clk_src.clkr, + [GCC_QUPV3_WRAP2_S3_CLK] = &gcc_qupv3_wrap2_s3_clk.clkr, + [GCC_QUPV3_WRAP2_S3_CLK_SRC] = &gcc_qupv3_wrap2_s3_clk_src.clkr, + [GCC_QUPV3_WRAP2_S4_CLK] = &gcc_qupv3_wrap2_s4_clk.clkr, + [GCC_QUPV3_WRAP2_S4_CLK_SRC] = &gcc_qupv3_wrap2_s4_clk_src.clkr, + [GCC_QUPV3_WRAP2_S5_CLK] = &gcc_qupv3_wrap2_s5_clk.clkr, + [GCC_QUPV3_WRAP2_S5_CLK_SRC] = &gcc_qupv3_wrap2_s5_clk_src.clkr, + [GCC_QUPV3_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.clkr, + [GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr, + [GCC_QUPV3_WRAP_1_M_AHB_CLK] = &gcc_qupv3_wrap_1_m_ahb_clk.clkr, + [GCC_QUPV3_WRAP_1_S_AHB_CLK] = &gcc_qupv3_wrap_1_s_ahb_clk.clkr, + [GCC_QUPV3_WRAP_2_M_AHB_CLK] = &gcc_qupv3_wrap_2_m_ahb_clk.clkr, + [GCC_QUPV3_WRAP_2_S_AHB_CLK] = &gcc_qupv3_wrap_2_s_ahb_clk.clkr, + [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, + [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, + [GCC_SDCC2_APPS_CLK_SRC] = &gcc_sdcc2_apps_clk_src.clkr, + [GCC_SDCC4_AHB_CLK] = &gcc_sdcc4_ahb_clk.clkr, + [GCC_SDCC4_APPS_CLK] = &gcc_sdcc4_apps_clk.clkr, + [GCC_SDCC4_APPS_CLK_SRC] = &gcc_sdcc4_apps_clk_src.clkr, + [GCC_TSIF_AHB_CLK] = &gcc_tsif_ahb_clk.clkr, + [GCC_TSIF_INACTIVITY_TIMERS_CLK] = &gcc_tsif_inactivity_timers_clk.clkr, + [GCC_TSIF_REF_CLK] = &gcc_tsif_ref_clk.clkr, + [GCC_TSIF_REF_CLK_SRC] = &gcc_tsif_ref_clk_src.clkr, + [GCC_UFS_1X_CLKREF_EN] = &gcc_ufs_1x_clkref_en.clkr, + [GCC_UFS_CARD_AHB_CLK] = &gcc_ufs_card_ahb_clk.clkr, + [GCC_UFS_CARD_AXI_CLK] = &gcc_ufs_card_axi_clk.clkr, + [GCC_UFS_CARD_AXI_CLK_SRC] = &gcc_ufs_card_axi_clk_src.clkr, + [GCC_UFS_CARD_ICE_CORE_CLK] = &gcc_ufs_card_ice_core_clk.clkr, + [GCC_UFS_CARD_ICE_CORE_CLK_SRC] = &gcc_ufs_card_ice_core_clk_src.clkr, + [GCC_UFS_CARD_PHY_AUX_CLK] = &gcc_ufs_card_phy_aux_clk.clkr, + [GCC_UFS_CARD_PHY_AUX_CLK_SRC] = &gcc_ufs_card_phy_aux_clk_src.clkr, + [GCC_UFS_CARD_RX_SYMBOL_0_CLK] = &gcc_ufs_card_rx_symbol_0_clk.clkr, + [GCC_UFS_CARD_RX_SYMBOL_1_CLK] = &gcc_ufs_card_rx_symbol_1_clk.clkr, + [GCC_UFS_CARD_TX_SYMBOL_0_CLK] = &gcc_ufs_card_tx_symbol_0_clk.clkr, + [GCC_UFS_CARD_UNIPRO_CORE_CLK] = &gcc_ufs_card_unipro_core_clk.clkr, + [GCC_UFS_CARD_UNIPRO_CORE_CLK_SRC] = + &gcc_ufs_card_unipro_core_clk_src.clkr, + [GCC_UFS_PHY_AHB_CLK] = &gcc_ufs_phy_ahb_clk.clkr, + [GCC_UFS_PHY_AXI_CLK] = &gcc_ufs_phy_axi_clk.clkr, + [GCC_UFS_PHY_AXI_CLK_SRC] = &gcc_ufs_phy_axi_clk_src.clkr, + [GCC_UFS_PHY_ICE_CORE_CLK] = &gcc_ufs_phy_ice_core_clk.clkr, + [GCC_UFS_PHY_ICE_CORE_CLK_SRC] = &gcc_ufs_phy_ice_core_clk_src.clkr, + [GCC_UFS_PHY_PHY_AUX_CLK] = &gcc_ufs_phy_phy_aux_clk.clkr, + [GCC_UFS_PHY_PHY_AUX_CLK_SRC] = &gcc_ufs_phy_phy_aux_clk_src.clkr, + [GCC_UFS_PHY_RX_SYMBOL_0_CLK] = &gcc_ufs_phy_rx_symbol_0_clk.clkr, + [GCC_UFS_PHY_RX_SYMBOL_1_CLK] = &gcc_ufs_phy_rx_symbol_1_clk.clkr, + [GCC_UFS_PHY_TX_SYMBOL_0_CLK] = &gcc_ufs_phy_tx_symbol_0_clk.clkr, + [GCC_UFS_PHY_UNIPRO_CORE_CLK] = &gcc_ufs_phy_unipro_core_clk.clkr, + [GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC] = + &gcc_ufs_phy_unipro_core_clk_src.clkr, + [GCC_USB30_PRIM_MASTER_CLK] = &gcc_usb30_prim_master_clk.clkr, + [GCC_USB30_PRIM_MASTER_CLK_SRC] = &gcc_usb30_prim_master_clk_src.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_CLK] = &gcc_usb30_prim_mock_utmi_clk.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC] = + &gcc_usb30_prim_mock_utmi_clk_src.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_POSTDIV_CLK_SRC] = + &gcc_usb30_prim_mock_utmi_postdiv_clk_src.clkr, + [GCC_USB30_PRIM_SLEEP_CLK] = &gcc_usb30_prim_sleep_clk.clkr, + [GCC_USB30_SEC_MASTER_CLK] = &gcc_usb30_sec_master_clk.clkr, + [GCC_USB30_SEC_MASTER_CLK_SRC] = &gcc_usb30_sec_master_clk_src.clkr, + [GCC_USB30_SEC_MOCK_UTMI_CLK] = &gcc_usb30_sec_mock_utmi_clk.clkr, + [GCC_USB30_SEC_MOCK_UTMI_CLK_SRC] = + &gcc_usb30_sec_mock_utmi_clk_src.clkr, + [GCC_USB30_SEC_MOCK_UTMI_POSTDIV_CLK_SRC] = + &gcc_usb30_sec_mock_utmi_postdiv_clk_src.clkr, + [GCC_USB30_SEC_SLEEP_CLK] = &gcc_usb30_sec_sleep_clk.clkr, + [GCC_USB3_PRIM_PHY_AUX_CLK] = &gcc_usb3_prim_phy_aux_clk.clkr, + [GCC_USB3_PRIM_PHY_AUX_CLK_SRC] = &gcc_usb3_prim_phy_aux_clk_src.clkr, + [GCC_USB3_PRIM_PHY_COM_AUX_CLK] = &gcc_usb3_prim_phy_com_aux_clk.clkr, + [GCC_USB3_PRIM_PHY_PIPE_CLK] = &gcc_usb3_prim_phy_pipe_clk.clkr, + [GCC_USB3_SEC_CLKREF_EN] = &gcc_usb3_sec_clkref_en.clkr, + [GCC_USB3_SEC_PHY_AUX_CLK] = &gcc_usb3_sec_phy_aux_clk.clkr, + [GCC_USB3_SEC_PHY_AUX_CLK_SRC] = &gcc_usb3_sec_phy_aux_clk_src.clkr, + [GCC_USB3_SEC_PHY_COM_AUX_CLK] = &gcc_usb3_sec_phy_com_aux_clk.clkr, + [GCC_USB3_SEC_PHY_PIPE_CLK] = &gcc_usb3_sec_phy_pipe_clk.clkr, + [GCC_VIDEO_AXI0_CLK] = &gcc_video_axi0_clk.clkr, + [GCC_VIDEO_AXI1_CLK] = &gcc_video_axi1_clk.clkr, + [GCC_VIDEO_XO_CLK] = &gcc_video_xo_clk.clkr, + [GPLL0] = &gpll0.clkr, + [GPLL0_OUT_EVEN] = &gpll0_out_even.clkr, + [GPLL4] = &gpll4.clkr, + [GPLL9] = &gpll9.clkr, +}; + +static struct gdsc *gcc_sm8250_gdscs[] = { + [PCIE_0_GDSC] = &pcie_0_gdsc, + [PCIE_1_GDSC] = &pcie_1_gdsc, + [PCIE_2_GDSC] = &pcie_2_gdsc, + [UFS_CARD_GDSC] = &ufs_card_gdsc, + [UFS_PHY_GDSC] = &ufs_phy_gdsc, + [USB30_PRIM_GDSC] = &usb30_prim_gdsc, + [USB30_SEC_GDSC] = &usb30_sec_gdsc, + [HLOS1_VOTE_MMNOC_MMU_TBU_HF0_GDSC] = + &hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc, + [HLOS1_VOTE_MMNOC_MMU_TBU_HF1_GDSC] = + &hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc, + [HLOS1_VOTE_MMNOC_MMU_TBU_SF0_GDSC] = + &hlos1_vote_mmnoc_mmu_tbu_sf0_gdsc, + [HLOS1_VOTE_MMNOC_MMU_TBU_SF1_GDSC] = + &hlos1_vote_mmnoc_mmu_tbu_sf1_gdsc, +}; + +static const struct qcom_reset_map gcc_sm8250_resets[] = { + [GCC_GPU_BCR] = { 0x71000 }, + [GCC_MMSS_BCR] = { 0xb000 }, + [GCC_NPU_BWMON_BCR] = { 0x73000 }, + [GCC_NPU_BCR] = { 0x4d000 }, + [GCC_PCIE_0_BCR] = { 0x6b000 }, + [GCC_PCIE_0_LINK_DOWN_BCR] = { 0x6c014 }, + [GCC_PCIE_0_NOCSR_COM_PHY_BCR] = { 0x6c020 }, + [GCC_PCIE_0_PHY_BCR] = { 0x6c01c }, + [GCC_PCIE_0_PHY_NOCSR_COM_PHY_BCR] = { 0x6c028 }, + [GCC_PCIE_1_BCR] = { 0x8d000 }, + [GCC_PCIE_1_LINK_DOWN_BCR] = { 0x8e014 }, + [GCC_PCIE_1_NOCSR_COM_PHY_BCR] = { 0x8e020 }, + [GCC_PCIE_1_PHY_BCR] = { 0x8e01c }, + [GCC_PCIE_1_PHY_NOCSR_COM_PHY_BCR] = { 0x8e000 }, + [GCC_PCIE_2_BCR] = { 0x6000 }, + [GCC_PCIE_2_LINK_DOWN_BCR] = { 0x1f014 }, + [GCC_PCIE_2_NOCSR_COM_PHY_BCR] = { 0x1f020 }, + [GCC_PCIE_2_PHY_BCR] = { 0x1f01c }, + [GCC_PCIE_2_PHY_NOCSR_COM_PHY_BCR] = { 0x1f028 }, + [GCC_PCIE_PHY_BCR] = { 0x6f000 }, + [GCC_PCIE_PHY_CFG_AHB_BCR] = { 0x6f00c }, + [GCC_PCIE_PHY_COM_BCR] = { 0x6f010 }, + [GCC_PDM_BCR] = { 0x33000 }, + [GCC_PRNG_BCR] = { 0x34000 }, + [GCC_QUPV3_WRAPPER_0_BCR] = { 0x17000 }, + [GCC_QUPV3_WRAPPER_1_BCR] = { 0x18000 }, + [GCC_QUPV3_WRAPPER_2_BCR] = { 0x1e000 }, + [GCC_QUSB2PHY_PRIM_BCR] = { 0x12000 }, + [GCC_QUSB2PHY_SEC_BCR] = { 0x12004 }, + [GCC_SDCC2_BCR] = { 0x14000 }, + [GCC_SDCC4_BCR] = { 0x16000 }, + [GCC_TSIF_BCR] = { 0x36000 }, + [GCC_UFS_CARD_BCR] = { 0x75000 }, + [GCC_UFS_PHY_BCR] = { 0x77000 }, + [GCC_USB30_PRIM_BCR] = { 0xf000 }, + [GCC_USB30_SEC_BCR] = { 0x10000 }, + [GCC_USB3_DP_PHY_PRIM_BCR] = { 0x50008 }, + [GCC_USB3_DP_PHY_SEC_BCR] = { 0x50014 }, + [GCC_USB3_PHY_PRIM_BCR] = { 0x50000 }, + [GCC_USB3_PHY_SEC_BCR] = { 0x5000c }, + [GCC_USB3PHY_PHY_PRIM_BCR] = { 0x50004 }, + [GCC_USB3PHY_PHY_SEC_BCR] = { 0x50010 }, + [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 }, + [GCC_VIDEO_AXI0_CLK_ARES] = { 0xb024, 2 }, + [GCC_VIDEO_AXI1_CLK_ARES] = { 0xb028, 2 }, +}; + +static const struct clk_rcg_dfs_data gcc_dfs_clocks[] = { + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s2_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s3_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s4_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s5_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s6_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s7_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s0_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s1_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s2_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s3_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s4_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s5_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap2_s0_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap2_s1_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap2_s2_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap2_s3_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap2_s4_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap2_s5_clk_src), +}; + +static const struct regmap_config gcc_sm8250_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x9c100, + .fast_io = true, +}; + +static const struct qcom_cc_desc gcc_sm8250_desc = { + .config = &gcc_sm8250_regmap_config, + .clks = gcc_sm8250_clocks, + .num_clks = ARRAY_SIZE(gcc_sm8250_clocks), + .resets = gcc_sm8250_resets, + .num_resets = ARRAY_SIZE(gcc_sm8250_resets), + .gdscs = gcc_sm8250_gdscs, + .num_gdscs = ARRAY_SIZE(gcc_sm8250_gdscs), +}; + +static const struct of_device_id gcc_sm8250_match_table[] = { + { .compatible = "qcom,gcc-sm8250" }, + { } +}; +MODULE_DEVICE_TABLE(of, gcc_sm8250_match_table); + +static int gcc_sm8250_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + int ret; + + regmap = qcom_cc_map(pdev, &gcc_sm8250_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + /* + * Disable the GPLL0 active input to NPU and GPU + * via MISC registers. + */ + regmap_update_bits(regmap, 0x4d110, 0x3, 0x3); + regmap_update_bits(regmap, 0x71028, 0x3, 0x3); + + /* + * Keep the clocks always-ON + * GCC_VIDEO_AHB_CLK, GCC_CAMERA_AHB_CLK, GCC_DISP_AHB_CLK, + * GCC_CPUSS_DVM_BUS_CLK, GCC_GPU_CFG_AHB_CLK, + * GCC_SYS_NOC_CPUSS_AHB_CLK + */ + regmap_update_bits(regmap, 0x0b004, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x0b008, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x0b00c, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x4818c, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x71004, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x52000, BIT(0), BIT(0)); + + ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks, + ARRAY_SIZE(gcc_dfs_clocks)); + if (ret) + return ret; + + return qcom_cc_really_probe(pdev, &gcc_sm8250_desc, regmap); +} + +static struct platform_driver gcc_sm8250_driver = { + .probe = gcc_sm8250_probe, + .driver = { + .name = "gcc-sm8250", + .of_match_table = gcc_sm8250_match_table, + }, +}; + +static int __init gcc_sm8250_init(void) +{ + return platform_driver_register(&gcc_sm8250_driver); +} +subsys_initcall(gcc_sm8250_init); + +static void __exit gcc_sm8250_exit(void) +{ + platform_driver_unregister(&gcc_sm8250_driver); +} +module_exit(gcc_sm8250_exit); + +MODULE_DESCRIPTION("QTI GCC SM8250 Driver"); +MODULE_LICENSE("GPL v2"); From 1910ee13a12ce7cab99d97a278ef6083a3cb922a Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Fri, 24 Jan 2020 09:43:49 +0100 Subject: [PATCH 1367/4444] ARM: multi_v7_defconfig: enable drm imx support It will be useful to have it enabled for KernelCI boot and runtime testing. Signed-off-by: Christian Gmeiner Signed-off-by: Shawn Guo --- arch/arm/configs/multi_v7_defconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 017d65f86eba..c5ff91211947 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -640,6 +640,7 @@ CONFIG_CEC_PLATFORM_DRIVERS=y CONFIG_VIDEO_SAMSUNG_S5P_CEC=m CONFIG_VIDEO_ADV7180=m CONFIG_VIDEO_ML86V7667=m +CONFIG_IMX_IPUV3_CORE=m CONFIG_DRM=y # CONFIG_DRM_I2C_CH7006 is not set # CONFIG_DRM_I2C_SIL164 is not set @@ -655,6 +656,11 @@ CONFIG_ROCKCHIP_ANALOGIX_DP=y CONFIG_ROCKCHIP_DW_HDMI=y CONFIG_ROCKCHIP_DW_MIPI_DSI=y CONFIG_ROCKCHIP_INNO_HDMI=y +CONFIG_DRM_IMX=m +CONFIG_DRM_IMX_PARALLEL_DISPLAY=m +CONFIG_DRM_IMX_TVE=m +CONFIG_DRM_IMX_LDB=m +CONFIG_DRM_IMX_HDMI=m CONFIG_DRM_ATMEL_HLCDC=m CONFIG_DRM_RCAR_DU=m CONFIG_DRM_RCAR_LVDS=y From 705dcca91d0a75f5657f3d5465f7dbd31c3efa8b Mon Sep 17 00:00:00 2001 From: Joakim Zhang Date: Mon, 17 Feb 2020 11:19:15 +0800 Subject: [PATCH 1368/4444] firmware: imx: scu-pd: add power domain for I2C and INTMUX in CM40 SS Add power domain for I2C and INTMUX in CM40 SS. Signed-off-by: Joakim Zhang Signed-off-by: Shawn Guo --- drivers/firmware/imx/scu-pd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c index 09cfa268c6bd..f3b4246ff200 100644 --- a/drivers/firmware/imx/scu-pd.c +++ b/drivers/firmware/imx/scu-pd.c @@ -165,6 +165,10 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { /* DC SS */ { "dc0", IMX_SC_R_DC_0, 1, false, 0 }, { "dc0-pll", IMX_SC_R_DC_0_PLL_0, 2, true, 0 }, + + /* CM40 SS */ + { "cm40_i2c", IMX_SC_R_M4_0_I2C, 1, 0 }, + { "cm40_intmux", IMX_SC_R_M4_0_INTMUX, 1, 0 }, }; static const struct imx_sc_pd_soc imx8qxp_scu_pd = { From 28b2f82e0383e27476be8a5e13d2aea07ebeb275 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 19 Feb 2020 15:59:46 +0800 Subject: [PATCH 1369/4444] clk: imx: Fix division by zero warning on pfdv2 Fix below division by zero warning: [ 3.176443] Division by zero in kernel. [ 3.181809] CPU: 0 PID: 88 Comm: kworker/0:2 Not tainted 5.3.0-rc2-next-20190730-63758-ge08da51-dirty #124 [ 3.191817] Hardware name: Freescale i.MX7ULP (Device Tree) [ 3.197821] Workqueue: events dbs_work_handler [ 3.202849] [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [ 3.211058] [] (show_stack) from [] (dump_stack+0xd8/0x110) [ 3.218820] [] (dump_stack) from [] (Ldiv0_64+0x8/0x18) [ 3.226263] [] (Ldiv0_64) from [] (clk_pfdv2_set_rate+0x54/0xac) [ 3.234487] [] (clk_pfdv2_set_rate) from [] (clk_change_rate+0x1a4/0x698) [ 3.243468] [] (clk_change_rate) from [] (clk_change_rate+0x280/0x698) [ 3.252180] [] (clk_change_rate) from [] (clk_core_set_rate_nolock+0x1a0/0x278) [ 3.261679] [] (clk_core_set_rate_nolock) from [] (clk_set_rate+0x30/0x64) [ 3.270743] [] (clk_set_rate) from [] (imx7ulp_set_target+0x184/0x2a4) [ 3.279501] [] (imx7ulp_set_target) from [] (__cpufreq_driver_target+0x188/0x514) [ 3.289196] [] (__cpufreq_driver_target) from [] (od_dbs_update+0x130/0x15c) [ 3.298438] [] (od_dbs_update) from [] (dbs_work_handler+0x2c/0x5c) [ 3.306914] [] (dbs_work_handler) from [] (process_one_work+0x2ac/0x704) [ 3.315826] [] (process_one_work) from [] (worker_thread+0x2c/0x574) [ 3.324404] [] (worker_thread) from [] (kthread+0x134/0x148) [ 3.332278] [] (kthread) from [] (ret_from_fork+0x14/0x20) [ 3.339858] Exception stack(0xe82d5fb0 to 0xe82d5ff8) [ 3.345314] 5fa0: 00000000 00000000 00000000 00000000 [ 3.353926] 5fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 3.362519] 5fe0: 00000000 00000000 00000000 00000000 00000013 00000000 Signed-off-by: Anson Huang Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-pfdv2.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/clk/imx/clk-pfdv2.c b/drivers/clk/imx/clk-pfdv2.c index de93ce73101b..f8707278aad9 100644 --- a/drivers/clk/imx/clk-pfdv2.c +++ b/drivers/clk/imx/clk-pfdv2.c @@ -139,6 +139,12 @@ static int clk_pfdv2_set_rate(struct clk_hw *hw, unsigned long rate, u32 val; u8 frac; + if (!rate) + return -EINVAL; + + /* PFD can NOT change rate without gating */ + WARN_ON(clk_pfdv2_is_enabled(hw)); + tmp = tmp * 18 + rate / 2; do_div(tmp, rate); frac = tmp; From 8ffe9c7bb9e47745b8a678629b22f57b23b8dac5 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Feb 2020 15:59:47 +0800 Subject: [PATCH 1370/4444] clk: imx: pfdv2: switch to use determine_rate Per clk_ops, compared with round_rate, determine_rate could optionally support the parent clock that should be used to provide the clock rate. In this patch, the parent clock is just parent->rate as round_rate. The following patch will calculate the best parent clock. Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-pfdv2.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/clk/imx/clk-pfdv2.c b/drivers/clk/imx/clk-pfdv2.c index f8707278aad9..28b5f208ced9 100644 --- a/drivers/clk/imx/clk-pfdv2.c +++ b/drivers/clk/imx/clk-pfdv2.c @@ -98,10 +98,11 @@ static unsigned long clk_pfdv2_recalc_rate(struct clk_hw *hw, return tmp; } -static long clk_pfdv2_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_pfdv2_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - u64 tmp = *prate; + u64 tmp = req->best_parent_rate; + u64 rate = req->rate; u8 frac; tmp = tmp * 18 + rate / 2; @@ -113,11 +114,13 @@ static long clk_pfdv2_round_rate(struct clk_hw *hw, unsigned long rate, else if (frac > 35) frac = 35; - tmp = *prate; + tmp = req->best_parent_rate; tmp *= 18; do_div(tmp, frac); - return tmp; + req->rate = tmp; + + return 0; } static int clk_pfdv2_is_enabled(struct clk_hw *hw) @@ -167,7 +170,7 @@ static const struct clk_ops clk_pfdv2_ops = { .enable = clk_pfdv2_enable, .disable = clk_pfdv2_disable, .recalc_rate = clk_pfdv2_recalc_rate, - .round_rate = clk_pfdv2_round_rate, + .determine_rate = clk_pfdv2_determine_rate, .set_rate = clk_pfdv2_set_rate, .is_enabled = clk_pfdv2_is_enabled, }; From c88a4c797a50574c90ca11f72ab10dbded7d768e Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Feb 2020 15:59:48 +0800 Subject: [PATCH 1371/4444] clk: imx: pfdv2: determine best parent rate pfdv2 is only used in i.MX7ULP. To get best pfd output, the i.MX7ULP Datasheet defines two best PLL rate and pfd frac. Per Datasheel All PLLs on i.MX 7ULP either have VCO base frequency of 480 MHz or 528 MHz. So when determine best rate, we also determine best parent rate which could match the requirement. For some reason the current parent might not be 480MHz or 528MHz, so we still take current parent rate as a choice. And we also enable flag CLK_SET_RATE_PARENT to let parent rate to be configured. Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-pfdv2.c | 44 +++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/drivers/clk/imx/clk-pfdv2.c b/drivers/clk/imx/clk-pfdv2.c index 28b5f208ced9..78e1f7641aaa 100644 --- a/drivers/clk/imx/clk-pfdv2.c +++ b/drivers/clk/imx/clk-pfdv2.c @@ -101,24 +101,40 @@ static unsigned long clk_pfdv2_recalc_rate(struct clk_hw *hw, static int clk_pfdv2_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { - u64 tmp = req->best_parent_rate; - u64 rate = req->rate; + unsigned long parent_rates[] = { + 480000000, + 528000000, + req->best_parent_rate + }; + unsigned long best_rate = -1UL, rate = req->rate; + unsigned long best_parent_rate = req->best_parent_rate; + u64 tmp; u8 frac; + int i; - tmp = tmp * 18 + rate / 2; - do_div(tmp, rate); - frac = tmp; + for (i = 0; i < ARRAY_SIZE(parent_rates); i++) { + tmp = parent_rates[i]; + tmp = tmp * 18 + rate / 2; + do_div(tmp, rate); + frac = tmp; - if (frac < 12) - frac = 12; - else if (frac > 35) - frac = 35; + if (frac < 12) + frac = 12; + else if (frac > 35) + frac = 35; - tmp = req->best_parent_rate; - tmp *= 18; - do_div(tmp, frac); + tmp = parent_rates[i]; + tmp *= 18; + do_div(tmp, frac); - req->rate = tmp; + if (abs(tmp - req->rate) < abs(best_rate - req->rate)) { + best_rate = tmp; + best_parent_rate = parent_rates[i]; + } + } + + req->best_parent_rate = best_parent_rate; + req->rate = best_rate; return 0; } @@ -198,7 +214,7 @@ struct clk_hw *imx_clk_hw_pfdv2(const char *name, const char *parent_name, init.ops = &clk_pfdv2_ops; init.parent_names = &parent_name; init.num_parents = 1; - init.flags = CLK_SET_RATE_GATE; + init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT; pfd->hw.init = &init; From d678d83c583dd6d00b7e3e0c5c78e8441e1a9131 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Feb 2020 15:59:49 +0800 Subject: [PATCH 1372/4444] clk: imx: pllv4: use prepare/unprepare It is not good to use enable/disable for PLLv4 which needs time to lock, because enable/disable is expected to be able run in interrupt context. So use prepare/unprepare. Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-pllv4.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/imx/clk-pllv4.c b/drivers/clk/imx/clk-pllv4.c index f51a800c268c..a49450431855 100644 --- a/drivers/clk/imx/clk-pllv4.c +++ b/drivers/clk/imx/clk-pllv4.c @@ -54,7 +54,7 @@ static inline int clk_pllv4_wait_lock(struct clk_pllv4 *pll) csr, csr & PLL_VLD, 0, LOCK_TIMEOUT_US); } -static int clk_pllv4_is_enabled(struct clk_hw *hw) +static int clk_pllv4_is_prepared(struct clk_hw *hw) { struct clk_pllv4 *pll = to_clk_pllv4(hw); @@ -175,7 +175,7 @@ static int clk_pllv4_set_rate(struct clk_hw *hw, unsigned long rate, return 0; } -static int clk_pllv4_enable(struct clk_hw *hw) +static int clk_pllv4_prepare(struct clk_hw *hw) { u32 val; struct clk_pllv4 *pll = to_clk_pllv4(hw); @@ -187,7 +187,7 @@ static int clk_pllv4_enable(struct clk_hw *hw) return clk_pllv4_wait_lock(pll); } -static void clk_pllv4_disable(struct clk_hw *hw) +static void clk_pllv4_unprepare(struct clk_hw *hw) { u32 val; struct clk_pllv4 *pll = to_clk_pllv4(hw); @@ -201,9 +201,9 @@ static const struct clk_ops clk_pllv4_ops = { .recalc_rate = clk_pllv4_recalc_rate, .round_rate = clk_pllv4_round_rate, .set_rate = clk_pllv4_set_rate, - .enable = clk_pllv4_enable, - .disable = clk_pllv4_disable, - .is_enabled = clk_pllv4_is_enabled, + .prepare = clk_pllv4_prepare, + .unprepare = clk_pllv4_unprepare, + .is_prepared = clk_pllv4_is_prepared, }; struct clk_hw *imx_clk_hw_pllv4(const char *name, const char *parent_name, From 60378f1a171e25b7a2eb8ec820a1d0477e879309 Mon Sep 17 00:00:00 2001 From: Venkata Narendra Kumar Gutta Date: Tue, 10 Mar 2020 10:39:10 +0530 Subject: [PATCH 1373/4444] arm64: dts: qcom: sm8250: Add sm8250 dts file Add sm8250 devicetree file for SM8250 SoC and SM8250 MTP platform. This file adds the basic nodes like cpu, psci and other required configuration for booting up to the serial console. Signed-off-by: Venkata Narendra Kumar Gutta Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20200310050910.506854-1-vkoul@kernel.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/Makefile | 1 + arch/arm64/boot/dts/qcom/sm8250-mtp.dts | 29 ++ arch/arm64/boot/dts/qcom/sm8250.dtsi | 444 ++++++++++++++++++++++++ 3 files changed, 474 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sm8250-mtp.dts create mode 100644 arch/arm64/boot/dts/qcom/sm8250.dtsi diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 204775f3af50..cc103f7020fd 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -23,5 +23,6 @@ dtb-$(CONFIG_ARCH_QCOM) += sdm845-db845c.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm845-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm850-lenovo-yoga-c630.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8150-mtp.dtb +dtb-$(CONFIG_ARCH_QCOM) += sm8250-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-1000.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-4000.dtb diff --git a/arch/arm64/boot/dts/qcom/sm8250-mtp.dts b/arch/arm64/boot/dts/qcom/sm8250-mtp.dts new file mode 100644 index 000000000000..224d0f1ea6f9 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm8250-mtp.dts @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +/dts-v1/; + +#include "sm8250.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SM8250 MTP"; + compatible = "qcom,sm8250-mtp"; + + aliases { + serial0 = &uart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&qupv3_id_1 { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi new file mode 100644 index 000000000000..891d83b2afea --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi @@ -0,0 +1,444 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include + +/ { + interrupt-parent = <&intc>; + + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + clocks { + xo_board: xo-board { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <38400000>; + clock-output-names = "xo_board"; + }; + + sleep_clk: sleep-clk { + compatible = "fixed-clock"; + clock-frequency = <32000>; + #clock-cells = <0>; + }; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + CPU0: cpu@0 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x0>; + enable-method = "psci"; + next-level-cache = <&L2_0>; + L2_0: l2-cache { + compatible = "cache"; + next-level-cache = <&L3_0>; + L3_0: l3-cache { + compatible = "cache"; + }; + }; + }; + + CPU1: cpu@100 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x100>; + enable-method = "psci"; + next-level-cache = <&L2_100>; + L2_100: l2-cache { + compatible = "cache"; + next-level-cache = <&L3_0>; + }; + }; + + CPU2: cpu@200 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x200>; + enable-method = "psci"; + next-level-cache = <&L2_200>; + L2_200: l2-cache { + compatible = "cache"; + next-level-cache = <&L3_0>; + }; + }; + + CPU3: cpu@300 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x300>; + enable-method = "psci"; + next-level-cache = <&L2_300>; + L2_300: l2-cache { + compatible = "cache"; + next-level-cache = <&L3_0>; + }; + }; + + CPU4: cpu@400 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x400>; + enable-method = "psci"; + next-level-cache = <&L2_400>; + L2_400: l2-cache { + compatible = "cache"; + next-level-cache = <&L3_0>; + }; + }; + + CPU5: cpu@500 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x500>; + enable-method = "psci"; + next-level-cache = <&L2_500>; + L2_500: l2-cache { + compatible = "cache"; + next-level-cache = <&L3_0>; + }; + + }; + + CPU6: cpu@600 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x600>; + enable-method = "psci"; + next-level-cache = <&L2_600>; + L2_600: l2-cache { + compatible = "cache"; + next-level-cache = <&L3_0>; + }; + }; + + CPU7: cpu@700 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x700>; + enable-method = "psci"; + next-level-cache = <&L2_700>; + L2_700: l2-cache { + compatible = "cache"; + next-level-cache = <&L3_0>; + }; + }; + }; + + firmware { + scm: scm { + compatible = "qcom,scm"; + #reset-cells = <1>; + }; + }; + + tcsr_mutex: hwlock { + compatible = "qcom,tcsr-mutex"; + syscon = <&tcsr_mutex_regs 0 0x1000>; + #hwlock-cells = <1>; + }; + + memory@80000000 { + device_type = "memory"; + /* We expect the bootloader to fill in the size */ + reg = <0x0 0x80000000 0x0 0x0>; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = ; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + hyp_mem: memory@80000000 { + reg = <0x0 0x80000000 0x0 0x600000>; + no-map; + }; + + xbl_aop_mem: memory@80700000 { + reg = <0x0 0x80700000 0x0 0x160000>; + no-map; + }; + + cmd_db: memory@80860000 { + compatible = "qcom,cmd-db"; + reg = <0x0 0x80860000 0x0 0x20000>; + no-map; + }; + + smem_mem: memory@80900000 { + reg = <0x0 0x80900000 0x0 0x200000>; + no-map; + }; + + removed_mem: memory@80b00000 { + reg = <0x0 0x80b00000 0x0 0x5300000>; + no-map; + }; + + camera_mem: memory@86200000 { + reg = <0x0 0x86200000 0x0 0x500000>; + no-map; + }; + + wlan_mem: memory@86700000 { + reg = <0x0 0x86700000 0x0 0x100000>; + no-map; + }; + + ipa_fw_mem: memory@86800000 { + reg = <0x0 0x86800000 0x0 0x10000>; + no-map; + }; + + ipa_gsi_mem: memory@86810000 { + reg = <0x0 0x86810000 0x0 0xa000>; + no-map; + }; + + gpu_mem: memory@8681a000 { + reg = <0x0 0x8681a000 0x0 0x2000>; + no-map; + }; + + npu_mem: memory@86900000 { + reg = <0x0 0x86900000 0x0 0x500000>; + no-map; + }; + + video_mem: memory@86e00000 { + reg = <0x0 0x86e00000 0x0 0x500000>; + no-map; + }; + + cvp_mem: memory@87300000 { + reg = <0x0 0x87300000 0x0 0x500000>; + no-map; + }; + + cdsp_mem: memory@87800000 { + reg = <0x0 0x87800000 0x0 0x1400000>; + no-map; + }; + + slpi_mem: memory@88c00000 { + reg = <0x0 0x88c00000 0x0 0x1500000>; + no-map; + }; + + adsp_mem: memory@8a100000 { + reg = <0x0 0x8a100000 0x0 0x1d00000>; + no-map; + }; + + spss_mem: memory@8be00000 { + reg = <0x0 0x8be00000 0x0 0x100000>; + no-map; + }; + + cdsp_secure_heap: memory@8bf00000 { + reg = <0x0 0x8bf00000 0x0 0x4600000>; + no-map; + }; + }; + + smem: qcom,smem { + compatible = "qcom,smem"; + memory-region = <&smem_mem>; + hwlocks = <&tcsr_mutex 3>; + }; + + soc: soc@0 { + #address-cells = <2>; + #size-cells = <2>; + ranges = <0 0 0 0 0x10 0>; + dma-ranges = <0 0 0 0 0x10 0>; + compatible = "simple-bus"; + + gcc: clock-controller@100000 { + compatible = "qcom,gcc-sm8250"; + reg = <0x0 0x00100000 0x0 0x1f0000>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + clock-names = "bi_tcxo", "sleep_clk"; + clocks = <&rpmhcc RPMH_CXO_CLK>, <&sleep_clk>; + }; + + qupv3_id_1: geniqup@ac0000 { + compatible = "qcom,geni-se-qup"; + reg = <0x0 0x00ac0000 0x0 0x6000>; + clock-names = "m-ahb", "s-ahb"; + clocks = <&gcc 133>, <&gcc 134>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + uart2: serial@a90000 { + compatible = "qcom,geni-debug-uart"; + reg = <0x0 0x00a90000 0x0 0x4000>; + clock-names = "se"; + clocks = <&gcc 113>; + interrupts = ; + status = "disabled"; + }; + }; + + intc: interrupt-controller@17a00000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x0 0x17a00000 0x0 0x10000>, /* GICD */ + <0x0 0x17a60000 0x0 0x100000>; /* GICR * 8 */ + interrupts = ; + }; + + pdc: interrupt-controller@b220000 { + compatible = "qcom,sm8250-pdc"; + reg = <0x0b220000 0x30000>, <0x17c000f0 0x60>; + qcom,pdc-ranges = <0 480 94>, <94 609 31>, + <125 63 1>, <126 716 12>; + #interrupt-cells = <2>; + interrupt-parent = <&intc>; + interrupt-controller; + }; + + spmi: qcom,spmi@c440000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x0 0x0c440000 0x0 0x0001100>, + <0x0 0x0c600000 0x0 0x2000000>, + <0x0 0x0e600000 0x0 0x0100000>, + <0x0 0x0e700000 0x0 0x00a0000>, + <0x0 0x0c40a000 0x0 0x0026000>; + reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; + interrupt-names = "periph_irq"; + interrupts-extended = <&pdc 1 IRQ_TYPE_LEVEL_HIGH>; + qcom,ee = <0>; + qcom,channel = <0>; + #address-cells = <2>; + #size-cells = <0>; + interrupt-controller; + #interrupt-cells = <4>; + }; + + apps_rsc: rsc@18200000 { + label = "apps_rsc"; + compatible = "qcom,rpmh-rsc"; + reg = <0x0 0x18200000 0x0 0x10000>, + <0x0 0x18210000 0x0 0x10000>, + <0x0 0x18220000 0x0 0x10000>; + reg-names = "drv-0", "drv-1", "drv-2"; + interrupts = , + , + ; + qcom,tcs-offset = <0xd00>; + qcom,drv-id = <2>; + qcom,tcs-config = , , + , ; + + rpmhcc: clock-controller { + compatible = "qcom,sm8250-rpmh-clk"; + #clock-cells = <1>; + clock-names = "xo"; + clocks = <&xo_board>; + }; + }; + + tcsr_mutex_regs: syscon@1f40000 { + compatible = "syscon"; + reg = <0x0 0x01f40000 0x0 0x40000>; + }; + + timer@17c20000 { + #address-cells = <2>; + #size-cells = <2>; + ranges; + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x17c20000 0x0 0x1000>; + clock-frequency = <19200000>; + + frame@17c21000 { + frame-number = <0>; + interrupts = , + ; + reg = <0x0 0x17c21000 0x0 0x1000>, + <0x0 0x17c22000 0x0 0x1000>; + }; + + frame@17c23000 { + frame-number = <1>; + interrupts = ; + reg = <0x0 0x17c23000 0x0 0x1000>; + status = "disabled"; + }; + + frame@17c25000 { + frame-number = <2>; + interrupts = ; + reg = <0x0 0x17c25000 0x0 0x1000>; + status = "disabled"; + }; + + frame@17c27000 { + frame-number = <3>; + interrupts = ; + reg = <0x0 0x17c27000 0x0 0x1000>; + status = "disabled"; + }; + + frame@17c29000 { + frame-number = <4>; + interrupts = ; + reg = <0x0 0x17c29000 0x0 0x1000>; + status = "disabled"; + }; + + frame@17c2b000 { + frame-number = <5>; + interrupts = ; + reg = <0x0 0x17c2b000 0x0 0x1000>; + status = "disabled"; + }; + + frame@17c2d000 { + frame-number = <6>; + interrupts = ; + reg = <0x0 0x17c2d000 0x0 0x1000>; + status = "disabled"; + }; + }; + + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; +}; From 8cdff3241f63da30b0228d8719cf04b72d671f7d Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 19 Feb 2020 10:07:12 -0300 Subject: [PATCH 1374/4444] ARM: dts: imx6sx-softing-vining-2000: Enable PCI support Add PCI support. Since this board has an active high PCI reset line, pass the 'reset-gpio-active-high' property. Signed-off-by: Fabio Estevam Reviewed-by: Marek Vasut Tested-by: Marek Vasut Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sx-softing-vining-2000.dts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm/boot/dts/imx6sx-softing-vining-2000.dts b/arch/arm/boot/dts/imx6sx-softing-vining-2000.dts index 61c7e723ad5d..6b728b03f1f2 100644 --- a/arch/arm/boot/dts/imx6sx-softing-vining-2000.dts +++ b/arch/arm/boot/dts/imx6sx-softing-vining-2000.dts @@ -352,6 +352,12 @@ >; }; + pinctrl_pcie: pciegrp { + fsl,pins = < + MX6SX_PAD_NAND_DATA02__GPIO4_IO_6 0x10b0 + >; + }; + pinctrl_pwm1: pwm1grp-1 { fsl,pins = < /* blue LED */ @@ -490,6 +496,14 @@ }; }; +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pcie>; + reset-gpio = <&gpio4 6 GPIO_ACTIVE_HIGH>; + reset-gpio-active-high; + status = "okay"; +}; + &pwm1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pwm1>; From 44d92b2c40da1a50ce1d6a116732b6724d5c4b74 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 10 Mar 2020 13:59:25 +0900 Subject: [PATCH 1375/4444] xtensa: remove meaningless export ccflags-y arch/xtensa/boot/Makefile does not define ccflags-y at all. Please do not export ccflags-y because it is meant to be effective only in the current Makefile. Signed-off-by: Masahiro Yamada Message-Id: <20200310045925.25396-1-masahiroy@kernel.org> Signed-off-by: Max Filippov --- arch/xtensa/boot/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/xtensa/boot/Makefile b/arch/xtensa/boot/Makefile index efb91bfda2b4..1a14d38d9b33 100644 --- a/arch/xtensa/boot/Makefile +++ b/arch/xtensa/boot/Makefile @@ -14,7 +14,6 @@ HOSTFLAGS += -Iarch/$(ARCH)/boot/include BIG_ENDIAN := $(shell echo __XTENSA_EB__ | $(CC) -E - | grep -v "\#") -export ccflags-y export BIG_ENDIAN subdir-y := lib From 34e46ed80df6cdeafad3cd344dd28837ba17053e Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Sat, 22 Feb 2020 08:08:51 +0800 Subject: [PATCH 1376/4444] arm64: defconfig: add i.MX system controller thermal support This patch enables CONFIG_IMX_SC_THERMAL as module. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 256345fef287..31d098438a43 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -454,6 +454,7 @@ CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y CONFIG_CPU_THERMAL=y CONFIG_THERMAL_EMULATION=y CONFIG_QORIQ_THERMAL=m +CONFIG_IMX_SC_THERMAL=m CONFIG_ROCKCHIP_THERMAL=m CONFIG_RCAR_THERMAL=y CONFIG_RCAR_GEN3_THERMAL=y From 1e95b4f8faaa6033f59423256e5e3a750cb3ee90 Mon Sep 17 00:00:00 2001 From: Yuya Hamamachi Date: Mon, 9 Mar 2020 15:44:24 +0900 Subject: [PATCH 1377/4444] dt-bindings: arm: renesas: Add M3ULCB with R-Car M3-W+ Add device tree binding documentation for the Renesas M3ULCB board equipped with an R-Car M3-W+ (R8A77961) SoC. Signed-off-by: Yuya Hamamachi Link: https://lore.kernel.org/r/20200309064425.25437-2-yuya.hamamachi.sx@renesas.com Signed-off-by: Geert Uytterhoeven --- Documentation/devicetree/bindings/arm/renesas.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/renesas.yaml b/Documentation/devicetree/bindings/arm/renesas.yaml index 9436124c5809..611094d9186b 100644 --- a/Documentation/devicetree/bindings/arm/renesas.yaml +++ b/Documentation/devicetree/bindings/arm/renesas.yaml @@ -208,6 +208,7 @@ properties: - description: R-Car M3-W+ (R8A77961) items: - enum: + - renesas,m3ulcb # M3ULCB (R-Car Starter Kit Pro, RTP8J77961ASKB0SK0SA05A (M3 ES3.0)) - renesas,salvator-xs # Salvator-XS (Salvator-X 2nd version, RTP0RC7796SIPB0012SA5A) - const: renesas,r8a77961 From a786b80c48c2d135a2387b870b19ab503701c314 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 25 Feb 2020 15:26:13 +0100 Subject: [PATCH 1378/4444] i2c: powermac: correct comment about custom handling The comment had some flaws which are now fixed: - the prefix is 'MAC' not 'AAPL' - no kernel coding style and too short length - 'we do' instead of 'we to' Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-powermac.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index 973e5339033c..d565714c1f13 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -279,14 +279,13 @@ static bool i2c_powermac_get_type(struct i2c_adapter *adap, { char tmp[16]; - /* Note: we to _NOT_ want the standard - * i2c drivers to match with any of our powermac stuff - * unless they have been specifically modified to handle - * it on a case by case basis. For example, for thermal - * control, things like lm75 etc... shall match with their - * corresponding windfarm drivers, _NOT_ the generic ones, - * so we force a prefix of AAPL, onto the modalias to - * make that happen + /* + * Note: we do _NOT_ want the standard i2c drivers to match with any of + * our powermac stuff unless they have been specifically modified to + * handle it on a case by case basis. For example, for thermal control, + * things like lm75 etc... shall match with their corresponding + * windfarm drivers, _NOT_ the generic ones, so we force a prefix of + * 'MAC', onto the modalias to make that happen */ /* First try proper modalias */ From 6b060d8a09e9ab03748d1134c34275714a3c0217 Mon Sep 17 00:00:00 2001 From: chenqiwu Date: Fri, 14 Feb 2020 20:56:37 +0800 Subject: [PATCH 1379/4444] i2c: use kobj_to_dev() API Use kobj_to_dev() API instead of container_of(). Signed-off-by: chenqiwu Reviewed-by: Luca Ceresoli Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-slave-eeprom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/i2c-slave-eeprom.c b/drivers/i2c/i2c-slave-eeprom.c index db9763cb4dae..cb415b10642f 100644 --- a/drivers/i2c/i2c-slave-eeprom.c +++ b/drivers/i2c/i2c-slave-eeprom.c @@ -96,7 +96,7 @@ static ssize_t i2c_slave_eeprom_bin_read(struct file *filp, struct kobject *kobj struct eeprom_data *eeprom; unsigned long flags; - eeprom = dev_get_drvdata(container_of(kobj, struct device, kobj)); + eeprom = dev_get_drvdata(kobj_to_dev(kobj)); spin_lock_irqsave(&eeprom->buffer_lock, flags); memcpy(buf, &eeprom->buffer[off], count); @@ -111,7 +111,7 @@ static ssize_t i2c_slave_eeprom_bin_write(struct file *filp, struct kobject *kob struct eeprom_data *eeprom; unsigned long flags; - eeprom = dev_get_drvdata(container_of(kobj, struct device, kobj)); + eeprom = dev_get_drvdata(kobj_to_dev(kobj)); spin_lock_irqsave(&eeprom->buffer_lock, flags); memcpy(&eeprom->buffer[off], buf, count); From f16c140810e739ba2b7af2fecfd2c84fb1af8aef Mon Sep 17 00:00:00 2001 From: chenqiwu Date: Sat, 15 Feb 2020 16:36:43 +0800 Subject: [PATCH 1380/4444] i2c: omap: use devm_platform_ioremap_resource() Use a new API devm_platform_ioremap_resource() to simplify code. Signed-off-by: chenqiwu Tested-by: Luca Ceresoli Reviewed-by: Luca Ceresoli Reviewed-by: Vignesh Raghavendra Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-omap.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 2dfea357b131..47d994a7c473 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1355,7 +1355,6 @@ omap_i2c_probe(struct platform_device *pdev) { struct omap_i2c_dev *omap; struct i2c_adapter *adap; - struct resource *mem; const struct omap_i2c_bus_platform_data *pdata = dev_get_platdata(&pdev->dev); struct device_node *node = pdev->dev.of_node; @@ -1375,8 +1374,7 @@ omap_i2c_probe(struct platform_device *pdev) if (!omap) return -ENOMEM; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - omap->base = devm_ioremap_resource(&pdev->dev, mem); + omap->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(omap->base)) return PTR_ERR(omap->base); From 7038781331ac09fa2f489f3de3fcdd87a9fad535 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 24 Feb 2020 10:06:03 +0100 Subject: [PATCH 1381/4444] dt-bindings: i2c: brcmstb: Convert the BRCMSTB binding to a schema Switch the DT binding to a YAML schema to enable the DT validation. Signed-off-by: Maxime Ripard Acked-by: Florian Fainelli Reviewed-by: Rob Herring Signed-off-by: Wolfram Sang --- .../bindings/i2c/brcm,brcmstb-i2c.yaml | 59 +++++++++++++++++++ .../devicetree/bindings/i2c/i2c-brcmstb.txt | 26 -------- MAINTAINERS | 2 +- 3 files changed, 60 insertions(+), 27 deletions(-) create mode 100644 Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml delete mode 100644 Documentation/devicetree/bindings/i2c/i2c-brcmstb.txt diff --git a/Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml b/Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml new file mode 100644 index 000000000000..3189d74096e8 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/brcm,brcmstb-i2c.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom STB BSC IIC Master Controller + +maintainers: + - Kamal Dasu + +allOf: + - $ref: /schemas/i2c/i2c-controller.yaml# + +properties: + compatible: + enum: + - brcm,brcmstb-i2c + - brcm,brcmper-i2c + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + interrupt-names: + maxItems: 1 + + clock-frequency: + enum: + - 46875 + - 50000 + - 93750 + - 97500 + - 187500 + - 200000 + - 375000 + - 390000 + +required: + - compatible + - reg + - clock-frequency + +unevaluatedProperties: false + +examples: + - | + bsca: i2c@f0406200 { + clock-frequency = <390000>; + compatible = "brcm,brcmstb-i2c"; + interrupt-parent = <&irq0_intc>; + reg = <0xf0406200 0x58>; + interrupts = <0x18>; + interrupt-names = "upg_bsca"; + }; + +... diff --git a/Documentation/devicetree/bindings/i2c/i2c-brcmstb.txt b/Documentation/devicetree/bindings/i2c/i2c-brcmstb.txt deleted file mode 100644 index 0380609b177a..000000000000 --- a/Documentation/devicetree/bindings/i2c/i2c-brcmstb.txt +++ /dev/null @@ -1,26 +0,0 @@ -Broadcom stb bsc iic master controller - -Required properties: - -- compatible: should be "brcm,brcmstb-i2c" or "brcm,brcmper-i2c" -- clock-frequency: 32-bit decimal value of iic master clock freqency in Hz - valid values are 375000, 390000, 187500, 200000 - 93750, 97500, 46875 and 50000 -- reg: specifies the base physical address and size of the registers - -Optional properties : - -- interrupts: specifies the interrupt number, the irq line to be used -- interrupt-names: Interrupt name string - -Example: - -bsca: i2c@f0406200 { - clock-frequency = <390000>; - compatible = "brcm,brcmstb-i2c"; - interrupt-parent = <&irq0_intc>; - reg = <0xf0406200 0x58>; - interrupts = <0x18>; - interrupt-names = "upg_bsca"; -}; - diff --git a/MAINTAINERS b/MAINTAINERS index fcd79fc38928..e270e0cebc52 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3431,7 +3431,7 @@ L: linux-i2c@vger.kernel.org L: bcm-kernel-feedback-list@broadcom.com S: Supported F: drivers/i2c/busses/i2c-brcmstb.c -F: Documentation/devicetree/bindings/i2c/i2c-brcmstb.txt +F: Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml BROADCOM BRCMSTB USB2 and USB3 PHY DRIVER M: Al Cooper From 1de20644c4127db48ab408b0070d63d6b14c5caf Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 24 Feb 2020 10:06:04 +0100 Subject: [PATCH 1382/4444] dt-bindings: i2c: brcmstb: Add BCM2711 BSC/AUTO-I2C binding The HDMI blocks in the BCM2771 have an i2c controller to retrieve the EDID. This block is split into two parts, the BSC and the AUTO_I2C, lying in two separate register areas. The AUTO_I2C block has a mailbox-like interface and will take away the BSC control from the CPU if enabled. However, the BSC is the actually the same controller than the one supported by the brcmstb driver, and the AUTO_I2C doesn't really bring any immediate benefit. We can model it in the DT as a single device with two register range, which will allow us to use or or the other in the driver without changing anything in the DT. Signed-off-by: Maxime Ripard Acked-by: Florian Fainelli Reviewed-by: Rob Herring Signed-off-by: Wolfram Sang --- .../bindings/i2c/brcm,brcmstb-i2c.yaml | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml b/Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml index 3189d74096e8..edbca2476128 100644 --- a/Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml @@ -15,11 +15,21 @@ allOf: properties: compatible: enum: + - brcm,bcm2711-hdmi-i2c - brcm,brcmstb-i2c - brcm,brcmper-i2c reg: - maxItems: 1 + minItems: 1 + maxItems: 2 + items: + - description: BSC register range + - description: Auto-I2C register range + + reg-names: + items: + - const: bsc + - const: auto-i2c interrupts: maxItems: 1 @@ -45,6 +55,26 @@ required: unevaluatedProperties: false +if: + properties: + compatible: + contains: + enum: + - brcm,bcm2711-hdmi-i2c + +then: + properties: + reg: + minItems: 2 + + required: + - reg-names + +else: + properties: + reg: + maxItems: 1 + examples: - | bsca: i2c@f0406200 { @@ -56,4 +86,12 @@ examples: interrupt-names = "upg_bsca"; }; + - | + ddc0: i2c@7ef04500 { + compatible = "brcm,bcm2711-hdmi-i2c"; + reg = <0x7ef04500 0x100>, <0x7ef00b00 0x300>; + reg-names = "bsc", "auto-i2c"; + clock-frequency = <390000>; + }; + ... From d31f59eabea120b9ad149691f8314ce1b55a59ba Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 24 Feb 2020 10:06:05 +0100 Subject: [PATCH 1383/4444] i2c: brcmstb: Support BCM2711 HDMI BSC controllers The HDMI blocks in the BCM2771 have an i2c controller to retrieve the EDID. This block is split into two parts, the BSC and the AUTO_I2C, lying in two separate register areas. The AUTO_I2C block has a mailbox-like interface and will take away the BSC control from the CPU if enabled. However, the BSC is the actually the same controller than the one supported by the brcmstb driver, and the AUTO_I2C doesn't really bring any immediate benefit. Let's use the BSC then, but let's also tie the AUTO_I2C registers with a separate compatible so that we can enable AUTO_I2C if needed in the future. The AUTO_I2C is enabled by default at boot though, so we first need to release the BSC from the AUTO_I2C control. Cc: Kamal Dasu Cc: Florian Fainelli Cc: Wolfram Sang Cc: bcm-kernel-feedback-list@broadcom.com Cc: linux-i2c@vger.kernel.org Signed-off-by: Maxime Ripard Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-brcmstb.c | 33 ++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c index 506991596b68..169a2836922d 100644 --- a/drivers/i2c/busses/i2c-brcmstb.c +++ b/drivers/i2c/busses/i2c-brcmstb.c @@ -580,6 +580,31 @@ static void brcmstb_i2c_set_bsc_reg_defaults(struct brcmstb_i2c_dev *dev) brcmstb_i2c_set_bus_speed(dev); } +#define AUTOI2C_CTRL0 0x26c +#define AUTOI2C_CTRL0_RELEASE_BSC BIT(1) + +static int bcm2711_release_bsc(struct brcmstb_i2c_dev *dev) +{ + struct platform_device *pdev = to_platform_device(dev->device); + struct resource *iomem; + void __iomem *autoi2c; + + /* Map hardware registers */ + iomem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "auto-i2c"); + autoi2c = devm_ioremap_resource(&pdev->dev, iomem); + if (IS_ERR(autoi2c)) + return PTR_ERR(autoi2c); + + writel(AUTOI2C_CTRL0_RELEASE_BSC, autoi2c + AUTOI2C_CTRL0); + devm_iounmap(&pdev->dev, autoi2c); + + /* We need to reset the controller after the release */ + dev->bsc_regmap->iic_enable = 0; + bsc_writel(dev, dev->bsc_regmap->iic_enable, iic_enable); + + return 0; +} + static int brcmstb_i2c_probe(struct platform_device *pdev) { int rc = 0; @@ -609,6 +634,13 @@ static int brcmstb_i2c_probe(struct platform_device *pdev) goto probe_errorout; } + if (of_device_is_compatible(dev->device->of_node, + "brcm,bcm2711-hdmi-i2c")) { + rc = bcm2711_release_bsc(dev); + if (rc) + goto probe_errorout; + } + rc = of_property_read_string(dev->device->of_node, "interrupt-names", &int_name); if (rc < 0) @@ -705,6 +737,7 @@ static SIMPLE_DEV_PM_OPS(brcmstb_i2c_pm, brcmstb_i2c_suspend, static const struct of_device_id brcmstb_i2c_of_match[] = { {.compatible = "brcm,brcmstb-i2c"}, {.compatible = "brcm,brcmper-i2c"}, + {.compatible = "brcm,bcm2711-hdmi-i2c"}, {}, }; MODULE_DEVICE_TABLE(of, brcmstb_i2c_of_match); From 3347ea9bafe76305ac5305fc6eebefbc5e046d49 Mon Sep 17 00:00:00 2001 From: Alain Volmat Date: Mon, 2 Mar 2020 12:33:07 +0100 Subject: [PATCH 1384/4444] i2c: stm32f7: disable/restore Fast Mode Plus bits in low power modes Defer the initial enabling of the Fast Mode Plus bits after the stm32f7_i2c_setup_timing call in probe function in order to avoid enabling them if speed is downgraded. Clear & restore the Fast Mode Plus bits in the suspend/resume handlers of the driver. Signed-off-by: Alain Volmat Reviewed-by: Pierre-Yves MORDRET Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-stm32f7.c | 52 ++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index 378956ac6d1d..cfe6d790a8fc 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -303,6 +303,8 @@ struct stm32f7_i2c_msg { * @dma: dma data * @use_dma: boolean to know if dma is used in the current transfer * @regmap: holds SYSCFG phandle for Fast Mode Plus bits + * @fmp_reg: register address for setting Fast Mode Plus bits + * @fmp_mask: mask for Fast Mode Plus bits in set register * @wakeup_src: boolean to know if the device is a wakeup source */ struct stm32f7_i2c_dev { @@ -326,6 +328,8 @@ struct stm32f7_i2c_dev { struct stm32_i2c_dma *dma; bool use_dma; struct regmap *regmap; + u32 fmp_reg; + u32 fmp_mask; bool wakeup_src; }; @@ -1830,28 +1834,37 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave) return 0; } +static int stm32f7_i2c_write_fm_plus_bits(struct stm32f7_i2c_dev *i2c_dev, + bool enable) +{ + if (i2c_dev->speed != STM32_I2C_SPEED_FAST_PLUS || + IS_ERR_OR_NULL(i2c_dev->regmap)) + /* Optional */ + return 0; + + return regmap_update_bits(i2c_dev->regmap, i2c_dev->fmp_reg, + i2c_dev->fmp_mask, + enable ? i2c_dev->fmp_mask : 0); +} + static int stm32f7_i2c_setup_fm_plus_bits(struct platform_device *pdev, struct stm32f7_i2c_dev *i2c_dev) { struct device_node *np = pdev->dev.of_node; int ret; - u32 reg, mask; i2c_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg-fmp"); - if (IS_ERR(i2c_dev->regmap)) { + if (IS_ERR(i2c_dev->regmap)) /* Optional */ return 0; - } - ret = of_property_read_u32_index(np, "st,syscfg-fmp", 1, ®); + ret = of_property_read_u32_index(np, "st,syscfg-fmp", 1, + &i2c_dev->fmp_reg); if (ret) return ret; - ret = of_property_read_u32_index(np, "st,syscfg-fmp", 2, &mask); - if (ret) - return ret; - - return regmap_update_bits(i2c_dev->regmap, reg, mask, mask); + return of_property_read_u32_index(np, "st,syscfg-fmp", 2, + &i2c_dev->fmp_mask); } static u32 stm32f7_i2c_func(struct i2c_adapter *adap) @@ -1929,9 +1942,6 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) &clk_rate); if (!ret && clk_rate >= 1000000) { i2c_dev->speed = STM32_I2C_SPEED_FAST_PLUS; - ret = stm32f7_i2c_setup_fm_plus_bits(pdev, i2c_dev); - if (ret) - goto clk_free; } else if (!ret && clk_rate >= 400000) { i2c_dev->speed = STM32_I2C_SPEED_FAST; } else if (!ret && clk_rate >= 100000) { @@ -1991,6 +2001,15 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) if (ret) goto clk_free; + if (i2c_dev->speed == STM32_I2C_SPEED_FAST_PLUS) { + ret = stm32f7_i2c_setup_fm_plus_bits(pdev, i2c_dev); + if (ret) + goto clk_free; + ret = stm32f7_i2c_write_fm_plus_bits(i2c_dev, true); + if (ret) + goto clk_free; + } + adap = &i2c_dev->adap; i2c_set_adapdata(adap, i2c_dev); snprintf(adap->name, sizeof(adap->name), "STM32F7 I2C(%pa)", @@ -2015,7 +2034,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) if (ret != -EPROBE_DEFER) dev_err(&pdev->dev, "Failed to request dma error %i\n", ret); - goto clk_free; + goto fmp_clear; } if (i2c_dev->wakeup_src) { @@ -2069,6 +2088,9 @@ clr_wakeup_capable: i2c_dev->dma = NULL; } +fmp_clear: + stm32f7_i2c_write_fm_plus_bits(i2c_dev, false); + clk_free: clk_disable_unprepare(i2c_dev->clk); @@ -2101,6 +2123,8 @@ static int stm32f7_i2c_remove(struct platform_device *pdev) i2c_dev->dma = NULL; } + stm32f7_i2c_write_fm_plus_bits(i2c_dev, false); + clk_disable_unprepare(i2c_dev->clk); return 0; @@ -2148,6 +2172,7 @@ static int stm32f7_i2c_regs_backup(struct stm32f7_i2c_dev *i2c_dev) backup_regs->oar2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR2); backup_regs->pecr = readl_relaxed(i2c_dev->base + STM32F7_I2C_PECR); backup_regs->tmgr = readl_relaxed(i2c_dev->base + STM32F7_I2C_TIMINGR); + stm32f7_i2c_write_fm_plus_bits(i2c_dev, false); pm_runtime_put_sync(i2c_dev->dev); @@ -2179,6 +2204,7 @@ static int stm32f7_i2c_regs_restore(struct stm32f7_i2c_dev *i2c_dev) writel_relaxed(backup_regs->oar1, i2c_dev->base + STM32F7_I2C_OAR1); writel_relaxed(backup_regs->oar2, i2c_dev->base + STM32F7_I2C_OAR2); writel_relaxed(backup_regs->pecr, i2c_dev->base + STM32F7_I2C_PECR); + stm32f7_i2c_write_fm_plus_bits(i2c_dev, true); pm_runtime_put_sync(i2c_dev->dev); From 0f8205640784a263bf9fead2729a0820dae01eee Mon Sep 17 00:00:00 2001 From: Alain Volmat Date: Mon, 2 Mar 2020 12:33:16 +0100 Subject: [PATCH 1385/4444] i2c: stm32f7: add a new st, stm32mp15-i2c compatible Add a new stm32mp15 specific compatible to handle FastMode+ registers handling which is different on the stm32mp15 compared to the stm32f7 or stm32h7. Indeed, on the stm32mp15, the FastMode+ set and clear registers are separated while on the other platforms (F7 or H7) the control is done in a unique register. Signed-off-by: Alain Volmat Reviewed-by: Pierre-Yves MORDRET Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-stm32f7.c | 39 +++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index cfe6d790a8fc..8fe7f8caf91b 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -223,6 +223,7 @@ struct stm32f7_i2c_spec { * @fall_time: Fall time (ns) * @dnf: Digital filter coefficient (0-16) * @analog_filter: Analog filter delay (On/Off) + * @fmp_clr_offset: Fast Mode Plus clear register offset from set register */ struct stm32f7_i2c_setup { enum stm32_i2c_speed speed; @@ -232,6 +233,7 @@ struct stm32f7_i2c_setup { u32 fall_time; u8 dnf; bool analog_filter; + u32 fmp_clr_offset; }; /** @@ -303,7 +305,8 @@ struct stm32f7_i2c_msg { * @dma: dma data * @use_dma: boolean to know if dma is used in the current transfer * @regmap: holds SYSCFG phandle for Fast Mode Plus bits - * @fmp_reg: register address for setting Fast Mode Plus bits + * @fmp_sreg: register address for setting Fast Mode Plus bits + * @fmp_creg: register address for clearing Fast Mode Plus bits * @fmp_mask: mask for Fast Mode Plus bits in set register * @wakeup_src: boolean to know if the device is a wakeup source */ @@ -328,7 +331,8 @@ struct stm32f7_i2c_dev { struct stm32_i2c_dma *dma; bool use_dma; struct regmap *regmap; - u32 fmp_reg; + u32 fmp_sreg; + u32 fmp_creg; u32 fmp_mask; bool wakeup_src; }; @@ -386,6 +390,14 @@ static const struct stm32f7_i2c_setup stm32f7_setup = { .analog_filter = STM32F7_I2C_ANALOG_FILTER_ENABLE, }; +static const struct stm32f7_i2c_setup stm32mp15_setup = { + .rise_time = STM32F7_I2C_RISE_TIME_DEFAULT, + .fall_time = STM32F7_I2C_FALL_TIME_DEFAULT, + .dnf = STM32F7_I2C_DNF_DEFAULT, + .analog_filter = STM32F7_I2C_ANALOG_FILTER_ENABLE, + .fmp_clr_offset = 0x40, +}; + static inline void stm32f7_i2c_set_bits(void __iomem *reg, u32 mask) { writel_relaxed(readl_relaxed(reg) | mask, reg); @@ -1837,14 +1849,25 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave) static int stm32f7_i2c_write_fm_plus_bits(struct stm32f7_i2c_dev *i2c_dev, bool enable) { + int ret; + if (i2c_dev->speed != STM32_I2C_SPEED_FAST_PLUS || IS_ERR_OR_NULL(i2c_dev->regmap)) /* Optional */ return 0; - return regmap_update_bits(i2c_dev->regmap, i2c_dev->fmp_reg, - i2c_dev->fmp_mask, - enable ? i2c_dev->fmp_mask : 0); + if (i2c_dev->fmp_sreg == i2c_dev->fmp_creg) + ret = regmap_update_bits(i2c_dev->regmap, + i2c_dev->fmp_sreg, + i2c_dev->fmp_mask, + enable ? i2c_dev->fmp_mask : 0); + else + ret = regmap_write(i2c_dev->regmap, + enable ? i2c_dev->fmp_sreg : + i2c_dev->fmp_creg, + i2c_dev->fmp_mask); + + return ret; } static int stm32f7_i2c_setup_fm_plus_bits(struct platform_device *pdev, @@ -1859,10 +1882,13 @@ static int stm32f7_i2c_setup_fm_plus_bits(struct platform_device *pdev, return 0; ret = of_property_read_u32_index(np, "st,syscfg-fmp", 1, - &i2c_dev->fmp_reg); + &i2c_dev->fmp_sreg); if (ret) return ret; + i2c_dev->fmp_creg = i2c_dev->fmp_sreg + + i2c_dev->setup.fmp_clr_offset; + return of_property_read_u32_index(np, "st,syscfg-fmp", 2, &i2c_dev->fmp_mask); } @@ -2262,6 +2288,7 @@ static const struct dev_pm_ops stm32f7_i2c_pm_ops = { static const struct of_device_id stm32f7_i2c_match[] = { { .compatible = "st,stm32f7-i2c", .data = &stm32f7_setup}, + { .compatible = "st,stm32mp15-i2c", .data = &stm32mp15_setup}, {}, }; MODULE_DEVICE_TABLE(of, stm32f7_i2c_match); From ed680522268da2f6f2a67505dd144e718d726712 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 28 Feb 2020 18:12:20 +0100 Subject: [PATCH 1386/4444] i2c: convert SMBus alert setup function to return an ERRPTR Only few drivers use this call, so drivers and I2C core are converted at once with this patch. By simply using i2c_new_client_device() instead of i2c_new_device(), we easily can return an ERRPTR for this function as well. To make out of tree users aware that something changed, the function is renamed to i2c_new_smbus_alert_device(). Signed-off-by: Wolfram Sang Reviewed-by: Luca Ceresoli Signed-off-by: Wolfram Sang --- Documentation/i2c/smbus-protocol.rst | 2 +- drivers/i2c/busses/i2c-parport.c | 12 ++++++++---- drivers/i2c/busses/i2c-thunderx-pcidrv.c | 11 ++++++++--- drivers/i2c/busses/i2c-xlp9xx.c | 10 +++++++--- drivers/i2c/i2c-core-smbus.c | 21 ++++++++------------- drivers/i2c/i2c-smbus.c | 2 +- include/linux/i2c-smbus.h | 4 ++-- 7 files changed, 35 insertions(+), 27 deletions(-) diff --git a/Documentation/i2c/smbus-protocol.rst b/Documentation/i2c/smbus-protocol.rst index c122ed239f7f..c2e29633071e 100644 --- a/Documentation/i2c/smbus-protocol.rst +++ b/Documentation/i2c/smbus-protocol.rst @@ -274,7 +274,7 @@ to know which slave triggered the interrupt. This is implemented the following way in the Linux kernel: * I2C bus drivers which support SMBus alert should call - i2c_setup_smbus_alert() to setup SMBus alert support. + i2c_new_smbus_alert_device() to install SMBus alert support. * I2C drivers for devices which can trigger SMBus alerts should implement the optional alert() callback. diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c index 81eb441b2387..a535889acca6 100644 --- a/drivers/i2c/busses/i2c-parport.c +++ b/drivers/i2c/busses/i2c-parport.c @@ -333,13 +333,17 @@ static void i2c_parport_attach(struct parport *port) /* Setup SMBus alert if supported */ if (adapter_parm[type].smbus_alert) { - adapter->ara = i2c_setup_smbus_alert(&adapter->adapter, - &adapter->alert_data); - if (adapter->ara) + struct i2c_client *ara; + + ara = i2c_new_smbus_alert_device(&adapter->adapter, + &adapter->alert_data); + if (!IS_ERR(ara)) { + adapter->ara = ara; parport_enable_irq(port); - else + } else { dev_warn(&adapter->pdev->dev, "Failed to register ARA client\n"); + } } /* Add the new adapter to the list */ diff --git a/drivers/i2c/busses/i2c-thunderx-pcidrv.c b/drivers/i2c/busses/i2c-thunderx-pcidrv.c index 19f8eec38717..7d3b9d66ad36 100644 --- a/drivers/i2c/busses/i2c-thunderx-pcidrv.c +++ b/drivers/i2c/busses/i2c-thunderx-pcidrv.c @@ -118,6 +118,8 @@ static void thunder_i2c_clock_disable(struct device *dev, struct clk *clk) static int thunder_i2c_smbus_setup_of(struct octeon_i2c *i2c, struct device_node *node) { + struct i2c_client *ara; + if (!node) return -EINVAL; @@ -125,9 +127,12 @@ static int thunder_i2c_smbus_setup_of(struct octeon_i2c *i2c, if (!i2c->alert_data.irq) return -EINVAL; - i2c->ara = i2c_setup_smbus_alert(&i2c->adap, &i2c->alert_data); - if (!i2c->ara) - return -ENODEV; + ara = i2c_new_smbus_alert_device(&i2c->adap, &i2c->alert_data); + if (IS_ERR(ara)) + return PTR_ERR(ara); + + i2c->ara = ara; + return 0; } diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c index 8a873975cf12..823945bc3249 100644 --- a/drivers/i2c/busses/i2c-xlp9xx.c +++ b/drivers/i2c/busses/i2c-xlp9xx.c @@ -491,12 +491,16 @@ static int xlp9xx_i2c_get_frequency(struct platform_device *pdev, static int xlp9xx_i2c_smbus_setup(struct xlp9xx_i2c_dev *priv, struct platform_device *pdev) { + struct i2c_client *ara; + if (!priv->alert_data.irq) return -EINVAL; - priv->ara = i2c_setup_smbus_alert(&priv->adapter, &priv->alert_data); - if (!priv->ara) - return -ENODEV; + ara = i2c_new_smbus_alert_device(&priv->adapter, &priv->alert_data); + if (IS_ERR(ara)) + return PTR_ERR(ara); + + priv->ara = ara; return 0; } diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c index 3ac426a8ab5a..fd2b961f113e 100644 --- a/drivers/i2c/i2c-core-smbus.c +++ b/drivers/i2c/i2c-core-smbus.c @@ -666,7 +666,7 @@ s32 i2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client, EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data_or_emulated); /** - * i2c_setup_smbus_alert - Setup SMBus alert support + * i2c_new_smbus_alert_device - get ara client for SMBus alert support * @adapter: the target adapter * @setup: setup data for the SMBus alert handler * Context: can sleep @@ -682,25 +682,24 @@ EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data_or_emulated); * should have said it's level triggered. * * This returns the ara client, which should be saved for later use with - * i2c_handle_smbus_alert() and ultimately i2c_unregister_device(); or NULL - * to indicate an error. + * i2c_handle_smbus_alert() and ultimately i2c_unregister_device(); or an + * ERRPTR to indicate an error. */ -struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter, - struct i2c_smbus_alert_setup *setup) +struct i2c_client *i2c_new_smbus_alert_device(struct i2c_adapter *adapter, + struct i2c_smbus_alert_setup *setup) { struct i2c_board_info ara_board_info = { I2C_BOARD_INFO("smbus_alert", 0x0c), .platform_data = setup, }; - return i2c_new_device(adapter, &ara_board_info); + return i2c_new_client_device(adapter, &ara_board_info); } -EXPORT_SYMBOL_GPL(i2c_setup_smbus_alert); +EXPORT_SYMBOL_GPL(i2c_new_smbus_alert_device); #if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF) int of_i2c_setup_smbus_alert(struct i2c_adapter *adapter) { - struct i2c_client *client; int irq; irq = of_property_match_string(adapter->dev.of_node, "interrupt-names", @@ -710,11 +709,7 @@ int of_i2c_setup_smbus_alert(struct i2c_adapter *adapter) else if (irq < 0) return irq; - client = i2c_setup_smbus_alert(adapter, NULL); - if (!client) - return -ENODEV; - - return 0; + return PTR_ERR_OR_ZERO(i2c_new_smbus_alert_device(adapter, NULL)); } EXPORT_SYMBOL_GPL(of_i2c_setup_smbus_alert); #endif diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index 7e2f5d0eacdb..809bcf8387d0 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -184,7 +184,7 @@ static struct i2c_driver smbalert_driver = { * corresponding I2C device driver's alert function. * * It is assumed that ara is a valid i2c client previously returned by - * i2c_setup_smbus_alert(). + * i2c_new_smbus_alert_device(). */ int i2c_handle_smbus_alert(struct i2c_client *ara) { diff --git a/include/linux/i2c-smbus.h b/include/linux/i2c-smbus.h index 585ad6fc3847..802aac0d2010 100644 --- a/include/linux/i2c-smbus.h +++ b/include/linux/i2c-smbus.h @@ -31,8 +31,8 @@ struct i2c_smbus_alert_setup { int irq; }; -struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter, - struct i2c_smbus_alert_setup *setup); +struct i2c_client *i2c_new_smbus_alert_device(struct i2c_adapter *adapter, + struct i2c_smbus_alert_setup *setup); int i2c_handle_smbus_alert(struct i2c_client *ara); #if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF) From a47070aac935b9c0e5d0f99843e0c8784f455ea7 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 28 Feb 2020 18:12:21 +0100 Subject: [PATCH 1387/4444] i2c: smbus: remove outdated references to irq level triggers IRQ levels are now handled within the IRQ core. Remove the forgotten references from the documentation. Fixes: 9b9f2b8bc2ac ("i2c: i2c-smbus: Use threaded irq for smbalert") Signed-off-by: Wolfram Sang Reviewed-by: Luca Ceresoli Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core-smbus.c | 5 ----- include/linux/i2c-smbus.h | 5 ----- 2 files changed, 10 deletions(-) diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c index fd2b961f113e..b34d2ff06931 100644 --- a/drivers/i2c/i2c-core-smbus.c +++ b/drivers/i2c/i2c-core-smbus.c @@ -676,11 +676,6 @@ EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data_or_emulated); * Handling can be done either through our IRQ handler, or by the * adapter (from its handler, periodic polling, or whatever). * - * NOTE that if we manage the IRQ, we *MUST* know if it's level or - * edge triggered in order to hand it to the workqueue correctly. - * If triggering the alert seems to wedge the system, you probably - * should have said it's level triggered. - * * This returns the ara client, which should be saved for later use with * i2c_handle_smbus_alert() and ultimately i2c_unregister_device(); or an * ERRPTR to indicate an error. diff --git a/include/linux/i2c-smbus.h b/include/linux/i2c-smbus.h index 802aac0d2010..8c5459034f92 100644 --- a/include/linux/i2c-smbus.h +++ b/include/linux/i2c-smbus.h @@ -15,17 +15,12 @@ /** * i2c_smbus_alert_setup - platform data for the smbus_alert i2c client - * @alert_edge_triggered: whether the alert interrupt is edge (1) or level (0) - * triggered * @irq: IRQ number, if the smbus_alert driver should take care of interrupt * handling * * If irq is not specified, the smbus_alert driver doesn't take care of * interrupt handling. In that case it is up to the I2C bus driver to either * handle the interrupts or to poll for alerts. - * - * If irq is specified then it it crucial that alert_edge_triggered is - * properly set. */ struct i2c_smbus_alert_setup { int irq; From a22ae72b86a4f754e8d25fbf9ea5a8f77365e531 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 9 Mar 2020 14:27:43 -0500 Subject: [PATCH 1388/4444] ASoC: soc-core: disable route checks for legacy devices v5.4 changes in soc-core tightened the checks on soc_dapm_add_routes, which results in the ASoC card probe failing. Introduce a flag to be set in machine drivers to prevent the probe from stopping in case of incomplete topologies or missing routes. This flag is for backwards compatibility only and shall not be used for newer machine drivers. Example with an HDaudio card with a bad topology: [ 236.177898] skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: Failed to add route iDisp1_out -> direct -> iDisp1 Tx [ 236.177902] skl_hda_dsp_generic skl_hda_dsp_generic: snd_soc_bind_card: snd_soc_dapm_add_routes failed: -19 with the disable_route_checks set: [ 64.031657] skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: Failed to add route iDisp1_out -> direct -> iDisp1 Tx [ 64.031661] skl_hda_dsp_generic skl_hda_dsp_generic: snd_soc_bind_card: disable_route_checks set, ignoring errors on add_routes Fixes: daa480bde6b3a9 ("ASoC: soc-core: tidyup for snd_soc_dapm_add_routes()") Signed-off-by: Pierre-Louis Bossart Acked-by: Kuninori Morimoto Link: https://lore.kernel.org/r/20200309192744.18380-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/soc.h | 1 + sound/soc/soc-core.c | 28 ++++++++++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 8a2266676b2d..efb8bad7b0fa 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1058,6 +1058,7 @@ struct snd_soc_card { const struct snd_soc_dapm_route *of_dapm_routes; int num_of_dapm_routes; bool fully_routed; + bool disable_route_checks; /* lists of probed devices belonging to this card */ struct list_head component_dev_list; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 068d809c349a..b17366bac846 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1256,8 +1256,18 @@ static int soc_probe_component(struct snd_soc_card *card, ret = snd_soc_dapm_add_routes(dapm, component->driver->dapm_routes, component->driver->num_dapm_routes); - if (ret < 0) - goto err_probe; + if (ret < 0) { + if (card->disable_route_checks) { + dev_info(card->dev, + "%s: disable_route_checks set, ignoring errors on add_routes\n", + __func__); + } else { + dev_err(card->dev, + "%s: snd_soc_dapm_add_routes failed: %d\n", + __func__, ret); + goto err_probe; + } + } /* see for_each_card_components */ list_add(&component->card_list, &card->component_dev_list); @@ -1938,8 +1948,18 @@ static int snd_soc_bind_card(struct snd_soc_card *card) ret = snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes, card->num_dapm_routes); - if (ret < 0) - goto probe_end; + if (ret < 0) { + if (card->disable_route_checks) { + dev_info(card->dev, + "%s: disable_route_checks set, ignoring errors on add_routes\n", + __func__); + } else { + dev_err(card->dev, + "%s: snd_soc_dapm_add_routes failed: %d\n", + __func__, ret); + goto probe_end; + } + } ret = snd_soc_dapm_add_routes(&card->dapm, card->of_dapm_routes, card->num_of_dapm_routes); From c8061689ffadde941f9c3756f1362bd2b97311c8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 9 Mar 2020 14:27:44 -0500 Subject: [PATCH 1389/4444] ASoC: Intel: skl_nau88l25_ssm4567: disable route checks Deal with incomplete topologies, this patch restores sound on user devices. Fixes: daa480bde6b3a9 ("ASoC: soc-core: tidyup for snd_soc_dapm_add_routes()") Signed-off-by: Pierre-Louis Bossart Tested-by: ojab // Acked-by: Kuninori Morimoto Link: https://lore.kernel.org/r/20200309192744.18380-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/skl_nau88l25_ssm4567.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c index c99c8b23e509..b3b835156d77 100644 --- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c +++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c @@ -686,6 +686,7 @@ static struct snd_soc_card skylake_audio_card = { .codec_conf = ssm4567_codec_conf, .num_configs = ARRAY_SIZE(ssm4567_codec_conf), .fully_routed = true, + .disable_route_checks = true, .late_probe = skylake_card_late_probe, }; From 995cbc3ca1ab39fb5cf254181dcfba883c5d6d69 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 9 Mar 2020 13:07:29 +0900 Subject: [PATCH 1390/4444] ASoC: soc.h: add for_each_rtd_codecs/cpus_dai() macro We are using plural form for for_each_xxx() macro. But, for_each_rtd_codec/cpu_dai() are out of this rule. This patch adds plural form macro. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/8736aii326.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/include/sound/soc.h b/include/sound/soc.h index 9543d9246ca4..09bc45b8bf00 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1177,6 +1177,20 @@ struct snd_soc_pcm_runtime { #define for_each_rtd_cpu_dai_rollback(rtd, i, dai) \ for (; (--(i) >= 0) && ((dai) = rtd->cpu_dais[i]);) +#define for_each_rtd_cpu_dais(rtd, i, dai) \ + for ((i) = 0; \ + ((i) < rtd->num_cpus) && ((dai) = rtd->cpu_dais[i]); \ + (i)++) +#define for_each_rtd_cpu_dais_rollback(rtd, i, dai) \ + for (; (--(i) >= 0) && ((dai) = rtd->cpu_dais[i]);) +#define for_each_rtd_codec_dais(rtd, i, dai) \ + for ((i) = 0; \ + ((i) < rtd->num_codecs) && ((dai) = rtd->codec_dais[i]); \ + (i)++) +#define for_each_rtd_codec_dais_rollback(rtd, i, dai) \ + for (; (--(i) >= 0) && ((dai) = rtd->codec_dais[i]);) + + void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd); /* mixer control */ From 5dd1677c81c09932afad4dba2759dff7cf33ecbe Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 9 Mar 2020 13:07:35 +0900 Subject: [PATCH 1391/4444] ASoC: Intel: use for_each_rtd_codecs/cpus_dai() macro This patch switch to use plural form macro. - for_each_rtd_codec_dai() + for_each_rtd_codec_dais() - for_each_rtd_codec_dai_rollback() + for_each_rtd_codec_dais_rollback() - for_each_rtd_cpu_dai() + for_each_rtd_cpu_dais() - for_each_rtd_cpu_dai_rollback() + for_each_rtd_cpu_dais_rollback() Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/871rq2i320.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/cml_rt1011_rt5682.c | 2 +- sound/soc/intel/boards/kbl_da7219_max98927.c | 4 ++-- sound/soc/intel/boards/kbl_rt5663_max98927.c | 2 +- sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/intel/boards/cml_rt1011_rt5682.c b/sound/soc/intel/boards/cml_rt1011_rt5682.c index 02aa18d24319..2a6e5b124099 100644 --- a/sound/soc/intel/boards/cml_rt1011_rt5682.c +++ b/sound/soc/intel/boards/cml_rt1011_rt5682.c @@ -164,7 +164,7 @@ static int cml_rt1011_hw_params(struct snd_pcm_substream *substream, srate = params_rate(params); - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { /* 100 Fs to drive 24 bit data */ ret = snd_soc_dai_set_pll(codec_dai, 0, RT1011_PLL1_S_BCLK, diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c index 88f69e3697d2..0ceb1748a262 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98927.c +++ b/sound/soc/intel/boards/kbl_da7219_max98927.c @@ -179,7 +179,7 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai; int ret, j; - for_each_rtd_codec_dai(runtime, j, codec_dai) { + for_each_rtd_codec_dais(runtime, j, codec_dai) { if (!strcmp(codec_dai->component->name, MAX98927_DEV0_NAME)) { ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x30, 3, 8, 16); @@ -224,7 +224,7 @@ static int kabylake_ssp0_trigger(struct snd_pcm_substream *substream, int cmd) struct snd_soc_dai *codec_dai; int j, ret; - for_each_rtd_codec_dai(rtd, j, codec_dai) { + for_each_rtd_codec_dais(rtd, j, codec_dai) { const char *name = codec_dai->component->name; struct snd_soc_component *component = codec_dai->component; struct snd_soc_dapm_context *dapm = diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index d8f2ff7139a9..f65feee1c166 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -472,7 +472,7 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai; int ret = 0, j; - for_each_rtd_codec_dai(rtd, j, codec_dai) { + for_each_rtd_codec_dais(rtd, j, codec_dai) { if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME)) { /* * Use channel 4 and 5 for the first amp diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index 96c814f36458..341bb47311a6 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -399,7 +399,7 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai; int ret = 0, j; - for_each_rtd_codec_dai(rtd, j, codec_dai) { + for_each_rtd_codec_dais(rtd, j, codec_dai) { if (!strcmp(codec_dai->component->name, RT5514_DEV_NAME)) { ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0, 8, 16); if (ret < 0) { From c8654520234192688eefd7b40a66de7cf69c5189 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 9 Mar 2020 13:07:42 +0900 Subject: [PATCH 1392/4444] ASoC: mediatek: use for_each_rtd_codecs/cpus_dai() macro This patch switch to use plural form macro. - for_each_rtd_codec_dai() + for_each_rtd_codec_dais() - for_each_rtd_codec_dai_rollback() + for_each_rtd_codec_dais_rollback() - for_each_rtd_cpu_dai() + for_each_rtd_cpu_dais() - for_each_rtd_cpu_dai_rollback() + for_each_rtd_cpu_dais_rollback() Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87zhcqgohd.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c | 2 +- sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c | 2 +- sound/soc/mediatek/mt8173/mt8173-rt5650.c | 2 +- sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c index 2e1e61d8f127..5d82159f4f2e 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c @@ -47,7 +47,7 @@ static int mt8173_rt5650_rt5514_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai; int i, ret; - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { /* pll from mclk 12.288M */ ret = snd_soc_dai_set_pll(codec_dai, 0, 0, MCLK_FOR_CODECS, params_rate(params) * 512); diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c index ebcc0b86286b..f65e3ebe38b8 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c @@ -51,7 +51,7 @@ static int mt8173_rt5650_rt5676_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai; int i, ret; - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { /* pll from mclk 12.288M */ ret = snd_soc_dai_set_pll(codec_dai, 0, 0, MCLK_FOR_CODECS, params_rate(params) * 512); diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650.c b/sound/soc/mediatek/mt8173/mt8173-rt5650.c index 849b050a54d1..bbc4ad749892 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650.c @@ -78,7 +78,7 @@ static int mt8173_rt5650_hw_params(struct snd_pcm_substream *substream, break; } - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { /* pll from mclk */ ret = snd_soc_dai_set_pll(codec_dai, 0, 0, mclk_clock, params_rate(params) * 512); diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index 4a5ef07e956b..c4e4f1f99dde 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -52,7 +52,7 @@ static int mt8183_da7219_i2s_hw_params(struct snd_pcm_substream *substream, if (ret < 0) dev_err(rtd->dev, "failed to set cpu dai sysclk\n"); - for_each_rtd_codec_dai(rtd, j, codec_dai) { + for_each_rtd_codec_dais(rtd, j, codec_dai) { if (!strcmp(codec_dai->component->name, "da7219.5-001a")) { ret = snd_soc_dai_set_sysclk(codec_dai, @@ -85,7 +85,7 @@ static int mt8183_da7219_hw_free(struct snd_pcm_substream *substream) struct snd_soc_dai *codec_dai; int ret = 0, j; - for_each_rtd_codec_dai(rtd, j, codec_dai) { + for_each_rtd_codec_dais(rtd, j, codec_dai) { if (!strcmp(codec_dai->component->name, "da7219.5-001a")) { ret = snd_soc_dai_set_pll(codec_dai, From b5c52f5801c6e076377f7f411fb61bab86cb9542 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 9 Mar 2020 13:07:48 +0900 Subject: [PATCH 1393/4444] ASoC: meson: use for_each_rtd_codecs/cpus_dai() macro This patch switch to use plural form macro. - for_each_rtd_codec_dai() + for_each_rtd_codec_dais() - for_each_rtd_codec_dai_rollback() + for_each_rtd_codec_dais_rollback() - for_each_rtd_cpu_dai() + for_each_rtd_cpu_dais() - for_each_rtd_cpu_dai_rollback() + for_each_rtd_cpu_dais_rollback() Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87y2sagoh7.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-card.c | 2 +- sound/soc/meson/meson-card-utils.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index 48651631bdcf..77a7d5f36ebf 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c @@ -60,7 +60,7 @@ static int axg_card_tdm_dai_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_dai *codec_dai; int ret, i; - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { ret = snd_soc_dai_set_tdm_slot(codec_dai, be->codec_masks[i].tx, be->codec_masks[i].rx, diff --git a/sound/soc/meson/meson-card-utils.c b/sound/soc/meson/meson-card-utils.c index a70d244ef88b..b5d3c9f56bac 100644 --- a/sound/soc/meson/meson-card-utils.c +++ b/sound/soc/meson/meson-card-utils.c @@ -23,7 +23,7 @@ int meson_card_i2s_set_sysclk(struct snd_pcm_substream *substream, mclk = params_rate(params) * mclk_fs; - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN); if (ret && ret != -ENOTSUPP) From c998ee30e493ea3de0e52f0ec57995905d5ba43d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 9 Mar 2020 13:07:57 +0900 Subject: [PATCH 1394/4444] ASoC: qcom: use for_each_rtd_codecs/cpus_dai() macro This patch switch to use plural form macro. - for_each_rtd_codec_dai() + for_each_rtd_codec_dais() - for_each_rtd_codec_dai_rollback() + for_each_rtd_codec_dais_rollback() - for_each_rtd_cpu_dai() + for_each_rtd_cpu_dais() - for_each_rtd_cpu_dai_rollback() + for_each_rtd_cpu_dais_rollback() Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87wo7ugogy.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- drivers/soundwire/qcom.c | 2 +- sound/soc/qcom/apq8016_sbc.c | 2 +- sound/soc/qcom/sdm845.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index fb30bbec999a..440effed6df6 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -603,7 +603,7 @@ static int qcom_swrm_startup(struct snd_pcm_substream *substream, ctrl->sruntime[dai->id] = sruntime; - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { ret = snd_soc_dai_set_sdw_stream(codec_dai, sruntime, substream->stream); if (ret < 0 && ret != -ENOTSUPP) { diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 2d064f3bc9b6..7647af3e51f6 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -90,7 +90,7 @@ static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd) pdata->jack_setup = true; } - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { component = codec_dai->component; /* Set default mclk for internal codec */ diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c index 5a23597261ac..3ac02204a706 100644 --- a/sound/soc/qcom/sdm845.c +++ b/sound/soc/qcom/sdm845.c @@ -49,7 +49,7 @@ static int sdm845_slim_snd_hw_params(struct snd_pcm_substream *substream, u32 rx_ch_cnt = 0, tx_ch_cnt = 0; int ret = 0, i; - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { ret = snd_soc_dai_get_channel_map(codec_dai, &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch); @@ -126,7 +126,7 @@ static int sdm845_tdm_snd_hw_params(struct snd_pcm_substream *substream, } } - for_each_rtd_codec_dai(rtd, j, codec_dai) { + for_each_rtd_codec_dais(rtd, j, codec_dai) { if (!strcmp(codec_dai->component->name_prefix, "Left")) { ret = snd_soc_dai_set_tdm_slot( @@ -265,7 +265,7 @@ static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd) } break; case SLIMBUS_0_RX...SLIMBUS_6_TX: - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { rval = snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch), tx_ch, @@ -344,7 +344,7 @@ static int sdm845_snd_startup(struct snd_pcm_substream *substream) codec_dai_fmt |= SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_DSP_B; - for_each_rtd_codec_dai(rtd, j, codec_dai) { + for_each_rtd_codec_dais(rtd, j, codec_dai) { if (!strcmp(codec_dai->component->name_prefix, "Left")) { From a4be4187b2bfc66f4be8a6d35f497eb53a2c8d76 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 9 Mar 2020 13:08:04 +0900 Subject: [PATCH 1395/4444] ASoC: soc: use for_each_rtd_codecs/cpus_dai() macro This patch switch to use plural form macro. - for_each_rtd_codec_dai() + for_each_rtd_codec_dais() - for_each_rtd_codec_dai_rollback() + for_each_rtd_codec_dais_rollback() - for_each_rtd_cpu_dai() + for_each_rtd_cpu_dais() - for_each_rtd_cpu_dai_rollback() + for_each_rtd_cpu_dais_rollback() Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87v9negogr.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 16 +++--- sound/soc/soc-dapm.c | 10 ++-- sound/soc/soc-pcm.c | 124 +++++++++++++++++++++---------------------- 3 files changed, 75 insertions(+), 75 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f2cfbf182f49..4e0f55555e37 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -547,7 +547,7 @@ int snd_soc_suspend(struct device *dev) if (rtd->dai_link->ignore_suspend) continue; - for_each_rtd_codec_dai(rtd, i, dai) { + for_each_rtd_codec_dais(rtd, i, dai) { if (dai->stream_active[playback]) snd_soc_dai_digital_mute(dai, 1, playback); } @@ -689,7 +689,7 @@ static void soc_resume_deferred(struct work_struct *work) if (rtd->dai_link->ignore_suspend) continue; - for_each_rtd_codec_dai(rtd, i, dai) { + for_each_rtd_codec_dais(rtd, i, dai) { if (dai->stream_active[playback]) snd_soc_dai_digital_mute(dai, 0, playback); } @@ -1321,10 +1321,10 @@ static void soc_remove_link_dais(struct snd_soc_card *card) for_each_comp_order(order) { for_each_card_rtds(card, rtd) { /* remove the CODEC DAI */ - for_each_rtd_codec_dai(rtd, i, codec_dai) + for_each_rtd_codec_dais(rtd, i, codec_dai) soc_remove_dai(codec_dai, order); - for_each_rtd_cpu_dai(rtd, i, cpu_dai) + for_each_rtd_cpu_dais(rtd, i, cpu_dai) soc_remove_dai(cpu_dai, order); } } @@ -1344,14 +1344,14 @@ static int soc_probe_link_dais(struct snd_soc_card *card) card->name, rtd->num, order); /* probe the CPU DAI */ - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { ret = soc_probe_dai(cpu_dai, order); if (ret) return ret; } /* probe the CODEC DAI */ - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { ret = soc_probe_dai(codec_dai, order); if (ret) return ret; @@ -1486,7 +1486,7 @@ int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, unsigned int i; int ret; - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt); if (ret != 0 && ret != -ENOTSUPP) { dev_warn(codec_dai->dev, @@ -1514,7 +1514,7 @@ int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, inv_dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; break; } - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { unsigned int fmt = dai_fmt; if (cpu_dai->component->driver->non_legacy_dai_naming) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 09fa437fc33e..7374829c6675 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2437,7 +2437,7 @@ static ssize_t dapm_widget_show(struct device *dev, mutex_lock(&rtd->card->dapm_mutex); - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { struct snd_soc_component *cmpnt = codec_dai->component; count += dapm_widget_show_component(cmpnt, buf + count); @@ -4362,11 +4362,11 @@ static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, int i; if (rtd->num_cpus == 1) { - for_each_rtd_codec_dai(rtd, i, codec_dai) + for_each_rtd_codec_dais(rtd, i, codec_dai) dapm_add_valid_dai_widget(card, rtd, codec_dai, rtd->cpu_dais[0]); } else if (rtd->num_codecs == rtd->num_cpus) { - for_each_rtd_codec_dai(rtd, i, codec_dai) + for_each_rtd_codec_dais(rtd, i, codec_dai) dapm_add_valid_dai_widget(card, rtd, codec_dai, rtd->cpu_dais[i]); } else { @@ -4437,9 +4437,9 @@ static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, struct snd_soc_dai *cpu_dai; int i; - for_each_rtd_cpu_dai(rtd, i, cpu_dai) + for_each_rtd_cpu_dais(rtd, i, cpu_dai) soc_dapm_dai_stream_event(cpu_dai, stream, event); - for_each_rtd_codec_dai(rtd, i, codec_dai) + for_each_rtd_codec_dais(rtd, i, codec_dai) soc_dapm_dai_stream_event(codec_dai, stream, event); dapm_power_widgets(rtd->card, event); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index e7915adaaf0a..fbea005043de 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -265,17 +265,17 @@ static void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, lockdep_assert_held(&rtd->card->pcm_mutex); - for_each_rtd_cpu_dai(rtd, i, cpu_dai) + for_each_rtd_cpu_dais(rtd, i, cpu_dai) cpu_dai->stream_active[stream] += action; - for_each_rtd_codec_dai(rtd, i, codec_dai) + for_each_rtd_codec_dais(rtd, i, codec_dai) codec_dai->stream_active[stream] += action; - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { cpu_dai->active += action; cpu_dai->component->active += action; } - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { codec_dai->active += action; codec_dai->component->active += action; } @@ -455,14 +455,14 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, /* reject unmatched parameters when applying symmetry */ symmetry = rtd->dai_link->symmetric_rates; - for_each_rtd_cpu_dai(rtd, i, cpu_dai) + for_each_rtd_cpu_dais(rtd, i, cpu_dai) symmetry |= cpu_dai->driver->symmetric_rates; - for_each_rtd_codec_dai(rtd, i, codec_dai) + for_each_rtd_codec_dais(rtd, i, codec_dai) symmetry |= codec_dai->driver->symmetric_rates; if (symmetry) { - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { if (cpu_dai->rate && cpu_dai->rate != rate) { dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n", cpu_dai->rate, rate); @@ -473,14 +473,14 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, symmetry = rtd->dai_link->symmetric_channels; - for_each_rtd_cpu_dai(rtd, i, cpu_dai) + for_each_rtd_cpu_dais(rtd, i, cpu_dai) symmetry |= cpu_dai->driver->symmetric_channels; - for_each_rtd_codec_dai(rtd, i, codec_dai) + for_each_rtd_codec_dais(rtd, i, codec_dai) symmetry |= codec_dai->driver->symmetric_channels; if (symmetry) { - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { if (cpu_dai->channels && cpu_dai->channels != channels) { dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n", @@ -492,14 +492,14 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, symmetry = rtd->dai_link->symmetric_samplebits; - for_each_rtd_cpu_dai(rtd, i, cpu_dai) + for_each_rtd_cpu_dais(rtd, i, cpu_dai) symmetry |= cpu_dai->driver->symmetric_samplebits; - for_each_rtd_codec_dai(rtd, i, codec_dai) + for_each_rtd_codec_dais(rtd, i, codec_dai) symmetry |= codec_dai->driver->symmetric_samplebits; if (symmetry) { - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { if (cpu_dai->sample_bits && cpu_dai->sample_bits != sample_bits) { dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n", @@ -524,13 +524,13 @@ static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream) link->symmetric_channels || link->symmetric_samplebits; - for_each_rtd_cpu_dai(rtd, i, cpu_dai) + for_each_rtd_cpu_dais(rtd, i, cpu_dai) symmetry = symmetry || cpu_dai->driver->symmetric_rates || cpu_dai->driver->symmetric_channels || cpu_dai->driver->symmetric_samplebits; - for_each_rtd_codec_dai(rtd, i, codec_dai) + for_each_rtd_codec_dais(rtd, i, codec_dai) symmetry = symmetry || codec_dai->driver->symmetric_rates || codec_dai->driver->symmetric_channels || @@ -563,7 +563,7 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) int i; unsigned int bits = 0, cpu_bits = 0; - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { pcm_codec = snd_soc_dai_get_pcm_stream(codec_dai, stream); if (pcm_codec->sig_bits == 0) { @@ -573,7 +573,7 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) bits = max(pcm_codec->sig_bits, bits); } - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { pcm_cpu = snd_soc_dai_get_pcm_stream(cpu_dai, stream); if (pcm_cpu->sig_bits == 0) { @@ -612,7 +612,7 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, int i; /* first calculate min/max only for CPUs in the DAI link */ - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { /* * Skip CPUs which don't support the current stream type. @@ -635,7 +635,7 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, } /* second calculate min/max only for CODECs in the DAI link */ - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { /* * Skip CODECs which don't support the current stream type. @@ -780,10 +780,10 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) snd_soc_runtime_deactivate(rtd, substream->stream); - for_each_rtd_cpu_dai(rtd, i, cpu_dai) + for_each_rtd_cpu_dais(rtd, i, cpu_dai) snd_soc_dai_shutdown(cpu_dai, substream); - for_each_rtd_codec_dai(rtd, i, codec_dai) + for_each_rtd_codec_dais(rtd, i, codec_dai) snd_soc_dai_shutdown(codec_dai, substream); soc_rtd_shutdown(rtd, substream); @@ -842,7 +842,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) } /* startup the audio subsystem */ - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { ret = snd_soc_dai_startup(cpu_dai, substream); if (ret < 0) { dev_err(cpu_dai->dev, "ASoC: can't open interface %s: %d\n", @@ -851,7 +851,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) } } - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { ret = snd_soc_dai_startup(codec_dai, substream); if (ret < 0) { dev_err(codec_dai->dev, @@ -903,7 +903,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) soc_pcm_apply_msb(substream); /* Symmetry only applies if we've already got an active stream. */ - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { if (cpu_dai->active) { ret = soc_pcm_apply_symmetry(substream, cpu_dai); if (ret != 0) @@ -911,7 +911,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) } } - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { if (codec_dai->active) { ret = soc_pcm_apply_symmetry(substream, codec_dai); if (ret != 0) @@ -935,10 +935,10 @@ dynamic: return 0; config_err: - for_each_rtd_codec_dai(rtd, i, codec_dai) + for_each_rtd_codec_dais(rtd, i, codec_dai) snd_soc_dai_shutdown(codec_dai, substream); cpu_dai_err: - for_each_rtd_cpu_dai(rtd, i, cpu_dai) + for_each_rtd_cpu_dais(rtd, i, cpu_dai) snd_soc_dai_shutdown(cpu_dai, substream); soc_rtd_shutdown(rtd, substream); @@ -1000,7 +1000,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) } } - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { ret = snd_soc_dai_prepare(codec_dai, substream); if (ret < 0) { dev_err(codec_dai->dev, @@ -1010,7 +1010,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) } } - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { ret = snd_soc_dai_prepare(cpu_dai, substream); if (ret < 0) { dev_err(cpu_dai->dev, @@ -1029,10 +1029,10 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) snd_soc_dapm_stream_event(rtd, substream->stream, SND_SOC_DAPM_STREAM_START); - for_each_rtd_codec_dai(rtd, i, codec_dai) + for_each_rtd_codec_dais(rtd, i, codec_dai) snd_soc_dai_digital_mute(codec_dai, 0, substream->stream); - for_each_rtd_cpu_dai(rtd, i, cpu_dai) + for_each_rtd_cpu_dais(rtd, i, cpu_dai) snd_soc_dai_digital_mute(cpu_dai, 0, substream->stream); out: @@ -1097,7 +1097,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, goto out; } - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { struct snd_pcm_hw_params codec_params; /* @@ -1144,7 +1144,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, snd_soc_dapm_update_dai(substream, &codec_params, codec_dai); } - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { /* * Skip CPUs which don't support the current stream * type. See soc_pcm_init_runtime_hw() for more details @@ -1186,7 +1186,7 @@ component_err: i = rtd->num_cpus; interface_err: - for_each_rtd_cpu_dai_rollback(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais_rollback(rtd, i, cpu_dai) { if (!snd_soc_dai_stream_valid(cpu_dai, substream->stream)) continue; @@ -1197,7 +1197,7 @@ interface_err: i = rtd->num_codecs; codec_err: - for_each_rtd_codec_dai_rollback(rtd, i, codec_dai) { + for_each_rtd_codec_dais_rollback(rtd, i, codec_dai) { if (!snd_soc_dai_stream_valid(codec_dai, substream->stream)) continue; @@ -1224,7 +1224,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); /* clear the corresponding DAIs parameters when going to be inactive */ - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { if (cpu_dai->active == 1) { cpu_dai->rate = 0; cpu_dai->channels = 0; @@ -1232,7 +1232,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) } } - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { if (codec_dai->active == 1) { codec_dai->rate = 0; codec_dai->channels = 0; @@ -1241,7 +1241,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) } /* apply codec digital mute */ - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { int active = codec_dai->stream_active[substream->stream]; if (active == 1) @@ -1249,7 +1249,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) substream->stream); } - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { int active = cpu_dai->stream_active[substream->stream]; if (active == 1) @@ -1264,14 +1264,14 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) soc_pcm_components_hw_free(substream, NULL); /* now free hw params for the DAIs */ - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { if (!snd_soc_dai_stream_valid(codec_dai, substream->stream)) continue; snd_soc_dai_hw_free(codec_dai, substream); } - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { if (!snd_soc_dai_stream_valid(cpu_dai, substream->stream)) continue; @@ -1300,13 +1300,13 @@ static int soc_pcm_trigger_start(struct snd_pcm_substream *substream, int cmd) return ret; } - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { ret = snd_soc_dai_trigger(cpu_dai, substream, cmd); if (ret < 0) return ret; } - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { ret = snd_soc_dai_trigger(codec_dai, substream, cmd); if (ret < 0) return ret; @@ -1323,13 +1323,13 @@ static int soc_pcm_trigger_stop(struct snd_pcm_substream *substream, int cmd) struct snd_soc_dai *codec_dai; int i, ret; - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { ret = snd_soc_dai_trigger(codec_dai, substream, cmd); if (ret < 0) return ret; } - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { ret = snd_soc_dai_trigger(cpu_dai, substream, cmd); if (ret < 0) return ret; @@ -1378,13 +1378,13 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai; int i, ret; - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { ret = snd_soc_dai_bespoke_trigger(codec_dai, substream, cmd); if (ret < 0) return ret; } - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { ret = snd_soc_dai_bespoke_trigger(cpu_dai, substream, cmd); if (ret < 0) return ret; @@ -1417,13 +1417,13 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) /* base delay if assigned in pointer callback */ delay = runtime->delay; - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { cpu_delay = max(cpu_delay, snd_soc_dai_delay(cpu_dai, substream)); } delay += cpu_delay; - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { codec_delay = max(codec_delay, snd_soc_dai_delay(codec_dai, substream)); } @@ -1544,7 +1544,7 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, if (!be->dai_link->no_pcm) continue; - for_each_rtd_cpu_dai(be, i, dai) { + for_each_rtd_cpu_dais(be, i, dai) { w = snd_soc_dai_get_widget(dai, stream); dev_dbg(card->dev, "ASoC: try BE : %s\n", @@ -1554,7 +1554,7 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, return be; } - for_each_rtd_codec_dai(be, i, dai) { + for_each_rtd_codec_dais(be, i, dai) { w = snd_soc_dai_get_widget(dai, stream); if (w == widget) @@ -1642,7 +1642,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, /* is there a valid CPU DAI widget for this BE */ do_prune = 1; - for_each_rtd_cpu_dai(dpcm->be, i, dai) { + for_each_rtd_cpu_dais(dpcm->be, i, dai) { widget = snd_soc_dai_get_widget(dai, stream); /* @@ -1657,7 +1657,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, /* is there a valid CODEC DAI widget for this BE */ do_prune = 1; - for_each_rtd_codec_dai(dpcm->be, i, dai) { + for_each_rtd_codec_dais(dpcm->be, i, dai) { widget = snd_soc_dai_get_widget(dai, stream); /* prune the BE if it's no longer in our active list */ @@ -1910,7 +1910,7 @@ static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, struct snd_soc_pcm_stream *codec_stream; int i; - for_each_rtd_codec_dai(be, i, dai) { + for_each_rtd_codec_dais(be, i, dai) { /* * Skip CODECs which don't support the current stream * type. See soc_pcm_init_runtime_hw() for more details @@ -1948,7 +1948,7 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream, struct snd_soc_dai *dai; int i; - for_each_rtd_cpu_dai(be, i, dai) { + for_each_rtd_cpu_dais(be, i, dai) { /* * Skip CPUs which don't support the current stream * type. See soc_pcm_init_runtime_hw() for more details @@ -2003,7 +2003,7 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, struct snd_soc_dai *dai; int i; - for_each_rtd_cpu_dai(be, i, dai) { + for_each_rtd_cpu_dais(be, i, dai) { /* * Skip CPUs which don't support the current stream * type. See soc_pcm_init_runtime_hw() for more details @@ -2020,7 +2020,7 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, cpu_stream->rates); } - for_each_rtd_codec_dai(be, i, dai) { + for_each_rtd_codec_dais(be, i, dai) { /* * Skip CODECs which don't support the current stream * type. See soc_pcm_init_runtime_hw() for more details @@ -2046,7 +2046,7 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) struct snd_soc_dai *cpu_dai; int i; - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { /* * Skip CPUs which don't support the current stream * type. See soc_pcm_init_runtime_hw() for more details @@ -2102,7 +2102,7 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, if (soc_pcm_has_symmetry(fe_substream)) fe_substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; - for_each_rtd_cpu_dai (fe, i, fe_cpu_dai) { + for_each_rtd_cpu_dais (fe, i, fe_cpu_dai) { /* Symmetry only applies if we've got an active stream. */ if (fe_cpu_dai->active) { err = soc_pcm_apply_symmetry(fe_substream, fe_cpu_dai); @@ -2133,7 +2133,7 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, be_substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; /* Symmetry only applies if we've got an active stream. */ - for_each_rtd_cpu_dai(rtd, i, cpu_dai) { + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { if (cpu_dai->active) { err = soc_pcm_apply_symmetry(fe_substream, cpu_dai); @@ -2142,7 +2142,7 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, } } - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { if (codec_dai->active) { err = soc_pcm_apply_symmetry(fe_substream, codec_dai); @@ -3075,7 +3075,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) int cpu_playback = rtd->dai_link->params ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; - for_each_rtd_codec_dai(rtd, i, codec_dai) { + for_each_rtd_codec_dais(rtd, i, codec_dai) { if (rtd->num_cpus == 1) { cpu_dai = rtd->cpu_dais[0]; } else if (rtd->num_cpus == rtd->num_codecs) { From 17e6dab5013ddb36997011cf6daea7297dfc215e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 9 Mar 2020 13:08:10 +0900 Subject: [PATCH 1396/4444] ASoC: soc.h: remove non plural form for_each_xxx macro Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87tv2ygogl.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 09bc45b8bf00..5e1b4ef1543c 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1163,20 +1163,6 @@ struct snd_soc_pcm_runtime { for ((i) = 0; \ ((i) < rtd->num_components) && ((component) = rtd->components[i]);\ (i)++) -#define for_each_rtd_codec_dai(rtd, i, dai)\ - for ((i) = 0; \ - ((i) < rtd->num_codecs) && ((dai) = rtd->codec_dais[i]); \ - (i)++) -#define for_each_rtd_codec_dai_rollback(rtd, i, dai) \ - for (; (--(i) >= 0) && ((dai) = rtd->codec_dais[i]);) - -#define for_each_rtd_cpu_dai(rtd, i, dai)\ - for ((i) = 0; \ - ((i) < rtd->num_cpus) && ((dai) = rtd->cpu_dais[i]); \ - (i)++) -#define for_each_rtd_cpu_dai_rollback(rtd, i, dai) \ - for (; (--(i) >= 0) && ((dai) = rtd->cpu_dais[i]);) - #define for_each_rtd_cpu_dais(rtd, i, dai) \ for ((i) = 0; \ ((i) < rtd->num_cpus) && ((dai) = rtd->cpu_dais[i]); \ From df817f8e71e3a0256bd3d2d3a4e5399b409698f4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 9 Mar 2020 13:08:16 +0900 Subject: [PATCH 1397/4444] ASoC: soc-dapm: add for_each_card_dapms() macro To be more readable code, this patch adds new for_each_card_dapms() macro, and replace existing code to it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87sgiigogf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 3 +++ sound/soc/soc-dapm.c | 18 +++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 5e1b4ef1543c..3aee33c8249e 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1117,6 +1117,9 @@ struct snd_soc_card { #define for_each_card_components(card, component) \ list_for_each_entry(component, &(card)->component_dev_list, card_list) +#define for_each_card_dapms(card, dapm) \ + list_for_each_entry(dapm, &card->dapm_list, list) + /* SoC machine DAI configuration, glues a codec and cpu DAI together */ struct snd_soc_pcm_runtime { struct device *dev; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 7374829c6675..ac48303ea26d 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1716,9 +1716,8 @@ static void dapm_seq_run(struct snd_soc_card *card, i, cur_subseq); } - list_for_each_entry(d, &card->dapm_list, list) { + for_each_card_dapms(card, d) soc_dapm_async_complete(d); - } } static void dapm_widget_update(struct snd_soc_card *card) @@ -1949,7 +1948,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) trace_snd_soc_dapm_start(card); - list_for_each_entry(d, &card->dapm_list, list) { + for_each_card_dapms(card, d) { if (dapm_idle_bias_off(d)) d->target_bias_level = SND_SOC_BIAS_OFF; else @@ -2013,10 +2012,10 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) * they're not ground referenced. */ bias = SND_SOC_BIAS_OFF; - list_for_each_entry(d, &card->dapm_list, list) + for_each_card_dapms(card, d) if (d->target_bias_level > bias) bias = d->target_bias_level; - list_for_each_entry(d, &card->dapm_list, list) + for_each_card_dapms(card, d) if (!dapm_idle_bias_off(d)) d->target_bias_level = bias; @@ -2025,7 +2024,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) /* Run card bias changes at first */ dapm_pre_sequence_async(&card->dapm, 0); /* Run other bias changes in parallel */ - list_for_each_entry(d, &card->dapm_list, list) { + for_each_card_dapms(card, d) { if (d != &card->dapm && d->bias_level != d->target_bias_level) async_schedule_domain(dapm_pre_sequence_async, d, &async_domain); @@ -2049,7 +2048,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) dapm_seq_run(card, &up_list, event, true); /* Run all the bias changes in parallel */ - list_for_each_entry(d, &card->dapm_list, list) { + for_each_card_dapms(card, d) { if (d != &card->dapm && d->bias_level != d->target_bias_level) async_schedule_domain(dapm_post_sequence_async, d, &async_domain); @@ -2059,7 +2058,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) dapm_post_sequence_async(&card->dapm, 0); /* do we need to notify any clients that DAPM event is complete */ - list_for_each_entry(d, &card->dapm_list, list) { + for_each_card_dapms(card, d) { if (!d->component) continue; @@ -4776,6 +4775,7 @@ void snd_soc_dapm_init(struct snd_soc_dapm_context *dapm, } INIT_LIST_HEAD(&dapm->list); + /* see for_each_card_dapms */ list_add(&dapm->list, &card->dapm_list); } EXPORT_SYMBOL_GPL(snd_soc_dapm_init); @@ -4822,7 +4822,7 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card) { struct snd_soc_dapm_context *dapm; - list_for_each_entry(dapm, &card->dapm_list, list) { + for_each_card_dapms(card, dapm) { if (dapm != &card->dapm) { soc_dapm_shutdown_dapm(dapm); if (dapm->bias_level == SND_SOC_BIAS_STANDBY) From 14596692631eadbefba8419698cccfc23bfccd2b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 9 Mar 2020 13:08:21 +0900 Subject: [PATCH 1398/4444] ASoC: soc-dapm: add for_each_card_widgets() macro To be more readable code, this patch adds new for_each_card_widgets() macro, and replace existing code to it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87r1y2goga.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 5 +++++ sound/soc/soc-dapm.c | 25 +++++++++++++------------ sound/soc/soc-topology.c | 2 +- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 3aee33c8249e..03054bf9cd37 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1120,6 +1120,11 @@ struct snd_soc_card { #define for_each_card_dapms(card, dapm) \ list_for_each_entry(dapm, &card->dapm_list, list) +#define for_each_card_widgets(card, w)\ + list_for_each_entry(w, &card->widgets, list) +#define for_each_card_widgets_safe(card, w, _w) \ + list_for_each_entry_safe(w, _w, &card->widgets, list) + /* SoC machine DAI configuration, glues a codec and cpu DAI together */ struct snd_soc_pcm_runtime { struct device *dev; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index ac48303ea26d..e00a465a7c32 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -302,7 +302,7 @@ void dapm_mark_endpoints_dirty(struct snd_soc_card *card) mutex_lock(&card->dapm_mutex); - list_for_each_entry(w, &card->widgets, list) { + for_each_card_widgets(card, w) { if (w->is_ep) { dapm_mark_dirty(w, "Rechecking endpoints"); if (w->is_ep & SND_SOC_DAPM_EP_SINK) @@ -589,7 +589,7 @@ static void dapm_reset(struct snd_soc_card *card) memset(&card->dapm_stats, 0, sizeof(card->dapm_stats)); - list_for_each_entry(w, &card->widgets, list) { + for_each_card_widgets(card, w) { w->new_power = w->power; w->power_checked = false; } @@ -833,7 +833,7 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm, *kcontrol = NULL; - list_for_each_entry(w, &dapm->card->widgets, list) { + for_each_card_widgets(dapm->card, w) { if (w == kcontrolw || w->dapm != kcontrolw->dapm) continue; for (i = 0; i < w->num_kcontrols; i++) { @@ -1967,7 +1967,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) dapm_power_one_widget(w, &up_list, &down_list); } - list_for_each_entry(w, &card->widgets, list) { + for_each_card_widgets(card, w) { switch (w->id) { case snd_soc_dapm_pre: case snd_soc_dapm_post: @@ -2376,7 +2376,7 @@ static ssize_t dapm_widget_show_component(struct snd_soc_component *cmpnt, if (!cmpnt->card) return 0; - list_for_each_entry(w, &cmpnt->card->widgets, list) { + for_each_card_widgets(cmpnt->card, w) { if (w->dapm != dapm) continue; @@ -2496,7 +2496,7 @@ static void dapm_free_widgets(struct snd_soc_dapm_context *dapm) { struct snd_soc_dapm_widget *w, *next_w; - list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) { + for_each_card_widgets_safe(dapm->card, w, next_w) { if (w->dapm != dapm) continue; snd_soc_dapm_free_widget(w); @@ -2511,7 +2511,7 @@ static struct snd_soc_dapm_widget *dapm_find_widget( struct snd_soc_dapm_widget *w; struct snd_soc_dapm_widget *fallback = NULL; - list_for_each_entry(w, &dapm->card->widgets, list) { + for_each_card_widgets(dapm->card, w) { if (!strcmp(w->name, pin)) { if (w->dapm == dapm) return w; @@ -2910,7 +2910,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, * find src and dest widgets over all widgets but favor a widget from * current DAPM context */ - list_for_each_entry(w, &dapm->card->widgets, list) { + for_each_card_widgets(dapm->card, w) { if (!wsink && !(strcmp(w->name, sink))) { wtsink = w; if (w->dapm == dapm) { @@ -3189,7 +3189,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); - list_for_each_entry(w, &card->widgets, list) + for_each_card_widgets(card, w) { if (w->new) continue; @@ -3703,6 +3703,7 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, w->dapm = dapm; INIT_LIST_HEAD(&w->list); INIT_LIST_HEAD(&w->dirty); + /* see for_each_card_widgets */ list_add_tail(&w->list, &dapm->card->widgets); snd_soc_dapm_for_each_direction(dir) { @@ -4227,7 +4228,7 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card) struct snd_soc_dai *dai; /* For each DAI widget... */ - list_for_each_entry(dai_w, &card->widgets, list) { + for_each_card_widgets(card, dai_w) { switch (dai_w->id) { case snd_soc_dapm_dai_in: case snd_soc_dapm_dai_out: @@ -4246,7 +4247,7 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card) dai = dai_w->priv; /* ...find all widgets with the same stream and link them */ - list_for_each_entry(w, &card->widgets, list) { + for_each_card_widgets(card, w) { if (w->dapm != dai_w->dapm) continue; @@ -4789,7 +4790,7 @@ static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm) mutex_lock(&card->dapm_mutex); - list_for_each_entry(w, &dapm->card->widgets, list) { + for_each_card_widgets(dapm->card, w) { if (w->dapm != dapm) continue; if (w->power) { diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 575da6aba807..33909afd3bbc 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -2774,7 +2774,7 @@ void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm, { struct snd_soc_dapm_widget *w, *next_w; - list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) { + for_each_card_widgets_safe(dapm->card, w, next_w) { /* make sure we are a widget with correct context */ if (w->dobj.type != SND_SOC_DOBJ_WIDGET || w->dapm != dapm) From a3b7343e3f8c4c74516df41827b6d81905e346a1 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 9 Mar 2020 15:21:24 +0100 Subject: [PATCH 1399/4444] ASoC: SOF: Fix probe point getter Firmware API changes which introduced 'num_elems' param in several probe structs such as sof_ipc_probe_dma_add_params also impacted getter for both, DMA and probe points. All struct handlers except for sof_ipc_probe_info_params have been updated. Align said handler too to calculate payload size correctly. Fixes: f3b433e4699f ("ASoC: SOF: Implement Probe IPC API") Signed-off-by: Cezary Rojewski Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200309142124.29262-1-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/sof/probe.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/probe.c b/sound/soc/sof/probe.c index 2b2f3dcfc7e9..c38169fe00c5 100644 --- a/sound/soc/sof/probe.c +++ b/sound/soc/sof/probe.c @@ -95,13 +95,17 @@ static int sof_ipc_probe_info(struct snd_sof_dev *sdev, unsigned int cmd, if (!reply->num_elems) goto exit; - bytes = reply->num_elems * sizeof(reply->dma[0]); + if (cmd == SOF_IPC_PROBE_DMA_INFO) + bytes = sizeof(reply->dma[0]); + else + bytes = sizeof(reply->desc[0]); + bytes *= reply->num_elems; *params = kmemdup(&reply->dma[0], bytes, GFP_KERNEL); if (!*params) { ret = -ENOMEM; goto exit; } - *num_params = msg.num_elems; + *num_params = reply->num_elems; exit: kfree(reply); From 035f212fa7f21035537cf6dea620fe5653191eb6 Mon Sep 17 00:00:00 2001 From: Pierre Morel Date: Mon, 10 Feb 2020 17:53:25 +0100 Subject: [PATCH 1400/4444] s390/pci: embedding hotplug_slot in zdev Embedding the hotplug_slot in zdev structure allows to greatly simplify the hotplug handling by eliminating the handling of the slot_list. Signed-off-by: Pierre Morel Reviewed-by: Niklas Schnelle Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/pci.h | 2 + drivers/pci/hotplug/s390_pci_hpc.c | 99 +++++++++--------------------- 2 files changed, 31 insertions(+), 70 deletions(-) diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index b05187ce5dbd..73b69a777152 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -96,6 +97,7 @@ struct s390_domain; struct zpci_dev { struct pci_bus *bus; struct list_head entry; /* list of all zpci_devices, needed for hotplug, etc. */ + struct hotplug_slot hotplug_slot; enum zpci_state state; u32 fid; /* function ID, used by sclp */ diff --git a/drivers/pci/hotplug/s390_pci_hpc.c b/drivers/pci/hotplug/s390_pci_hpc.c index 30ee72268790..39295d88f670 100644 --- a/drivers/pci/hotplug/s390_pci_hpc.c +++ b/drivers/pci/hotplug/s390_pci_hpc.c @@ -19,7 +19,6 @@ #include #define SLOT_NAME_SIZE 10 -static LIST_HEAD(s390_hotplug_slot_list); static int zpci_fn_configured(enum zpci_state state) { @@ -27,97 +26,86 @@ static int zpci_fn_configured(enum zpci_state state) state == ZPCI_FN_STATE_ONLINE; } -/* - * struct slot - slot information for each *physical* slot - */ -struct slot { - struct list_head slot_list; - struct hotplug_slot hotplug_slot; - struct zpci_dev *zdev; -}; - -static inline struct slot *to_slot(struct hotplug_slot *hotplug_slot) +static inline int zdev_configure(struct zpci_dev *zdev) { - return container_of(hotplug_slot, struct slot, hotplug_slot); -} + int ret = sclp_pci_configure(zdev->fid); -static inline int slot_configure(struct slot *slot) -{ - int ret = sclp_pci_configure(slot->zdev->fid); - - zpci_dbg(3, "conf fid:%x, rc:%d\n", slot->zdev->fid, ret); + zpci_dbg(3, "conf fid:%x, rc:%d\n", zdev->fid, ret); if (!ret) - slot->zdev->state = ZPCI_FN_STATE_CONFIGURED; + zdev->state = ZPCI_FN_STATE_CONFIGURED; return ret; } -static inline int slot_deconfigure(struct slot *slot) +static inline int zdev_deconfigure(struct zpci_dev *zdev) { - int ret = sclp_pci_deconfigure(slot->zdev->fid); + int ret = sclp_pci_deconfigure(zdev->fid); - zpci_dbg(3, "deconf fid:%x, rc:%d\n", slot->zdev->fid, ret); + zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, ret); if (!ret) - slot->zdev->state = ZPCI_FN_STATE_STANDBY; + zdev->state = ZPCI_FN_STATE_STANDBY; return ret; } static int enable_slot(struct hotplug_slot *hotplug_slot) { - struct slot *slot = to_slot(hotplug_slot); + struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev, + hotplug_slot); int rc; - if (slot->zdev->state != ZPCI_FN_STATE_STANDBY) + if (zdev->state != ZPCI_FN_STATE_STANDBY) return -EIO; - rc = slot_configure(slot); + rc = zdev_configure(zdev); if (rc) return rc; - rc = zpci_enable_device(slot->zdev); + rc = zpci_enable_device(zdev); if (rc) goto out_deconfigure; - pci_scan_slot(slot->zdev->bus, ZPCI_DEVFN); + pci_scan_slot(zdev->bus, ZPCI_DEVFN); pci_lock_rescan_remove(); - pci_bus_add_devices(slot->zdev->bus); + pci_bus_add_devices(zdev->bus); pci_unlock_rescan_remove(); return rc; out_deconfigure: - slot_deconfigure(slot); + zdev_deconfigure(zdev); return rc; } static int disable_slot(struct hotplug_slot *hotplug_slot) { - struct slot *slot = to_slot(hotplug_slot); + struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev, + hotplug_slot); struct pci_dev *pdev; int rc; - if (!zpci_fn_configured(slot->zdev->state)) + if (!zpci_fn_configured(zdev->state)) return -EIO; - pdev = pci_get_slot(slot->zdev->bus, ZPCI_DEVFN); + pdev = pci_get_slot(zdev->bus, ZPCI_DEVFN); if (pdev) { pci_stop_and_remove_bus_device_locked(pdev); pci_dev_put(pdev); } - rc = zpci_disable_device(slot->zdev); + rc = zpci_disable_device(zdev); if (rc) return rc; - return slot_deconfigure(slot); + return zdev_deconfigure(zdev); } static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = to_slot(hotplug_slot); + struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev, + hotplug_slot); - switch (slot->zdev->state) { + switch (zdev->state) { case ZPCI_FN_STATE_STANDBY: *value = 0; break; @@ -145,44 +133,15 @@ static const struct hotplug_slot_ops s390_hotplug_slot_ops = { int zpci_init_slot(struct zpci_dev *zdev) { char name[SLOT_NAME_SIZE]; - struct slot *slot; - int rc; - if (!zdev) - return 0; - - slot = kzalloc(sizeof(*slot), GFP_KERNEL); - if (!slot) - goto error; - - slot->zdev = zdev; - slot->hotplug_slot.ops = &s390_hotplug_slot_ops; + zdev->hotplug_slot.ops = &s390_hotplug_slot_ops; snprintf(name, SLOT_NAME_SIZE, "%08x", zdev->fid); - rc = pci_hp_register(&slot->hotplug_slot, zdev->bus, - ZPCI_DEVFN, name); - if (rc) - goto error_reg; - - list_add(&slot->slot_list, &s390_hotplug_slot_list); - return 0; - -error_reg: - kfree(slot); -error: - return -ENOMEM; + return pci_hp_register(&zdev->hotplug_slot, zdev->bus, + ZPCI_DEVFN, name); } void zpci_exit_slot(struct zpci_dev *zdev) { - struct slot *slot, *next; - - list_for_each_entry_safe(slot, next, &s390_hotplug_slot_list, - slot_list) { - if (slot->zdev != zdev) - continue; - list_del(&slot->slot_list); - pci_hp_deregister(&slot->hotplug_slot); - kfree(slot); - } + pci_hp_deregister(&zdev->hotplug_slot); } From d68d5d51dc898895b4e15bea52e5668ca9e76180 Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Thu, 5 Mar 2020 07:44:09 +0100 Subject: [PATCH 1401/4444] s390/cpum_cf: Add new extended counters for IBM z15 Add CPU measurement counter facility event description for IBM z15. Signed-off-by: Thomas Richter Reviewed-by: Sumanth Korikkar Signed-off-by: Vasily Gorbik --- arch/s390/kernel/perf_cpum_cf_events.c | 123 ++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 1 deletion(-) diff --git a/arch/s390/kernel/perf_cpum_cf_events.c b/arch/s390/kernel/perf_cpum_cf_events.c index 8b33e03e47b8..1e3df52b2b65 100644 --- a/arch/s390/kernel/perf_cpum_cf_events.c +++ b/arch/s390/kernel/perf_cpum_cf_events.c @@ -238,6 +238,64 @@ CPUMF_EVENT_ATTR(cf_z14, TX_C_TABORT_SPECIAL, 0x00f5); CPUMF_EVENT_ATTR(cf_z14, MT_DIAG_CYCLES_ONE_THR_ACTIVE, 0x01c0); CPUMF_EVENT_ATTR(cf_z14, MT_DIAG_CYCLES_TWO_THR_ACTIVE, 0x01c1); +CPUMF_EVENT_ATTR(cf_z15, L1D_RO_EXCL_WRITES, 0x0080); +CPUMF_EVENT_ATTR(cf_z15, DTLB2_WRITES, 0x0081); +CPUMF_EVENT_ATTR(cf_z15, DTLB2_MISSES, 0x0082); +CPUMF_EVENT_ATTR(cf_z15, DTLB2_HPAGE_WRITES, 0x0083); +CPUMF_EVENT_ATTR(cf_z15, DTLB2_GPAGE_WRITES, 0x0084); +CPUMF_EVENT_ATTR(cf_z15, L1D_L2D_SOURCED_WRITES, 0x0085); +CPUMF_EVENT_ATTR(cf_z15, ITLB2_WRITES, 0x0086); +CPUMF_EVENT_ATTR(cf_z15, ITLB2_MISSES, 0x0087); +CPUMF_EVENT_ATTR(cf_z15, L1I_L2I_SOURCED_WRITES, 0x0088); +CPUMF_EVENT_ATTR(cf_z15, TLB2_PTE_WRITES, 0x0089); +CPUMF_EVENT_ATTR(cf_z15, TLB2_CRSTE_WRITES, 0x008a); +CPUMF_EVENT_ATTR(cf_z15, TLB2_ENGINES_BUSY, 0x008b); +CPUMF_EVENT_ATTR(cf_z15, TX_C_TEND, 0x008c); +CPUMF_EVENT_ATTR(cf_z15, TX_NC_TEND, 0x008d); +CPUMF_EVENT_ATTR(cf_z15, L1C_TLB2_MISSES, 0x008f); +CPUMF_EVENT_ATTR(cf_z15, L1D_ONCHIP_L3_SOURCED_WRITES, 0x0090); +CPUMF_EVENT_ATTR(cf_z15, L1D_ONCHIP_MEMORY_SOURCED_WRITES, 0x0091); +CPUMF_EVENT_ATTR(cf_z15, L1D_ONCHIP_L3_SOURCED_WRITES_IV, 0x0092); +CPUMF_EVENT_ATTR(cf_z15, L1D_ONCLUSTER_L3_SOURCED_WRITES, 0x0093); +CPUMF_EVENT_ATTR(cf_z15, L1D_ONCLUSTER_MEMORY_SOURCED_WRITES, 0x0094); +CPUMF_EVENT_ATTR(cf_z15, L1D_ONCLUSTER_L3_SOURCED_WRITES_IV, 0x0095); +CPUMF_EVENT_ATTR(cf_z15, L1D_OFFCLUSTER_L3_SOURCED_WRITES, 0x0096); +CPUMF_EVENT_ATTR(cf_z15, L1D_OFFCLUSTER_MEMORY_SOURCED_WRITES, 0x0097); +CPUMF_EVENT_ATTR(cf_z15, L1D_OFFCLUSTER_L3_SOURCED_WRITES_IV, 0x0098); +CPUMF_EVENT_ATTR(cf_z15, L1D_OFFDRAWER_L3_SOURCED_WRITES, 0x0099); +CPUMF_EVENT_ATTR(cf_z15, L1D_OFFDRAWER_MEMORY_SOURCED_WRITES, 0x009a); +CPUMF_EVENT_ATTR(cf_z15, L1D_OFFDRAWER_L3_SOURCED_WRITES_IV, 0x009b); +CPUMF_EVENT_ATTR(cf_z15, L1D_ONDRAWER_L4_SOURCED_WRITES, 0x009c); +CPUMF_EVENT_ATTR(cf_z15, L1D_OFFDRAWER_L4_SOURCED_WRITES, 0x009d); +CPUMF_EVENT_ATTR(cf_z15, L1D_ONCHIP_L3_SOURCED_WRITES_RO, 0x009e); +CPUMF_EVENT_ATTR(cf_z15, L1I_ONCHIP_L3_SOURCED_WRITES, 0x00a2); +CPUMF_EVENT_ATTR(cf_z15, L1I_ONCHIP_MEMORY_SOURCED_WRITES, 0x00a3); +CPUMF_EVENT_ATTR(cf_z15, L1I_ONCHIP_L3_SOURCED_WRITES_IV, 0x00a4); +CPUMF_EVENT_ATTR(cf_z15, L1I_ONCLUSTER_L3_SOURCED_WRITES, 0x00a5); +CPUMF_EVENT_ATTR(cf_z15, L1I_ONCLUSTER_MEMORY_SOURCED_WRITES, 0x00a6); +CPUMF_EVENT_ATTR(cf_z15, L1I_ONCLUSTER_L3_SOURCED_WRITES_IV, 0x00a7); +CPUMF_EVENT_ATTR(cf_z15, L1I_OFFCLUSTER_L3_SOURCED_WRITES, 0x00a8); +CPUMF_EVENT_ATTR(cf_z15, L1I_OFFCLUSTER_MEMORY_SOURCED_WRITES, 0x00a9); +CPUMF_EVENT_ATTR(cf_z15, L1I_OFFCLUSTER_L3_SOURCED_WRITES_IV, 0x00aa); +CPUMF_EVENT_ATTR(cf_z15, L1I_OFFDRAWER_L3_SOURCED_WRITES, 0x00ab); +CPUMF_EVENT_ATTR(cf_z15, L1I_OFFDRAWER_MEMORY_SOURCED_WRITES, 0x00ac); +CPUMF_EVENT_ATTR(cf_z15, L1I_OFFDRAWER_L3_SOURCED_WRITES_IV, 0x00ad); +CPUMF_EVENT_ATTR(cf_z15, L1I_ONDRAWER_L4_SOURCED_WRITES, 0x00ae); +CPUMF_EVENT_ATTR(cf_z15, L1I_OFFDRAWER_L4_SOURCED_WRITES, 0x00af); +CPUMF_EVENT_ATTR(cf_z15, BCD_DFP_EXECUTION_SLOTS, 0x00e0); +CPUMF_EVENT_ATTR(cf_z15, VX_BCD_EXECUTION_SLOTS, 0x00e1); +CPUMF_EVENT_ATTR(cf_z15, DECIMAL_INSTRUCTIONS, 0x00e2); +CPUMF_EVENT_ATTR(cf_z15, LAST_HOST_TRANSLATIONS, 0x00e8); +CPUMF_EVENT_ATTR(cf_z15, TX_NC_TABORT, 0x00f3); +CPUMF_EVENT_ATTR(cf_z15, TX_C_TABORT_NO_SPECIAL, 0x00f4); +CPUMF_EVENT_ATTR(cf_z15, TX_C_TABORT_SPECIAL, 0x00f5); +CPUMF_EVENT_ATTR(cf_z15, DFLT_ACCESS, 0x00f7); +CPUMF_EVENT_ATTR(cf_z15, DFLT_CYCLES, 0x00fc); +CPUMF_EVENT_ATTR(cf_z15, DFLT_CC, 0x00108); +CPUMF_EVENT_ATTR(cf_z15, DFLT_CCERROR, 0x00109); +CPUMF_EVENT_ATTR(cf_z15, MT_DIAG_CYCLES_ONE_THR_ACTIVE, 0x01c0); +CPUMF_EVENT_ATTR(cf_z15, MT_DIAG_CYCLES_TWO_THR_ACTIVE, 0x01c1); + static struct attribute *cpumcf_fvn1_pmu_event_attr[] __initdata = { CPUMF_EVENT_PTR(cf_fvn1, CPU_CYCLES), CPUMF_EVENT_PTR(cf_fvn1, INSTRUCTIONS), @@ -516,6 +574,67 @@ static struct attribute *cpumcf_z14_pmu_event_attr[] __initdata = { NULL, }; +static struct attribute *cpumcf_z15_pmu_event_attr[] __initdata = { + CPUMF_EVENT_PTR(cf_z15, L1D_RO_EXCL_WRITES), + CPUMF_EVENT_PTR(cf_z15, DTLB2_WRITES), + CPUMF_EVENT_PTR(cf_z15, DTLB2_MISSES), + CPUMF_EVENT_PTR(cf_z15, DTLB2_HPAGE_WRITES), + CPUMF_EVENT_PTR(cf_z15, DTLB2_GPAGE_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1D_L2D_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, ITLB2_WRITES), + CPUMF_EVENT_PTR(cf_z15, ITLB2_MISSES), + CPUMF_EVENT_PTR(cf_z15, L1I_L2I_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, TLB2_PTE_WRITES), + CPUMF_EVENT_PTR(cf_z15, TLB2_CRSTE_WRITES), + CPUMF_EVENT_PTR(cf_z15, TLB2_ENGINES_BUSY), + CPUMF_EVENT_PTR(cf_z15, TX_C_TEND), + CPUMF_EVENT_PTR(cf_z15, TX_NC_TEND), + CPUMF_EVENT_PTR(cf_z15, L1C_TLB2_MISSES), + CPUMF_EVENT_PTR(cf_z15, L1D_ONCHIP_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1D_ONCHIP_MEMORY_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1D_ONCHIP_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z15, L1D_ONCLUSTER_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1D_ONCLUSTER_MEMORY_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1D_ONCLUSTER_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z15, L1D_OFFCLUSTER_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1D_OFFCLUSTER_MEMORY_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1D_OFFCLUSTER_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z15, L1D_OFFDRAWER_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1D_OFFDRAWER_MEMORY_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1D_OFFDRAWER_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z15, L1D_ONDRAWER_L4_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1D_OFFDRAWER_L4_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1D_ONCHIP_L3_SOURCED_WRITES_RO), + CPUMF_EVENT_PTR(cf_z15, L1I_ONCHIP_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1I_ONCHIP_MEMORY_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1I_ONCHIP_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z15, L1I_ONCLUSTER_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1I_ONCLUSTER_MEMORY_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1I_ONCLUSTER_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z15, L1I_OFFCLUSTER_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1I_OFFCLUSTER_MEMORY_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1I_OFFCLUSTER_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z15, L1I_OFFDRAWER_L3_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1I_OFFDRAWER_MEMORY_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1I_OFFDRAWER_L3_SOURCED_WRITES_IV), + CPUMF_EVENT_PTR(cf_z15, L1I_ONDRAWER_L4_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, L1I_OFFDRAWER_L4_SOURCED_WRITES), + CPUMF_EVENT_PTR(cf_z15, BCD_DFP_EXECUTION_SLOTS), + CPUMF_EVENT_PTR(cf_z15, VX_BCD_EXECUTION_SLOTS), + CPUMF_EVENT_PTR(cf_z15, DECIMAL_INSTRUCTIONS), + CPUMF_EVENT_PTR(cf_z15, LAST_HOST_TRANSLATIONS), + CPUMF_EVENT_PTR(cf_z15, TX_NC_TABORT), + CPUMF_EVENT_PTR(cf_z15, TX_C_TABORT_NO_SPECIAL), + CPUMF_EVENT_PTR(cf_z15, TX_C_TABORT_SPECIAL), + CPUMF_EVENT_PTR(cf_z15, DFLT_ACCESS), + CPUMF_EVENT_PTR(cf_z15, DFLT_CYCLES), + CPUMF_EVENT_PTR(cf_z15, DFLT_CC), + CPUMF_EVENT_PTR(cf_z15, DFLT_CCERROR), + CPUMF_EVENT_PTR(cf_z15, MT_DIAG_CYCLES_ONE_THR_ACTIVE), + CPUMF_EVENT_PTR(cf_z15, MT_DIAG_CYCLES_TWO_THR_ACTIVE), + NULL, +}; + /* END: CPUM_CF COUNTER DEFINITIONS ===================================== */ static struct attribute_group cpumcf_pmu_events_group = { @@ -624,9 +743,11 @@ __init const struct attribute_group **cpumf_cf_event_group(void) break; case 0x3906: case 0x3907: + model = cpumcf_z14_pmu_event_attr; + break; case 0x8561: case 0x8562: - model = cpumcf_z14_pmu_event_attr; + model = cpumcf_z15_pmu_event_attr; break; default: model = none; From d2abfbe4652d2b49d30fe77548cf663e63d2d469 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 5 Mar 2020 15:01:21 +0100 Subject: [PATCH 1402/4444] s390: enable bpf jit by default when not built as always-on This is the s390 variant of commit 81c22041d9f1 ("bpf, x86, arm64: Enable jit by default when not built as always-on"). Acked-by: Ilya Leoshkevich Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 6b1f715dd8bb..f4ff75ff62f2 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -109,6 +109,7 @@ config S390 select ARCH_USE_BUILTIN_BSWAP select ARCH_USE_CMPXCHG_LOCKREF select ARCH_WANTS_DYNAMIC_TASK_STRUCT + select ARCH_WANT_DEFAULT_BPF_JIT select ARCH_WANT_IPC_PARSE_VERSION select BUILDTIME_TABLE_SORT select CLONE_BACKWARDS2 From 0b38b5e1d0e2f361e418e05c179db05bb688bbd6 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Wed, 22 Jan 2020 13:38:22 +0100 Subject: [PATCH 1403/4444] s390: prevent leaking kernel address in BEAR When userspace executes a syscall or gets interrupted, BEAR contains a kernel address when returning to userspace. This make it pretty easy to figure out where the kernel is mapped even with KASLR enabled. To fix this, add lpswe to lowcore and always execute it there, so userspace sees only the lowcore address of lpswe. For this we have to extend both critical_cleanup and the SWITCH_ASYNC macro to also check for lpswe addresses in lowcore. Fixes: b2d24b97b2a9 ("s390/kernel: add support for kernel address space layout randomization (KASLR)") Cc: # v5.2+ Reviewed-by: Gerald Schaefer Signed-off-by: Sven Schnelle Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/lowcore.h | 4 +- arch/s390/include/asm/processor.h | 1 + arch/s390/include/asm/setup.h | 7 ++++ arch/s390/kernel/asm-offsets.c | 2 + arch/s390/kernel/entry.S | 65 ++++++++++++++++++------------- arch/s390/kernel/process.c | 1 + arch/s390/kernel/setup.c | 3 ++ arch/s390/kernel/smp.c | 2 + arch/s390/mm/vmem.c | 4 ++ 9 files changed, 62 insertions(+), 27 deletions(-) diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 237ee0c4169f..612ed3c6d581 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -141,7 +141,9 @@ struct lowcore { /* br %r1 trampoline */ __u16 br_r1_trampoline; /* 0x0400 */ - __u8 pad_0x0402[0x0e00-0x0402]; /* 0x0402 */ + __u32 return_lpswe; /* 0x0402 */ + __u32 return_mcck_lpswe; /* 0x0406 */ + __u8 pad_0x040a[0x0e00-0x040a]; /* 0x040a */ /* * 0xe00 contains the address of the IPL Parameter Information diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 361ef5eda468..c9522346799f 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -162,6 +162,7 @@ typedef struct thread_struct thread_struct; #define INIT_THREAD { \ .ksp = sizeof(init_stack) + (unsigned long) &init_stack, \ .fpu.regs = (void *) init_task.thread.fpu.fprs, \ + .last_break = 1, \ } /* diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index b241ddb67caf..534f212753d6 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -8,6 +8,7 @@ #include #include +#include #define EP_OFFSET 0x10008 #define EP_STRING "S390EP" @@ -162,6 +163,12 @@ static inline unsigned long kaslr_offset(void) return __kaslr_offset; } +static inline u32 gen_lpswe(unsigned long addr) +{ + BUILD_BUG_ON(addr > 0xfff); + return 0xb2b20000 | addr; +} + #else /* __ASSEMBLY__ */ #define IPL_DEVICE (IPL_DEVICE_OFFSET) diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index ce33406cfe83..e80f0e6f5972 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -124,6 +124,8 @@ int main(void) OFFSET(__LC_EXT_DAMAGE_CODE, lowcore, external_damage_code); OFFSET(__LC_MCCK_FAIL_STOR_ADDR, lowcore, failing_storage_address); OFFSET(__LC_LAST_BREAK, lowcore, breaking_event_addr); + OFFSET(__LC_RETURN_LPSWE, lowcore, return_lpswe); + OFFSET(__LC_RETURN_MCCK_LPSWE, lowcore, return_mcck_lpswe); OFFSET(__LC_RST_OLD_PSW, lowcore, restart_old_psw); OFFSET(__LC_EXT_OLD_PSW, lowcore, external_old_psw); OFFSET(__LC_SVC_OLD_PSW, lowcore, svc_old_psw); diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 9205add8481d..3ae64914bd14 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -115,26 +115,29 @@ _LPP_OFFSET = __LC_LPP .macro SWITCH_ASYNC savearea,timer tmhh %r8,0x0001 # interrupting from user ? - jnz 1f + jnz 2f lgr %r14,%r9 + cghi %r14,__LC_RETURN_LPSWE + je 0f slg %r14,BASED(.Lcritical_start) clg %r14,BASED(.Lcritical_length) - jhe 0f + jhe 1f +0: lghi %r11,\savearea # inside critical section, do cleanup brasl %r14,cleanup_critical tmhh %r8,0x0001 # retest problem state after cleanup - jnz 1f -0: lg %r14,__LC_ASYNC_STACK # are we already on the target stack? + jnz 2f +1: lg %r14,__LC_ASYNC_STACK # are we already on the target stack? slgr %r14,%r15 srag %r14,%r14,STACK_SHIFT - jnz 2f + jnz 3f CHECK_STACK \savearea aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) - j 3f -1: UPDATE_VTIME %r14,%r15,\timer + j 4f +2: UPDATE_VTIME %r14,%r15,\timer BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP -2: lg %r15,__LC_ASYNC_STACK # load async stack -3: la %r11,STACK_FRAME_OVERHEAD(%r15) +3: lg %r15,__LC_ASYNC_STACK # load async stack +4: la %r11,STACK_FRAME_OVERHEAD(%r15) .endm .macro UPDATE_VTIME w1,w2,enter_timer @@ -401,7 +404,7 @@ ENTRY(system_call) stpt __LC_EXIT_TIMER mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER lmg %r11,%r15,__PT_R11(%r11) - lpswe __LC_RETURN_PSW + b __LC_RETURN_LPSWE(%r0) .Lsysc_done: # @@ -608,43 +611,50 @@ ENTRY(pgm_check_handler) BPOFF stmg %r8,%r15,__LC_SAVE_AREA_SYNC lg %r10,__LC_LAST_BREAK - lg %r12,__LC_CURRENT + srag %r11,%r10,12 + jnz 0f + /* if __LC_LAST_BREAK is < 4096, it contains one of + * the lpswe addresses in lowcore. Set it to 1 (initial state) + * to prevent leaking that address to userspace. + */ + lghi %r10,1 +0: lg %r12,__LC_CURRENT lghi %r11,0 larl %r13,cleanup_critical lmg %r8,%r9,__LC_PGM_OLD_PSW tmhh %r8,0x0001 # test problem state bit - jnz 2f # -> fault in user space + jnz 3f # -> fault in user space #if IS_ENABLED(CONFIG_KVM) # cleanup critical section for program checks in sie64a lgr %r14,%r9 slg %r14,BASED(.Lsie_critical_start) clg %r14,BASED(.Lsie_critical_length) - jhe 0f + jhe 1f lg %r14,__SF_SIE_CONTROL(%r15) # get control block pointer ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE lctlg %c1,%c1,__LC_USER_ASCE # load primary asce larl %r9,sie_exit # skip forward to sie_exit lghi %r11,_PIF_GUEST_FAULT #endif -0: tmhh %r8,0x4000 # PER bit set in old PSW ? - jnz 1f # -> enabled, can't be a double fault +1: tmhh %r8,0x4000 # PER bit set in old PSW ? + jnz 2f # -> enabled, can't be a double fault tm __LC_PGM_ILC+3,0x80 # check for per exception jnz .Lpgm_svcper # -> single stepped svc -1: CHECK_STACK __LC_SAVE_AREA_SYNC +2: CHECK_STACK __LC_SAVE_AREA_SYNC aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) - # CHECK_VMAP_STACK branches to stack_overflow or 4f - CHECK_VMAP_STACK __LC_SAVE_AREA_SYNC,4f -2: UPDATE_VTIME %r14,%r15,__LC_SYNC_ENTER_TIMER + # CHECK_VMAP_STACK branches to stack_overflow or 5f + CHECK_VMAP_STACK __LC_SAVE_AREA_SYNC,5f +3: UPDATE_VTIME %r14,%r15,__LC_SYNC_ENTER_TIMER BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP lg %r15,__LC_KERNEL_STACK lgr %r14,%r12 aghi %r14,__TASK_thread # pointer to thread_struct lghi %r13,__LC_PGM_TDB tm __LC_PGM_ILC+2,0x02 # check for transaction abort - jz 3f + jz 4f mvc __THREAD_trap_tdb(256,%r14),0(%r13) -3: stg %r10,__THREAD_last_break(%r14) -4: lgr %r13,%r11 +4: stg %r10,__THREAD_last_break(%r14) +5: lgr %r13,%r11 la %r11,STACK_FRAME_OVERHEAD(%r15) stmg %r0,%r7,__PT_R0(%r11) # clear user controlled registers to prevent speculative use @@ -663,14 +673,14 @@ ENTRY(pgm_check_handler) stg %r13,__PT_FLAGS(%r11) stg %r10,__PT_ARGS(%r11) tm __LC_PGM_ILC+3,0x80 # check for per exception - jz 5f + jz 6f tmhh %r8,0x0001 # kernel per event ? jz .Lpgm_kprobe oi __PT_FLAGS+7(%r11),_PIF_PER_TRAP mvc __THREAD_per_address(8,%r14),__LC_PER_ADDRESS mvc __THREAD_per_cause(2,%r14),__LC_PER_CODE mvc __THREAD_per_paid(1,%r14),__LC_PER_ACCESS_ID -5: REENABLE_IRQS +6: REENABLE_IRQS xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) larl %r1,pgm_check_table llgh %r10,__PT_INT_CODE+2(%r11) @@ -775,7 +785,7 @@ ENTRY(io_int_handler) mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER .Lio_exit_kernel: lmg %r11,%r15,__PT_R11(%r11) - lpswe __LC_RETURN_PSW + b __LC_RETURN_LPSWE(%r0) .Lio_done: # @@ -1214,7 +1224,7 @@ ENTRY(mcck_int_handler) stpt __LC_EXIT_TIMER mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER 0: lmg %r11,%r15,__PT_R11(%r11) - lpswe __LC_RETURN_MCCK_PSW + b __LC_RETURN_MCCK_LPSWE .Lmcck_panic: lg %r15,__LC_NODAT_STACK @@ -1271,6 +1281,8 @@ ENDPROC(stack_overflow) #endif ENTRY(cleanup_critical) + cghi %r9,__LC_RETURN_LPSWE + je .Lcleanup_lpswe #if IS_ENABLED(CONFIG_KVM) clg %r9,BASED(.Lcleanup_table_sie) # .Lsie_gmap jl 0f @@ -1424,6 +1436,7 @@ ENDPROC(cleanup_critical) mvc __LC_RETURN_PSW(16),__PT_PSW(%r9) mvc 0(64,%r11),__PT_R8(%r9) lmg %r0,%r7,__PT_R0(%r9) +.Lcleanup_lpswe: 1: lmg %r8,%r9,__LC_RETURN_PSW BR_EX %r14,%r11 .Lcleanup_sysc_restore_insn: diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 6ccef5f29761..eb6e23ad15a2 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -106,6 +106,7 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long new_stackp, p->thread.system_timer = 0; p->thread.hardirq_timer = 0; p->thread.softirq_timer = 0; + p->thread.last_break = 1; frame->sf.back_chain = 0; /* new return point is ret_from_fork */ diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 1158a63a8e0e..26de59256466 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -73,6 +73,7 @@ #include #include #include +#include #include "entry.h" /* @@ -450,6 +451,8 @@ static void __init setup_lowcore_dat_off(void) lc->spinlock_index = 0; arch_spin_lock_setup(0); lc->br_r1_trampoline = 0x07f1; /* br %r1 */ + lc->return_lpswe = gen_lpswe(__LC_RETURN_PSW); + lc->return_mcck_lpswe = gen_lpswe(__LC_RETURN_MCCK_PSW); set_prefix((u32)(unsigned long) lc); lowcore_ptr[0] = lc; diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index a08bd2522dd9..f87d4e14269c 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -212,6 +212,8 @@ static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu) lc->spinlock_lockval = arch_spin_lockval(cpu); lc->spinlock_index = 0; lc->br_r1_trampoline = 0x07f1; /* br %r1 */ + lc->return_lpswe = gen_lpswe(__LC_RETURN_PSW); + lc->return_mcck_lpswe = gen_lpswe(__LC_RETURN_MCCK_PSW); if (nmi_alloc_per_cpu(lc)) goto out_async; if (vdso_alloc_per_cpu(lc)) diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index b403fa14847d..f810930aff42 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c @@ -415,6 +415,10 @@ void __init vmem_map_init(void) SET_MEMORY_RO | SET_MEMORY_X); __set_memory(__stext_dma, (__etext_dma - __stext_dma) >> PAGE_SHIFT, SET_MEMORY_RO | SET_MEMORY_X); + + /* we need lowcore executable for our LPSWE instructions */ + set_memory_x(0, 1); + pr_info("Write protected kernel read-only data: %luk\n", (unsigned long)(__end_rodata - _stext) >> 10); } From fb83510295d7a6cdeb46242515c3180f9adafc85 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Wed, 29 Jan 2020 12:15:15 +0100 Subject: [PATCH 1404/4444] s390/cpuinfo: add system topology information This update adjusts /proc/cpuinfo format to meet some user level programs expectations. It also makes the layout consistent with x86 where CPU topology is presented as blocks of key-value pairs. Reviewed-by: Vasily Gorbik Signed-off-by: Alexander Gordeev Signed-off-by: Vasily Gorbik --- arch/s390/kernel/processor.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index 6ebc2117c66c..2c13ca562b48 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c @@ -151,6 +151,26 @@ static void show_cpu_summary(struct seq_file *m, void *v) } } +static void show_cpu_topology(struct seq_file *m, unsigned long n) +{ +#ifdef CONFIG_SCHED_TOPOLOGY + seq_printf(m, "physical id : %d\n", topology_physical_package_id(n)); + seq_printf(m, "core id : %d\n", topology_core_id(n)); + seq_printf(m, "book id : %d\n", topology_book_id(n)); + seq_printf(m, "drawer id : %d\n", topology_drawer_id(n)); + seq_printf(m, "dedicated : %d\n", topology_cpu_dedicated(n)); +#endif /* CONFIG_SCHED_TOPOLOGY */ +} + +static void show_cpu_ids(struct seq_file *m, unsigned long n) +{ + struct cpuid *id = &per_cpu(cpu_info.cpu_id, n); + + seq_printf(m, "version : %02X\n", id->version); + seq_printf(m, "identification : %06X\n", id->ident); + seq_printf(m, "machine : %04X\n", id->machine); +} + static void show_cpu_mhz(struct seq_file *m, unsigned long n) { struct cpu_info *c = per_cpu_ptr(&cpu_info, n); @@ -171,6 +191,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) if (!machine_has_cpu_mhz) return 0; seq_printf(m, "\ncpu number : %ld\n", n); + show_cpu_topology(m, n); + show_cpu_ids(m, n); show_cpu_mhz(m, n); return 0; } From d940aa07ed464d884d254f6f3bf321fe5b01d59a Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 25 Feb 2020 18:26:46 +0800 Subject: [PATCH 1405/4444] f2fs: fix to check i_compr_blocks correctly inode.i_blocks counts based on 512byte sector, we need to convert to 4kb sized block count before comparing to i_compr_blocks. In addition, add to print message when sanity check on inode compression configs failed. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/inode.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 78c3f1d70f1d..9b49832296cf 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -291,13 +291,30 @@ static bool sanity_check_inode(struct inode *inode, struct page *node_page) fi->i_flags & F2FS_COMPR_FL && F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, i_log_cluster_size)) { - if (ri->i_compress_algorithm >= COMPRESS_MAX) + if (ri->i_compress_algorithm >= COMPRESS_MAX) { + f2fs_warn(sbi, "%s: inode (ino=%lx) has unsupported " + "compress algorithm: %u, run fsck to fix", + __func__, inode->i_ino, + ri->i_compress_algorithm); return false; - if (le64_to_cpu(ri->i_compr_blocks) > inode->i_blocks) + } + if (le64_to_cpu(ri->i_compr_blocks) > + SECTOR_TO_BLOCK(inode->i_blocks)) { + f2fs_warn(sbi, "%s: inode (ino=%lx) has inconsistent " + "i_compr_blocks:%llu, i_blocks:%llu, run fsck to fix", + __func__, inode->i_ino, + le64_to_cpu(ri->i_compr_blocks), + SECTOR_TO_BLOCK(inode->i_blocks)); return false; + } if (ri->i_log_cluster_size < MIN_COMPRESS_LOG_SIZE || - ri->i_log_cluster_size > MAX_COMPRESS_LOG_SIZE) + ri->i_log_cluster_size > MAX_COMPRESS_LOG_SIZE) { + f2fs_warn(sbi, "%s: inode (ino=%lx) has unsupported " + "log cluster size: %u, run fsck to fix", + __func__, inode->i_ino, + ri->i_log_cluster_size); return false; + } } return true; From c10c98203222f4baef78a641bbb525a00eeebd2f Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Thu, 27 Feb 2020 19:30:03 +0800 Subject: [PATCH 1406/4444] f2fs: cover last_disk_size update with spinlock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change solves below hangtask issue: INFO: task kworker/u16:1:58 blocked for more than 122 seconds. Not tainted 5.6.0-rc2-00590-g9983bdae4974e #11 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. kworker/u16:1 D 0 58 2 0x00000000 Workqueue: writeback wb_workfn (flush-179:0) Backtrace: (__schedule) from [] (schedule+0x78/0xf4) (schedule) from [] (rwsem_down_write_slowpath+0x24c/0x4c0) (rwsem_down_write_slowpath) from [] (down_write+0x6c/0x70) (down_write) from [] (f2fs_write_single_data_page+0x608/0x7ac) (f2fs_write_single_data_page) from [] (f2fs_write_cache_pages+0x2b4/0x7c4) (f2fs_write_cache_pages) from [] (f2fs_write_data_pages+0x344/0x35c) (f2fs_write_data_pages) from [] (do_writepages+0x3c/0xd4) (do_writepages) from [] (__writeback_single_inode+0x44/0x454) (__writeback_single_inode) from [] (writeback_sb_inodes+0x204/0x4b0) (writeback_sb_inodes) from [] (__writeback_inodes_wb+0x50/0xe4) (__writeback_inodes_wb) from [] (wb_writeback+0x294/0x338) (wb_writeback) from [] (wb_workfn+0x35c/0x54c) (wb_workfn) from [] (process_one_work+0x214/0x544) (process_one_work) from [] (worker_thread+0x4c/0x574) (worker_thread) from [] (kthread+0x144/0x170) (kthread) from [] (ret_from_fork+0x14/0x2c) Reported-and-tested-by: Ondřej Jirman Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/compress.c | 4 ++-- fs/f2fs/data.c | 4 ++-- fs/f2fs/f2fs.h | 5 +++-- fs/f2fs/file.c | 4 ++-- fs/f2fs/super.c | 1 + 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 6da33ba2b2db..25bc6154c31c 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -898,10 +898,10 @@ unlock_continue: f2fs_put_dnode(&dn); f2fs_unlock_op(sbi); - down_write(&fi->i_sem); + spin_lock(&fi->i_size_lock); if (fi->last_disk_size < psize) fi->last_disk_size = psize; - up_write(&fi->i_sem); + spin_unlock(&fi->i_size_lock); f2fs_put_rpages(cc); f2fs_destroy_compress_ctx(cc); diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index b27b72107911..e5dc1ebb5305 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -2647,10 +2647,10 @@ write: if (err) { file_set_keep_isize(inode); } else { - down_write(&F2FS_I(inode)->i_sem); + spin_lock(&F2FS_I(inode)->i_size_lock); if (F2FS_I(inode)->last_disk_size < psize) F2FS_I(inode)->last_disk_size = psize; - up_write(&F2FS_I(inode)->i_sem); + spin_unlock(&F2FS_I(inode)->i_size_lock); } done: diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index a5656dd00bc2..43900c1e34fc 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -696,6 +696,7 @@ struct f2fs_inode_info { struct task_struct *cp_task; /* separate cp/wb IO stats*/ nid_t i_xattr_nid; /* node id that contains xattrs */ loff_t last_disk_size; /* lastly written file size */ + spinlock_t i_size_lock; /* protect last_disk_size */ #ifdef CONFIG_QUOTA struct dquot *i_dquot[MAXQUOTAS]; @@ -2855,9 +2856,9 @@ static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync) if (!f2fs_is_time_consistent(inode)) return false; - down_read(&F2FS_I(inode)->i_sem); + spin_lock(&F2FS_I(inode)->i_size_lock); ret = F2FS_I(inode)->last_disk_size == i_size_read(inode); - up_read(&F2FS_I(inode)->i_sem); + spin_unlock(&F2FS_I(inode)->i_size_lock); return ret; } diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 0d4da644df3b..867bd6e444e7 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -929,10 +929,10 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr) if (err) return err; - down_write(&F2FS_I(inode)->i_sem); + spin_lock(&F2FS_I(inode)->i_size_lock); inode->i_mtime = inode->i_ctime = current_time(inode); F2FS_I(inode)->last_disk_size = i_size_read(inode); - up_write(&F2FS_I(inode)->i_sem); + spin_unlock(&F2FS_I(inode)->i_size_lock); } __setattr_copy(inode, attr); diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 686f5402660e..ca34c214cc88 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -960,6 +960,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) /* Initialize f2fs-specific inode info */ atomic_set(&fi->dirty_pages, 0); init_rwsem(&fi->i_sem); + spin_lock_init(&fi->i_size_lock); INIT_LIST_HEAD(&fi->dirty_list); INIT_LIST_HEAD(&fi->gdirty_list); INIT_LIST_HEAD(&fi->inmem_ilist); From 3addc1aed38234e21cb6f9e4df0f6795ec075059 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Thu, 27 Feb 2020 19:30:04 +0800 Subject: [PATCH 1407/4444] f2fs: remove i_sem lock coverage in f2fs_setxattr() f2fs_inode.xattr_ver field was gone after commit d260081ccf37 ("f2fs: change recovery policy of xattr node block"), remove i_sem lock coverage in f2fs_setxattr() Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/xattr.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 296b3189448a..6794a13064be 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -758,12 +758,9 @@ int f2fs_setxattr(struct inode *inode, int index, const char *name, f2fs_balance_fs(sbi, true); f2fs_lock_op(sbi); - /* protect xattr_ver */ - down_write(&F2FS_I(inode)->i_sem); down_write(&F2FS_I(inode)->i_xattr_sem); err = __f2fs_setxattr(inode, index, name, value, size, ipage, flags); up_write(&F2FS_I(inode)->i_xattr_sem); - up_write(&F2FS_I(inode)->i_sem); f2fs_unlock_op(sbi); f2fs_update_time(sbi, REQ_TIME); From 7a88ddb56077d07257a5d0393a4be13e424ca755 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Thu, 27 Feb 2020 19:30:05 +0800 Subject: [PATCH 1408/4444] f2fs: fix inconsistent comments Lack of maintenance on comments may mislead developers, fix them. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/checkpoint.c | 18 ++++-------------- fs/f2fs/data.c | 19 ++++++------------- fs/f2fs/f2fs.h | 2 +- fs/f2fs/file.c | 1 - fs/f2fs/gc.c | 5 ++++- fs/f2fs/inode.c | 2 +- fs/f2fs/namei.c | 2 +- fs/f2fs/node.c | 6 +----- fs/f2fs/shrinker.c | 2 +- fs/f2fs/super.c | 4 ++-- 10 files changed, 21 insertions(+), 40 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 9c88fb3d255a..0dea31f1ddad 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -50,9 +50,6 @@ repeat: return page; } -/* - * We guarantee no failure on the returned page. - */ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index, bool is_meta) { @@ -206,7 +203,7 @@ bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi, } /* - * Readahead CP/NAT/SIT/SSA pages + * Readahead CP/NAT/SIT/SSA/POR pages */ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, int type, bool sync) @@ -898,7 +895,7 @@ int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi) return -ENOMEM; /* * Finding out valid cp block involves read both - * sets( cp pack1 and cp pack 2) + * sets( cp pack 1 and cp pack 2) */ cp_start_blk_no = le32_to_cpu(fsb->cp_blkaddr); cp1 = validate_checkpoint(sbi, cp_start_blk_no, &cp1_version); @@ -1385,10 +1382,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) /* Flush all the NAT/SIT pages */ f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO); - /* - * modify checkpoint - * version number is already updated - */ + /* start to update checkpoint, cp ver is already updated previously */ ckpt->elapsed_time = cpu_to_le64(get_mtime(sbi, true)); ckpt->free_segment_count = cpu_to_le32(free_segments(sbi)); for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) { @@ -1541,9 +1535,6 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) return unlikely(f2fs_cp_error(sbi)) ? -EIO : 0; } -/* - * We guarantee that this checkpoint procedure will not fail. - */ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) { struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); @@ -1611,7 +1602,6 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) f2fs_flush_sit_entries(sbi, cpc); - /* unlock all the fs_lock[] in do_checkpoint() */ err = do_checkpoint(sbi, cpc); if (err) f2fs_release_discard_addrs(sbi); @@ -1624,7 +1614,7 @@ stop: if (cpc->reason & CP_RECOVERY) f2fs_notice(sbi, "checkpoint: version = %llx", ckpt_ver); - /* do checkpoint periodically */ + /* update CP_TIME to trigger checkpoint periodically */ f2fs_update_time(sbi, CP_TIME); trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish checkpoint"); out: diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index e5dc1ebb5305..cd388e72390b 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -364,9 +364,6 @@ static void f2fs_write_end_io(struct bio *bio) bio_put(bio); } -/* - * Return true, if pre_bio's bdev is same as its target device. - */ struct block_device *f2fs_target_device(struct f2fs_sb_info *sbi, block_t blk_addr, struct bio *bio) { @@ -403,6 +400,9 @@ int f2fs_target_device_index(struct f2fs_sb_info *sbi, block_t blkaddr) return 0; } +/* + * Return true, if pre_bio's bdev is same as its target device. + */ static bool __same_bdev(struct f2fs_sb_info *sbi, block_t blk_addr, struct bio *bio) { @@ -410,9 +410,6 @@ static bool __same_bdev(struct f2fs_sb_info *sbi, return bio->bi_disk == b->bd_disk && bio->bi_partno == b->bd_partno; } -/* - * Low-level block read/write IO operations. - */ static struct bio *__bio_alloc(struct f2fs_io_info *fio, int npages) { struct f2fs_sb_info *sbi = fio->sbi; @@ -1388,13 +1385,9 @@ void __do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock) } /* - * f2fs_map_blocks() now supported readahead/bmap/rw direct_IO with - * f2fs_map_blocks structure. - * If original data blocks are allocated, then give them to blockdev. - * Otherwise, - * a. preallocate requested block addresses - * b. do not use extent cache for better performance - * c. give the block addresses to blockdev + * f2fs_map_blocks() tries to find or build mapping relationship which + * maps continuous logical blocks to physical blocks, and return such + * info via f2fs_map_blocks structure. */ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int create, int flag) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 43900c1e34fc..760a05f98ac7 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2388,9 +2388,9 @@ static inline block_t datablock_addr(struct inode *inode, raw_node = F2FS_NODE(node_page); - /* from GC path only */ if (is_inode) { if (!inode) + /* from GC path only */ base = offset_in_addr(&raw_node->i); else if (f2fs_has_extra_attr(inode)) base = get_extra_isize(inode); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 867bd6e444e7..8c725111840e 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -112,7 +112,6 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf) } } - /* fill the page */ f2fs_wait_on_page_writeback(page, DATA, false, true); /* wait for GCed page writeback via META_MAPPING */ diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index db8725d473b5..608d04950f05 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -192,7 +192,10 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type, p->ofs_unit = sbi->segs_per_sec; } - /* we need to check every dirty segments in the FG_GC case */ + /* + * adjust candidates range, should select all dirty segments for + * foreground GC and urgent GC cases. + */ if (gc_type != FG_GC && (sbi->gc_mode != GC_URGENT) && p->max_search > sbi->max_victim_search) diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 9b49832296cf..45aff90af5c5 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -776,7 +776,7 @@ no_delete: else f2fs_inode_synced(inode); - /* ino == 0, if f2fs_new_inode() was failed t*/ + /* for the case f2fs_new_inode() was failed, .i_ino is zero, skip it */ if (inode->i_ino) invalidate_mapping_pages(NODE_MAPPING(sbi), inode->i_ino, inode->i_ino); diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 2aa035422c0f..b75c70813f9e 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -177,7 +177,7 @@ static inline int is_extension_exist(const unsigned char *s, const char *sub) } /* - * Set multimedia files as cold files for hot/cold data separation + * Set file's temperature for hot/cold data separation */ static inline void set_file_temperature(struct f2fs_sb_info *sbi, struct inode *inode, const unsigned char *name) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index d29774df0d64..6006802f9220 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -510,9 +510,6 @@ int f2fs_try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink) return nr - nr_shrink; } -/* - * This function always returns success - */ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni) { @@ -716,8 +713,7 @@ got: /* * Caller should call f2fs_put_dnode(dn). * Also, it should grab and release a rwsem by calling f2fs_lock_op() and - * f2fs_unlock_op() only if ro is not set RDONLY_NODE. - * In the case of RDONLY_NODE, we don't need to care about mutex. + * f2fs_unlock_op() only if mode is set with ALLOC_NODE. */ int f2fs_get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode) { diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c index a467aca29cfe..d66de5999a26 100644 --- a/fs/f2fs/shrinker.c +++ b/fs/f2fs/shrinker.c @@ -58,7 +58,7 @@ unsigned long f2fs_shrink_count(struct shrinker *shrink, /* count extent cache entries */ count += __count_extent_cache(sbi); - /* shrink clean nat cache entries */ + /* count clean nat cache entries */ count += __count_nat_entries(sbi); /* count free nids cache entries */ diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index ca34c214cc88..dcf9042d246c 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1658,7 +1658,7 @@ static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi) out_unlock: up_write(&sbi->gc_lock); restore_flag: - sbi->sb->s_flags = s_flags; /* Restore MS_RDONLY status */ + sbi->sb->s_flags = s_flags; /* Restore SB_RDONLY status */ return err; } @@ -3590,7 +3590,7 @@ try_onemore: f2fs_err(sbi, "Cannot turn on quotas: error %d", err); } #endif - /* if there are nt orphan nodes free them */ + /* if there are any orphan inodes, free them */ err = f2fs_recover_orphan_inodes(sbi); if (err) goto free_meta; From 06c7540fd29ccae351d1a9e0a0a817cb235618bd Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 2 Mar 2020 17:34:27 +0800 Subject: [PATCH 1409/4444] f2fs: fix to avoid using uninitialized variable In f2fs_vm_page_mkwrite(), if inode is compress one, and current mmapped page locates in compressed cluster, we have to call f2fs_get_dnode_of_data() to get its physical block address before f2fs_wait_on_block_writeback(). Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 8c725111840e..b443dc2947c7 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -106,10 +106,18 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf) err = f2fs_get_block(&dn, page->index); f2fs_put_dnode(&dn); __do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, false); - if (err) { - unlock_page(page); - goto out_sem; - } + } + +#ifdef CONFIG_F2FS_FS_COMPRESSION + if (!need_alloc) { + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = f2fs_get_dnode_of_data(&dn, page->index, LOOKUP_NODE); + f2fs_put_dnode(&dn); + } +#endif + if (err) { + unlock_page(page); + goto out_sem; } f2fs_wait_on_page_writeback(page, DATA, false, true); From 95978caa138948054e06d00bfc3432b518699f1b Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Fri, 28 Feb 2020 18:08:46 +0800 Subject: [PATCH 1410/4444] f2fs: fix to avoid use-after-free in f2fs_write_multi_pages() In compress cluster, if physical block number is less than logic page number, race condition will cause use-after-free issue as described below: - f2fs_write_compressed_pages - fio.page = cic->rpages[0]; - f2fs_outplace_write_data - f2fs_compress_write_end_io - kfree(cic->rpages); - kfree(cic); - fio.page = cic->rpages[1]; f2fs_write_multi_pages+0xfd0/0x1a98 f2fs_write_data_pages+0x74c/0xb5c do_writepages+0x64/0x108 __writeback_single_inode+0xdc/0x4b8 writeback_sb_inodes+0x4d0/0xa68 __writeback_inodes_wb+0x88/0x178 wb_writeback+0x1f0/0x424 wb_workfn+0x2f4/0x574 process_one_work+0x210/0x48c worker_thread+0x2e8/0x44c kthread+0x110/0x120 ret_from_fork+0x10/0x18 Fixes: 4c8ff7095bef ("f2fs: support data compression") Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 25bc6154c31c..411d1a5679ac 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -848,7 +848,7 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc, blkaddr = datablock_addr(dn.inode, dn.node_page, dn.ofs_in_node); - fio.page = cic->rpages[i]; + fio.page = cc->rpages[i]; fio.old_blkaddr = blkaddr; /* cluster header */ From 99eabb914e0f870445d065e83e857507f9728a33 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 5 Mar 2020 15:20:26 -0800 Subject: [PATCH 1411/4444] f2fs: fix wrong check on F2FS_IOC_FSSETXATTR This fixes the incorrect failure when enabling project quota on casefold-enabled file. Cc: Daniel Rosenberg Cc: kernel-team@android.com Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index b443dc2947c7..07f636732199 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1794,12 +1794,15 @@ static int f2fs_file_flush(struct file *file, fl_owner_t id) static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask) { struct f2fs_inode_info *fi = F2FS_I(inode); + u32 masked_flags = fi->i_flags & mask; + + f2fs_bug_on(F2FS_I_SB(inode), (iflags & ~mask)); /* Is it quota file? Do not allow user to mess with it */ if (IS_NOQUOTA(inode)) return -EPERM; - if ((iflags ^ fi->i_flags) & F2FS_CASEFOLD_FL) { + if ((iflags ^ masked_flags) & F2FS_CASEFOLD_FL) { if (!f2fs_sb_has_casefold(F2FS_I_SB(inode))) return -EOPNOTSUPP; if (!f2fs_empty_dir(inode)) @@ -1813,9 +1816,9 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask) return -EINVAL; } - if ((iflags ^ fi->i_flags) & F2FS_COMPR_FL) { + if ((iflags ^ masked_flags) & F2FS_COMPR_FL) { if (S_ISREG(inode->i_mode) && - (fi->i_flags & F2FS_COMPR_FL || i_size_read(inode) || + (masked_flags & F2FS_COMPR_FL || i_size_read(inode) || F2FS_HAS_BLOCKS(inode))) return -EINVAL; if (iflags & F2FS_NOCOMP_FL) @@ -1832,8 +1835,8 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask) set_compress_context(inode); } } - if ((iflags ^ fi->i_flags) & F2FS_NOCOMP_FL) { - if (fi->i_flags & F2FS_COMPR_FL) + if ((iflags ^ masked_flags) & F2FS_NOCOMP_FL) { + if (masked_flags & F2FS_COMPR_FL) return -EINVAL; } From 2ef81057d80456870b97890dd79c8f56a85b1242 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Thu, 5 Mar 2020 15:53:08 +0100 Subject: [PATCH 1412/4444] ASoC: Intel: Skylake: Remove superfluous chip initialization Skylake driver does the controller init operation twice: - first during probe (only to stop it just before scheduling probe_work) - and during said probe_work where the actual correct sequence is executed To properly complete boot sequence when iDisp codec is present, bus initialization has to be called only after _i915_init() finishes. With additional _reset_list preceding _i915_init(), iDisp codec never gets the chance to enumerate on the link. Remove the superfluous initialization to address the issue. Signed-off-by: Cezary Rojewski Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200305145314.32579-2-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index f755ca2484cf..d66231525356 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -803,6 +803,9 @@ static void skl_probe_work(struct work_struct *work) return; } + skl_init_pci(skl); + skl_dum_set(bus); + err = skl_init_chip(bus, true); if (err < 0) { dev_err(bus->dev, "Init chip failed with err: %d\n", err); @@ -918,8 +921,6 @@ static int skl_first_init(struct hdac_bus *bus) return -ENXIO; } - snd_hdac_bus_reset_link(bus, true); - snd_hdac_bus_parse_capabilities(bus); /* check if PPCAP exists */ @@ -967,11 +968,7 @@ static int skl_first_init(struct hdac_bus *bus) if (err < 0) return err; - /* initialize chip */ - skl_init_pci(skl); - skl_dum_set(bus); - - return skl_init_chip(bus, true); + return 0; } static int skl_probe(struct pci_dev *pci, @@ -1064,8 +1061,6 @@ static int skl_probe(struct pci_dev *pci, if (bus->mlcap) snd_hdac_ext_bus_get_ml_capabilities(bus); - snd_hdac_bus_stop_chip(bus); - /* create device for soc dmic */ err = skl_dmic_device_register(skl); if (err < 0) { From a66f88394a78fec9a05fa6e517e9603e8eca8363 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Thu, 5 Mar 2020 15:53:09 +0100 Subject: [PATCH 1413/4444] ASoC: Intel: Skylake: Select hda configuration permissively With _reset_link removed from the probe sequence, codec_mask at the time skl_find_hda_machine() is invoked will always be 0, so hda machine will never be chosen. Rather than reorganizing boot flow, be permissive about invalid mask. codec_mask will be set to proper value during probe_work - before skl_codec_create() ever gets called. Signed-off-by: Cezary Rojewski Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200305145314.32579-3-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index d66231525356..4827fe6bc1cb 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -481,13 +481,8 @@ static struct skl_ssp_clk skl_ssp_clks[] = { static struct snd_soc_acpi_mach *skl_find_hda_machine(struct skl_dev *skl, struct snd_soc_acpi_mach *machines) { - struct hdac_bus *bus = skl_to_bus(skl); struct snd_soc_acpi_mach *mach; - /* check if we have any codecs detected on bus */ - if (bus->codec_mask == 0) - return NULL; - /* point to common table */ mach = snd_soc_acpi_intel_hda_machines; From e603f11d5df8997d104ab405ff27640b90baffaa Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Thu, 5 Mar 2020 15:53:10 +0100 Subject: [PATCH 1414/4444] ASoC: Intel: Skylake: Enable codec wakeup during chip init Follow the recommendation set by hda_intel.c and enable HDMI/DP codec wakeup during bus initialization procedure. Disable wakeup once init completes. Signed-off-by: Cezary Rojewski Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200305145314.32579-4-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 4827fe6bc1cb..e2e531c96dd1 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -130,6 +130,7 @@ static int skl_init_chip(struct hdac_bus *bus, bool full_reset) struct hdac_ext_link *hlink; int ret; + snd_hdac_set_codec_wakeup(bus, true); skl_enable_miscbdcge(bus->dev, false); ret = snd_hdac_bus_init_chip(bus, full_reset); @@ -138,6 +139,7 @@ static int skl_init_chip(struct hdac_bus *bus, bool full_reset) writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); skl_enable_miscbdcge(bus->dev, true); + snd_hdac_set_codec_wakeup(bus, false); return ret; } From 9e6c382f5a6161eb55115fb56614b9827f2e7da3 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Thu, 5 Mar 2020 15:53:11 +0100 Subject: [PATCH 1415/4444] ASoC: Intel: Skylake: Shield against no-NHLT configurations Some configurations expose no NHLT table at all within their /sys/firmware/acpi/tables. To prevent NULL-dereference errors from occurring, adjust probe flow and append additional safety checks in functions involved in NHLT lifecycle. Signed-off-by: Cezary Rojewski Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200305145314.32579-5-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-nhlt.c | 3 ++- sound/soc/intel/skylake/skl.c | 9 +++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c index 19f328d71f24..d9c8f5cb389e 100644 --- a/sound/soc/intel/skylake/skl-nhlt.c +++ b/sound/soc/intel/skylake/skl-nhlt.c @@ -182,7 +182,8 @@ void skl_nhlt_remove_sysfs(struct skl_dev *skl) { struct device *dev = &skl->pci->dev; - sysfs_remove_file(&dev->kobj, &dev_attr_platform_id.attr); + if (skl->nhlt) + sysfs_remove_file(&dev->kobj, &dev_attr_platform_id.attr); } /* diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index e2e531c96dd1..7ad8a75759bd 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -633,6 +633,9 @@ static int skl_clock_device_register(struct skl_dev *skl) struct platform_device_info pdevinfo = {NULL}; struct skl_clk_pdata *clk_pdata; + if (!skl->nhlt) + return 0; + clk_pdata = devm_kzalloc(&skl->pci->dev, sizeof(*clk_pdata), GFP_KERNEL); if (!clk_pdata) @@ -1074,7 +1077,8 @@ out_dsp_free: out_clk_free: skl_clock_device_unregister(skl); out_nhlt_free: - intel_nhlt_free(skl->nhlt); + if (skl->nhlt) + intel_nhlt_free(skl->nhlt); out_free: skl_free(bus); @@ -1123,7 +1127,8 @@ static void skl_remove(struct pci_dev *pci) skl_dmic_device_unregister(skl); skl_clock_device_unregister(skl); skl_nhlt_remove_sysfs(skl); - intel_nhlt_free(skl->nhlt); + if (skl->nhlt) + intel_nhlt_free(skl->nhlt); skl_free(bus); dev_set_drvdata(&pci->dev, NULL); } From 024aa45f55ccd40704cfdef61b2a8b6d0de9cdd1 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Thu, 5 Mar 2020 15:53:13 +0100 Subject: [PATCH 1416/4444] ASoC: Intel: Allow for ROM init retry on CNL platforms Due to unconditional initial timeouts, firmware may fail to load during its initialization. This issue cannot be resolved on driver side as it is caused by external sources such as CSME but has to be accounted for nonetheless. Fixes: cb6a55284629 ("ASoC: Intel: cnl: Add sst library functions for cnl platform") Signed-off-by: Cezary Rojewski Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200305145314.32579-7-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/skylake/bxt-sst.c | 2 -- sound/soc/intel/skylake/cnl-sst.c | 15 ++++++++++----- sound/soc/intel/skylake/skl-sst-dsp.h | 1 + 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index 92a82e6b5fe6..cdafade8abd6 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -38,8 +38,6 @@ /* Delay before scheduling D0i3 entry */ #define BXT_D0I3_DELAY 5000 -#define BXT_FW_ROM_INIT_RETRY 3 - static unsigned int bxt_get_errorcode(struct sst_dsp *ctx) { return sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE); diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c index 4f64f097e9ae..060e47ae3391 100644 --- a/sound/soc/intel/skylake/cnl-sst.c +++ b/sound/soc/intel/skylake/cnl-sst.c @@ -109,7 +109,7 @@ static int cnl_load_base_firmware(struct sst_dsp *ctx) { struct firmware stripped_fw; struct skl_dev *cnl = ctx->thread_context; - int ret; + int ret, i; if (!ctx->fw) { ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev); @@ -131,12 +131,16 @@ static int cnl_load_base_firmware(struct sst_dsp *ctx) stripped_fw.size = ctx->fw->size; skl_dsp_strip_extended_manifest(&stripped_fw); - ret = cnl_prepare_fw(ctx, stripped_fw.data, stripped_fw.size); - if (ret < 0) { - dev_err(ctx->dev, "prepare firmware failed: %d\n", ret); - goto cnl_load_base_firmware_failed; + for (i = 0; i < BXT_FW_ROM_INIT_RETRY; i++) { + ret = cnl_prepare_fw(ctx, stripped_fw.data, stripped_fw.size); + if (!ret) + break; + dev_dbg(ctx->dev, "prepare firmware failed: %d\n", ret); } + if (ret < 0) + goto cnl_load_base_firmware_failed; + ret = sst_transfer_fw_host_dma(ctx); if (ret < 0) { dev_err(ctx->dev, "transfer firmware failed: %d\n", ret); @@ -158,6 +162,7 @@ static int cnl_load_base_firmware(struct sst_dsp *ctx) return 0; cnl_load_base_firmware_failed: + dev_err(ctx->dev, "firmware load failed: %d\n", ret); release_firmware(ctx->fw); ctx->fw = NULL; diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index cdfec0fca577..067d1ea11cde 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -67,6 +67,7 @@ struct skl_dev; #define SKL_FW_INIT 0x1 #define SKL_FW_RFW_START 0xf +#define BXT_FW_ROM_INIT_RETRY 3 #define SKL_ADSPIC_IPC 1 #define SKL_ADSPIS_IPC 1 From 7693cadac86548b30389a6e11d78c38db654f393 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Thu, 5 Mar 2020 15:53:14 +0100 Subject: [PATCH 1417/4444] ASoC: Intel: Skylake: Await purge request ack on CNL Each purge request is sent by driver after master core is powered up and unresetted but before it is unstalled. On unstall, ROM begins processing the request and initializing environment for FW load. Host should await ROM's ack before moving forward. Without doing so, ROM init poll may start too early and false timeouts can occur. Fixes: cb6a55284629 ("ASoC: Intel: cnl: Add sst library functions for cnl platform") Signed-off-by: Cezary Rojewski Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200305145314.32579-8-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/skylake/bxt-sst.c | 1 - sound/soc/intel/skylake/cnl-sst.c | 20 ++++++++++++++++++-- sound/soc/intel/skylake/skl-sst-dsp.h | 1 + 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index cdafade8abd6..38b9d7494083 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -17,7 +17,6 @@ #include "skl.h" #define BXT_BASEFW_TIMEOUT 3000 -#define BXT_INIT_TIMEOUT 300 #define BXT_ROM_INIT_TIMEOUT 70 #define BXT_IPC_PURGE_FW 0x01004000 diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c index 060e47ae3391..c6abcd5aa67b 100644 --- a/sound/soc/intel/skylake/cnl-sst.c +++ b/sound/soc/intel/skylake/cnl-sst.c @@ -57,18 +57,34 @@ static int cnl_prepare_fw(struct sst_dsp *ctx, const void *fwdata, u32 fwsize) ctx->dsp_ops.stream_tag = stream_tag; memcpy(ctx->dmab.area, fwdata, fwsize); + ret = skl_dsp_core_power_up(ctx, SKL_DSP_CORE0_MASK); + if (ret < 0) { + dev_err(ctx->dev, "dsp core0 power up failed\n"); + ret = -EIO; + goto base_fw_load_failed; + } + /* purge FW request */ sst_dsp_shim_write(ctx, CNL_ADSP_REG_HIPCIDR, CNL_ADSP_REG_HIPCIDR_BUSY | (CNL_IPC_PURGE | ((stream_tag - 1) << CNL_ROM_CTRL_DMA_ID))); - ret = cnl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK); + ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK); if (ret < 0) { - dev_err(ctx->dev, "dsp boot core failed ret: %d\n", ret); + dev_err(ctx->dev, "Start dsp core failed ret: %d\n", ret); ret = -EIO; goto base_fw_load_failed; } + ret = sst_dsp_register_poll(ctx, CNL_ADSP_REG_HIPCIDA, + CNL_ADSP_REG_HIPCIDA_DONE, + CNL_ADSP_REG_HIPCIDA_DONE, + BXT_INIT_TIMEOUT, "HIPCIDA Done"); + if (ret < 0) { + dev_err(ctx->dev, "timeout for purge request: %d\n", ret); + goto base_fw_load_failed; + } + /* enable interrupt */ cnl_ipc_int_enable(ctx); cnl_ipc_op_int_enable(ctx); diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index 067d1ea11cde..1df9ef422f61 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -68,6 +68,7 @@ struct skl_dev; #define SKL_FW_INIT 0x1 #define SKL_FW_RFW_START 0xf #define BXT_FW_ROM_INIT_RETRY 3 +#define BXT_INIT_TIMEOUT 300 #define SKL_ADSPIC_IPC 1 #define SKL_ADSPIS_IPC 1 From feefd39ab6bb6a746364ef00c39cce2e33a0fde7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 21 Jan 2020 11:01:50 +0100 Subject: [PATCH 1418/4444] arm64: bcm2835: Drop select of nonexistent HAVE_ARM_ARCH_TIMER Unlike on arm32, the HAVE_ARM_ARCH_TIMER config symbol does not exist on arm64. Note that the toplevel ARM64 symbol always selects ARM_ARCH_TIMER, so support for it is always included. Fixes: 628d30d1ccb897fe ("arm64: Add platform selection for BCM2835.") Signed-off-by: Geert Uytterhoeven Reviewed-by: Nicolas Saenz Julienne Signed-off-by: Florian Fainelli --- arch/arm64/Kconfig.platforms | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index b2b504ea6fd6..ad4335122e70 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -39,7 +39,6 @@ config ARCH_BCM2835 select ARM_AMBA select ARM_GIC select ARM_TIMER_SP804 - select HAVE_ARM_ARCH_TIMER help This enables support for the Broadcom BCM2837 and BCM2711 SoC. These SoCs are used in the Raspberry Pi 3 and 4 devices. From 824ca3a2cc0b500adac7fcdc79d6a67a4f7802c4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 21 Jan 2020 11:37:08 +0100 Subject: [PATCH 1419/4444] ARM: bcm: Drop unneeded select of PCI_DOMAINS_GENERIC, HAVE_SMP, TIMER_OF Support for Broadcom SoCs depends on ARCH_MULTI_V6_V7, and thus on ARCH_MULTIPLATFORM, which selects PCI_DOMAINS_GENERIC and TIMER_OF. Support for the various Broadcom IPROC architected SoCs depends on ARCH_MULTI_V7, which selects HAVE_SMP. Hence there is no need for the Broadcom-specific symbols to select any of them. Signed-off-by: Geert Uytterhoeven Cc: Florian Fainelli Cc: Ray Jui Cc: Scott Branden Cc: bcm-kernel-feedback-list@broadcom.com Signed-off-by: Florian Fainelli --- arch/arm/mach-bcm/Kconfig | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index fcfe2a0e8058..6aa938b949db 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -20,7 +20,6 @@ config ARCH_BCM_IPROC select GPIOLIB select ARM_AMBA select PINCTRL - select PCI_DOMAINS_GENERIC if PCI help This enables support for systems based on Broadcom IPROC architected SoCs. The IPROC complex contains one or more ARM CPUs along with common @@ -54,7 +53,6 @@ config ARCH_BCM_NSP select ARM_ERRATA_754322 select ARM_ERRATA_775420 select ARM_ERRATA_764369 if SMP - select HAVE_SMP select THERMAL select THERMAL_OF help @@ -73,7 +71,6 @@ config ARCH_BCM_5301X select ARM_ERRATA_754322 select ARM_ERRATA_775420 select ARM_ERRATA_764369 if SMP - select HAVE_SMP help Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores. @@ -109,7 +106,6 @@ config ARCH_BCM_281XX bool "Broadcom BCM281XX SoC family" depends on ARCH_MULTI_V7 select ARCH_BCM_MOBILE - select HAVE_SMP help Enable support for the BCM281XX family, which includes BCM11130, BCM11140, BCM11351, BCM28145 and BCM28155 @@ -119,7 +115,6 @@ config ARCH_BCM_21664 bool "Broadcom BCM21664 SoC family" depends on ARCH_MULTI_V7 select ARCH_BCM_MOBILE - select HAVE_SMP help Enable support for the BCM21664 family, which includes BCM21663 and BCM21664 variants. @@ -128,7 +123,6 @@ config ARCH_BCM_23550 bool "Broadcom BCM23550 SoC" depends on ARCH_MULTI_V7 select ARCH_BCM_MOBILE - select HAVE_SMP help Enable support for the BCM23550. @@ -165,7 +159,6 @@ config ARCH_BCM2835 select ZONE_DMA if ARCH_MULTI_V7 select ARM_TIMER_SP804 select HAVE_ARM_ARCH_TIMER if ARCH_MULTI_V7 - select TIMER_OF select BCM2835_TIMER select PINCTRL select PINCTRL_BCM2835 @@ -201,7 +194,6 @@ config ARCH_BCM_63XX select HAVE_ARM_ARCH_TIMER select HAVE_ARM_TWD if SMP select HAVE_ARM_SCU if SMP - select HAVE_SMP help This enables support for systems based on Broadcom DSL SoCs. It currently supports the 'BCM63XX' ARM-based family, which includes From 5549ea64799784308cc03313a86dea3de56d48ce Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 10 Mar 2020 11:35:07 -0500 Subject: [PATCH 1420/4444] ASoC: rt5682: fix unmet dependencies The rt5682 code can be used in I2C or SoundWire mode. When I2C is not selected, we have the following issue: WARNING: unmet direct dependencies detected for SND_SOC_RT5682 Depends on [n]: SOUND [=m] && !UML && SND [=m] && SND_SOC [=m] && I2C [=n] Selected by [m]: - SND_SOC_RT5682_SDW [=m] && SOUND [=m] && !UML && SND [=m] && SND_SOC [=m] && SOUNDWIRE [=m] Fix by adding SOUNDWIRE as a dependency. Fixes: 03f6fc6de9192f ('ASoC: rt5682: Add the soundwire support') Reported-by: kbuild test robot Signed-off-by: Pierre-Louis Bossart Cc: Oder Chiou Link: https://lore.kernel.org/r/20200310163509.14466-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 6aee70ed43df..78be69e9b618 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -1135,7 +1135,7 @@ config SND_SOC_RT5677_SPI config SND_SOC_RT5682 tristate - depends on I2C + depends on I2C || SOUNDWIRE config SND_SOC_RT5682_SDW tristate "Realtek RT5682 Codec - SDW" From 724cc62f7a71e3a04112126806c62d9c639ab92c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 10 Mar 2020 11:35:09 -0500 Subject: [PATCH 1421/4444] ASoC: rt5682-sdw: fix 'defined but not used' pm functions Gcc reports the following warnings: sound/soc/codecs/rt5682-sdw.c:286:12: warning: 'rt5682_dev_resume' defined but not used [-Wunused-function] static int rt5682_dev_resume(struct device *dev) ^~~~~~~~~~~~~~~~~ sound/soc/codecs/rt5682-sdw.c:273:12: warning: 'rt5682_dev_suspend' defined but not used [-Wunused-function] static int rt5682_dev_suspend(struct device *dev) ^~~~~~~~~~~~~~~~~~ Fix by adding maybe_unused as done for other SoundWire codecs Fixes: 03f6fc6de9192f ('ASoC: rt5682: Add the soundwire support') Reported-by: kbuild test robot Signed-off-by: Pierre-Louis Bossart Cc: Oder Chiou Link: https://lore.kernel.org/r/20200310163509.14466-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682-sdw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 1d6963dd6403..a2d1d3ae1e31 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -270,7 +270,7 @@ static const struct sdw_device_id rt5682_id[] = { }; MODULE_DEVICE_TABLE(sdw, rt5682_id); -static int rt5682_dev_suspend(struct device *dev) +static int __maybe_unused rt5682_dev_suspend(struct device *dev) { struct rt5682_priv *rt5682 = dev_get_drvdata(dev); @@ -283,7 +283,7 @@ static int rt5682_dev_suspend(struct device *dev) return 0; } -static int rt5682_dev_resume(struct device *dev) +static int __maybe_unused rt5682_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt5682_priv *rt5682 = dev_get_drvdata(dev); From d0c9abb8339dfdb5c5fcdfab5aefcba578a4d50d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 10 Mar 2020 17:36:25 +0100 Subject: [PATCH 1422/4444] ASoC: pcm: Fix (again) possible buffer overflow in dpcm state sysfs output This is re-applying the fix that went into 5.6 (commit 6c89ffea60aa) as the changes were wiped out after merging the other code refactoring. Basically the same changes, just replacing the suspicious calls of snprintf() with scnprintf(). Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20200310163625.10838-1-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index fbea005043de..733d7e8a0e55 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -66,16 +66,16 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe, unsigned long flags; /* FE state */ - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, "[%s - %s]\n", fe->dai_link->name, stream ? "Capture" : "Playback"); - offset += snprintf(buf + offset, size - offset, "State: %s\n", + offset += scnprintf(buf + offset, size - offset, "State: %s\n", dpcm_state_string(fe->dpcm[stream].state)); if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) && (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP)) - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, "Hardware Params: " "Format = %s, Channels = %d, Rate = %d\n", snd_pcm_format_name(params_format(params)), @@ -83,10 +83,10 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe, params_rate(params)); /* BEs state */ - offset += snprintf(buf + offset, size - offset, "Backends:\n"); + offset += scnprintf(buf + offset, size - offset, "Backends:\n"); if (list_empty(&fe->dpcm[stream].be_clients)) { - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, " No active DSP links\n"); goto out; } @@ -96,16 +96,16 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe, struct snd_soc_pcm_runtime *be = dpcm->be; params = &dpcm->hw_params; - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, "- %s\n", be->dai_link->name); - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, " State: %s\n", dpcm_state_string(be->dpcm[stream].state)); if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) && (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP)) - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, " Hardware Params: " "Format = %s, Channels = %d, Rate = %d\n", snd_pcm_format_name(params_format(params)), From e56faff57f0b39661093c00e0262d4ab9088830e Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 28 Feb 2020 15:02:03 -0600 Subject: [PATCH 1423/4444] PCI: Add pci_speed_string() Add pci_speed_string() to return a text description of the supplied bus or link speed. The slot code previously used the private pci_bus_speed_strings[] array for this purpose, but adding this interface will enable us to consolidate similar code elsewhere. Export pcie_link_speed[] and pci_speed_string() so they can be used by modules. Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.h | 1 + drivers/pci/probe.c | 40 ++++++++++++++++++++++++++++++++++++++++ drivers/pci/slot.c | 38 +------------------------------------- include/linux/pci.h | 2 +- 4 files changed, 43 insertions(+), 38 deletions(-) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index f65912e0f30d..809753b10fad 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -310,6 +310,7 @@ void pci_bus_put(struct pci_bus *bus); (speed) == PCIE_SPEED_2_5GT ? 2500*8/10 : \ 0) +const char *pci_speed_string(enum pci_bus_speed speed); enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev); enum pcie_link_width pcie_get_width_cap(struct pci_dev *dev); u32 pcie_bandwidth_capable(struct pci_dev *dev, enum pci_bus_speed *speed, diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 512cb4312ddd..4fc41b71cc95 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -640,6 +640,7 @@ void pci_free_host_bridge(struct pci_host_bridge *bridge) } EXPORT_SYMBOL(pci_free_host_bridge); +/* Indexed by PCI_X_SSTATUS_FREQ (secondary bus mode and frequency) */ static const unsigned char pcix_bus_speed[] = { PCI_SPEED_UNKNOWN, /* 0 */ PCI_SPEED_66MHz_PCIX, /* 1 */ @@ -659,6 +660,7 @@ static const unsigned char pcix_bus_speed[] = { PCI_SPEED_133MHz_PCIX_533 /* F */ }; +/* Indexed by PCI_EXP_LNKCAP_SLS, PCI_EXP_LNKSTA_CLS */ const unsigned char pcie_link_speed[] = { PCI_SPEED_UNKNOWN, /* 0 */ PCIE_SPEED_2_5GT, /* 1 */ @@ -677,6 +679,44 @@ const unsigned char pcie_link_speed[] = { PCI_SPEED_UNKNOWN, /* E */ PCI_SPEED_UNKNOWN /* F */ }; +EXPORT_SYMBOL_GPL(pcie_link_speed); + +const char *pci_speed_string(enum pci_bus_speed speed) +{ + /* Indexed by the pci_bus_speed enum */ + static const char *speed_strings[] = { + "33 MHz PCI", /* 0x00 */ + "66 MHz PCI", /* 0x01 */ + "66 MHz PCI-X", /* 0x02 */ + "100 MHz PCI-X", /* 0x03 */ + "133 MHz PCI-X", /* 0x04 */ + NULL, /* 0x05 */ + NULL, /* 0x06 */ + NULL, /* 0x07 */ + NULL, /* 0x08 */ + "66 MHz PCI-X 266", /* 0x09 */ + "100 MHz PCI-X 266", /* 0x0a */ + "133 MHz PCI-X 266", /* 0x0b */ + "Unknown AGP", /* 0x0c */ + "1x AGP", /* 0x0d */ + "2x AGP", /* 0x0e */ + "4x AGP", /* 0x0f */ + "8x AGP", /* 0x10 */ + "66 MHz PCI-X 533", /* 0x11 */ + "100 MHz PCI-X 533", /* 0x12 */ + "133 MHz PCI-X 533", /* 0x13 */ + "2.5 GT/s PCIe", /* 0x14 */ + "5.0 GT/s PCIe", /* 0x15 */ + "8.0 GT/s PCIe", /* 0x16 */ + "16.0 GT/s PCIe", /* 0x17 */ + "32.0 GT/s PCIe", /* 0x18 */ + }; + + if (speed < ARRAY_SIZE(speed_strings)) + return speed_strings[speed]; + return "Unknown"; +} +EXPORT_SYMBOL_GPL(pci_speed_string); void pcie_update_link_speed(struct pci_bus *bus, u16 linksta) { diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index ae4aa0e1f2f4..cc386ef2fa12 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c @@ -49,45 +49,9 @@ static ssize_t address_read_file(struct pci_slot *slot, char *buf) slot->number); } -/* these strings match up with the values in pci_bus_speed */ -static const char *pci_bus_speed_strings[] = { - "33 MHz PCI", /* 0x00 */ - "66 MHz PCI", /* 0x01 */ - "66 MHz PCI-X", /* 0x02 */ - "100 MHz PCI-X", /* 0x03 */ - "133 MHz PCI-X", /* 0x04 */ - NULL, /* 0x05 */ - NULL, /* 0x06 */ - NULL, /* 0x07 */ - NULL, /* 0x08 */ - "66 MHz PCI-X 266", /* 0x09 */ - "100 MHz PCI-X 266", /* 0x0a */ - "133 MHz PCI-X 266", /* 0x0b */ - "Unknown AGP", /* 0x0c */ - "1x AGP", /* 0x0d */ - "2x AGP", /* 0x0e */ - "4x AGP", /* 0x0f */ - "8x AGP", /* 0x10 */ - "66 MHz PCI-X 533", /* 0x11 */ - "100 MHz PCI-X 533", /* 0x12 */ - "133 MHz PCI-X 533", /* 0x13 */ - "2.5 GT/s PCIe", /* 0x14 */ - "5.0 GT/s PCIe", /* 0x15 */ - "8.0 GT/s PCIe", /* 0x16 */ - "16.0 GT/s PCIe", /* 0x17 */ - "32.0 GT/s PCIe", /* 0x18 */ -}; - static ssize_t bus_speed_read(enum pci_bus_speed speed, char *buf) { - const char *speed_string; - - if (speed < ARRAY_SIZE(pci_bus_speed_strings)) - speed_string = pci_bus_speed_strings[speed]; - else - speed_string = "Unknown"; - - return sprintf(buf, "%s\n", speed_string); + return sprintf(buf, "%s\n", pci_speed_string(speed)); } static ssize_t max_speed_read_file(struct pci_slot *slot, char *buf) diff --git a/include/linux/pci.h b/include/linux/pci.h index 3840a541a9de..76f4806a154c 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -236,7 +236,7 @@ enum pcie_link_width { PCIE_LNK_WIDTH_UNKNOWN = 0xff, }; -/* Based on the PCI Hotplug Spec, but some values are made up by us */ +/* See matching string table in pci_speed_string() */ enum pci_bus_speed { PCI_SPEED_33MHz = 0x00, PCI_SPEED_66MHz = 0x01, From 6348a34dcb98d8e285685a205f2a601817fa2d38 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 28 Feb 2020 15:24:52 -0600 Subject: [PATCH 1424/4444] PCI: Use pci_speed_string() for all PCI/PCI-X/PCIe strings Previously some PCI speed strings came from pci_speed_string(), some came from the PCIe-specific PCIE_SPEED2STR(), and some came from a PCIe-specific switch statement. These methods were inconsistent: pci_speed_string() PCIE_SPEED2STR() switch ------------------ ---------------- ------ 33 MHz PCI ... 2.5 GT/s PCIe 2.5 GT/s 2.5 GT/s 5.0 GT/s PCIe 5 GT/s 5 GT/s 8.0 GT/s PCIe 8 GT/s 8 GT/s 16.0 GT/s PCIe 16 GT/s 16 GT/s 32.0 GT/s PCIe 32 GT/s 32 GT/s Standardize on pci_speed_string() as the single source of these strings. Note that this adds ".0" and "PCIe" to some messages, including sysfs "max_link_speed" files, a brcmstb "link up" message, and the link status dmesg logging, e.g., nvme 0000:01:00.0: 16.000 Gb/s available PCIe bandwidth, limited by 5.0 GT/s PCIe x4 link at 0000:00:01.1 (capable of 31.504 Gb/s with 8.0 GT/s PCIe x4 link) I think it's better to standardize on a single version of the speed text. Previously we had strings like this: /sys/bus/pci/slots/0/cur_bus_speed: 8.0 GT/s PCIe /sys/bus/pci/slots/0/max_bus_speed: 8.0 GT/s PCIe /sys/devices/pci0000:00/0000:00:1c.0/current_link_speed: 8 GT/s /sys/devices/pci0000:00/0000:00:1c.0/max_link_speed: 8 GT/s This changes the latter two to match the slots files: /sys/devices/pci0000:00/0000:00:1c.0/current_link_speed: 8.0 GT/s PCIe /sys/devices/pci0000:00/0000:00:1c.0/max_link_speed: 8.0 GT/s PCIe Based-on-patch by: Yicong Yang Signed-off-by: Bjorn Helgaas --- drivers/pci/controller/pcie-brcmstb.c | 4 ++-- drivers/pci/pci-sysfs.c | 27 +++++---------------------- drivers/pci/pci.c | 6 +++--- drivers/pci/pci.h | 9 --------- 4 files changed, 10 insertions(+), 36 deletions(-) diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c index d20aabc26273..7234eb2a54c9 100644 --- a/drivers/pci/controller/pcie-brcmstb.c +++ b/drivers/pci/controller/pcie-brcmstb.c @@ -824,8 +824,8 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie) cls = FIELD_GET(PCI_EXP_LNKSTA_CLS, lnksta); nlw = FIELD_GET(PCI_EXP_LNKSTA_NLW, lnksta); dev_info(dev, "link up, %s x%u %s\n", - PCIE_SPEED2STR(cls + PCI_SPEED_133MHz_PCIX_533), - nlw, ssc_good ? "(SSC)" : "(!SSC)"); + pci_speed_string(pcie_link_speed[cls]), nlw, + ssc_good ? "(SSC)" : "(!SSC)"); /* PCIe->SCB endian mode for BAR */ tmp = readl(base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1); diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 13f766db0684..d123d1087061 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -156,7 +156,8 @@ static ssize_t max_link_speed_show(struct device *dev, { struct pci_dev *pdev = to_pci_dev(dev); - return sprintf(buf, "%s\n", PCIE_SPEED2STR(pcie_get_speed_cap(pdev))); + return sprintf(buf, "%s\n", + pci_speed_string(pcie_get_speed_cap(pdev))); } static DEVICE_ATTR_RO(max_link_speed); @@ -175,33 +176,15 @@ static ssize_t current_link_speed_show(struct device *dev, struct pci_dev *pci_dev = to_pci_dev(dev); u16 linkstat; int err; - const char *speed; + enum pci_bus_speed speed; err = pcie_capability_read_word(pci_dev, PCI_EXP_LNKSTA, &linkstat); if (err) return -EINVAL; - switch (linkstat & PCI_EXP_LNKSTA_CLS) { - case PCI_EXP_LNKSTA_CLS_32_0GB: - speed = "32 GT/s"; - break; - case PCI_EXP_LNKSTA_CLS_16_0GB: - speed = "16 GT/s"; - break; - case PCI_EXP_LNKSTA_CLS_8_0GB: - speed = "8 GT/s"; - break; - case PCI_EXP_LNKSTA_CLS_5_0GB: - speed = "5 GT/s"; - break; - case PCI_EXP_LNKSTA_CLS_2_5GB: - speed = "2.5 GT/s"; - break; - default: - speed = "Unknown speed"; - } + speed = pcie_link_speed[linkstat & PCI_EXP_LNKSTA_CLS]; - return sprintf(buf, "%s\n", speed); + return sprintf(buf, "%s\n", pci_speed_string(speed)); } static DEVICE_ATTR_RO(current_link_speed); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d828ca835a98..421587badecf 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -5872,14 +5872,14 @@ void __pcie_print_link_status(struct pci_dev *dev, bool verbose) if (bw_avail >= bw_cap && verbose) pci_info(dev, "%u.%03u Gb/s available PCIe bandwidth (%s x%d link)\n", bw_cap / 1000, bw_cap % 1000, - PCIE_SPEED2STR(speed_cap), width_cap); + pci_speed_string(speed_cap), width_cap); else if (bw_avail < bw_cap) pci_info(dev, "%u.%03u Gb/s available PCIe bandwidth, limited by %s x%d link at %s (capable of %u.%03u Gb/s with %s x%d link)\n", bw_avail / 1000, bw_avail % 1000, - PCIE_SPEED2STR(speed), width, + pci_speed_string(speed), width, limiting_dev ? pci_name(limiting_dev) : "", bw_cap / 1000, bw_cap % 1000, - PCIE_SPEED2STR(speed_cap), width_cap); + pci_speed_string(speed_cap), width_cap); } /** diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 809753b10fad..01f5d7f449a5 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -292,15 +292,6 @@ void pci_disable_bridge_window(struct pci_dev *dev); struct pci_bus *pci_bus_get(struct pci_bus *bus); void pci_bus_put(struct pci_bus *bus); -/* PCIe link information */ -#define PCIE_SPEED2STR(speed) \ - ((speed) == PCIE_SPEED_32_0GT ? "32 GT/s" : \ - (speed) == PCIE_SPEED_16_0GT ? "16 GT/s" : \ - (speed) == PCIE_SPEED_8_0GT ? "8 GT/s" : \ - (speed) == PCIE_SPEED_5_0GT ? "5 GT/s" : \ - (speed) == PCIE_SPEED_2_5GT ? "2.5 GT/s" : \ - "Unknown speed") - /* PCIe speed to Mb/s reduced by encoding overhead */ #define PCIE_SPEED2MBS_ENC(speed) \ ((speed) == PCIE_SPEED_32_0GT ? 32000*128/130 : \ From 757bfaa2c3515803dde9a6728bbf8c8a3c5f098a Mon Sep 17 00:00:00 2001 From: Yicong Yang Date: Mon, 17 Feb 2020 19:13:03 +0800 Subject: [PATCH 1425/4444] PCI: Add PCIE_LNKCAP2_SLS2SPEED() macro Add PCIE_LNKCAP2_SLS2SPEED macro for transforming raw Link Capabilities 2 values to the pci_bus_speed. This is next to PCIE_SPEED2MBS_ENC() to make it easier to update both places when adding support for new speeds. Link: https://lore.kernel.org/r/1581937984-40353-10-git-send-email-yangyicong@hisilicon.com Signed-off-by: Yicong Yang Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 17 ++++------------- drivers/pci/pci.h | 9 +++++++++ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 421587badecf..e79cccbbdd39 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -5784,19 +5784,10 @@ enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev) * where only 2.5 GT/s and 5.0 GT/s speeds were defined. */ pcie_capability_read_dword(dev, PCI_EXP_LNKCAP2, &lnkcap2); - if (lnkcap2) { /* PCIe r3.0-compliant */ - if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_32_0GB) - return PCIE_SPEED_32_0GT; - else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_16_0GB) - return PCIE_SPEED_16_0GT; - else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB) - return PCIE_SPEED_8_0GT; - else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB) - return PCIE_SPEED_5_0GT; - else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB) - return PCIE_SPEED_2_5GT; - return PCI_SPEED_UNKNOWN; - } + + /* PCIe r3.0-compliant */ + if (lnkcap2) + return PCIE_LNKCAP2_SLS2SPEED(lnkcap2); pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap); if ((lnkcap & PCI_EXP_LNKCAP_SLS) == PCI_EXP_LNKCAP_SLS_5_0GB) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 01f5d7f449a5..75d027ecfbcd 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -292,6 +292,15 @@ void pci_disable_bridge_window(struct pci_dev *dev); struct pci_bus *pci_bus_get(struct pci_bus *bus); void pci_bus_put(struct pci_bus *bus); +/* PCIe link information from Link Capabilities 2 */ +#define PCIE_LNKCAP2_SLS2SPEED(lnkcap2) \ + ((lnkcap2) & PCI_EXP_LNKCAP2_SLS_32_0GB ? PCIE_SPEED_32_0GT : \ + (lnkcap2) & PCI_EXP_LNKCAP2_SLS_16_0GB ? PCIE_SPEED_16_0GT : \ + (lnkcap2) & PCI_EXP_LNKCAP2_SLS_8_0GB ? PCIE_SPEED_8_0GT : \ + (lnkcap2) & PCI_EXP_LNKCAP2_SLS_5_0GB ? PCIE_SPEED_5_0GT : \ + (lnkcap2) & PCI_EXP_LNKCAP2_SLS_2_5GB ? PCIE_SPEED_2_5GT : \ + PCI_SPEED_UNKNOWN) + /* PCIe speed to Mb/s reduced by encoding overhead */ #define PCIE_SPEED2MBS_ENC(speed) \ ((speed) == PCIE_SPEED_32_0GT ? 32000*128/130 : \ From ae9fdd23e6284979ba9829a2e7acdf295d554a32 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Mon, 2 Mar 2020 14:39:10 +0100 Subject: [PATCH 1426/4444] dt-bindings: serial: snps-dw-apb-uart: add compatible property for rk3308 uart A test with the command below gives these errors: arch/arm64/boot/dts/rockchip/rk3308-evb.dt.yaml: serial@ff0d0000: compatible: ['rockchip,rk3308-uart', 'snps,dw-apb-uart'] is not valid under any of the given schemas arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dt.yaml: serial@ff0a0000: compatible: ['rockchip,rk3308-uart', 'snps,dw-apb-uart'] is not valid under any of the given schemas The compatible property for the Rockchip rk3308 uart was somehow never added to the documention. Fix this error by adding 'rockchip,rk3308-uart' to snps-dw-apb-uart.yaml. make ARCH=arm64 dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/serial/ snps-dw-apb-uart.yaml Signed-off-by: Johan Jonker Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml index b42002542690..b962f8db4ce9 100644 --- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml +++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml @@ -27,6 +27,7 @@ properties: - rockchip,rk3066-uart - rockchip,rk3188-uart - rockchip,rk3288-uart + - rockchip,rk3308-uart - rockchip,rk3328-uart - rockchip,rk3368-uart - rockchip,rk3399-uart From 98d9098e7f57e1a34db38cfb6277bf5ab4dd103c Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 4 Feb 2020 15:55:41 -0800 Subject: [PATCH 1427/4444] dt-bindings: arm: bcm: Convert Cygnus to YAML Update the Broadocom Cygnus SoC binding document for boards/SoCs to use YAML. Verified with dt_binding_check and dtbs_check. Acked-by: Scott Branden Reviewed-by: Rob Herring Signed-off-by: Florian Fainelli --- .../bindings/arm/bcm/brcm,cygnus.txt | 31 ------------------- .../bindings/arm/bcm/brcm,cygnus.yaml | 29 +++++++++++++++++ 2 files changed, 29 insertions(+), 31 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,cygnus.txt create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,cygnus.yaml diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,cygnus.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,cygnus.txt deleted file mode 100644 index 4c77169bb534..000000000000 --- a/Documentation/devicetree/bindings/arm/bcm/brcm,cygnus.txt +++ /dev/null @@ -1,31 +0,0 @@ -Broadcom Cygnus device tree bindings ------------------------------------- - - -Boards with Cygnus SoCs shall have the following properties: - -Required root node property: - -BCM11300 -compatible = "brcm,bcm11300", "brcm,cygnus"; - -BCM11320 -compatible = "brcm,bcm11320", "brcm,cygnus"; - -BCM11350 -compatible = "brcm,bcm11350", "brcm,cygnus"; - -BCM11360 -compatible = "brcm,bcm11360", "brcm,cygnus"; - -BCM58300 -compatible = "brcm,bcm58300", "brcm,cygnus"; - -BCM58302 -compatible = "brcm,bcm58302", "brcm,cygnus"; - -BCM58303 -compatible = "brcm,bcm58303", "brcm,cygnus"; - -BCM58305 -compatible = "brcm,bcm58305", "brcm,cygnus"; diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,cygnus.yaml b/Documentation/devicetree/bindings/arm/bcm/brcm,cygnus.yaml new file mode 100644 index 000000000000..fe111e72dac3 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,cygnus.yaml @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/bcm/brcm,cygnus.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom Cygnus device tree bindings + +maintainers: + - Ray Jui + - Scott Branden + +properties: + $nodename: + const: '/' + compatible: + items: + - enum: + - brcm,bcm11300 + - brcm,bcm11320 + - brcm,bcm11350 + - brcm,bcm11360 + - brcm,bcm58300 + - brcm,bcm58302 + - brcm,bcm58303 + - brcm,bcm58305 + - const: brcm,cygnus + +... From e73db888e55a2cb53a3a8e5f05622e60b924bd43 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 4 Feb 2020 15:55:42 -0800 Subject: [PATCH 1428/4444] dt-bindings: arm: bcm: Convert Hurricane 2 to YAML Update the Broadcom Hurricane 2 SoC binding document for boards/SoCs to use YAML. Verified with dt_binding_check and dtbs_check. Acked-by: Scott Branden Reviewed-by: Rob Herring Signed-off-by: Florian Fainelli --- .../devicetree/bindings/arm/bcm/brcm,hr2.txt | 14 ---------- .../devicetree/bindings/arm/bcm/brcm,hr2.yaml | 28 +++++++++++++++++++ 2 files changed, 28 insertions(+), 14 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,hr2.txt create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,hr2.yaml diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,hr2.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,hr2.txt deleted file mode 100644 index a124c7fc4dcd..000000000000 --- a/Documentation/devicetree/bindings/arm/bcm/brcm,hr2.txt +++ /dev/null @@ -1,14 +0,0 @@ -Broadcom Hurricane 2 device tree bindings ---------------------------------------- - -Broadcom Hurricane 2 family of SoCs are used for switching control. These SoCs -are based on Broadcom's iProc SoC architecture and feature a single core Cortex -A9 ARM CPUs, DDR2/DDR3 memory, PCIe GEN-2, USB 2.0 and USB 3.0, serial and NAND -flash and a PCIe attached integrated switching engine. - -Boards with Hurricane SoCs shall have the following properties: - -Required root node property: - -BCM53342 -compatible = "brcm,bcm53342", "brcm,hr2"; diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,hr2.yaml b/Documentation/devicetree/bindings/arm/bcm/brcm,hr2.yaml new file mode 100644 index 000000000000..1158f49b0b83 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,hr2.yaml @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/bcm/brcm,hr2.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom Hurricane 2 device tree bindings + +description: + Broadcom Hurricane 2 family of SoCs are used for switching control. These SoCs + are based on Broadcom's iProc SoC architecture and feature a single core Cortex + A9 ARM CPUs, DDR2/DDR3 memory, PCIe GEN-2, USB 2.0 and USB 3.0, serial and NAND + flash and a PCIe attached integrated switching engine. + +maintainers: + - Florian Fainelli + +properties: + $nodename: + const: '/' + compatible: + items: + - enum: + - ubnt,unifi-switch8 + - const: brcm,bcm53342 + - const: brcm,hr2 + +... From 6570e8bdf71e3ecf2b4dcca98d551b8d0a8211a3 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 4 Feb 2020 15:55:43 -0800 Subject: [PATCH 1429/4444] dt-bindings: arm: bcm: Convert Northstar Plus to YAML Update the Broadcom Northstar Plus SoC binding document for boards/SoCs to use YAML. Verified with dt_binding_check and dtbs_check. Acked-by: Scott Branden Reviewed-by: Rob Herring Signed-off-by: Florian Fainelli --- .../devicetree/bindings/arm/bcm/brcm,nsp.txt | 34 ------------------ .../devicetree/bindings/arm/bcm/brcm,nsp.yaml | 36 +++++++++++++++++++ 2 files changed, 36 insertions(+), 34 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,nsp.txt create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,nsp.yaml diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,nsp.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,nsp.txt deleted file mode 100644 index eae53e4556be..000000000000 --- a/Documentation/devicetree/bindings/arm/bcm/brcm,nsp.txt +++ /dev/null @@ -1,34 +0,0 @@ -Broadcom Northstar Plus device tree bindings --------------------------------------------- - -Broadcom Northstar Plus family of SoCs are used for switching control -and management applications as well as residential router/gateway -applications. The SoC features dual core Cortex A9 ARM CPUs, integrating -several peripheral interfaces including multiple Gigabit Ethernet PHYs, -DDR3 memory, PCIE Gen-2, USB 2.0 and USB 3.0, serial and NAND flash, -SATA and several other IO controllers. - -Boards with Northstar Plus SoCs shall have the following properties: - -Required root node property: - -BCM58522 -compatible = "brcm,bcm58522", "brcm,nsp"; - -BCM58525 -compatible = "brcm,bcm58525", "brcm,nsp"; - -BCM58535 -compatible = "brcm,bcm58535", "brcm,nsp"; - -BCM58622 -compatible = "brcm,bcm58622", "brcm,nsp"; - -BCM58623 -compatible = "brcm,bcm58623", "brcm,nsp"; - -BCM58625 -compatible = "brcm,bcm58625", "brcm,nsp"; - -BCM88312 -compatible = "brcm,bcm88312", "brcm,nsp"; diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,nsp.yaml b/Documentation/devicetree/bindings/arm/bcm/brcm,nsp.yaml new file mode 100644 index 000000000000..fe364cebf57f --- /dev/null +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,nsp.yaml @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/bcm/brcm,nsp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom Northstar Plus device tree bindings + +description: + Broadcom Northstar Plus family of SoCs are used for switching control + and management applications as well as residential router/gateway + applications. The SoC features dual core Cortex A9 ARM CPUs, integrating + several peripheral interfaces including multiple Gigabit Ethernet PHYs, + DDR3 memory, PCIE Gen-2, USB 2.0 and USB 3.0, serial and NAND flash, + SATA and several other IO controllers. + +maintainers: + - Ray Jui + - Scott Branden + +properties: + $nodename: + const: '/' + compatible: + items: + - enum: + - brcm,bcm58522 + - brcm,bcm58525 + - brcm,bcm58535 + - brcm,bcm58622 + - brcm,bcm58623 + - brcm,bcm58625 + - brcm,bcm88312 + - const: brcm,nsp + +... From 0899c8ff466352d449ac5a04c065c22744b989ef Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 4 Feb 2020 15:55:44 -0800 Subject: [PATCH 1430/4444] dt-bindings: arm: bcm: Convert Northstar 2 to YAML Update the Broadcom Northstar 2 SoC binding document for boards/SoCs to use YAML. Verified with dt_binding_check and dtbs_check. Acked-by: Scott Branden Reviewed-by: Rob Herring Signed-off-by: Florian Fainelli --- .../devicetree/bindings/arm/bcm/brcm,ns2.txt | 9 -------- .../devicetree/bindings/arm/bcm/brcm,ns2.yaml | 23 +++++++++++++++++++ 2 files changed, 23 insertions(+), 9 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,ns2.txt create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,ns2.yaml diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,ns2.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,ns2.txt deleted file mode 100644 index 35f056f4a1c3..000000000000 --- a/Documentation/devicetree/bindings/arm/bcm/brcm,ns2.txt +++ /dev/null @@ -1,9 +0,0 @@ -Broadcom North Star 2 (NS2) device tree bindings ------------------------------------------------- - -Boards with NS2 shall have the following properties: - -Required root node property: - -NS2 SVK board -compatible = "brcm,ns2-svk", "brcm,ns2"; diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,ns2.yaml b/Documentation/devicetree/bindings/arm/bcm/brcm,ns2.yaml new file mode 100644 index 000000000000..2451704f87f0 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,ns2.yaml @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/bcm/brcm,ns2.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom North Star 2 (NS2) device tree bindings + +maintainers: + - Ray Jui + - Scott Branden + +properties: + $nodename: + const: '/' + compatible: + items: + - enum: + - brcm,ns2-svk + - brcm,ns2-xmc + - const: brcm,ns2 + +... From 4b968636a3b76070fbadb600c5c96bf89da2128e Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 4 Feb 2020 15:55:45 -0800 Subject: [PATCH 1431/4444] dt-bindings: arm: bcm: Convert Stingray to YAML Update the Broadcom Stingray SoC binding document for boards/SoCs to use YAML. Verified with dt_binding_check and dtbs_check. Acked-by: Scott Branden Reviewed-by: Rob Herring Signed-off-by: Florian Fainelli --- .../bindings/arm/bcm/brcm,stingray.txt | 12 ---------- .../bindings/arm/bcm/brcm,stingray.yaml | 24 +++++++++++++++++++ 2 files changed, 24 insertions(+), 12 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,stingray.txt create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,stingray.yaml diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,stingray.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,stingray.txt deleted file mode 100644 index 23a02178dd44..000000000000 --- a/Documentation/devicetree/bindings/arm/bcm/brcm,stingray.txt +++ /dev/null @@ -1,12 +0,0 @@ -Broadcom Stingray device tree bindings ------------------------------------------------- - -Boards with Stingray shall have the following properties: - -Required root node property: - -Stingray Combo SVK board -compatible = "brcm,bcm958742k", "brcm,stingray"; - -Stingray SST100 board -compatible = "brcm,bcm958742t", "brcm,stingray"; diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,stingray.yaml b/Documentation/devicetree/bindings/arm/bcm/brcm,stingray.yaml new file mode 100644 index 000000000000..4ad2b2124ab4 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,stingray.yaml @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/bcm/brcm,stingray.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom Stingray device tree bindings + +maintainers: + - Ray Jui + - Scott Branden + +properties: + $nodename: + const: '/' + compatible: + items: + - enum: + - brcm,bcm958742k + - brcm,bcm958742t + - brcm,bcm958802a802x + - const: brcm,stingray + +... From 1c4311c1ccb9f22803ca80edb4d04e1f7a65f128 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 4 Feb 2020 15:55:46 -0800 Subject: [PATCH 1432/4444] dt-bindings: arm: bcm: Convert BCM21664 to YAML Update the Broadcom BCM21664 SoC binding document for boards/SoCs to use YAML. Verified with dt_binding_check and dtbs_check. Acked-by: Scott Branden Reviewed-by: Rob Herring Signed-off-by: Florian Fainelli --- .../bindings/arm/bcm/brcm,bcm21664.txt | 15 ------------- .../bindings/arm/bcm/brcm,bcm21664.yaml | 21 +++++++++++++++++++ 2 files changed, 21 insertions(+), 15 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm21664.txt create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm21664.yaml diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm21664.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm21664.txt deleted file mode 100644 index e0774255e1a6..000000000000 --- a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm21664.txt +++ /dev/null @@ -1,15 +0,0 @@ -Broadcom BCM21664 device tree bindings --------------------------------------- - -This document describes the device tree bindings for boards with the BCM21664 -SoC. - -Required root node property: - - compatible: brcm,bcm21664 - -Example: - / { - model = "BCM21664 SoC"; - compatible = "brcm,bcm21664"; - [...] - } diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm21664.yaml b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm21664.yaml new file mode 100644 index 000000000000..aafbd6a27708 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm21664.yaml @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/bcm/brcm,bcm21664.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom BCM21664 device tree bindings + +maintainers: + - Florian Fainelli + +properties: + $nodename: + const: '/' + compatible: + items: + - enum: + - brcm,bcm21664-garnet + - const: brcm,bcm21664 + +... From 06c1426b3a6a1c87bf001771dee81d1838dba412 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 4 Feb 2020 15:55:47 -0800 Subject: [PATCH 1433/4444] dt-bindings: arm: bcm: Convert BCM23550 to YAML Update the Broadcom BCM23550 SoC binding document for boards/SoCs to use YAML. Verified with dt_binding_check and dtbs_check. Acked-by: Scott Branden Reviewed-by: Rob Herring Signed-off-by: Florian Fainelli --- .../bindings/arm/bcm/brcm,bcm23550.txt | 15 ------------- .../bindings/arm/bcm/brcm,bcm23550.yaml | 21 +++++++++++++++++++ 2 files changed, 21 insertions(+), 15 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.txt create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.yaml diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.txt deleted file mode 100644 index 080baad923d6..000000000000 --- a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.txt +++ /dev/null @@ -1,15 +0,0 @@ -Broadcom BCM23550 device tree bindings --------------------------------------- - -This document describes the device tree bindings for boards with the BCM23550 -SoC. - -Required root node property: - - compatible: brcm,bcm23550 - -Example: - / { - model = "BCM23550 SoC"; - compatible = "brcm,bcm23550"; - [...] - } diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.yaml b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.yaml new file mode 100644 index 000000000000..c4b4efd28a55 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.yaml @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/bcm/brcm,bcm23550.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom BCM23550 device tree bindings + +maintainers: + - Florian Fainelli + +properties: + $nodename: + const: '/' + compatible: + items: + - enum: + - brcm,bcm23550-sparrow + - const: brcm,bcm23550 + +... From 4cb5201fcb5d4599bf602101ece5465cdc65081b Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 4 Feb 2020 15:55:48 -0800 Subject: [PATCH 1434/4444] dt-bindings: arm: bcm: Convert BCM4708 to YAML Update the Broadcom BCM4708 SoC family binding document for boards/SoCs to use YAML. Verified with dt_binding_check and dtbs_check. Acked-by: Scott Branden Reviewed-by: Rob Herring Signed-off-by: Florian Fainelli --- .../bindings/arm/bcm/brcm,bcm4708.txt | 15 ---- .../bindings/arm/bcm/brcm,bcm4708.yaml | 88 +++++++++++++++++++ 2 files changed, 88 insertions(+), 15 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.txt create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.yaml diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.txt deleted file mode 100644 index 8608a776caa7..000000000000 --- a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.txt +++ /dev/null @@ -1,15 +0,0 @@ -Broadcom BCM4708 device tree bindings -------------------------------------------- - -Boards with the BCM4708 SoC shall have the following properties: - -Required root node property: - -bcm4708 -compatible = "brcm,bcm4708"; - -bcm4709 -compatible = "brcm,bcm4709"; - -bcm53012 -compatible = "brcm,bcm53012"; diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.yaml b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.yaml new file mode 100644 index 000000000000..d48313c7ae45 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.yaml @@ -0,0 +1,88 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/bcm/brcm,bcm4708.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom BCM4708 device tree bindings + +description: + Broadcom BCM4708/47081/4709/47094/53012 Wi-Fi/network SoCs based + on the iProc architecture (Northstar). + +maintainers: + - Florian Fainelli + - Hauke Mehrtens + - Rafal Milecki + +properties: + $nodename: + const: '/' + compatible: + oneOf: + - description: BCM4708 based boards + items: + - enum: + - asus,rt-ac56u + - asus,rt-ac68u + - buffalo,wzr-1750dhp + - linksys,ea6300-v1 + - linksys,ea6500-v2 + - luxul,xap-1510v1 + - luxul,xwc-1000 + - netgear,r6250v1 + - netgear,r6300v2 + - smartrg,sr400ac + - brcm,bcm94708 + - const: brcm,bcm4708 + + - description: BCM47081 based boards + items: + - enum: + - asus,rt-n18u + - buffalo,wzr-600dhp2 + - buffalo,wzr-900dhp + - luxul,xap-1410v1 + - luxul,xwr-1200v1 + - tplink,archer-c5-v2 + - const: brcm,bcm47081 + - const: brcm,bcm4708 + + - description: BCM4709 based boards + items: + - enum: + - asus,rt-ac87u + - buffalo,wxr-1900dhp + - linksys,ea9200 + - netgear,r7000 + - netgear,r8000 + - tplink,archer-c9-v1 + - brcm,bcm94709 + - const: brcm,bcm4709 + - const: brcm,bcm4708 + + - description: BCM47094 based boards + items: + - enum: + - dlink,dir-885l + - linksys,panamera + - luxul,abr-4500-v1 + - luxul,xap-1610-v1 + - luxul,xbr-4500-v1 + - luxul,xwc-2000-v1 + - luxul,xwr-3100v1 + - luxul,xwr-3150-v1 + - netgear,r8500 + - phicomm,k3 + - const: brcm,bcm47094 + - const: brcm,bcm4708 + + - description: BCM53012 based boards + items: + - enum: + - brcm,bcm953012er + - brcm,bcm953012hr + - brcm,bcm953012k + - const: brcm,brcm53012 + - const: brcm,bcm4708 +... From 73e1b88f341477492c735770e29843f0b9f2e103 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 4 Feb 2020 15:55:49 -0800 Subject: [PATCH 1435/4444] dt-bindings: arm: bcm: Convert BCM11351 to YAML Update the Broadcom BCM11351 SoC family binding document for boards/SoCs to use YAML. Verified with dt_binding_check and dtbs_check. Acked-by: Scott Branden Reviewed-by: Rob Herring Signed-off-by: Florian Fainelli --- .../bindings/arm/bcm/brcm,bcm11351.txt | 10 --------- .../bindings/arm/bcm/brcm,bcm11351.yaml | 21 +++++++++++++++++++ 2 files changed, 21 insertions(+), 10 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351.txt create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351.yaml diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351.txt deleted file mode 100644 index 0ff6560e6094..000000000000 --- a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351.txt +++ /dev/null @@ -1,10 +0,0 @@ -Broadcom BCM11351 device tree bindings -------------------------------------------- - -Boards with the bcm281xx SoC family (which includes bcm11130, bcm11140, -bcm11351, bcm28145, bcm28155 SoCs) shall have the following properties: - -Required root node property: - -compatible = "brcm,bcm11351"; -DEPRECATED: compatible = "bcm,bcm11351"; diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351.yaml b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351.yaml new file mode 100644 index 000000000000..b5ef2666e6b2 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351.yaml @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/bcm/brcm,bcm11351.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom BCM11351 device tree bindings + +maintainers: + - Florian Fainelli + +properties: + $nodename: + const: '/' + compatible: + items: + - enum: + - brcm,bcm28155-ap + - const: brcm,bcm11351 + +... From b63b50ab0613a3e8b53441668219e96a61a17b6b Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 4 Feb 2020 15:55:50 -0800 Subject: [PATCH 1436/4444] dt-bindings: arm: bcm: Convert Vulcan to YAML Update Vulcan SoC family binding document for boards/SoCs to use YAML. Verified with dt_binding_check and dtbs_check. Acked-by: Scott Branden Reviewed-by: Rob Herring Signed-off-by: Florian Fainelli --- .../bindings/arm/bcm/brcm,vulcan-soc.txt | 10 --------- .../bindings/arm/bcm/brcm,vulcan-soc.yaml | 22 +++++++++++++++++++ 2 files changed, 22 insertions(+), 10 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,vulcan-soc.txt create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,vulcan-soc.yaml diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,vulcan-soc.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,vulcan-soc.txt deleted file mode 100644 index 223ed3471c08..000000000000 --- a/Documentation/devicetree/bindings/arm/bcm/brcm,vulcan-soc.txt +++ /dev/null @@ -1,10 +0,0 @@ -Broadcom Vulcan device tree bindings ------------------------------------- - -Boards with Broadcom Vulcan shall have the following root property: - -Broadcom Vulcan Evaluation Board: - compatible = "brcm,vulcan-eval", "brcm,vulcan-soc"; - -Generic Vulcan board: - compatible = "brcm,vulcan-soc"; diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,vulcan-soc.yaml b/Documentation/devicetree/bindings/arm/bcm/brcm,vulcan-soc.yaml new file mode 100644 index 000000000000..c5b6f31c20b9 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,vulcan-soc.yaml @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/bcm/brcm,vulcan-soc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom Vulcan device tree bindings + +maintainers: + - Robert Richter + +properties: + $nodename: + const: '/' + compatible: + items: + - enum: + - brcm,vulcan-eval + - cavium,thunderx2-cn9900 + - const: brcm,vulcan-soc + +... From 14e1eb5a91a96d9e1ce8051f752b7b6645bc8e10 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 4 Feb 2020 15:55:51 -0800 Subject: [PATCH 1437/4444] dt-bindings: arm: Document Broadcom SoCs 'secondary-boot-reg' Consolidate and move the 'secondary-boot-reg' property from the 3 existing binding documents into the main cpus.yaml documentation, also make sure that the property is enforced when relevant. Acked-by: Maxime Ripard Acked-by: Scott Branden Reviewed-by: Rob Herring Signed-off-by: Florian Fainelli --- .../arm/bcm/brcm,bcm11351-cpu-method.txt | 36 ----------------- .../arm/bcm/brcm,bcm23550-cpu-method.txt | 36 ----------------- .../bindings/arm/bcm/brcm,nsp-cpu-method.txt | 39 ------------------- .../devicetree/bindings/arm/cpus.yaml | 33 ++++++++++++++++ 4 files changed, 33 insertions(+), 111 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method.txt delete mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt delete mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,nsp-cpu-method.txt diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method.txt deleted file mode 100644 index e3f996920403..000000000000 --- a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method.txt +++ /dev/null @@ -1,36 +0,0 @@ -Broadcom Kona Family CPU Enable Method --------------------------------------- -This binding defines the enable method used for starting secondary -CPUs in the following Broadcom SoCs: - BCM11130, BCM11140, BCM11351, BCM28145, BCM28155, BCM21664 - -The enable method is specified by defining the following required -properties in the "cpu" device tree node: - - enable-method = "brcm,bcm11351-cpu-method"; - - secondary-boot-reg = <...>; - -The secondary-boot-reg property is a u32 value that specifies the -physical address of the register used to request the ROM holding pen -code release a secondary CPU. The value written to the register is -formed by encoding the target CPU id into the low bits of the -physical start address it should jump to. - -Example: - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu0: cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <0>; - }; - - cpu1: cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <1>; - enable-method = "brcm,bcm11351-cpu-method"; - secondary-boot-reg = <0x3500417c>; - }; - }; diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt deleted file mode 100644 index a3af54c0e404..000000000000 --- a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt +++ /dev/null @@ -1,36 +0,0 @@ -Broadcom Kona Family CPU Enable Method --------------------------------------- -This binding defines the enable method used for starting secondary -CPUs in the following Broadcom SoCs: - BCM23550 - -The enable method is specified by defining the following required -properties in the "cpu" device tree node: - - enable-method = "brcm,bcm23550"; - - secondary-boot-reg = <...>; - -The secondary-boot-reg property is a u32 value that specifies the -physical address of the register used to request the ROM holding pen -code release a secondary CPU. The value written to the register is -formed by encoding the target CPU id into the low bits of the -physical start address it should jump to. - -Example: - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu0: cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <0>; - }; - - cpu1: cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <1>; - enable-method = "brcm,bcm23550"; - secondary-boot-reg = <0x3500417c>; - }; - }; diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,nsp-cpu-method.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,nsp-cpu-method.txt deleted file mode 100644 index 677ef9d9f445..000000000000 --- a/Documentation/devicetree/bindings/arm/bcm/brcm,nsp-cpu-method.txt +++ /dev/null @@ -1,39 +0,0 @@ -Broadcom Northstar Plus SoC CPU Enable Method ---------------------------------------------- -This binding defines the enable method used for starting secondary -CPU in the following Broadcom SoCs: - BCM58522, BCM58525, BCM58535, BCM58622, BCM58623, BCM58625, BCM88312 - -The enable method is specified by defining the following required -properties in the corresponding secondary "cpu" device tree node: - - enable-method = "brcm,bcm-nsp-smp"; - - secondary-boot-reg = <...>; - -The secondary-boot-reg property is a u32 value that specifies the -physical address of the register which should hold the common -entry point for a secondary CPU. This entry is cpu node specific -and should be added per cpu. E.g., in case of NSP (BCM58625) which -is a dual core CPU SoC, this entry should be added to cpu1 node. - - -Example: - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu0: cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - next-level-cache = <&L2>; - reg = <0>; - }; - - cpu1: cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - next-level-cache = <&L2>; - enable-method = "brcm,bcm-nsp-smp"; - secondary-boot-reg = <0xffff042c>; - reg = <1>; - }; - }; diff --git a/Documentation/devicetree/bindings/arm/cpus.yaml b/Documentation/devicetree/bindings/arm/cpus.yaml index 7a9c3ce2dbef..644dfc5f0731 100644 --- a/Documentation/devicetree/bindings/arm/cpus.yaml +++ b/Documentation/devicetree/bindings/arm/cpus.yaml @@ -287,6 +287,39 @@ properties: While optional, it is the preferred way to get access to the cpu-core power-domains. + secondary-boot-reg: + $ref: '/schemas/types.yaml#/definitions/uint32' + description: | + Required for systems that have an "enable-method" property value of + "brcm,bcm11351-cpu-method", "brcm,bcm23550" or "brcm,bcm-nsp-smp". + + This includes the following SoCs: | + BCM11130, BCM11140, BCM11351, BCM28145, BCM28155, BCM21664, BCM23550 + BCM58522, BCM58525, BCM58535, BCM58622, BCM58623, BCM58625, BCM88312 + + The secondary-boot-reg property is a u32 value that specifies the + physical address of the register used to request the ROM holding pen + code release a secondary CPU. The value written to the register is + formed by encoding the target CPU id into the low bits of the + physical start address it should jump to. + +if: + # If the enable-method property contains one of those values + properties: + enable-method: + contains: + enum: + - brcm,bcm11351-cpu-method + - brcm,bcm23550 + - brcm,bcm-nsp-smp + # and if enable-method is present + required: + - enable-method + +then: + required: + - secondary-boot-reg + required: - device_type - reg From 905fc6b1bfb4a631e8447da88de2998ebda547e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Thu, 5 Mar 2020 01:55:37 +0100 Subject: [PATCH 1438/4444] dt-bindings: rcar-vin: Convert bindings to json-schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert Renesas R-Car VIN bindings documentation to json-schema. As the examples in the bindings now can be tested add a new one which describes how the both a parallel and a CSI-2 source can be connected on Gen3 SoCs. Signed-off-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Signed-off-by: Rob Herring --- .../devicetree/bindings/media/renesas,vin.txt | 217 ---------- .../bindings/media/renesas,vin.yaml | 402 ++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 403 insertions(+), 218 deletions(-) delete mode 100644 Documentation/devicetree/bindings/media/renesas,vin.txt create mode 100644 Documentation/devicetree/bindings/media/renesas,vin.yaml diff --git a/Documentation/devicetree/bindings/media/renesas,vin.txt b/Documentation/devicetree/bindings/media/renesas,vin.txt deleted file mode 100644 index 5eefd62ac5c5..000000000000 --- a/Documentation/devicetree/bindings/media/renesas,vin.txt +++ /dev/null @@ -1,217 +0,0 @@ -Renesas R-Car Video Input driver (rcar_vin) -------------------------------------------- - -The rcar_vin device provides video input capabilities for the Renesas R-Car -family of devices. - -Each VIN instance has a single parallel input that supports RGB and YUV video, -with both external synchronization and BT.656 synchronization for the latter. -Depending on the instance the VIN input is connected to external SoC pins, or -on Gen3 and RZ/G2 platforms to a CSI-2 receiver. - - - compatible: Must be one or more of the following - - "renesas,vin-r8a7743" for the R8A7743 device - - "renesas,vin-r8a7744" for the R8A7744 device - - "renesas,vin-r8a7745" for the R8A7745 device - - "renesas,vin-r8a77470" for the R8A77470 device - - "renesas,vin-r8a774a1" for the R8A774A1 device - - "renesas,vin-r8a774b1" for the R8A774B1 device - - "renesas,vin-r8a774c0" for the R8A774C0 device - - "renesas,vin-r8a7778" for the R8A7778 device - - "renesas,vin-r8a7779" for the R8A7779 device - - "renesas,vin-r8a7790" for the R8A7790 device - - "renesas,vin-r8a7791" for the R8A7791 device - - "renesas,vin-r8a7792" for the R8A7792 device - - "renesas,vin-r8a7793" for the R8A7793 device - - "renesas,vin-r8a7794" for the R8A7794 device - - "renesas,vin-r8a7795" for the R8A7795 device - - "renesas,vin-r8a7796" for the R8A7796 device - - "renesas,vin-r8a77965" for the R8A77965 device - - "renesas,vin-r8a77970" for the R8A77970 device - - "renesas,vin-r8a77980" for the R8A77980 device - - "renesas,vin-r8a77990" for the R8A77990 device - - "renesas,vin-r8a77995" for the R8A77995 device - - "renesas,rcar-gen2-vin" for a generic R-Car Gen2 or RZ/G1 compatible - device. - - When compatible with the generic version nodes must list the - SoC-specific version corresponding to the platform first - followed by the generic version. - - - reg: the register base and size for the device registers - - interrupts: the interrupt for the device - - clocks: Reference to the parent clock - -The per-board settings for Gen2 and RZ/G1 platforms: - -- port - sub-node describing a single endpoint connected to the VIN - from external SoC pins as described in video-interfaces.txt[1]. - Only the first one will be considered as each vin interface has one - input port. - - - Optional properties for endpoint nodes: - - hsync-active: see [1] for description. Default is active high. - - vsync-active: see [1] for description. Default is active high. - If both HSYNC and VSYNC polarities are not specified, embedded - synchronization is selected. - - field-active-even: see [1] for description. Default is active high. - - bus-width: see [1] for description. The selected bus width depends on - the SoC type and selected input image format. - Valid values are: 8, 10, 12, 16, 24 and 32. - - data-shift: see [1] for description. Valid values are 0 and 8. - - data-enable-active: polarity of CLKENB signal, see [1] for - description. Default is active high. - -The per-board settings for Gen3 and RZ/G2 platforms: - -Gen3 and RZ/G2 platforms can support both a single connected parallel input -source from external SoC pins (port@0) and/or multiple parallel input sources -from local SoC CSI-2 receivers (port@1) depending on SoC. - -- renesas,id - ID number of the VIN, VINx in the documentation. -- ports - - port@0 - sub-node describing a single endpoint connected to the VIN - from external SoC pins as described in video-interfaces.txt[1]. - Describing more than one endpoint in port@0 is invalid. Only VIN - instances that are connected to external pins should have port@0. - - Endpoint nodes of port@0 support the optional properties listed in - the Gen2 per-board settings description. - - - port@1 - sub-nodes describing one or more endpoints connected to - the VIN from local SoC CSI-2 receivers. The endpoint numbers must - use the following schema. - - - endpoint@0 - sub-node describing the endpoint connected to CSI20 - - endpoint@1 - sub-node describing the endpoint connected to CSI21 - - endpoint@2 - sub-node describing the endpoint connected to CSI40 - - endpoint@3 - sub-node describing the endpoint connected to CSI41 - - Endpoint nodes of port@1 do not support any optional endpoint property. - -Device node example for Gen2 platforms --------------------------------------- - - aliases { - vin0 = &vin0; - }; - - vin0: vin@e6ef0000 { - compatible = "renesas,vin-r8a7790", "renesas,rcar-gen2-vin"; - clocks = <&mstp8_clks R8A7790_CLK_VIN0>; - reg = <0 0xe6ef0000 0 0x1000>; - interrupts = <0 188 IRQ_TYPE_LEVEL_HIGH>; - status = "disabled"; - }; - -Board setup example for Gen2 platforms (vin1 composite video input) -------------------------------------------------------------------- - -&i2c2 { - status = "okay"; - pinctrl-0 = <&i2c2_pins>; - pinctrl-names = "default"; - - adv7180@20 { - compatible = "adi,adv7180"; - reg = <0x20>; - remote = <&vin1>; - - port { - adv7180: endpoint { - bus-width = <8>; - remote-endpoint = <&vin1ep0>; - }; - }; - }; -}; - -/* composite video input */ -&vin1 { - pinctrl-0 = <&vin1_pins>; - pinctrl-names = "default"; - - status = "okay"; - - port { - vin1ep0: endpoint { - remote-endpoint = <&adv7180>; - bus-width = <8>; - }; - }; -}; - -Device node example for Gen3 platforms --------------------------------------- - - vin0: video@e6ef0000 { - compatible = "renesas,vin-r8a7795"; - reg = <0 0xe6ef0000 0 0x1000>; - interrupts = ; - clocks = <&cpg CPG_MOD 811>; - power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - resets = <&cpg 811>; - renesas,id = <0>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@1 { - #address-cells = <1>; - #size-cells = <0>; - - reg = <1>; - - vin0csi20: endpoint@0 { - reg = <0>; - remote-endpoint= <&csi20vin0>; - }; - vin0csi21: endpoint@1 { - reg = <1>; - remote-endpoint= <&csi21vin0>; - }; - vin0csi40: endpoint@2 { - reg = <2>; - remote-endpoint= <&csi40vin0>; - }; - }; - }; - }; - - csi20: csi2@fea80000 { - compatible = "renesas,r8a7795-csi2"; - reg = <0 0xfea80000 0 0x10000>; - interrupts = ; - clocks = <&cpg CPG_MOD 714>; - power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - resets = <&cpg 714>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - csi20_in: endpoint { - clock-lanes = <0>; - data-lanes = <1>; - remote-endpoint = <&adv7482_txb>; - }; - }; - - port@1 { - #address-cells = <1>; - #size-cells = <0>; - - reg = <1>; - - csi20vin0: endpoint@0 { - reg = <0>; - remote-endpoint = <&vin0csi20>; - }; - }; - }; - }; - -[1] video-interfaces.txt common video media interface diff --git a/Documentation/devicetree/bindings/media/renesas,vin.yaml b/Documentation/devicetree/bindings/media/renesas,vin.yaml new file mode 100644 index 000000000000..1ec947b4781f --- /dev/null +++ b/Documentation/devicetree/bindings/media/renesas,vin.yaml @@ -0,0 +1,402 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2020 Renesas Electronics Corp. +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/renesas,vin.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas R-Car Video Input (VIN) + +maintainers: + - Niklas Söderlund + +description: + The R-Car Video Input (VIN) device provides video input capabilities for the + Renesas R-Car family of devices. + + Each VIN instance has a single parallel input that supports RGB and YUV video, + with both external synchronization and BT.656 synchronization for the latter. + Depending on the instance the VIN input is connected to external SoC pins, or + on Gen3 and RZ/G2 platforms to a CSI-2 receiver. + +properties: + compatible: + oneOf: + - items: + - enum: + - renesas,vin-r8a7743 # RZ/G1M + - renesas,vin-r8a7744 # RZ/G1N + - renesas,vin-r8a7745 # RZ/G1E + - renesas,vin-r8a77470 # RZ/G1C + - renesas,vin-r8a7790 # R-Car H2 + - renesas,vin-r8a7791 # R-Car M2-W + - renesas,vin-r8a7792 # R-Car V2H + - renesas,vin-r8a7793 # R-Car M2-N + - renesas,vin-r8a7794 # R-Car E2 + - const: renesas,rcar-gen2-vin # Generic R-Car Gen2 or RZ/G1 + + - items: + - enum: + - renesas,vin-r8a774a1 # RZ/G2M + - renesas,vin-r8a774b1 # RZ/G2N + - renesas,vin-r8a774c0 # RZ/G2E + - renesas,vin-r8a7778 # R-Car M1 + - renesas,vin-r8a7779 # R-Car H1 + - renesas,vin-r8a7795 # R-Car H3 + - renesas,vin-r8a7796 # R-Car M3-W + - renesas,vin-r8a77965 # R-Car M3-N + - renesas,vin-r8a77970 # R-Car V3M + - renesas,vin-r8a77980 # R-Car V3H + - renesas,vin-r8a77990 # R-Car E3 + - renesas,vin-r8a77995 # R-Car D3 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + power-domains: + maxItems: 1 + + resets: + maxItems: 1 + + #The per-board settings for Gen2 and RZ/G1 platforms: + port: + type: object + description: + A node containing a parallel input with a single endpoint definitions as + documented in + Documentation/devicetree/bindings/media/video-interfaces.txt + + properties: + endpoint: + type: object + + properties: + hsync-active: + description: + If both HSYNC and VSYNC polarities are not specified, embedded + synchronization is selected. + default: 1 + + vsync-active: + description: + If both HSYNC and VSYNC polarities are not specified, embedded + synchronization is selected. + default: 1 + + field-active-even: true + + bus-width: true + + data-shift: true + + data-enable-active: + description: Polarity of CLKENB signal + default: 1 + + pclk-sample: true + + data-active: true + + remote-endpoint: true + + required: + - remote-endpoint + + additionalProperties: false + + additionalProperties: false + + #The per-board settings for Gen3 and RZ/G2 platforms: + renesas,id: + description: VIN channel number + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - minimum: 0 + - maximum: 15 + + ports: + type: object + description: + A node containing input nodes with endpoint definitions as documented in + Documentation/devicetree/bindings/media/video-interfaces.txt + + properties: + port@0: + type: object + description: + Input port node, single endpoint describing a parallel input source. + + properties: + reg: + const: 0 + + endpoint: + type: object + + properties: + hsync-active: + description: + If both HSYNC and VSYNC polarities are not specified, embedded + synchronization is selected. + default: 1 + + vsync-active: + description: + If both HSYNC and VSYNC polarities are not specified, embedded + synchronization is selected. + default: 1 + + field-active-even: true + + bus-width: true + + data-shift: true + + data-enable-active: + description: Polarity of CLKENB signal + default: 1 + + pclk-sample: true + + data-active: true + + remote-endpoint: true + + required: + - remote-endpoint + + additionalProperties: false + + required: + - endpoint + + additionalProperties: false + + port@1: + type: object + description: + Input port node, multiple endpoints describing all the R-Car CSI-2 + modules connected the VIN. + + properties: + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + reg: + const: 1 + + endpoint@0: + type: object + description: Endpoint connected to CSI20. + + properties: + reg: + const: 0 + + remote-endpoint: true + + required: + - reg + - remote-endpoint + + additionalProperties: false + + endpoint@1: + type: object + description: Endpoint connected to CSI21. + + properties: + reg: + const: 1 + + remote-endpoint: true + + required: + - reg + - remote-endpoint + + additionalProperties: false + + endpoint@2: + type: object + description: Endpoint connected to CSI40. + + properties: + reg: + const: 2 + + remote-endpoint: true + + required: + - reg + - remote-endpoint + + additionalProperties: false + + endpoint@3: + type: object + description: Endpoint connected to CSI41. + + properties: + reg: + const: 3 + + remote-endpoint: true + + required: + - reg + - remote-endpoint + + additionalProperties: false + + anyOf: + - required: + - endpoint@0 + - required: + - endpoint@1 + - required: + - endpoint@2 + - required: + - endpoint@3 + + additionalProperties: false + +required: + - compatible + - reg + - interrupts + - clocks + - power-domains + - resets + +if: + properties: + compatible: + contains: + enum: + - renesas,vin-r8a7778 + - renesas,vin-r8a7779 + - renesas,rcar-gen2-vin +then: + required: + - port +else: + required: + - renesas,id + - ports + +additionalProperties: false + +examples: + # Device node example for Gen2 platform + - | + #include + #include + #include + + vin1: vin@e6ef1000 { + compatible = "renesas,vin-r8a7790", + "renesas,rcar-gen2-vin"; + reg = <0 0xe6ef1000 0 0x1000>; + interrupts = ; + clocks = <&cpg CPG_MOD 810>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; + resets = <&cpg 810>; + + port { + vin1ep0: endpoint { + remote-endpoint = <&adv7180>; + bus-width = <8>; + }; + }; + }; + + # Device node example for Gen3 platform with only CSI-2 + - | + #include + #include + #include + + vin0: video@e6ef0000 { + compatible = "renesas,vin-r8a7795"; + reg = <0 0xe6ef0000 0 0x1000>; + interrupts = ; + clocks = <&cpg CPG_MOD 811>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + resets = <&cpg 811>; + renesas,id = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <1>; + + vin0csi20: endpoint@0 { + reg = <0>; + remote-endpoint= <&csi20vin0>; + }; + vin0csi40: endpoint@2 { + reg = <2>; + remote-endpoint= <&csi40vin0>; + }; + }; + }; + }; + + # Device node example for Gen3 platform with CSI-2 and parallel + - | + #include + #include + #include + + vin2: video@e6ef2000 { + compatible = "renesas,vin-r8a77970"; + reg = <0 0xe6ef2000 0 0x1000>; + interrupts = ; + clocks = <&cpg CPG_MOD 809>; + power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; + resets = <&cpg 809>; + renesas,id = <2>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + vin2_in: endpoint { + remote-endpoint = <&adv7612_out>; + hsync-active = <0>; + vsync-active = <0>; + }; + }; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <1>; + + vin2csi40: endpoint@2 { + reg = <2>; + remote-endpoint = <&csi40vin2>; + }; + }; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 04b5ad842fbc..de04a82e1874 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10434,7 +10434,7 @@ L: linux-renesas-soc@vger.kernel.org T: git git://linuxtv.org/media_tree.git S: Supported F: Documentation/devicetree/bindings/media/renesas,csi2.yaml -F: Documentation/devicetree/bindings/media/renesas,vin.txt +F: Documentation/devicetree/bindings/media/renesas,vin.yaml F: drivers/media/platform/rcar-vin/ MEDIA DRIVERS FOR RENESAS - VSP1 From 135be16d350565a1779db3548d751eea663f0d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Tue, 25 Feb 2020 16:11:57 +0000 Subject: [PATCH 1439/4444] ARM: dts: imx7s: add snvs clock to pwrkey MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On i.MX7, the SNVS requires a clock. This is similar to the clock bound to the SNVS RTC node, but if the SNVS RTC driver isn't enabled, then SNVS doesn't work, and as such the pwrkey driver doesn't work (i.e. hangs the kernel, as the clock isn't enabled). Also see commit ec2a844ef7c1 ("ARM: dts: imx7s: add snvs rtc clock") for a similar fix. Signed-off-by: André Draszik Acked-by: Rob Herring Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx7s.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index 196bbd6f6fcc..5df205f8a066 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -606,6 +606,8 @@ compatible = "fsl,sec-v4.0-pwrkey"; regmap = <&snvs>; interrupts = ; + clocks = <&clks IMX7D_SNVS_CLK>; + clock-names = "snvs-pwrkey"; linux,keycode = ; wakeup-source; status = "disabled"; From 34aa7994ad15af31f2a7c1146d03b1f8d08af3cc Mon Sep 17 00:00:00 2001 From: Jules Irenge Date: Wed, 11 Mar 2020 01:09:07 +0000 Subject: [PATCH 1440/4444] ALSA: firewire-tascam: Add missing annotation for tscm_hwdep_read_queue() Sparse reports a warning at tscm_hwdep_read_queue() warning: context imbalance in tscm_hwdep_read_queue() - unexpected unlock The root cause is the missing annotation at tscm_hwdep_read_queue() Add the missing __releases(&tscm->lock) annotation Signed-off-by: Jules Irenge Acked-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200311010908.42366-8-jbi.octave@gmail.com Signed-off-by: Takashi Iwai --- sound/firewire/tascam/tascam-hwdep.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c index c29a97f6f638..9801e33e7f2a 100644 --- a/sound/firewire/tascam/tascam-hwdep.c +++ b/sound/firewire/tascam/tascam-hwdep.c @@ -36,6 +36,7 @@ static long tscm_hwdep_read_locked(struct snd_tscm *tscm, char __user *buf, static long tscm_hwdep_read_queue(struct snd_tscm *tscm, char __user *buf, long remained, loff_t *offset) + __releases(&tscm->lock) { char __user *pos = buf; unsigned int type = SNDRV_FIREWIRE_EVENT_TASCAM_CONTROL; From 3db1b00f2122bfe259bdb19f7c0bfcaec54568e3 Mon Sep 17 00:00:00 2001 From: Jules Irenge Date: Wed, 11 Mar 2020 01:09:08 +0000 Subject: [PATCH 1441/4444] ALSA: firewire-tascam: Add missing annotation for tscm_hwdep_read_locked() Sparse reports a warning at tscm_hwdep_read_locked() warning: context imbalance in tscm_hwdep_read_locked() - unexpected unlock The root cause is the missing annotation at tscm_hwdep_read_locked() Add the missing __releases(&tscm->lock) annotation Signed-off-by: Jules Irenge Acked-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20200311010908.42366-9-jbi.octave@gmail.com Signed-off-by: Takashi Iwai --- sound/firewire/tascam/tascam-hwdep.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c index 9801e33e7f2a..6f38335fe10b 100644 --- a/sound/firewire/tascam/tascam-hwdep.c +++ b/sound/firewire/tascam/tascam-hwdep.c @@ -17,6 +17,7 @@ static long tscm_hwdep_read_locked(struct snd_tscm *tscm, char __user *buf, long count, loff_t *offset) + __releases(&tscm->lock) { struct snd_firewire_event_lock_status event = { .type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS, From e20703f00b1206b89edb1b4a7cabe36257242a9f Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 25 Feb 2020 16:49:11 +0800 Subject: [PATCH 1442/4444] clk: imx8mn: A53 core clock no need to be critical 'A53_CORE' is just a mux and no need to be critical, being critical will cause its parent clock always ON which does NOT make sense, to make sure CPU's hardware clock source NOT being disabled during clock tree setup, need to move the 'A53_SRC'/'A53_CORE' reparent operations to after critical clock 'ARM_CLK' setup finished. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mn.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c index 83618affca8b..0bc7070235bd 100644 --- a/drivers/clk/imx/clk-imx8mn.c +++ b/drivers/clk/imx/clk-imx8mn.c @@ -428,7 +428,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) hws[IMX8MN_CLK_GPU_SHADER_DIV] = hws[IMX8MN_CLK_GPU_SHADER]; /* CORE SEL */ - hws[IMX8MN_CLK_A53_CORE] = imx_clk_hw_mux2_flags("arm_a53_core", base + 0x9880, 24, 1, imx8mn_a53_core_sels, ARRAY_SIZE(imx8mn_a53_core_sels), CLK_IS_CRITICAL); + hws[IMX8MN_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", base + 0x9880, 24, 1, imx8mn_a53_core_sels, ARRAY_SIZE(imx8mn_a53_core_sels)); /* BUS */ hws[IMX8MN_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mn_main_axi_sels, base + 0x8800); @@ -559,15 +559,15 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) hws[IMX8MN_CLK_DRAM_ALT_ROOT] = imx_clk_hw_fixed_factor("dram_alt_root", "dram_alt", 1, 4); - clk_hw_set_parent(hws[IMX8MN_CLK_A53_SRC], hws[IMX8MN_SYS_PLL1_800M]); - clk_hw_set_parent(hws[IMX8MN_CLK_A53_CORE], hws[IMX8MN_ARM_PLL_OUT]); - hws[IMX8MN_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_core", hws[IMX8MN_CLK_A53_CORE]->clk, hws[IMX8MN_CLK_A53_CORE]->clk, hws[IMX8MN_ARM_PLL_OUT]->clk, hws[IMX8MN_CLK_A53_DIV]->clk); + clk_hw_set_parent(hws[IMX8MN_CLK_A53_SRC], hws[IMX8MN_SYS_PLL1_800M]); + clk_hw_set_parent(hws[IMX8MN_CLK_A53_CORE], hws[IMX8MN_ARM_PLL_OUT]); + imx_check_clk_hws(hws, IMX8MN_CLK_END); ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data); From 81aa844bb53bc711b943db2113d7794912f047b8 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 25 Feb 2020 16:49:12 +0800 Subject: [PATCH 1443/4444] clk: imx8mm: A53 core clock no need to be critical 'A53_CORE' is just a mux and no need to be critical, being critical will cause its parent clock always ON which does NOT make sense, to make sure CPU's hardware clock source NOT being disabled during clock tree setup, need to move the 'A53_SRC'/'A53_CORE' reparent operations to after critical clock 'ARM_CLK' setup finished. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c index 9feda4f5b3d6..925670438f23 100644 --- a/drivers/clk/imx/clk-imx8mm.c +++ b/drivers/clk/imx/clk-imx8mm.c @@ -440,7 +440,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev) hws[IMX8MM_CLK_GPU2D_DIV] = hws[IMX8MM_CLK_GPU2D_CORE]; /* CORE SEL */ - hws[IMX8MM_CLK_A53_CORE] = imx_clk_hw_mux2_flags("arm_a53_core", base + 0x9880, 24, 1, imx8mm_a53_core_sels, ARRAY_SIZE(imx8mm_a53_core_sels), CLK_IS_CRITICAL); + hws[IMX8MM_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", base + 0x9880, 24, 1, imx8mm_a53_core_sels, ARRAY_SIZE(imx8mm_a53_core_sels)); /* BUS */ hws[IMX8MM_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mm_main_axi_sels, base + 0x8800); @@ -608,15 +608,15 @@ static int imx8mm_clocks_probe(struct platform_device *pdev) hws[IMX8MM_CLK_DRAM_ALT_ROOT] = imx_clk_hw_fixed_factor("dram_alt_root", "dram_alt", 1, 4); hws[IMX8MM_CLK_DRAM_CORE] = imx_clk_hw_mux2_flags("dram_core_clk", base + 0x9800, 24, 1, imx8mm_dram_core_sels, ARRAY_SIZE(imx8mm_dram_core_sels), CLK_IS_CRITICAL); - clk_hw_set_parent(hws[IMX8MM_CLK_A53_SRC], hws[IMX8MM_SYS_PLL1_800M]); - clk_hw_set_parent(hws[IMX8MM_CLK_A53_CORE], hws[IMX8MM_ARM_PLL_OUT]); - hws[IMX8MM_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_core", hws[IMX8MM_CLK_A53_CORE]->clk, hws[IMX8MM_CLK_A53_CORE]->clk, hws[IMX8MM_ARM_PLL_OUT]->clk, hws[IMX8MM_CLK_A53_DIV]->clk); + clk_hw_set_parent(hws[IMX8MM_CLK_A53_SRC], hws[IMX8MM_SYS_PLL1_800M]); + clk_hw_set_parent(hws[IMX8MM_CLK_A53_CORE], hws[IMX8MM_ARM_PLL_OUT]); + imx_check_clk_hws(hws, IMX8MM_CLK_END); ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data); From 0d77abc4fc31e038c6c5b1f08f115eb022b3c4f5 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 25 Feb 2020 16:49:13 +0800 Subject: [PATCH 1444/4444] clk: imx8mp: A53 core clock no need to be critical 'A53_CORE' is just a mux and no need to be critical, being critical will cause its parent clock always ON which does NOT make sense, to make sure CPU's hardware clock source NOT being disabled during clock tree setup, need to move the 'A53_SRC'/'A53_CORE' reparent operations to after critical clock 'ARM_CLK' setup finished. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index c6161a4af201..c9e204edd247 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -557,7 +557,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) hws[IMX8MP_CLK_MEDIA_ISP_DIV] = imx_clk_hw_divider2("media_isp_div", "media_isp_cg", ccm_base + 0x8400, 0, 3); /* CORE SEL */ - hws[IMX8MP_CLK_A53_CORE] = imx_clk_hw_mux2_flags("arm_a53_core", ccm_base + 0x9880, 24, 1, imx8mp_a53_core_sels, ARRAY_SIZE(imx8mp_a53_core_sels), CLK_IS_CRITICAL); + hws[IMX8MP_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", ccm_base + 0x9880, 24, 1, imx8mp_a53_core_sels, ARRAY_SIZE(imx8mp_a53_core_sels)); hws[IMX8MP_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mp_main_axi_sels, ccm_base + 0x8800); hws[IMX8MP_CLK_ENET_AXI] = imx8m_clk_hw_composite("enet_axi", imx8mp_enet_axi_sels, ccm_base + 0x8880); @@ -729,15 +729,15 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) hws[IMX8MP_CLK_VPU_ROOT] = imx_clk_hw_gate4("vpu_root_clk", "vpu_bus", ccm_base + 0x4630, 0); hws[IMX8MP_CLK_AUDIO_ROOT] = imx_clk_hw_gate4("audio_root_clk", "ipg_root", ccm_base + 0x4650, 0); - clk_hw_set_parent(hws[IMX8MP_CLK_A53_SRC], hws[IMX8MP_SYS_PLL1_800M]); - clk_hw_set_parent(hws[IMX8MP_CLK_A53_CORE], hws[IMX8MP_ARM_PLL_OUT]); - hws[IMX8MP_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_core", hws[IMX8MP_CLK_A53_CORE]->clk, hws[IMX8MP_CLK_A53_CORE]->clk, hws[IMX8MP_ARM_PLL_OUT]->clk, hws[IMX8MP_CLK_A53_DIV]->clk); + clk_hw_set_parent(hws[IMX8MP_CLK_A53_SRC], hws[IMX8MP_SYS_PLL1_800M]); + clk_hw_set_parent(hws[IMX8MP_CLK_A53_CORE], hws[IMX8MP_ARM_PLL_OUT]); + imx_check_clk_hws(hws, IMX8MP_CLK_END); of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data); From b4fc6f72ddc1d4a53d3367b2d473e39d5d07a083 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 25 Feb 2020 16:49:14 +0800 Subject: [PATCH 1445/4444] clk: imx8mq: A53 core clock no need to be critical 'A53_CORE' is just a mux and no need to be critical, being critical will cause its parent clock always ON which does NOT make sense, to make sure CPU's hardware clock source NOT being disabled during clock tree setup, need to move the 'A53_SRC'/'A53_CORE' reparent operations to after critical clock 'ARM_CLK' setup finished. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx8mq.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c index b81f02ab7eb1..fdc68db68de5 100644 --- a/drivers/clk/imx/clk-imx8mq.c +++ b/drivers/clk/imx/clk-imx8mq.c @@ -428,7 +428,7 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) hws[IMX8MQ_CLK_GPU_SHADER_DIV] = hws[IMX8MQ_CLK_GPU_SHADER]; /* CORE SEL */ - hws[IMX8MQ_CLK_A53_CORE] = imx_clk_hw_mux2_flags("arm_a53_core", base + 0x9880, 24, 1, imx8mq_a53_core_sels, ARRAY_SIZE(imx8mq_a53_core_sels), CLK_IS_CRITICAL); + hws[IMX8MQ_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", base + 0x9880, 24, 1, imx8mq_a53_core_sels, ARRAY_SIZE(imx8mq_a53_core_sels)); /* BUS */ hws[IMX8MQ_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mq_main_axi_sels, base + 0x8800); @@ -593,15 +593,15 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) hws[IMX8MQ_GPT_3M_CLK] = imx_clk_hw_fixed_factor("gpt_3m", "osc_25m", 1, 8); hws[IMX8MQ_CLK_DRAM_ALT_ROOT] = imx_clk_hw_fixed_factor("dram_alt_root", "dram_alt", 1, 4); - clk_hw_set_parent(hws[IMX8MQ_CLK_A53_SRC], hws[IMX8MQ_SYS1_PLL_800M]); - clk_hw_set_parent(hws[IMX8MQ_CLK_A53_CORE], hws[IMX8MQ_ARM_PLL_OUT]); - hws[IMX8MQ_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_core", hws[IMX8MQ_CLK_A53_CORE]->clk, hws[IMX8MQ_CLK_A53_CORE]->clk, hws[IMX8MQ_ARM_PLL_OUT]->clk, hws[IMX8MQ_CLK_A53_DIV]->clk); + clk_hw_set_parent(hws[IMX8MQ_CLK_A53_SRC], hws[IMX8MQ_SYS1_PLL_800M]); + clk_hw_set_parent(hws[IMX8MQ_CLK_A53_CORE], hws[IMX8MQ_ARM_PLL_OUT]); + imx_check_clk_hws(hws, IMX8MQ_CLK_END); err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data); From 62d1c1df85832d75acacb1e5cab2b1e7b80d3c1e Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 26 Feb 2020 12:16:57 +0800 Subject: [PATCH 1446/4444] ARM: imx: Remove unnecessary blank lines Remove unnecessary blank lines for cleanup. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/mach-imx/anatop.c | 1 - arch/arm/mach-imx/gpc.c | 1 - arch/arm/mach-imx/mach-imx6ul.c | 1 - 3 files changed, 3 deletions(-) diff --git a/arch/arm/mach-imx/anatop.c b/arch/arm/mach-imx/anatop.c index ea4a59648932..d841bed8664d 100644 --- a/arch/arm/mach-imx/anatop.c +++ b/arch/arm/mach-imx/anatop.c @@ -89,7 +89,6 @@ void imx_anatop_post_resume(void) if (cpu_is_imx6sl()) imx_anatop_disconnect_high_snvs(false); - } void __init imx_init_revision_from_anatop(void) diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c index fb3cba87940d..ebc4339b8be4 100644 --- a/arch/arm/mach-imx/gpc.c +++ b/arch/arm/mach-imx/gpc.c @@ -111,7 +111,6 @@ void imx_gpc_mask_all(void) gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4); writel_relaxed(~0, reg_imr1 + i * 4); } - } void imx_gpc_restore_all(void) diff --git a/arch/arm/mach-imx/mach-imx6ul.c b/arch/arm/mach-imx/mach-imx6ul.c index 311f5e4ff723..3b0e16ccd59d 100644 --- a/arch/arm/mach-imx/mach-imx6ul.c +++ b/arch/arm/mach-imx/mach-imx6ul.c @@ -25,7 +25,6 @@ static void __init imx6ul_enet_clk_init(void) IMX6UL_GPR1_ENET_CLK_OUTPUT); else pr_err("failed to find fsl,imx6ul-iomux-gpr regmap\n"); - } static int ksz8081_phy_fixup(struct phy_device *dev) From 756931e058ec3dc625f85a09ae0c3143d2a6ef72 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 26 Feb 2020 12:34:26 +0800 Subject: [PATCH 1447/4444] ARM: imx: Drop unnecessary src_base check src_base is already checked during src driver initialization, no need to check its availability again when using it. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/mach-imx/src.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c index 0beea6d0217f..f52f371292ac 100644 --- a/arch/arm/mach-imx/src.c +++ b/arch/arm/mach-imx/src.c @@ -43,9 +43,6 @@ static int imx_src_reset_module(struct reset_controller_dev *rcdev, int bit; u32 val; - if (!src_base) - return -ENODEV; - if (sw_reset_idx >= ARRAY_SIZE(sw_reset_bits)) return -EINVAL; From 684720000af86ae04191c3a88bf07b972f7f4a4c Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 26 Feb 2020 13:36:18 +0800 Subject: [PATCH 1448/4444] ARM: dts: imx: Make iomuxc node name generic Node name should be generic, use "pinctrl" instead of "iomuxc" for all i.MX6/7 SoCs. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6dl.dtsi | 2 +- arch/arm/boot/dts/imx6q.dtsi | 2 +- arch/arm/boot/dts/imx6qdl.dtsi | 2 +- arch/arm/boot/dts/imx6sl.dtsi | 2 +- arch/arm/boot/dts/imx6sx.dtsi | 2 +- arch/arm/boot/dts/imx6ul.dtsi | 2 +- arch/arm/boot/dts/imx7s.dtsi | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi index 4b3a128d9260..bba25d069786 100644 --- a/arch/arm/boot/dts/imx6dl.dtsi +++ b/arch/arm/boot/dts/imx6dl.dtsi @@ -86,7 +86,7 @@ }; aips1: bus@2000000 { - iomuxc: iomuxc@20e0000 { + iomuxc: pinctrl@20e0000 { compatible = "fsl,imx6dl-iomuxc"; }; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index 0fad13f9d336..907cf8306645 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -181,7 +181,7 @@ }; }; - iomuxc: iomuxc@20e0000 { + iomuxc: pinctrl@20e0000 { compatible = "fsl,imx6q-iomuxc"; }; }; diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index 70fb8b56b1d7..8baad7481744 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -908,7 +908,7 @@ }; }; - iomuxc: iomuxc@20e0000 { + iomuxc: pinctrl@20e0000 { compatible = "fsl,imx6dl-iomuxc", "fsl,imx6q-iomuxc"; reg = <0x20e0000 0x4000>; }; diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi index c8ec46fe8302..0359902fd421 100644 --- a/arch/arm/boot/dts/imx6sl.dtsi +++ b/arch/arm/boot/dts/imx6sl.dtsi @@ -728,7 +728,7 @@ reg = <0x020e0000 0x38>; }; - iomuxc: iomuxc@20e0000 { + iomuxc: pinctrl@20e0000 { compatible = "fsl,imx6sl-iomuxc"; reg = <0x020e0000 0x4000>; }; diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index e47d346a3543..43e36e1854f3 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -806,7 +806,7 @@ }; }; - iomuxc: iomuxc@20e0000 { + iomuxc: pinctrl@20e0000 { compatible = "fsl,imx6sx-iomuxc"; reg = <0x020e0000 0x4000>; }; diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi index e1807e9d385a..c53898b2c76d 100644 --- a/arch/arm/boot/dts/imx6ul.dtsi +++ b/arch/arm/boot/dts/imx6ul.dtsi @@ -693,7 +693,7 @@ interrupt-parent = <&intc>; }; - iomuxc: iomuxc@20e0000 { + iomuxc: pinctrl@20e0000 { compatible = "fsl,imx6ul-iomuxc"; reg = <0x020e0000 0x4000>; }; diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index 5df205f8a066..05da9999817b 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -490,7 +490,7 @@ status = "disabled"; }; - iomuxc: iomuxc@30330000 { + iomuxc: pinctrl@30330000 { compatible = "fsl,imx7d-iomuxc"; reg = <0x30330000 0x10000>; }; From 1f4e29d24b9da9854456cd3c517a8cf6bd2bfd67 Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Thu, 27 Feb 2020 12:06:04 +0100 Subject: [PATCH 1449/4444] ARM: dts: imx6: phycore-som: explicit disable pmic watchdog during suspend By default the phycore-som has support for two watchdog devices: 1st the internal imx6 watchdog and 2nd the DA9062 PMIC watchdog. According [1] the PMIC watchdog is used as boot watchdog. It is common to use this watchdog during "system up" time too. Furthermore the PMIC watchdog can be used to address ERR007117 since the phycore-som can be equipped with NAND or eMMC storage. The PMIC watchdog can be enabled/disabled by the PMIC itself if the PMIC enters POWERDOWN mode or by the host. The PMIC powerdown mode can't be used due to the PCB design. So the watchdog is still enabled during a suspend which causes a system reset. We need to tell the driver to disable the watchdog during a system suspend and to reenable it upon a resume to fix this. [1] https://git.pengutronix.de/cgit/barebox/tree/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi#n73 Signed-off-by: Marco Felsch Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi index 978dc1c2ff1b..356fe5673be9 100644 --- a/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi +++ b/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi @@ -107,6 +107,7 @@ watchdog { compatible = "dlg,da9062-watchdog"; + dlg,use-sw-pm; }; regulators { From 50f5b89a32ec69fa80601e575a99a062f0b4904e Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Thu, 27 Feb 2020 12:06:05 +0100 Subject: [PATCH 1450/4444] ARM: dts: imx6: phycore-som: add da9062 gpio support The pmic is a mfd device and supports gpios. Those gpios are not routed to the SoM baseboard pin header but they are connected to the i.MX6. We need the GPIO's to configure the pmic to select between the suspend/resume arm and soc voltages Signed-off-by: Marco Felsch Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi index 356fe5673be9..a8ae654159a9 100644 --- a/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi +++ b/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi @@ -88,7 +88,7 @@ reg = <0x50>; }; - pmic@58 { + pmic: pmic@58 { compatible = "dlg,da9062"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pmic>; @@ -96,6 +96,8 @@ interrupt-parent = <&gpio1>; interrupts = <2 IRQ_TYPE_LEVEL_LOW>; interrupt-controller; + gpio-controller; + #gpio-cells = <2>; da9062_rtc: rtc { compatible = "dlg,da9062-rtc"; From b7dc7205b2ae6b6c9d9cfc3e47d6f08da8647b10 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 27 Feb 2020 12:18:51 +0000 Subject: [PATCH 1451/4444] ARM: dts: imx6qdl-sr-som-ti: indicate powering off wifi is safe We need to indicate that powering off the TI WiFi is safe, to avoid: wl18xx_driver wl18xx.2.auto: Unbalanced pm_runtime_enable! wl1271_sdio mmc0:0001:2: wl12xx_sdio_power_on: failed to get_sync(-13) which prevents the WiFi being functional. Signed-off-by: Russell King Reviewed-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-sr-som-ti.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/imx6qdl-sr-som-ti.dtsi b/arch/arm/boot/dts/imx6qdl-sr-som-ti.dtsi index 44a97ba93a95..352ac585ca6b 100644 --- a/arch/arm/boot/dts/imx6qdl-sr-som-ti.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sr-som-ti.dtsi @@ -153,6 +153,7 @@ bus-width = <4>; keep-power-in-suspend; mmc-pwrseq = <&pwrseq_ti_wifi>; + cap-power-off-card; non-removable; vmmc-supply = <&vcc_3v3>; /* vqmmc-supply = <&nvcc_sd1>; - MMC layer doesn't like it! */ From 8023321d30be83cb9a9ef57376fa5a9c7c8bd887 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 23 Feb 2020 22:47:11 +0200 Subject: [PATCH 1452/4444] arm64: dts: ls1028a: delete extraneous #interrupt-cells for ENETC RCIE This specifier overrides the interrupt specifier with 3 cells from gic (/interrupt-controller@6000000), but in fact ENETC is not an interrupt controller, so the property is bogus. Interrupts used by the children of the ENETC RCIE must use the full 3-cell specifier required by the GIC. The issue has no functional consequence so there is no real reason to port the patch to stable trees. Fixes: 927d7f857542 ("arm64: dts: fsl: ls1028a: Add PCI IERC node and ENETC endpoints") Signed-off-by: Vladimir Oltean Tested-by: Michael Walle Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi index 8694098aa94b..6e406a6a16cf 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi @@ -722,7 +722,6 @@ reg = <0x01 0xf0000000 0x0 0x100000>; #address-cells = <3>; #size-cells = <2>; - #interrupt-cells = <1>; msi-parent = <&its>; device_type = "pci"; bus-range = <0x0 0x0>; From 1a4bfe0f517ac99d85d4d5628b77f311cb8a169e Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 23 Feb 2020 22:47:12 +0200 Subject: [PATCH 1453/4444] arm64: dts: ls1028a: disable all enetc ports by default There are few boards that enable all ENETC ports, so instead of having board DTs disable them, do so in the DTSI and have the boards enable the ports they use. Signed-off-by: Vladimir Oltean Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts | 1 + arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts | 5 +---- arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi | 5 +++++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts index ca409d907b36..dd69c5b821e9 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts @@ -225,6 +225,7 @@ &enetc_port1 { phy-handle = <&qds_phy1>; phy-connection-type = "rgmii-id"; + status = "okay"; }; &sai1 { diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts index afb55653850d..14efe3b06042 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts @@ -180,6 +180,7 @@ &enetc_port0 { phy-handle = <&sgmii_phy0>; phy-connection-type = "sgmii"; + status = "okay"; mdio { #address-cells = <1>; @@ -190,10 +191,6 @@ }; }; -&enetc_port1 { - status = "disabled"; -}; - &sai4 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi index 6e406a6a16cf..9e7436a390fd 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi @@ -744,17 +744,22 @@ enetc_port0: ethernet@0,0 { compatible = "fsl,enetc"; reg = <0x000000 0 0 0 0>; + status = "disabled"; }; + enetc_port1: ethernet@0,1 { compatible = "fsl,enetc"; reg = <0x000100 0 0 0 0>; + status = "disabled"; }; + enetc_mdio_pf3: mdio@0,3 { compatible = "fsl,enetc-mdio"; reg = <0x000300 0 0 0 0>; #address-cells = <1>; #size-cells = <0>; }; + ethernet@0,4 { compatible = "fsl,enetc-ptp"; reg = <0x000400 0 0 0 0>; From b1520d8b9b0d19ce868cc99cf55f4db073ab7678 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Mon, 24 Feb 2020 19:16:16 +0800 Subject: [PATCH 1454/4444] arm64: dts: ls1028a: add node for Felix switch Add the switch device node, available on PF5, so that the switch port sub-nodes (net devices) can be linked to corresponding board specific phy nodes (external ports) or have their link mode defined (internal ports). The switch device features 6 ports, 4 with external links and 2 internally facing to the LS1028A SoC and connected via fixed links to 2 internal ENETC Ethernet controller ports. Add the corresponding ENETC host port device nodes, mapped to PF2 and PF6 PCIe functions. Since the switch only supports tagging on one CPU port, only one port pair (swp4, eno2) is enabled by default and the other, lower speed, port pair is disabled to prevent the PCI core from probing them. If enabled, swp5 will be a fixed-link slave port. DSA tagging can also be moved from the swp4-eno2 2.5G port pair to the 1G swp5-eno3 pair by changing the ethernet = <&enetc_port2> phandle to <&enetc_port3> and moving it under port5, but in that case enetc_port2 should not be disabled, because it is the hardware owner of the Felix PCS and disabling its memory would result in access faults in the Felix DSA driver. All ports are disabled by default, including the CPU port, and need to be enabled on a per-board basis. The phy-mode binding of the internal ENETC ports was modified from "gmii" to "internal" to match the phy-mode of the internal-facing switch ports connected to them. The ENETC driver does not perform any phy_mode validation anyway, so the change is only cosmetic. Also, enetc_port2 is defined as a fixed-link 1000 Mbps port even though it is 2500 Mbps (as can be seen by the fact that it is connected to mscc_felix_port4). The fact that it is currently defined as 1000 Mbps is an artifact of its PHYLIB implementation instead of PHYLINK (the former can't describe a fixed-link speed higher than what swphy can emulate from the Clause 22 MDIO spec). The switch's INTB interrupt line signals: - PTP TX timestamp availability - TSN Frame Preemption And don't forget to enable the 4MB BAR4 in the root complex ECAM space, where the switch registers are mapped. Signed-off-by: Claudiu Manoil Signed-off-by: Alex Marginean Signed-off-by: Yangbo Lu Signed-off-by: Vladimir Oltean Tested-by: Michael Walle Signed-off-by: Shawn Guo --- .../arm64/boot/dts/freescale/fsl-ls1028a.dtsi | 83 ++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi index 9e7436a390fd..41c9633293fb 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi @@ -739,7 +739,9 @@ /* PF1: VF0-1 BAR0 - non-prefetchable memory */ 0x82000000 0x0 0x00000000 0x1 0xf8210000 0x0 0x020000 /* PF1: VF0-1 BAR2 - prefetchable memory */ - 0xc2000000 0x0 0x00000000 0x1 0xf8230000 0x0 0x020000>; + 0xc2000000 0x0 0x00000000 0x1 0xf8230000 0x0 0x020000 + /* BAR4 (PF5) - non-prefetchable memory */ + 0x82000000 0x0 0x00000000 0x1 0xfc000000 0x0 0x400000>; enetc_port0: ethernet@0,0 { compatible = "fsl,enetc"; @@ -753,6 +755,18 @@ status = "disabled"; }; + enetc_port2: ethernet@0,2 { + compatible = "fsl,enetc"; + reg = <0x000200 0 0 0 0>; + phy-mode = "internal"; + status = "disabled"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + enetc_mdio_pf3: mdio@0,3 { compatible = "fsl,enetc-mdio"; reg = <0x000300 0 0 0 0>; @@ -767,6 +781,73 @@ little-endian; fsl,extts-fifo; }; + + ethernet-switch@0,5 { + reg = <0x000500 0 0 0 0>; + /* IEP INT_B */ + interrupts = ; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + /* External ports */ + mscc_felix_port0: port@0 { + reg = <0>; + status = "disabled"; + }; + + mscc_felix_port1: port@1 { + reg = <1>; + status = "disabled"; + }; + + mscc_felix_port2: port@2 { + reg = <2>; + status = "disabled"; + }; + + mscc_felix_port3: port@3 { + reg = <3>; + status = "disabled"; + }; + + /* Internal ports */ + mscc_felix_port4: port@4 { + reg = <4>; + phy-mode = "internal"; + status = "disabled"; + + fixed-link { + speed = <2500>; + full-duplex; + }; + }; + + mscc_felix_port5: port@5 { + reg = <5>; + phy-mode = "internal"; + status = "disabled"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; + }; + + enetc_port3: ethernet@0,6 { + compatible = "fsl,enetc"; + reg = <0x000600 0 0 0 0>; + phy-mode = "internal"; + status = "disabled"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; }; }; From 8aa80fc8bdf229fa772c9bfdff96920da8db784f Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Sun, 23 Feb 2020 22:47:16 +0200 Subject: [PATCH 1455/4444] arm64: dts: ls1028a: enable switch PHYs on RDB Link the switch PHY nodes to the central MDIO controller PCIe endpoint node on LS1028A (implemented as PF3) so that PHYs are accessible via MDIO. Enable SGMII AN on the Felix PCS by telling PHYLINK that the VSC8514 quad PHY is capable of in-band-status. The PHYs are used in poll mode due to an issue with the interrupt line on current revisions of the LS1028A-RDB board. Signed-off-by: Claudiu Manoil Signed-off-by: Alex Marginean Signed-off-by: Vladimir Oltean Reviewed-by: Andrew Lunn Signed-off-by: Shawn Guo --- .../boot/dts/freescale/fsl-ls1028a-rdb.dts | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts index 14efe3b06042..6d05b76c2c7a 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts @@ -177,6 +177,25 @@ status = "okay"; }; +&enetc_mdio_pf3 { + /* VSC8514 QSGMII quad PHY */ + qsgmii_phy0: ethernet-phy@10 { + reg = <0x10>; + }; + + qsgmii_phy1: ethernet-phy@11 { + reg = <0x11>; + }; + + qsgmii_phy2: ethernet-phy@12 { + reg = <0x12>; + }; + + qsgmii_phy3: ethernet-phy@13 { + reg = <0x13>; + }; +}; + &enetc_port0 { phy-handle = <&sgmii_phy0>; phy-connection-type = "sgmii"; @@ -191,6 +210,47 @@ }; }; +&enetc_port2 { + status = "okay"; +}; + +&mscc_felix_port0 { + label = "swp0"; + managed = "in-band-status"; + phy-handle = <&qsgmii_phy0>; + phy-mode = "qsgmii"; + status = "okay"; +}; + +&mscc_felix_port1 { + label = "swp1"; + managed = "in-band-status"; + phy-handle = <&qsgmii_phy1>; + phy-mode = "qsgmii"; + status = "okay"; +}; + +&mscc_felix_port2 { + label = "swp2"; + managed = "in-band-status"; + phy-handle = <&qsgmii_phy2>; + phy-mode = "qsgmii"; + status = "okay"; +}; + +&mscc_felix_port3 { + label = "swp3"; + managed = "in-band-status"; + phy-handle = <&qsgmii_phy3>; + phy-mode = "qsgmii"; + status = "okay"; +}; + +&mscc_felix_port4 { + ethernet = <&enetc_port2>; + status = "okay"; +}; + &sai4 { status = "okay"; }; From e46b08b09919df757a907d161cd8b8c28e73a022 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Mon, 24 Feb 2020 12:50:52 +0100 Subject: [PATCH 1456/4444] arm64: dts: ls1028: sl28: explicitly enable network ports Since commit b9213899d2b0 ("arm64: dts: ls1028a: disable all enetc ports by default") all the network ports are disabled by default. This makes sense, but now we have to enable them explicitly in the boards. Do so for the sl28 module. Since we are at it. Make sure the second port is only enabled for the variant 4 of the module. Variant 3 has only one network port. Signed-off-by: Michael Walle Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var4.dts | 1 + arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28.dts | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var4.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var4.dts index f659e89face8..df212ed5bb94 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var4.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var4.dts @@ -21,6 +21,7 @@ &enetc_port1 { phy-handle = <&phy1>; phy-connection-type = "rgmii-id"; + status = "okay"; mdio { #address-cells = <1>; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28.dts index d221ed471cde..e6ad2f64e64e 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28.dts @@ -35,6 +35,7 @@ &enetc_port0 { phy-handle = <&phy0>; phy-connection-type = "sgmii"; + status = "okay"; mdio { #address-cells = <1>; From f0cac1412ca46b3d5ea5b5e21a9083217673fe93 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Sat, 22 Feb 2020 08:08:52 +0800 Subject: [PATCH 1457/4444] arm64: dts: imx: add i.MX8QXP thermal support Add i.MX8QXP CPU thermal zone support. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8qxp.dtsi | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi index fb5f752b15fe..e8ffb7590656 100644 --- a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi @@ -11,6 +11,7 @@ #include #include #include +#include / { interrupt-parent = <&gic>; @@ -189,6 +190,11 @@ compatible = "fsl,imx8qxp-sc-wdt", "fsl,imx-sc-wdt"; timeout-sec = <60>; }; + + tsens: thermal-sensor { + compatible = "fsl,imx8qxp-sc-thermal", "fsl,imx-sc-thermal"; + #thermal-sensor-cells = <1>; + }; }; timer { @@ -586,4 +592,37 @@ #clock-cells = <1>; }; }; + + thermal_zones: thermal-zones { + cpu-thermal0 { + polling-delay-passive = <250>; + polling-delay = <2000>; + thermal-sensors = <&tsens IMX_SC_R_SYSTEM>; + + trips { + cpu_alert0: trip0 { + temperature = <107000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit0: trip1 { + temperature = <127000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_alert0>; + cooling-device = + <&A35_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&A35_1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&A35_2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&A35_3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + }; }; From d3a719e3d07e211d468bafa8353e2394d947b8c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Mon, 24 Feb 2020 14:50:23 +0200 Subject: [PATCH 1458/4444] arm64: dts: imx8mp: add crypto node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add node for CAAM - Cryptographic Acceleration and Assurance Module. Signed-off-by: Horia Geantă Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mp.dtsi | 30 +++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi index 71b0c8f23693..8703ef14fbc0 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi @@ -451,6 +451,36 @@ status = "disabled"; }; + crypto: crypto@30900000 { + compatible = "fsl,sec-v4.0"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x30900000 0x40000>; + ranges = <0 0x30900000 0x40000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_AHB>, + <&clk IMX8MP_CLK_IPG_ROOT>; + clock-names = "aclk", "ipg"; + + sec_jr0: jr@1000 { + compatible = "fsl,sec-v4.0-job-ring"; + reg = <0x1000 0x1000>; + interrupts = ; + }; + + sec_jr1: jr@2000 { + compatible = "fsl,sec-v4.0-job-ring"; + reg = <0x2000 0x1000>; + interrupts = ; + }; + + sec_jr2: jr@3000 { + compatible = "fsl,sec-v4.0-job-ring"; + reg = <0x3000 0x1000>; + interrupts = ; + }; + }; + i2c1: i2c@30a20000 { compatible = "fsl,imx8mp-i2c", "fsl,imx21-i2c"; #address-cells = <1>; From 46770eae2120ec374811070de1987752c84bd08b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Tue, 25 Feb 2020 16:11:58 +0000 Subject: [PATCH 1459/4444] arm64: dts: imx8mm: add snvs clock to pwrkey MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On i.MX8MM, the SNVS requires a clock. This is similar to the clock bound to the SNVS RTC node, but if the SNVS RTC driver isn't enabled, then SNVS doesn't work, and as such the pwrkey driver doesn't work (i.e. hangs the kernel, as the clock isn't enabled). Also see commit ec2a844ef7c1 ("ARM: dts: imx7s: add snvs rtc clock") for a similar fix. Signed-off-by: André Draszik Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mm.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi index b3d0b29d7007..970a86c724ba 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi @@ -455,6 +455,8 @@ compatible = "fsl,sec-v4.0-pwrkey"; regmap = <&snvs>; interrupts = ; + clocks = <&clk IMX8MM_CLK_SNVS_ROOT>; + clock-names = "snvs-pwrkey"; linux,keycode = ; wakeup-source; status = "disabled"; From edd91ba6b82cf5849d60c62d10042106cf15a96c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Tue, 25 Feb 2020 16:11:59 +0000 Subject: [PATCH 1460/4444] arm64: dts: imx8mq: add snvs clock to pwrkey MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On i.MX8MM, the SNVS requires a clock. This is similar to the clock bound to the SNVS RTC node, but if the SNVS RTC driver isn't enabled, then SNVS doesn't work, and as such the pwrkey driver doesn't work (i.e. hangs the kernel, as the clock isn't enabled). Also see commit ec2a844ef7c1 ("ARM: dts: imx7s: add snvs rtc clock") for a similar fix. Signed-off-by: André Draszik Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mq.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi index 6a1e83922c71..460ff0acdc40 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi @@ -574,6 +574,8 @@ compatible = "fsl,sec-v4.0-pwrkey"; regmap = <&snvs>; interrupts = ; + clocks = <&clk IMX8MQ_CLK_SNVS_ROOT>; + clock-names = "snvs-pwrkey"; linux,keycode = ; wakeup-source; status = "disabled"; From c18696de2cd95a4cbbf876a6c4f13ab797b34e1f Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 26 Feb 2020 13:36:17 +0800 Subject: [PATCH 1461/4444] arm64: dts: imx8mq: Align iomuxc node name Node name should be generic, use "pinctrl" instead of "iomuxc" for all i.MX8M SoCs. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mq.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi index 460ff0acdc40..985a1a68b6d1 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi @@ -521,7 +521,7 @@ status = "disabled"; }; - iomuxc: iomuxc@30330000 { + iomuxc: pinctrl@30330000 { compatible = "fsl,imx8mq-iomuxc"; reg = <0x30330000 0x10000>; }; From 455ae0c368f23a6fc6ac597f562a193252ca0be3 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 26 Feb 2020 17:13:50 +0800 Subject: [PATCH 1462/4444] arm64: dts: imx8mp: Add src node Add src node to support i.MX8MP reset controller. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mp.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi index 8703ef14fbc0..d92199bf6635 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi @@ -306,6 +306,12 @@ <393216000>, <361267200>; }; + + src: reset-controller@30390000 { + compatible = "fsl,imx8mp-src", "syscon"; + reg = <0x30390000 0x10000>; + #reset-cells = <1>; + }; }; aips2: bus@30400000 { From 1f5b12d4a9229d4c1271652af1f4562a9ee1785c Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 27 Feb 2020 12:06:22 +0000 Subject: [PATCH 1463/4444] arm64: dts: lx2160a-cex7: add support for ltc3882 regulator Add support for the LTC3882 regulator so that the hardware monitoring can be used with this device. This regulator provides the 0.78V supply for the LX2160A. Signed-off-by: Russell King Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi index 071e21678f77..01c5420f334e 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi @@ -73,6 +73,17 @@ }; }; + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + regulator@5c { + compatible = "lltc,ltc3882"; + reg = <0x5c>; + }; + }; + i2c@3 { #address-cells = <1>; #size-cells = <0>; From f26d7effb7ecc3d0ca2876bf2d3295fffae99c53 Mon Sep 17 00:00:00 2001 From: Rabeeh Khoury Date: Thu, 27 Feb 2020 12:06:27 +0000 Subject: [PATCH 1464/4444] arm64: dts: lx2160a-cex7: add on-module eeproms This patch adds 4 eeprom support on i2c mux channel #0 - 1. Bootable 512Kbit eeprom at address 0x50. 2. Memory SO-DIMMs SPD channels at 0x51 (upper SO-DIMM) and 0x53. 3. 2Kb eeprom at 0x57 will be used by SolidRun to hold manufacturing data. Signed-off-by: Rabeeh Khoury Signed-off-by: Russell King Signed-off-by: Shawn Guo --- .../boot/dts/freescale/fsl-lx2160a-cex7.dtsi | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi index 01c5420f334e..d87d16460875 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi @@ -59,6 +59,32 @@ #size-cells = <0>; reg = <0x77>; + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + eeprom@50 { + compatible = "atmel,24c512"; + reg = <0x50>; + }; + + eeprom@51 { + compatible = "atmel,spd"; + reg = <0x51>; + }; + + eeprom@53 { + compatible = "atmel,spd"; + reg = <0x53>; + }; + + eeprom@57 { + compatible = "atmel,24c02"; + reg = <0x57>; + }; + }; + i2c@1 { #address-cells = <1>; #size-cells = <0>; From dde061b865598ad91f50140760e1d224e5045db9 Mon Sep 17 00:00:00 2001 From: "Angus Ainslie (Purism)" Date: Thu, 27 Feb 2020 14:17:26 +0100 Subject: [PATCH 1465/4444] arm64: dts: librem5-devkit: add a vbus supply to usb0 Without a VBUS supply the dwc3 driver won't go into otg mode. Fixes: eb4ea0857c83 ("arm64: dts: fsl: librem5: Add a device tree for the Librem5 devkit") Signed-off-by: Angus Ainslie (Purism) Signed-off-by: Martin Kepplinger Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts index 007c14eec676..bab039500f2b 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts @@ -762,6 +762,7 @@ }; &usb3_phy0 { + vbus-supply = <®_5v_p>; status = "okay"; }; From c53f016663996f08cb03930d8e8c76a56f06249a Mon Sep 17 00:00:00 2001 From: "Angus Ainslie (Purism)" Date: Thu, 27 Feb 2020 14:17:27 +0100 Subject: [PATCH 1466/4444] arm64: dts: librem5-devkit: add the sgtl5000 i2c audio codec Describe the sgtl5000 of the librem 5 devkit in devicetree. Signed-off-by: Angus Ainslie (Purism) Signed-off-by: Martin Kepplinger Signed-off-by: Shawn Guo --- .../dts/freescale/imx8mq-librem5-devkit.dts | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts index bab039500f2b..c829e4579540 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts @@ -148,6 +148,34 @@ regulator-always-on; }; + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "sgtl5000"; + simple-audio-card,format = "i2s"; + simple-audio-card,widgets = + "Microphone", "Microphone Jack", + "Headphone", "Headphone Jack", + "Speaker", "Speaker Ext", + "Line", "Line In Jack"; + simple-audio-card,routing = + "MIC_IN", "Microphone Jack", + "Microphone Jack", "Mic Bias", + "LINE_IN", "Line In Jack", + "Headphone Jack", "HP_OUT", + "Speaker Ext", "LINE_OUT"; + + simple-audio-card,cpu { + sound-dai = <&sai2>; + }; + + simple-audio-card,codec { + sound-dai = <&sgtl5000>; + clocks = <&clk IMX8MQ_CLK_SAI2_ROOT>; + frame-master; + bitclock-master; + }; + }; + vibrator { compatible = "gpio-vibrator"; pinctrl-names = "default"; @@ -426,6 +454,19 @@ vddio-supply = <®_3v3_p>; }; + sgtl5000: audio-codec@a { + compatible = "fsl,sgtl5000"; + clocks = <&clk IMX8MQ_CLK_SAI2_ROOT>; + assigned-clocks = <&clk IMX8MQ_CLK_SAI2>; + assigned-clock-parents = <&clk IMX8MQ_AUDIO_PLL1_OUT>; + assigned-clock-rates = <24576000>; + #sound-dai-cells = <0>; + reg = <0x0a>; + VDDD-supply = <®_1v8_p>; + VDDIO-supply = <®_3v3_p>; + VDDA-supply = <®_3v3_p>; + }; + touchscreen@5d { compatible = "goodix,gt5688"; reg = <0x5d>; @@ -567,6 +608,16 @@ >; }; + pinctrl_sai2: sai2grp { + fsl,pins = < + MX8MQ_IOMUXC_SAI2_TXFS_SAI2_TX_SYNC 0xd6 + MX8MQ_IOMUXC_SAI2_TXC_SAI2_TX_BCLK 0xd6 + MX8MQ_IOMUXC_SAI2_TXD0_SAI2_TX_DATA0 0xd6 + MX8MQ_IOMUXC_SAI2_RXD0_SAI2_RX_DATA0 0xd6 + MX8MQ_IOMUXC_SAI2_MCLK_SAI2_MCLK 0xd6 + >; + }; + pinctrl_typec: typecgrp { fsl,pins = < MX8MQ_IOMUXC_NAND_DATA06_GPIO3_IO12 0x16 @@ -742,6 +793,15 @@ status = "okay"; }; +&sai2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sai2>; + assigned-clocks = <&clk IMX8MQ_CLK_SAI2>; + assigned-clock-parents = <&clk IMX8MQ_AUDIO_PLL1_OUT>; + assigned-clock-rates = <24576000>; + status = "okay"; +}; + &uart1 { /* console */ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart1>; From 7f7b799717cb0437283e5789083f6d78e8a3a993 Mon Sep 17 00:00:00 2001 From: "Angus Ainslie (Purism)" Date: Thu, 27 Feb 2020 14:17:28 +0100 Subject: [PATCH 1467/4444] arm64: dts: librem5-devkit: add the simcom 7100 modem and audio Add the simcom SIM7100 modem and the sai6 interface that connects it. Signed-off-by: Angus Ainslie (Purism) Signed-off-by: Martin Kepplinger Signed-off-by: Shawn Guo --- .../dts/freescale/imx8mq-librem5-devkit.dts | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts index c829e4579540..84443e4857d5 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts @@ -148,6 +148,11 @@ regulator-always-on; }; + wwan_codec: sound-wwan-codec { + compatible = "option,gtm601"; + #sound-dai-cells = <0>; + }; + sound { compatible = "simple-audio-card"; simple-audio-card,name = "sgtl5000"; @@ -176,6 +181,22 @@ }; }; + sound-wwan { + compatible = "simple-audio-card"; + simple-audio-card,name = "SIMCom SIM7100"; + simple-audio-card,format = "dsp_a"; + + simple-audio-card,cpu { + sound-dai = <&sai6>; + }; + + telephony_link_master: simple-audio-card,codec { + sound-dai = <&wwan_codec>; + frame-master; + bitclock-master; + }; + }; + vibrator { compatible = "gpio-vibrator"; pinctrl-names = "default"; @@ -618,6 +639,15 @@ >; }; + pinctrl_sai6: sai6grp { + fsl,pins = < + MX8MQ_IOMUXC_SAI1_RXD5_SAI6_RX_DATA0 0xd6 + MX8MQ_IOMUXC_SAI1_RXD6_SAI6_RX_SYNC 0xd6 + MX8MQ_IOMUXC_SAI1_TXD4_SAI6_RX_BCLK 0xd6 + MX8MQ_IOMUXC_SAI1_TXD5_SAI6_TX_DATA0 0xd6 + >; + }; + pinctrl_typec: typecgrp { fsl,pins = < MX8MQ_IOMUXC_NAND_DATA06_GPIO3_IO12 0x16 @@ -802,6 +832,16 @@ status = "okay"; }; +&sai6 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sai6>; + assigned-clocks = <&clk IMX8MQ_CLK_SAI6>; + assigned-clock-parents = <&clk IMX8MQ_AUDIO_PLL1_OUT>; + assigned-clock-rates = <24576000>; + fsl,sai-synchronous-rx; + status = "okay"; +}; + &uart1 { /* console */ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart1>; From 3ef506b3e62a3128ac0288e13906514d9e68ff6a Mon Sep 17 00:00:00 2001 From: "Angus Ainslie (Purism)" Date: Thu, 27 Feb 2020 14:17:29 +0100 Subject: [PATCH 1468/4444] arm64: dts: librem5-devkit: allow modem to wake the system from suspend Connect the WoWWAN signal to a gpio key to wake up the system from suspend. Signed-off-by: Angus Ainslie (Purism) Signed-off-by: Martin Kepplinger Signed-off-by: Shawn Guo --- .../arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts index 84443e4857d5..823d5c60a8fa 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts @@ -55,6 +55,15 @@ wakeup-source; linux,code = ; }; + + wwan-wake { + label = "WWAN_WAKE"; + gpios = <&gpio3 8 GPIO_ACTIVE_LOW>; + interrupt-parent = <&gpio3>; + interrupts = <8 GPIO_ACTIVE_LOW>; + wakeup-source; + linux,code = ; + }; }; leds { @@ -576,6 +585,7 @@ MX8MQ_IOMUXC_SAI2_RXFS_GPIO4_IO21 0x16 MX8MQ_IOMUXC_SAI2_RXC_GPIO4_IO22 0x16 MX8MQ_IOMUXC_SAI5_RXC_GPIO3_IO20 0x180 /* HP_DET */ + MX8MQ_IOMUXC_NAND_DATA02_GPIO3_IO8 0x80 /* nWoWWAN */ >; }; From a2e47ba221921713f1e8dd251086468cefb92d5d Mon Sep 17 00:00:00 2001 From: "Angus Ainslie (Purism)" Date: Thu, 27 Feb 2020 14:17:30 +0100 Subject: [PATCH 1469/4444] arm64: dts: librem5-devkit: add the regulators for DVFS Specify which regulator is used for cpufreq DVFS. Signed-off-by: Angus Ainslie (Purism) Signed-off-by: Martin Kepplinger Signed-off-by: Shawn Guo --- .../boot/dts/freescale/imx8mq-librem5-devkit.dts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts index 823d5c60a8fa..6ba65a807b25 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts @@ -227,6 +227,22 @@ }; }; +&A53_0 { + cpu-supply = <&buck2_reg>; +}; + +&A53_1 { + cpu-supply = <&buck2_reg>; +}; + +&A53_2 { + cpu-supply = <&buck2_reg>; +}; + +&A53_3 { + cpu-supply = <&buck2_reg>; +}; + &clk { assigned-clocks = <&clk IMX8MQ_AUDIO_PLL1>, <&clk IMX8MQ_AUDIO_PLL2>; assigned-clock-rates = <786432000>, <722534400>; From 9dae8563bfdbab16308933ed04ca5e1fa7443501 Mon Sep 17 00:00:00 2001 From: "Angus Ainslie (Purism)" Date: Thu, 27 Feb 2020 14:17:31 +0100 Subject: [PATCH 1470/4444] arm64: dts: librem5-devkit: allow the redpine card to be removed By adding broken-cd to the usdhc2 stanza the Redpine card can be detected when the HKS is turned off and on. Signed-off-by: Angus Ainslie (Purism) Signed-off-by: Martin Kepplinger Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts index 6ba65a807b25..12a91d2d36db 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts @@ -947,7 +947,7 @@ bus-width = <4>; vmmc-supply = <®_usdhc2_vmmc>; power-supply = <&wifi_pwr_en>; - non-removable; + broken-cd; disable-wp; cap-sdio-irq; keep-power-in-suspend; From 5369d1914514936bf578e445b11737669692a6be Mon Sep 17 00:00:00 2001 From: "Angus Ainslie (Purism)" Date: Thu, 27 Feb 2020 14:17:32 +0100 Subject: [PATCH 1471/4444] arm64: dts: librem5-devkit: increase the VBUS current in the kernel The poly fuses can handle 6V 4Amps so incease the kernel limts to 5V 3.5Amps. Signed-off-by: Angus Ainslie (Purism) Signed-off-by: Martin Kepplinger Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts index 12a91d2d36db..72c622ffe6de 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts @@ -428,10 +428,10 @@ PDO_FIXED_USB_COMM | PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP )>; - sink-pdos = ; + PDO_VAR(5000, 5000, 3500)>; op-sink-microwatt = <10000000>; ports { From eef22bb129dfef560e9a17dac6fc751b24832bd1 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Thu, 27 Feb 2020 14:17:33 +0100 Subject: [PATCH 1472/4444] arm64: dts: librem5-devkit: add lsm9ds1 mount matrix The IMU chip on the librem5-devkit is not mounted at the "natural" place that would match normal phone orientation (see the documentation for the details about what that is). Since the lsm9ds1 driver supports providing a mount matrix, we can describe the orientation on the board in the dts: Create a right-handed coordinate system (x * -1; see the datasheet for the axis) and rotate 180 degrees around the y axis because the device sits on the back side from the display. Signed-off-by: Martin Kepplinger Reviewed-by: Marco Felsch Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts index 72c622ffe6de..10eca94194be 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts @@ -539,6 +539,9 @@ reg = <0x6a>; vdd-supply = <®_3v3_p>; vddio-supply = <®_3v3_p>; + mount-matrix = "1", "0", "0", + "0", "1", "0", + "0", "0", "-1"; }; }; From 7f61dff1ed915c44845d6865d295853b1c39b6d7 Mon Sep 17 00:00:00 2001 From: Marian-Cristian Rotariu Date: Tue, 3 Mar 2020 12:44:50 +0000 Subject: [PATCH 1473/4444] ARM: dts: iwg22d-sodimm: Enable LCD panel On the Generic SODIMM Development Platform there is an RGB LCD panel directly connected to the DU output. It uses the TPU0 as backlight, one GPIO pull-up configuration for power enable, R[2:7], G[2:7], B[2:7], VSYNC, HSYNC, DU0_DISP and, DU0_CLK as inputs. There is no encoder between the DU and the panel, therefore the default connector driver is used. The two variants of the iW-G22D should be mutually exclusive, therefore this patch also disables the RGB LCD display when the HDMI extension board is used. Signed-off-by: Marian-Cristian Rotariu Link: https://lore.kernel.org/r/1583239490-8837-1-git-send-email-marian-cristian.rotariu.rb@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- .../dts/r8a7745-iwg22d-sodimm-dbhd-ca.dts | 6 ++ arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts | 60 +++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/arch/arm/boot/dts/r8a7745-iwg22d-sodimm-dbhd-ca.dts b/arch/arm/boot/dts/r8a7745-iwg22d-sodimm-dbhd-ca.dts index 2aeebfc9e4f1..92aa26ba423c 100644 --- a/arch/arm/boot/dts/r8a7745-iwg22d-sodimm-dbhd-ca.dts +++ b/arch/arm/boot/dts/r8a7745-iwg22d-sodimm-dbhd-ca.dts @@ -108,6 +108,12 @@ }; }; +&lcd_panel { + status = "disabled"; + + /delete-node/ port; +}; + &pfc { can1_pins: can1 { groups = "can1_data_b"; diff --git a/arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts b/arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts index 58d369ad8279..2487ba0e9c9f 100644 --- a/arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts +++ b/arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts @@ -30,6 +30,7 @@ /dts-v1/; #include "r8a7745-iwg22m.dtsi" +#include / { model = "iWave Systems RainboW-G22D-SODIMM board based on RZ/G1E"; @@ -78,6 +79,49 @@ gpios-states = <1>; states = <3300000 1>, <1800000 0>; }; + + vccq_panel: regulator-vccq-panel { + compatible = "regulator-fixed"; + regulator-name = "Panel VccQ"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio1 13 GPIO_ACTIVE_LOW>; + enable-active-high; + }; + + backlight_lcd: backlight { + compatible = "pwm-backlight"; + pwms = <&tpu 3 5000000 PWM_POLARITY_INVERTED>; + brightness-levels = <0 4 8 16 32 64 128 255>; + default-brightness-level = <7>; + }; + + lcd_panel: lcd { + compatible = "edt,etm043080dh6gp"; + power-supply = <&vccq_panel>; + backlight = <&backlight_lcd>; + + port { + lcd_in: endpoint { + remote-endpoint = <&du_out_rgb0>; + }; + }; + }; +}; + +&du { + pinctrl-0 = <&du0_pins>; + pinctrl-names = "default"; + + status = "okay"; + + ports { + port@0 { + endpoint { + remote-endpoint = <&lcd_in>; + }; + }; + }; }; &avb { @@ -149,11 +193,21 @@ function = "avb"; }; + backlight_pins: backlight { + groups = "tpu_to3_c"; + function = "tpu"; + }; + can0_pins: can0 { groups = "can0_data"; function = "can0"; }; + du0_pins: du0 { + groups = "du0_rgb666", "du0_sync", "du0_disp", "du0_clk0_out"; + function = "du0"; + }; + hscif1_pins: hscif1 { groups = "hscif1_data", "hscif1_ctrl"; function = "hscif1"; @@ -229,6 +283,12 @@ shared-pin; }; +&tpu { + pinctrl-0 = <&backlight_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + &usbphy { status = "okay"; }; From 99ae78f1fc3a73c88fe726c676ae963ce722bf20 Mon Sep 17 00:00:00 2001 From: Marian-Cristian Rotariu Date: Wed, 4 Mar 2020 15:44:10 +0000 Subject: [PATCH 1474/4444] ARM: dts: iwg22d-sodimm: Enable touchscreen In one of the iWave-G22D development board variants, called Generic SODIMM Development Platform, we have an LCD with touchscreen. The resistive touch controller, STMPE811 is on the development board and is connected through the i2c5 of the RZ-G1E. Additionally, this controller should generate an interrupt to the CPU and it is connected through GPIO4,4 to the GIC. Touch was tested with one of our iW-RainboW-G22D-SODIMM RZ/G1E development platforms. More details on the iWave website: https://www.iwavesystems.com/rz-g1e-sodimm-development-kit.html Signed-off-by: Marian-Cristian Rotariu Link: https://lore.kernel.org/r/1583336650-25848-1-git-send-email-marian-cristian.rotariu.rb@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts b/arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts index 2487ba0e9c9f..b15b1b088a32 100644 --- a/arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts +++ b/arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts @@ -171,6 +171,39 @@ status = "okay"; clock-frequency = <400000>; + stmpe811@44 { + compatible = "st,stmpe811"; + reg = <0x44>; + interrupt-parent = <&gpio4>; + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; + + /* 3.25 MHz ADC clock speed */ + st,adc-freq = <1>; + /* ADC converstion time: 80 clocks */ + st,sample-time = <4>; + /* 12-bit ADC */ + st,mod-12b = <1>; + /* internal ADC reference */ + st,ref-sel = <0>; + + stmpe_touchscreen { + compatible = "st,stmpe-ts"; + /* 8 sample average control */ + st,ave-ctrl = <3>; + /* 7 length fractional part in z */ + st,fraction-z = <7>; + /* + * 50 mA typical 80 mA max touchscreen drivers + * current limit value + */ + st,i-drive = <1>; + /* 1 ms panel driver settling time */ + st,settling = <3>; + /* 5 ms touch detect interrupt delay */ + st,touch-det-delay = <5>; + }; + }; + sgtl5000: codec@a { compatible = "fsl,sgtl5000"; #sound-dai-cells = <0>; From eeb40fda056ce2f914fff000525ca5a7b2ddec50 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 3 Mar 2020 10:48:48 +0100 Subject: [PATCH 1475/4444] dt-bindings: clock: renesas: cpg-mssr: Convert to json-schema Convert the Renesas Clock Pulse Generator / Module Standby and Software Reset Device Tree binding documentation to json-schema. Note that #reset-cells was incorrecty marked a required property for RZ/A2 before. Signed-off-by: Geert Uytterhoeven Reviewed-by: Stephen Boyd Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20200303094848.23670-1-geert+renesas@glider.be --- .../bindings/clock/renesas,cpg-mssr.txt | 100 --------------- .../bindings/clock/renesas,cpg-mssr.yaml | 119 ++++++++++++++++++ 2 files changed, 119 insertions(+), 100 deletions(-) delete mode 100644 Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt create mode 100644 Documentation/devicetree/bindings/clock/renesas,cpg-mssr.yaml diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt deleted file mode 100644 index f4d153f24a0f..000000000000 --- a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt +++ /dev/null @@ -1,100 +0,0 @@ -* Renesas Clock Pulse Generator / Module Standby and Software Reset - -On Renesas ARM SoCs (SH/R-Mobile, R-Car, RZ), the CPG (Clock Pulse Generator) -and MSSR (Module Standby and Software Reset) blocks are intimately connected, -and share the same register block. - -They provide the following functionalities: - - The CPG block generates various core clocks, - - The MSSR block provides two functions: - 1. Module Standby, providing a Clock Domain to control the clock supply - to individual SoC devices, - 2. Reset Control, to perform a software reset of individual SoC devices. - -Required Properties: - - compatible: Must be one of: - - "renesas,r7s9210-cpg-mssr" for the r7s9210 SoC (RZ/A2) - - "renesas,r8a7743-cpg-mssr" for the r8a7743 SoC (RZ/G1M) - - "renesas,r8a7744-cpg-mssr" for the r8a7744 SoC (RZ/G1N) - - "renesas,r8a7745-cpg-mssr" for the r8a7745 SoC (RZ/G1E) - - "renesas,r8a77470-cpg-mssr" for the r8a77470 SoC (RZ/G1C) - - "renesas,r8a774a1-cpg-mssr" for the r8a774a1 SoC (RZ/G2M) - - "renesas,r8a774b1-cpg-mssr" for the r8a774b1 SoC (RZ/G2N) - - "renesas,r8a774c0-cpg-mssr" for the r8a774c0 SoC (RZ/G2E) - - "renesas,r8a7790-cpg-mssr" for the r8a7790 SoC (R-Car H2) - - "renesas,r8a7791-cpg-mssr" for the r8a7791 SoC (R-Car M2-W) - - "renesas,r8a7792-cpg-mssr" for the r8a7792 SoC (R-Car V2H) - - "renesas,r8a7793-cpg-mssr" for the r8a7793 SoC (R-Car M2-N) - - "renesas,r8a7794-cpg-mssr" for the r8a7794 SoC (R-Car E2) - - "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3) - - "renesas,r8a7796-cpg-mssr" for the r8a77960 SoC (R-Car M3-W) - - "renesas,r8a77961-cpg-mssr" for the r8a77961 SoC (R-Car M3-W+) - - "renesas,r8a77965-cpg-mssr" for the r8a77965 SoC (R-Car M3-N) - - "renesas,r8a77970-cpg-mssr" for the r8a77970 SoC (R-Car V3M) - - "renesas,r8a77980-cpg-mssr" for the r8a77980 SoC (R-Car V3H) - - "renesas,r8a77990-cpg-mssr" for the r8a77990 SoC (R-Car E3) - - "renesas,r8a77995-cpg-mssr" for the r8a77995 SoC (R-Car D3) - - - reg: Base address and length of the memory resource used by the CPG/MSSR - block - - - clocks: References to external parent clocks, one entry for each entry in - clock-names - - clock-names: List of external parent clock names. Valid names are: - - "extal" (r7s9210, r8a7743, r8a7744, r8a7745, r8a77470, r8a774a1, - r8a774b1, r8a774c0, r8a7790, r8a7791, r8a7792, r8a7793, - r8a7794, r8a7795, r8a77960, r8a77961, r8a77965, r8a77970, - r8a77980, r8a77990, r8a77995) - - "extalr" (r8a774a1, r8a774b1, r8a7795, r8a77960, r8a77961, r8a77965, - r8a77970, r8a77980) - - "usb_extal" (r8a7743, r8a7744, r8a7745, r8a77470, r8a7790, r8a7791, - r8a7793, r8a7794) - - - #clock-cells: Must be 2 - - For CPG core clocks, the two clock specifier cells must be "CPG_CORE" - and a core clock reference, as defined in - . - - For module clocks, the two clock specifier cells must be "CPG_MOD" and - a module number, as defined in the datasheet. - - - #power-domain-cells: Must be 0 - - SoC devices that are part of the CPG/MSSR Clock Domain and can be - power-managed through Module Standby should refer to the CPG device - node in their "power-domains" property, as documented by the generic PM - Domain bindings in - Documentation/devicetree/bindings/power/power-domain.yaml. - - - #reset-cells: Must be 1 - - The single reset specifier cell must be the module number, as defined - in the datasheet. - - -Examples --------- - - - CPG device node: - - cpg: clock-controller@e6150000 { - compatible = "renesas,r8a7795-cpg-mssr"; - reg = <0 0xe6150000 0 0x1000>; - clocks = <&extal_clk>, <&extalr_clk>; - clock-names = "extal", "extalr"; - #clock-cells = <2>; - #power-domain-cells = <0>; - #reset-cells = <1>; - }; - - - - CPG/MSSR Clock Domain member device node: - - scif2: serial@e6e88000 { - compatible = "renesas,scif-r8a7795", "renesas,scif"; - reg = <0 0xe6e88000 0 64>; - interrupts = ; - clocks = <&cpg CPG_MOD 310>; - clock-names = "fck"; - dmas = <&dmac1 0x13>, <&dmac1 0x12>; - dma-names = "tx", "rx"; - power-domains = <&cpg>; - resets = <&cpg 310>; - }; diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.yaml b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.yaml new file mode 100644 index 000000000000..9cd102e5fed5 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.yaml @@ -0,0 +1,119 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/clock/renesas,cpg-mssr.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Renesas Clock Pulse Generator / Module Standby and Software Reset + +maintainers: + - Geert Uytterhoeven + +description: | + On Renesas ARM SoCs (SH/R-Mobile, R-Car, RZ), the CPG (Clock Pulse Generator) + and MSSR (Module Standby and Software Reset) blocks are intimately connected, + and share the same register block. + + They provide the following functionalities: + - The CPG block generates various core clocks, + - The MSSR block provides two functions: + 1. Module Standby, providing a Clock Domain to control the clock supply + to individual SoC devices, + 2. Reset Control, to perform a software reset of individual SoC devices. + +properties: + compatible: + enum: + - renesas,r7s9210-cpg-mssr # RZ/A2 + - renesas,r8a7743-cpg-mssr # RZ/G1M + - renesas,r8a7744-cpg-mssr # RZ/G1N + - renesas,r8a7745-cpg-mssr # RZ/G1E + - renesas,r8a77470-cpg-mssr # RZ/G1C + - renesas,r8a774a1-cpg-mssr # RZ/G2M + - renesas,r8a774b1-cpg-mssr # RZ/G2N + - renesas,r8a774c0-cpg-mssr # RZ/G2E + - renesas,r8a7790-cpg-mssr # R-Car H2 + - renesas,r8a7791-cpg-mssr # R-Car M2-W + - renesas,r8a7792-cpg-mssr # R-Car V2H + - renesas,r8a7793-cpg-mssr # R-Car M2-N + - renesas,r8a7794-cpg-mssr # R-Car E2 + - renesas,r8a7795-cpg-mssr # R-Car H3 + - renesas,r8a7796-cpg-mssr # R-Car M3-W + - renesas,r8a77961-cpg-mssr # R-Car M3-W+ + - renesas,r8a77965-cpg-mssr # R-Car M3-N + - renesas,r8a77970-cpg-mssr # R-Car V3M + - renesas,r8a77980-cpg-mssr # R-Car V3H + - renesas,r8a77990-cpg-mssr # R-Car E3 + - renesas,r8a77995-cpg-mssr # R-Car D3 + + reg: + maxItems: 1 + + clocks: + minItems: 1 + maxItems: 2 + + clock-names: + minItems: 1 + maxItems: 2 + items: + enum: + - extal # All + - extalr # Most R-Car Gen3 and RZ/G2 + - usb_extal # Most R-Car Gen2 and RZ/G1 + + '#clock-cells': + description: | + - For CPG core clocks, the two clock specifier cells must be "CPG_CORE" + and a core clock reference, as defined in + + - For module clocks, the two clock specifier cells must be "CPG_MOD" and + a module number, as defined in the datasheet. + const: 2 + + '#power-domain-cells': + description: + SoC devices that are part of the CPG/MSSR Clock Domain and can be + power-managed through Module Standby should refer to the CPG device node + in their "power-domains" property, as documented by the generic PM Domain + bindings in Documentation/devicetree/bindings/power/power-domain.yaml. + const: 0 + + '#reset-cells': + description: + The single reset specifier cell must be the module number, as defined in + the datasheet. + const: 1 + +if: + not: + properties: + compatible: + items: + enum: + - renesas,r7s9210-cpg-mssr +then: + required: + - '#reset-cells' + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - '#power-domain-cells' + +additionalProperties: false + +examples: + - | + cpg: clock-controller@e6150000 { + compatible = "renesas,r8a7795-cpg-mssr"; + reg = <0xe6150000 0x1000>; + clocks = <&extal_clk>, <&extalr_clk>; + clock-names = "extal", "extalr"; + #clock-cells = <2>; + #power-domain-cells = <0>; + #reset-cells = <1>; + }; From d2cf2f91ba5b6d7696b1870e28017a3e1a7a1bb8 Mon Sep 17 00:00:00 2001 From: Tim Harvey Date: Fri, 28 Feb 2020 11:46:07 -0800 Subject: [PATCH 1476/4444] ARM: dts: imx6qdl-gw5910: add CC1352 UART The GW5910-C revision adds a TI CC1352 connected to IMX UART4 Signed-off-by: Tim Harvey Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-gw5910.dtsi | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm/boot/dts/imx6qdl-gw5910.dtsi b/arch/arm/boot/dts/imx6qdl-gw5910.dtsi index be1af7482f89..30fe47ff64a4 100644 --- a/arch/arm/boot/dts/imx6qdl-gw5910.dtsi +++ b/arch/arm/boot/dts/imx6qdl-gw5910.dtsi @@ -220,6 +220,14 @@ status = "okay"; }; +/* cc1352 */ +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + uart-has-rtscts; + status = "okay"; +}; + /* Sterling-LWB Bluetooth */ &uart4 { pinctrl-names = "default"; @@ -411,6 +419,23 @@ >; }; + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1 + MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1 + MX6QDL_PAD_EIM_D23__UART3_RTS_B 0x1b0b1 + MX6QDL_PAD_EIM_D31__UART3_CTS_B 0x1b0b1 + MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x4001b0b1 /* DIO20 */ + MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05 0x4001b0b1 /* DIO14 */ + MX6QDL_PAD_DISP0_DAT12__GPIO5_IO06 0x4001b0b1 /* DIO15 */ + MX6QDL_PAD_DISP0_DAT14__GPIO5_IO08 0x1b0b1 /* TMS */ + MX6QDL_PAD_DISP0_DAT15__GPIO5_IO09 0x1b0b1 /* TCK */ + MX6QDL_PAD_DISP0_DAT16__GPIO5_IO10 0x1b0b1 /* TDO */ + MX6QDL_PAD_DISP0_DAT17__GPIO5_IO11 0x1b0b1 /* TDI */ + MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17 0x4001b0b1 /* RST# */ + >; + }; + pinctrl_uart4: uart4grp { fsl,pins = < MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1 From 194153403da834700a92bc9cf1c8acf030cef62b Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Mon, 2 Mar 2020 10:27:57 +0100 Subject: [PATCH 1477/4444] dt-bindings: arm: fix Rockchip Kylin board bindings A test with the command below gives this error: arch/arm/boot/dts/rk3036-kylin.dt.yaml: /: compatible: ['rockchip,rk3036-kylin', 'rockchip,rk3036'] is not valid under any of the given schemas Normally the dt-binding is the authoritative part, so boards should follow the binding, but in the kylin-case the compatible from the .dts is used for years in the field now, so fix the binding, as otherwise we would break old users. Fix this error by changing 'rockchip,kylin-rk3036' to 'rockchip,rk3036-kylin' in rockchip.yaml. make ARCH=arm dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/arm/rockchip.yaml Signed-off-by: Johan Jonker Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20200302092759.3291-1-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- Documentation/devicetree/bindings/arm/rockchip.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml index 874b0eaa2a75..2031580386f7 100644 --- a/Documentation/devicetree/bindings/arm/rockchip.yaml +++ b/Documentation/devicetree/bindings/arm/rockchip.yaml @@ -443,7 +443,7 @@ properties: - description: Rockchip Kylin items: - - const: rockchip,kylin-rk3036 + - const: rockchip,rk3036-kylin - const: rockchip,rk3036 - description: Rockchip PX3 Evaluation board From ee3eff7e14eb0a2e16055ad4a6c180754391a3ac Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Mon, 2 Mar 2020 10:27:58 +0100 Subject: [PATCH 1478/4444] dt-bindings: arm: add Rockchip rk3036-evb board A test with the command below gives this error: arch/arm/boot/dts/rk3036-evb.dt.yaml: /: compatible: ['rockchip,rk3036-evb', 'rockchip,rk3036'] is not valid under any of the given schemas This board was somehow never added to the documentation. Fix this error by adding the rk3036-evb board to rockchip.yaml. make ARCH=arm dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/arm/rockchip.yaml Signed-off-by: Johan Jonker Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20200302092759.3291-2-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- Documentation/devicetree/bindings/arm/rockchip.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml index 2031580386f7..d303790f5d22 100644 --- a/Documentation/devicetree/bindings/arm/rockchip.yaml +++ b/Documentation/devicetree/bindings/arm/rockchip.yaml @@ -468,6 +468,11 @@ properties: - const: rockchip,r88 - const: rockchip,rk3368 + - description: Rockchip RK3036 Evaluation board + items: + - const: rockchip,rk3036-evb + - const: rockchip,rk3036 + - description: Rockchip RK3228 Evaluation board items: - const: rockchip,rk3228-evb From bf14bc6169cdb94f14f9c1d69541334f1d942ef8 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Mon, 2 Mar 2020 10:27:59 +0100 Subject: [PATCH 1479/4444] arm64: dts: rockchip: fix compatible property for rk3399-evb A test with the command below gives this error: arch/arm64/boot/dts/rockchip/rk3399-evb.dt.yaml: /: compatible: ['rockchip,rk3399-evb', 'rockchip,rk3399', 'google,rk3399evb-rev2'] is not valid under any of the given schemas 'google,rk3399evb-rev2' was a no longer used variant for Google. The binding only mentions 'rockchip,rk3399-evb', 'rockchip,rk3399', so fix this error by removing 'google,rk3399evb-rev2' from the compatible property in rk3399-evb.dts and change it into generic rk3399-evb support only. make ARCH=arm64 dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/arm/rockchip.yaml Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200302092759.3291-3-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3399-evb.dts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts index 5e5d49f3c229..694b0d08d644 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts @@ -9,8 +9,7 @@ / { model = "Rockchip RK3399 Evaluation Board"; - compatible = "rockchip,rk3399-evb", "rockchip,rk3399", - "google,rk3399evb-rev2"; + compatible = "rockchip,rk3399-evb", "rockchip,rk3399"; backlight: backlight { compatible = "pwm-backlight"; From d3f46dd47ff73c14184d5f3a9c031d6b2cd55f3c Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Sat, 29 Feb 2020 22:03:01 +0800 Subject: [PATCH 1480/4444] arm64: dts: imx8mn-evk: Add i2c3 support Enable i2c3 for i.MX8MN EVK board. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi b/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi index 0d2ec4a2c7f2..2fb599fa7cee 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi @@ -102,6 +102,13 @@ }; }; +&i2c3 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + status = "okay"; +}; + &snvs_pwrkey { status = "okay"; }; @@ -202,6 +209,13 @@ >; }; + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX8MN_IOMUXC_I2C3_SCL_I2C3_SCL 0x400001c3 + MX8MN_IOMUXC_I2C3_SDA_I2C3_SDA 0x400001c3 + >; + }; + pinctrl_reg_usdhc2_vmmc: regusdhc2vmmc { fsl,pins = < MX8MN_IOMUXC_SD2_RESET_B_GPIO2_IO19 0x41 From ded9e59b39016f607f18e3b46d13720e22a715d5 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Sat, 29 Feb 2020 22:03:02 +0800 Subject: [PATCH 1481/4444] arm64: dts: imx8mn-evk: Enable pca6416 on i2c3 bus Enable pca6416 on i.MX8MN EVK board's i2c3 bus. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi b/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi index 2fb599fa7cee..85fc0aa38c4f 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi @@ -107,6 +107,13 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c3>; status = "okay"; + + pca6416: gpio@20 { + compatible = "ti,tca6416"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + }; }; &snvs_pwrkey { From 5e4a67ff7f698ff1af6ebcd9bec7d8de6711ec57 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Sat, 29 Feb 2020 22:16:25 +0800 Subject: [PATCH 1482/4444] arm64: dts: imx8mp-evk: Add i2c3 support Enable i2c3 for i.MX8MP EVK board. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts index a97a03c81517..b70c42aa9f42 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts @@ -66,6 +66,13 @@ }; }; +&i2c3 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + status = "okay"; +}; + &snvs_pwrkey { status = "okay"; }; @@ -138,6 +145,13 @@ >; }; + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX8MP_IOMUXC_I2C3_SCL__I2C3_SCL 0x400001c3 + MX8MP_IOMUXC_I2C3_SDA__I2C3_SDA 0x400001c3 + >; + }; + pinctrl_reg_usdhc2_vmmc: regusdhc2vmmc { fsl,pins = < MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19 0x41 From 2dfb4b13161aead1806037e7baae0baa07224afa Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Sat, 29 Feb 2020 22:16:26 +0800 Subject: [PATCH 1483/4444] arm64: dts: imx8mp-evk: Enable pca6416 on i2c3 bus Enable pca6416 on i.MX8MP EVK board's i2c3 bus. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts index b70c42aa9f42..3da1fff3d6fd 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts @@ -71,6 +71,13 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c3>; status = "okay"; + + pca6416: gpio@20 { + compatible = "ti,tca6416"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + }; }; &snvs_pwrkey { From f93f1e721cc7c5e6af7f1b2ada62b1c7b3a93426 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Mon, 2 Mar 2020 12:20:27 +0800 Subject: [PATCH 1484/4444] arm64: dts: layerscape: add iommu-map property to pci nodes Add the iommu-map property to the pci nodes so that the firmware fixes it up with the required values thus enabling iommu for devices connected over pci. Signed-off-by: Hou Zhiqiang Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 3 +++ arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi | 4 ++++ arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi | 6 ++++++ 3 files changed, 13 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi index ec6013a8137d..36a799554620 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi @@ -494,6 +494,7 @@ <0000 0 0 2 &gic 0 0 0 110 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 3 &gic 0 0 0 111 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 4 &gic 0 0 0 112 IRQ_TYPE_LEVEL_HIGH>; + iommu-map = <0 &smmu 0 1>; /* Fixed-up by bootloader */ status = "disabled"; }; @@ -519,6 +520,7 @@ <0000 0 0 2 &gic 0 0 0 115 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 3 &gic 0 0 0 116 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 4 &gic 0 0 0 117 IRQ_TYPE_LEVEL_HIGH>; + iommu-map = <0 &smmu 0 1>; /* Fixed-up by bootloader */ status = "disabled"; }; @@ -544,6 +546,7 @@ <0000 0 0 2 &gic 0 0 0 120 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 3 &gic 0 0 0 121 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 4 &gic 0 0 0 122 IRQ_TYPE_LEVEL_HIGH>; + iommu-map = <0 &smmu 0 1>; /* Fixed-up by bootloader */ status = "disabled"; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi index f96d06da96be..3944ef16ec60 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi @@ -648,6 +648,7 @@ <0000 0 0 2 &gic 0 0 0 110 4>, <0000 0 0 3 &gic 0 0 0 111 4>, <0000 0 0 4 &gic 0 0 0 112 4>; + iommu-map = <0 &smmu 0 1>; /* Fixed-up by bootloader */ status = "disabled"; }; @@ -669,6 +670,7 @@ <0000 0 0 2 &gic 0 0 0 115 4>, <0000 0 0 3 &gic 0 0 0 116 4>, <0000 0 0 4 &gic 0 0 0 117 4>; + iommu-map = <0 &smmu 0 1>; /* Fixed-up by bootloader */ status = "disabled"; }; @@ -690,6 +692,7 @@ <0000 0 0 2 &gic 0 0 0 120 4>, <0000 0 0 3 &gic 0 0 0 121 4>, <0000 0 0 4 &gic 0 0 0 122 4>; + iommu-map = <0 &smmu 0 1>; /* Fixed-up by bootloader */ status = "disabled"; }; @@ -711,6 +714,7 @@ <0000 0 0 2 &gic 0 0 0 125 4>, <0000 0 0 3 &gic 0 0 0 126 4>, <0000 0 0 4 &gic 0 0 0 127 4>; + iommu-map = <0 &smmu 0 1>; /* Fixed-up by bootloader */ status = "disabled"; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi index 98a8f6def55e..ae1b113ab162 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi @@ -858,6 +858,7 @@ <0000 0 0 2 &gic 0 0 GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 3 &gic 0 0 GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 4 &gic 0 0 GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>; + iommu-map = <0 &smmu 0 1>; /* Fixed-up by bootloader */ status = "disabled"; }; @@ -885,6 +886,7 @@ <0000 0 0 2 &gic 0 0 GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 3 &gic 0 0 GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 4 &gic 0 0 GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>; + iommu-map = <0 &smmu 0 1>; /* Fixed-up by bootloader */ status = "disabled"; }; @@ -912,6 +914,7 @@ <0000 0 0 2 &gic 0 0 GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 3 &gic 0 0 GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 4 &gic 0 0 GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>; + iommu-map = <0 &smmu 0 1>; /* Fixed-up by bootloader */ status = "disabled"; }; @@ -939,6 +942,7 @@ <0000 0 0 2 &gic 0 0 GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 3 &gic 0 0 GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 4 &gic 0 0 GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>; + iommu-map = <0 &smmu 0 1>; /* Fixed-up by bootloader */ status = "disabled"; }; @@ -966,6 +970,7 @@ <0000 0 0 2 &gic 0 0 GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 3 &gic 0 0 GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 4 &gic 0 0 GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>; + iommu-map = <0 &smmu 0 1>; /* Fixed-up by bootloader */ status = "disabled"; }; @@ -993,6 +998,7 @@ <0000 0 0 2 &gic 0 0 GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 3 &gic 0 0 GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 4 &gic 0 0 GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>; + iommu-map = <0 &smmu 0 1>; /* Fixed-up by bootloader */ status = "disabled"; }; From c5486819d26339d398f0972a528e189a3db1427e Mon Sep 17 00:00:00 2001 From: Vitor Massaru Iha Date: Mon, 2 Mar 2020 22:15:16 -0300 Subject: [PATCH 1485/4444] arm64: dts: imx8mq-phanbell: Add gpio-fan/thermal support It was based on Google Source Code for Coral Edge TPU Mendel release: https://coral.googlesource.com/linux-imx/ It was tested on Coral Dev Board using this command: sudo stress --cpu 4 --timeout 3600 Signed-off-by: Vitor Massaru Iha Reviewed-by: Fabio Estevam Signed-off-by: Shawn Guo --- .../boot/dts/freescale/imx8mq-phanbell.dts | 63 +++++++++++++++++++ arch/arm64/boot/dts/freescale/imx8mq.dtsi | 2 +- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts b/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts index 16ed13c44a47..1a04d01acc18 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts @@ -35,6 +35,16 @@ gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>; enable-active-high; }; + + fan: gpio-fan { + compatible = "gpio-fan"; + gpio-fan,speed-map = <0 0 8600 1>; + gpios = <&gpio3 5 GPIO_ACTIVE_HIGH>; + #cooling-cells = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_fan>; + status = "okay"; + }; }; &A53_0 { @@ -53,6 +63,53 @@ cpu-supply = <&buck2>; }; +&cpu_thermal { + trips { + cpu_alert0: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_alert1: trip1 { + temperature = <80000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit0: trip3 { + temperature = <90000>; + hysteresis = <2000>; + type = "critical"; + }; + + fan_toggle0: trip4 { + temperature = <65000>; + hysteresis = <10000>; + type = "active"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_alert0>; + cooling-device = + <&A53_0 0 1>; /* Exclude highest OPP */ + }; + + map1 { + trip = <&cpu_alert1>; + cooling-device = + <&A53_0 0 2>; /* Exclude two highest OPPs */ + }; + + map4 { + trip = <&fan_toggle0>; + cooling-device = <&fan 0 1>; + }; + }; +}; + &i2c1 { clock-frequency = <400000>; pinctrl-names = "default"; @@ -295,6 +352,12 @@ >; }; + pinctrl_gpio_fan: gpiofangrp { + fsl,pins = < + MX8MQ_IOMUXC_NAND_CLE_GPIO3_IO5 0x16 + >; + }; + pinctrl_i2c1: i2c1grp { fsl,pins = < MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL 0x4000007f diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi index 985a1a68b6d1..9bbdaf2d6e34 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi @@ -198,7 +198,7 @@ }; thermal-zones { - cpu-thermal { + cpu_thermal: cpu-thermal { polling-delay-passive = <250>; polling-delay = <2000>; thermal-sensors = <&tmu 0>; From 8755963aec62ccb92e075f1419c5b6f41329f866 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Tue, 3 Mar 2020 12:08:31 +0530 Subject: [PATCH 1486/4444] arm64: dts: lx2160ardb: Update FSPI node properties Update fspi node compatibles of LX2160A-RDB to "jedec,spi-nor" for automatic detection of flash. This also helps in fixing below warning: spi-nor spi0.0: found mt35xu512aba, expected m25p80 spi-nor spi0.1: found mt35xu512aba, expected m25p80 Signed-off-by: Kuldeep Singh Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-lx2160a-rdb.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-lx2160a-rdb.dts index 51615de102fe..22d0308eb13b 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-rdb.dts +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-rdb.dts @@ -84,7 +84,7 @@ mt35xu512aba0: flash@0 { #address-cells = <1>; #size-cells = <1>; - compatible = "spansion,m25p80"; + compatible = "jedec,spi-nor"; m25p,fast-read; spi-max-frequency = <50000000>; reg = <0>; @@ -95,7 +95,7 @@ mt35xu512aba1: flash@1 { #address-cells = <1>; #size-cells = <1>; - compatible = "spansion,m25p80"; + compatible = "jedec,spi-nor"; m25p,fast-read; spi-max-frequency = <50000000>; reg = <1>; From 035af82a5fe15ae92b273b8014dbd02518e4a4fc Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Tue, 3 Mar 2020 12:08:32 +0530 Subject: [PATCH 1487/4444] arm64: dts: lx2160aqds: Add FSPI node properties lx2160a-qds has 2 micron "mt35xu512aba" flashes of size 64M each connected on A0 and B1 i.e on CS0 and CS3. Since flashes are connected on different buses, only one flash can be probed at a time. Add fspi node properties aligned with LX2160A-RDB fspi properties. Signed-off-by: Kuldeep Singh Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/fsl-lx2160a-qds.dts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-lx2160a-qds.dts index 1a5acf62f23c..3b88e1efe4db 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-qds.dts +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-qds.dts @@ -43,6 +43,21 @@ status = "okay"; }; +&fspi { + status = "okay"; + + mt35xu512aba0: flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + m25p,fast-read; + spi-max-frequency = <50000000>; + reg = <0>; + spi-rx-bus-width = <8>; + spi-tx-bus-width = <8>; + }; +}; + &i2c0 { status = "okay"; From 6cef60ff174f411f5678ee83fd15494e82169045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Thu, 5 Mar 2020 15:59:08 +0200 Subject: [PATCH 1488/4444] ARM: dts: imx: align name for crypto node and child nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit crypto node should use the "crypto" generic naming, and not a specific one ("sahara", "dcp", "caam"). Child nodes of the crypto node for caam crypto engine should use the "jr" name (without an index), as indicated in the DT binding. Signed-off-by: Horia Geantă Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx23.dtsi | 2 +- arch/arm/boot/dts/imx27.dtsi | 2 +- arch/arm/boot/dts/imx28.dtsi | 2 +- arch/arm/boot/dts/imx6qdl.dtsi | 6 +++--- arch/arm/boot/dts/imx6sl.dtsi | 2 +- arch/arm/boot/dts/imx6sll.dtsi | 2 +- arch/arm/boot/dts/imx6sx.dtsi | 6 +++--- arch/arm/boot/dts/imx6ul.dtsi | 8 ++++---- arch/arm/boot/dts/imx7s.dtsi | 8 ++++---- arch/arm/boot/dts/imx7ulp.dtsi | 4 ++-- 10 files changed, 21 insertions(+), 21 deletions(-) diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi index 8257630f7a49..eb0aeda1682c 100644 --- a/arch/arm/boot/dts/imx23.dtsi +++ b/arch/arm/boot/dts/imx23.dtsi @@ -422,7 +422,7 @@ clocks = <&clks 16>; }; - dcp@80028000 { + dcp: crypto@80028000 { compatible = "fsl,imx23-dcp"; reg = <0x80028000 0x2000>; interrupts = <53 54>; diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi index f3464cf52e49..002cd223f22d 100644 --- a/arch/arm/boot/dts/imx27.dtsi +++ b/arch/arm/boot/dts/imx27.dtsi @@ -525,7 +525,7 @@ reg = <0x10024600 0x200>; }; - sahara2: sahara@10025000 { + sahara2: crypto@10025000 { compatible = "fsl,imx27-sahara"; reg = <0x10025000 0x1000>; interrupts = <59>; diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi index e14d8ef0158b..a1cbbeb39a4f 100644 --- a/arch/arm/boot/dts/imx28.dtsi +++ b/arch/arm/boot/dts/imx28.dtsi @@ -998,7 +998,7 @@ clocks = <&clks 26>; }; - dcp: dcp@80028000 { + dcp: crypto@80028000 { compatible = "fsl,imx28-dcp", "fsl,imx23-dcp"; reg = <0x80028000 0x2000>; interrupts = <52 53 54>; diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index 8baad7481744..33efe7ec7006 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -942,7 +942,7 @@ reg = <0x02100000 0x100000>; ranges; - crypto: caam@2100000 { + crypto: crypto@2100000 { compatible = "fsl,sec-v4.0"; #address-cells = <1>; #size-cells = <1>; @@ -954,13 +954,13 @@ <&clks IMX6QDL_CLK_EIM_SLOW>; clock-names = "mem", "aclk", "ipg", "emi_slow"; - sec_jr0: jr0@1000 { + sec_jr0: jr@1000 { compatible = "fsl,sec-v4.0-job-ring"; reg = <0x1000 0x1000>; interrupts = ; }; - sec_jr1: jr1@2000 { + sec_jr1: jr@2000 { compatible = "fsl,sec-v4.0-job-ring"; reg = <0x2000 0x1000>; interrupts = ; diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi index 0359902fd421..c6141ed87e4d 100644 --- a/arch/arm/boot/dts/imx6sl.dtsi +++ b/arch/arm/boot/dts/imx6sl.dtsi @@ -777,7 +777,7 @@ power-domains = <&pd_disp>; }; - dcp: dcp@20fc000 { + dcp: crypto@20fc000 { compatible = "fsl,imx6sl-dcp", "fsl,imx28-dcp"; reg = <0x020fc000 0x4000>; interrupts = <0 99 IRQ_TYPE_LEVEL_HIGH>, diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/imx6sll.dtsi index 797f850492fe..e8e0fb334cfb 100644 --- a/arch/arm/boot/dts/imx6sll.dtsi +++ b/arch/arm/boot/dts/imx6sll.dtsi @@ -652,7 +652,7 @@ status = "disabled"; }; - dcp: dcp@20fc000 { + dcp: crypto@20fc000 { compatible = "fsl,imx28-dcp"; reg = <0x020fc000 0x4000>; interrupts = , diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index 43e36e1854f3..c48ef39db3fe 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -837,7 +837,7 @@ reg = <0x02100000 0x100000>; ranges; - crypto: caam@2100000 { + crypto: crypto@2100000 { compatible = "fsl,sec-v4.0"; #address-cells = <1>; #size-cells = <1>; @@ -850,13 +850,13 @@ <&clks IMX6SX_CLK_EIM_SLOW>; clock-names = "mem", "aclk", "ipg", "emi_slow"; - sec_jr0: jr0@1000 { + sec_jr0: jr@1000 { compatible = "fsl,sec-v4.0-job-ring"; reg = <0x1000 0x1000>; interrupts = ; }; - sec_jr1: jr1@2000 { + sec_jr1: jr@2000 { compatible = "fsl,sec-v4.0-job-ring"; reg = <0x2000 0x1000>; interrupts = ; diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi index c53898b2c76d..2ccf67c4ac1a 100644 --- a/arch/arm/boot/dts/imx6ul.dtsi +++ b/arch/arm/boot/dts/imx6ul.dtsi @@ -778,7 +778,7 @@ reg = <0x02100000 0x100000>; ranges; - crypto: caam@2140000 { + crypto: crypto@2140000 { compatible = "fsl,imx6ul-caam", "fsl,sec-v4.0"; #address-cells = <1>; #size-cells = <1>; @@ -789,19 +789,19 @@ <&clks IMX6UL_CLK_CAAM_MEM>; clock-names = "ipg", "aclk", "mem"; - sec_jr0: jr0@1000 { + sec_jr0: jr@1000 { compatible = "fsl,sec-v4.0-job-ring"; reg = <0x1000 0x1000>; interrupts = ; }; - sec_jr1: jr1@2000 { + sec_jr1: jr@2000 { compatible = "fsl,sec-v4.0-job-ring"; reg = <0x2000 0x1000>; interrupts = ; }; - sec_jr2: jr2@3000 { + sec_jr2: jr@3000 { compatible = "fsl,sec-v4.0-job-ring"; reg = <0x3000 0x1000>; interrupts = ; diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index 05da9999817b..76e3ffbbbfbf 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -934,7 +934,7 @@ }; }; - crypto: caam@30900000 { + crypto: crypto@30900000 { compatible = "fsl,sec-v4.0"; #address-cells = <1>; #size-cells = <1>; @@ -945,19 +945,19 @@ <&clks IMX7D_AHB_CHANNEL_ROOT_CLK>; clock-names = "ipg", "aclk"; - sec_jr0: jr0@1000 { + sec_jr0: jr@1000 { compatible = "fsl,sec-v4.0-job-ring"; reg = <0x1000 0x1000>; interrupts = ; }; - sec_jr1: jr1@2000 { + sec_jr1: jr@2000 { compatible = "fsl,sec-v4.0-job-ring"; reg = <0x2000 0x1000>; interrupts = ; }; - sec_jr2: jr1@3000 { + sec_jr2: jr@3000 { compatible = "fsl,sec-v4.0-job-ring"; reg = <0x3000 0x1000>; interrupts = ; diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi index ab91c98f2124..f7c4878534c8 100644 --- a/arch/arm/boot/dts/imx7ulp.dtsi +++ b/arch/arm/boot/dts/imx7ulp.dtsi @@ -132,13 +132,13 @@ <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>; clock-names = "aclk", "ipg"; - sec_jr0: jr0@1000 { + sec_jr0: jr@1000 { compatible = "fsl,sec-v4.0-job-ring"; reg = <0x1000 0x1000>; interrupts = ; }; - sec_jr1: jr1@2000 { + sec_jr1: jr@2000 { compatible = "fsl,sec-v4.0-job-ring"; reg = <0x2000 0x1000>; interrupts = ; From c2902fb04ed616e5215184e839159236dd1ba343 Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Thu, 5 Mar 2020 22:26:24 +0100 Subject: [PATCH 1489/4444] ARM: dts: imx25-pinfunc: add config for kpp rows 4 to 7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i.MX25's Keypad Port (KPP) can be used with a key pad matrix of up to 8 x 8 keys. Add pin configurations for rows 4 to 7. The new defines have been tested on an out-of-tree board. Signed-off-by: Martin Kaiser Reviewed-by: Uwe Kleine-König Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx25-pinfunc.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/imx25-pinfunc.h b/arch/arm/boot/dts/imx25-pinfunc.h index b5a12412440e..111bfdcbe552 100644 --- a/arch/arm/boot/dts/imx25-pinfunc.h +++ b/arch/arm/boot/dts/imx25-pinfunc.h @@ -255,10 +255,12 @@ #define MX25_PAD_LD12__LD12 0x0f8 0x2f0 0x000 0x00 0x000 #define MX25_PAD_LD12__CSPI2_MOSI 0x0f8 0x2f0 0x4a0 0x02 0x000 +#define MX25_PAD_LD12__KPP_ROW6 0x0f8 0x2f0 0x544 0x04 0x000 #define MX25_PAD_LD12__FEC_RDATA3 0x0f8 0x2f0 0x510 0x05 0x001 #define MX25_PAD_LD13__LD13 0x0fc 0x2f4 0x000 0x00 0x000 #define MX25_PAD_LD13__CSPI2_MISO 0x0fc 0x2f4 0x49c 0x02 0x000 +#define MX25_PAD_LD13__KPP_ROW7 0x0fc 0x2f4 0x548 0x04 0x000 #define MX25_PAD_LD13__FEC_TDATA2 0x0fc 0x2f4 0x000 0x05 0x000 #define MX25_PAD_LD14__LD14 0x100 0x2f8 0x000 0x00 0x000 @@ -516,9 +518,11 @@ #define MX25_PAD_FEC_TX_EN__FEC_TX_EN 0x1d8 0x3d0 0x000 0x00 0x000 #define MX25_PAD_FEC_TX_EN__GPIO_3_9 0x1d8 0x3d0 0x000 0x05 0x000 +#define MX25_PAD_FEC_TX_EN__KPP_ROW4 0x1d8 0x3d0 0x53c 0x06 0x000 #define MX25_PAD_FEC_RDATA0__FEC_RDATA0 0x1dc 0x3d4 0x000 0x00 0x000 #define MX25_PAD_FEC_RDATA0__GPIO_3_10 0x1dc 0x3d4 0x000 0x05 0x000 +#define MX25_PAD_FEC_RDATA0__KPP_ROW5 0x1dc 0x3d4 0x540 0x06 0x000 #define MX25_PAD_FEC_RDATA1__FEC_RDATA1 0x1e0 0x3d8 0x000 0x00 0x000 /* From 91da379fa5b42211660ef20b29e8b843784755b5 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Mon, 9 Mar 2020 13:51:45 +0100 Subject: [PATCH 1490/4444] arm64: dts: rockchip: remove max-freq from &spi1 node for Hugsun X99 A test with the command below does not detect all errors in combination with 'additionalProperties: false' and allOf: - $ref: "spi-controller.yaml#" 'additionalProperties' applies to all properties that are not accounted-for by 'properties' or 'patternProperties' in the immediate schema. First when we combine spi-rockchip.yaml and spi-controller.yaml it gives this error: arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dt.yaml: spi@ff1d0000: 'max-freq' does not match any of the regexes: '^.*@[0-9a-f]+$', '^slave$' 'max-freq' is not a valid property name for spi nodes, so remove it. make ARCH=arm64 dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/spi/spi-rockchip.yaml Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200309125145.14455-1-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts b/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts index d69a613fb65a..628796f3aa64 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts @@ -610,7 +610,6 @@ &spi1 { status = "okay"; - max-freq = <10000000>; flash@0 { compatible = "jedec,spi-nor"; From 541d99d977ac6d056f67c20ee08dcac89d0deb8a Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Mon, 9 Mar 2020 09:16:00 +0100 Subject: [PATCH 1491/4444] arm64: dts: rockchip: remove rockchip,grf from vop nodes for px30 An experimental test with the command below without additional properties in 'rockchip-vop.yaml' gives this error: arch/arm64/boot/dts/rockchip/px30-evb.dt.yaml: vop@ff470000: 'power-domains', 'rockchip,grf' do not match any of the regexes: 'pinctrl-[0-9]+' arch/arm64/boot/dts/rockchip/px30-evb.dt.yaml: vop@ff460000: 'power-domains', 'rockchip,grf' do not match any of the regexes: 'pinctrl-[0-9]+' 'rockchip,grf' is not used by the Rockchip VOP driver, so remove it from 'vop' nodes in 'px30.dtsi'. make ARCH=arm64 dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/display/ rockchip/rockchip-vop.yaml Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200309081600.3887-1-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/px30.dtsi | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 495212c288cf..6aed865fb7b3 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -1033,7 +1033,6 @@ reset-names = "axi", "ahb", "dclk"; iommus = <&vopb_mmu>; power-domains = <&power PX30_PD_VO>; - rockchip,grf = <&grf>; status = "disabled"; vopb_out: port { @@ -1075,7 +1074,6 @@ reset-names = "axi", "ahb", "dclk"; iommus = <&vopl_mmu>; power-domains = <&power PX30_PD_VO>; - rockchip,grf = <&grf>; status = "disabled"; vopl_out: port { From ba58672a2d1db3299ef7303b64e18f63d90e2564 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Sat, 7 Mar 2020 14:48:39 +0100 Subject: [PATCH 1492/4444] arm64: dts: remove no-emmc from mmc node for Rockchip PX5 EVB A test with the command below does not detect all errors in combination with 'additionalProperties: false' and allOf: - $ref: "synopsys-dw-mshc-common.yaml#" allOf: - $ref: "mmc-controller.yaml#" 'additionalProperties' applies to all properties that are not accounted-for by 'properties' or 'patternProperties' in the immediate schema. First when we combine rockchip-dw-mshc.yaml, synopsys-dw-mshc-common.yaml and mmc-controller.yaml it gives this error: arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dt.yaml: mmc@ff0c0000: 'no-emmc' does not match any of the regexes: '^.*@[0-9]+$', '^clk-phase-(legacy|sd-hs|mmc-(hs|hs[24]00|ddr52)| uhs-(sdr(12|25|50|104)|ddr50))$', 'pinctrl-[0-9]+' 'no-emmc' is not a valid property name for mmc nodes, so remove it. make ARCH=arm64 dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200307134841.13803-3-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts b/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts index 231db0305a03..5ffd7b4d3036 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts +++ b/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts @@ -239,7 +239,6 @@ cap-mmc-highspeed; cap-sd-highspeed; card-detect-delay = <200>; - no-emmc; no-sdio; sd-uhs-sdr12; sd-uhs-sdr25; From bfb70fa503e46dfb70ab795e6669010a1df8885b Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Sat, 7 Mar 2020 14:48:40 +0100 Subject: [PATCH 1493/4444] arm64: dts: rockchip: fix vqmmc-supply property name for rk3399 puma A test with the command below does not detect all errors in combination with 'additionalProperties: false' and allOf: - $ref: "synopsys-dw-mshc-common.yaml#" allOf: - $ref: "mmc-controller.yaml#" 'additionalProperties' applies to all properties that are not accounted-for by 'properties' or 'patternProperties' in the immediate schema. First when we combine rockchip-dw-mshc.yaml, synopsys-dw-mshc-common.yaml and mmc-controller.yaml it gives this error: arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dt.yaml: mmc@fe320000: 'vqmmc' does not match any of the regexes: '^.*@[0-9]+$', '^clk-phase-(legacy|sd-hs|mmc-(hs|hs[24]00|ddr52)| uhs-(sdr(12|25|50|104)|ddr50))$', 'pinctrl-[0-9]+' 'vqmmc' is not a valid property name for mmc nodes. Fix this error by renaming it to 'vqmmc-supply'. make ARCH=arm64 dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200307134841.13803-4-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi index c1edca3872c7..07694b196fdb 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi @@ -480,7 +480,7 @@ }; &sdmmc { - vqmmc = <&vcc_sd>; + vqmmc-supply = <&vcc_sd>; }; &spi1 { From b6e62d37c01601c3653a86156ad7ada5fb4bc963 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Sat, 7 Mar 2020 14:48:41 +0100 Subject: [PATCH 1494/4444] arm64: dts: rockchip: replace clock-freq-min-max by max-frequency A test with the command below does not detect all errors in combination with 'additionalProperties: false' and allOf: - $ref: "synopsys-dw-mshc-common.yaml#" allOf: - $ref: "mmc-controller.yaml#" 'additionalProperties' applies to all properties that are not accounted-for by 'properties' or 'patternProperties' in the immediate schema. First when we combine rockchip-dw-mshc.yaml, synopsys-dw-mshc-common.yaml and mmc-controller.yaml it gives for example this error: arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dt.yaml: mmc@fe320000: 'clock-freq-min-max' does not match any of the regexes: '^.*@[0-9]+$', '^clk-phase-(legacy|sd-hs|mmc-(hs|hs[24]00|ddr52)| uhs-(sdr(12|25|50|104)|ddr50))$', 'pinctrl-[0-9]+' 'clock-freq-min-max' is deprecated, so replace it by 'max-frequency'. make ARCH=arm64 dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200307134841.13803-5-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts | 2 +- arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts b/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts index 628796f3aa64..ee4867fbefe8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts @@ -555,7 +555,7 @@ &sdmmc { clock-frequency = <150000000>; - clock-freq-min-max = <200000 150000000>; + max-frequency = <150000000>; bus-width = <4>; cap-mmc-highspeed; cap-sd-highspeed; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi index b69f0f2cbd67..ba7c75c9f2a1 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi @@ -542,7 +542,7 @@ cap-mmc-highspeed; cap-sd-highspeed; clock-frequency = <100000000>; - clock-freq-min-max = <100000 100000000>; + max-frequency = <100000000>; cd-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; disable-wp; sd-uhs-sdr104; From 9cd568dc588c5d168615bf34f325fabe33b2c9a0 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Sat, 7 Mar 2020 14:48:37 +0100 Subject: [PATCH 1495/4444] ARM: dts: rockchip: fix vqmmc-supply property name for rk3188-bqedison2qc A test with the command below does not detect all errors in combination with 'additionalProperties: false' and allOf: - $ref: "synopsys-dw-mshc-common.yaml#" allOf: - $ref: "mmc-controller.yaml#" 'additionalProperties' applies to all properties that are not accounted-for by 'properties' or 'patternProperties' in the immediate schema. First when we combine rockchip-dw-mshc.yaml, synopsys-dw-mshc-common.yaml and mmc-controller.yaml it gives this error: arch/arm/boot/dts/rk3188-bqedison2qc.dt.yaml: mmc@10218000: 'vmmcq-supply' does not match any of the regexes: '^.*@[0-9]+$', '^clk-phase-(legacy|sd-hs|mmc-(hs|hs[24]00|ddr52)| uhs-(sdr(12|25|50|104)|ddr50))$', 'pinctrl-[0-9]+' 'vmmcq-supply' is not a valid property name for mmc nodes. Fix this error by renaming it to 'vqmmc-supply'. make ARCH=arm dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200307134841.13803-1-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3188-bqedison2qc.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk3188-bqedison2qc.dts b/arch/arm/boot/dts/rk3188-bqedison2qc.dts index ad1afd403052..8afb2fd5d9f1 100644 --- a/arch/arm/boot/dts/rk3188-bqedison2qc.dts +++ b/arch/arm/boot/dts/rk3188-bqedison2qc.dts @@ -465,7 +465,7 @@ non-removable; pinctrl-names = "default"; pinctrl-0 = <&sd1_clk>, <&sd1_cmd>, <&sd1_bus4>; - vmmcq-supply = <&vccio_wl>; + vqmmc-supply = <&vccio_wl>; #address-cells = <1>; #size-cells = <0>; status = "okay"; From 8a385eb57296e87d23fb12a2308e6b2fd1029713 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Sat, 7 Mar 2020 14:48:38 +0100 Subject: [PATCH 1496/4444] ARM: dts: rockchip: fix rockchip,default-sample-phase property names A test with the command below does not detect all errors in combination with 'additionalProperties: false' and allOf: - $ref: "synopsys-dw-mshc-common.yaml#" allOf: - $ref: "mmc-controller.yaml#" 'additionalProperties' applies to all properties that are not accounted-for by 'properties' or 'patternProperties' in the immediate schema. First when we combine rockchip-dw-mshc.yaml, synopsys-dw-mshc-common.yaml and mmc-controller.yaml it gives for example this error: arch/arm/boot/dts/rk3036-evb.dt.yaml: mmc@1021c000: 'default-sample-phase' does not match any of the regexes: '^.*@[0-9]+$', '^clk-phase-(legacy|sd-hs|mmc-(hs|hs[24]00|ddr52)| uhs-(sdr(12|25|50|104)|ddr50))$', 'pinctrl-[0-9]+' 'default-sample-phase' is not a valid property name for mmc nodes. Fix this error by renaming it to 'rockchip,default-sample-phase'. make ARCH=arm dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200307134841.13803-2-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3036-kylin.dts | 2 +- arch/arm/boot/dts/rk3036.dtsi | 2 +- arch/arm/boot/dts/rk322x.dtsi | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/rk3036-kylin.dts b/arch/arm/boot/dts/rk3036-kylin.dts index fb3cf005cc90..2ff9f152d29b 100644 --- a/arch/arm/boot/dts/rk3036-kylin.dts +++ b/arch/arm/boot/dts/rk3036-kylin.dts @@ -319,7 +319,7 @@ bus-width = <4>; cap-sd-highspeed; cap-sdio-irq; - default-sample-phase = <90>; + rockchip,default-sample-phase = <90>; keep-power-in-suspend; mmc-pwrseq = <&sdio_pwrseq>; non-removable; diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index b621385631a3..bc53f0ca0f25 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -263,7 +263,7 @@ clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>, <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>; clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; - default-sample-phase = <158>; + rockchip,default-sample-phase = <158>; disable-wp; dmas = <&pdma 12>; dma-names = "rx-tx"; diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index dac930be3fe0..166f56e639a2 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -698,7 +698,7 @@ <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>; clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; bus-width = <8>; - default-sample-phase = <158>; + rockchip,default-sample-phase = <158>; fifo-depth = <0x100>; pinctrl-names = "default"; pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; From 79f23601fcbbdd4ea00bb0165efbd52e47a69e16 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Mon, 9 Mar 2020 14:40:20 +0100 Subject: [PATCH 1497/4444] ARM: dts: rockchip: remove #dma-cells from dma client nodes for rv1108 When we combine spi-rockchip.yaml and spi-controller.yaml and add 'additionalProperties: false' it gives for example this error: arch/arm/boot/dts/rv1108-evb.dt.yaml: spi@10270000: '#dma-cells' does not match any of the regexes: '^.*@[0-9a-f]+$', '^slave$' '#dma-cells' are not used for dma clients, so remove them all. make ARCH=arm dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/spi/spi-rockchip.yaml Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200309134020.14935-1-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rv1108.dtsi | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm/boot/dts/rv1108.dtsi b/arch/arm/boot/dts/rv1108.dtsi index c3621b3e6556..8f8607ed721e 100644 --- a/arch/arm/boot/dts/rv1108.dtsi +++ b/arch/arm/boot/dts/rv1108.dtsi @@ -120,7 +120,6 @@ clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>; clock-names = "baudclk", "apb_pclk"; dmas = <&pdma 6>, <&pdma 7>; - #dma-cells = <2>; pinctrl-names = "default"; pinctrl-0 = <&uart2m0_xfer>; status = "disabled"; @@ -136,7 +135,6 @@ clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>; clock-names = "baudclk", "apb_pclk"; dmas = <&pdma 4>, <&pdma 5>; - #dma-cells = <2>; pinctrl-names = "default"; pinctrl-0 = <&uart1_xfer>; status = "disabled"; @@ -152,7 +150,6 @@ clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>; clock-names = "baudclk", "apb_pclk"; dmas = <&pdma 2>, <&pdma 3>; - #dma-cells = <2>; pinctrl-names = "default"; pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>; status = "disabled"; @@ -208,7 +205,6 @@ clock-names = "spiclk", "apb_pclk"; dmas = <&pdma 8>, <&pdma 9>; dma-names = "tx", "rx"; - #dma-cells = <2>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; From 67af8818ee88021f45656a690e3b3e4aba236999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Thu, 5 Mar 2020 15:59:05 +0200 Subject: [PATCH 1498/4444] dt-bindings: crypto: sahara: use generic node name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit crypto node should use the "crypto" generic naming, and not a specific one. Signed-off-by: Horia Geantă Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/crypto/fsl-imx-sahara.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/crypto/fsl-imx-sahara.txt b/Documentation/devicetree/bindings/crypto/fsl-imx-sahara.txt index e8a35c71e947..db690b10e582 100644 --- a/Documentation/devicetree/bindings/crypto/fsl-imx-sahara.txt +++ b/Documentation/devicetree/bindings/crypto/fsl-imx-sahara.txt @@ -8,7 +8,7 @@ Required properties: Example: -sah@10025000 { +sah: crypto@10025000 { compatible = "fsl,imx27-sahara"; reg = < 0x10025000 0x800>; interrupts = <75>; From 93003cc46d07d57bcb48e0d8830e4ee7dcbbe1bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Thu, 5 Mar 2020 15:59:06 +0200 Subject: [PATCH 1499/4444] dt-bindings: crypto: dcp: use generic node name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit crypto node should use the "crypto" generic naming, and not the "dcp" specific one. Signed-off-by: Horia Geantă Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/crypto/fsl-dcp.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/crypto/fsl-dcp.txt b/Documentation/devicetree/bindings/crypto/fsl-dcp.txt index 4e4d387e38a5..513499fcdb5b 100644 --- a/Documentation/devicetree/bindings/crypto/fsl-dcp.txt +++ b/Documentation/devicetree/bindings/crypto/fsl-dcp.txt @@ -11,7 +11,7 @@ Required properties: Example: -dcp@80028000 { +dcp: crypto@80028000 { compatible = "fsl,imx28-dcp", "fsl,imx23-dcp"; reg = <0x80028000 0x2000>; interrupts = <52 53>; From 5a02504f0ac98fee09e3442405eb574f0222ceec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Thu, 5 Mar 2020 15:59:07 +0200 Subject: [PATCH 1500/4444] dt-bindings: crypto: caam: use generic node name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i.MX6UL example uses a specific node name for the crypto node. Let's fix it so we avoid this propagating further. Signed-off-by: Horia Geantă Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/crypto/fsl-sec4.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt index 2fe245ca816a..8f359f473ada 100644 --- a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt +++ b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt @@ -138,7 +138,7 @@ iMX6QDL/SX requires four clocks iMX6UL does only require three clocks - crypto: caam@2140000 { + crypto: crypto@2140000 { compatible = "fsl,sec-v4.0"; #address-cells = <1>; #size-cells = <1>; From f5ff5a213b4d82e7be801071f6c570bb54cc251b Mon Sep 17 00:00:00 2001 From: Silvano di Ninno Date: Thu, 5 Mar 2020 15:59:09 +0200 Subject: [PATCH 1501/4444] arm64: dts: imx8mn: align name for crypto child nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit crypto child nodes should use the "jr" name (without an index), as indicated in the DT binding. Signed-off-by: Silvano di Ninno Signed-off-by: Horia Geantă Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mn.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi index f2775724377f..ff9c1ea38130 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi @@ -554,19 +554,19 @@ <&clk IMX8MN_CLK_IPG_ROOT>; clock-names = "aclk", "ipg"; - sec_jr0: jr0@1000 { + sec_jr0: jr@1000 { compatible = "fsl,sec-v4.0-job-ring"; reg = <0x1000 0x1000>; interrupts = ; }; - sec_jr1: jr1@2000 { + sec_jr1: jr@2000 { compatible = "fsl,sec-v4.0-job-ring"; reg = <0x2000 0x1000>; interrupts = ; }; - sec_jr2: jr2@3000 { + sec_jr2: jr@3000 { compatible = "fsl,sec-v4.0-job-ring"; reg = <0x3000 0x1000>; interrupts = ; From f0692bb890c177a5cec713f5dbcf1ea2cb19649c Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Fri, 6 Mar 2020 04:19:57 -0600 Subject: [PATCH 1502/4444] arm64: dts: enable fspi in imx8mm dts Pull in downstream patch from NXP repository to enable fspi device. Signed-off-by: Han Xu Signed-off-by: Adam Ford Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mm.dtsi | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi index 970a86c724ba..2e5e7c4457db 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi @@ -560,7 +560,8 @@ compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; - ranges = <0x30800000 0x30800000 0x400000>; + ranges = <0x30800000 0x30800000 0x400000>, + <0x8000000 0x8000000 0x10000000>; ecspi1: spi@30820000 { compatible = "fsl,imx8mm-ecspi", "fsl,imx51-ecspi"; @@ -762,6 +763,19 @@ status = "disabled"; }; + flexspi: spi@30bb0000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nxp,imx8mm-fspi"; + reg = <0x30bb0000 0x10000>, <0x8000000 0x10000000>; + reg-names = "fspi_base", "fspi_mmap"; + interrupts = ; + clocks = <&clk IMX8MM_CLK_QSPI_ROOT>, + <&clk IMX8MM_CLK_QSPI_ROOT>; + clock-names = "fspi", "fspi_en"; + status = "disabled"; + }; + sdma1: dma-controller@30bd0000 { compatible = "fsl,imx8mm-sdma", "fsl,imx8mq-sdma"; reg = <0x30bd0000 0x10000>; From 1436b5bc25a4e40a2b003e07a15884988ada4421 Mon Sep 17 00:00:00 2001 From: Alifer Moraes Date: Fri, 6 Mar 2020 07:42:19 -0300 Subject: [PATCH 1503/4444] arm64: dts: imx8mq-phanbell: Fix Ethernet PHY post-reset duration i.MX8MQ Phanbell board uses Realtek RTL8211FD as Ethernet PHY. Its datasheet states that the proper post reset duration should be at least 50 ms. Fixes: f34d4bfab354 ("arm64: dts: imx8mq-phanbell: Add support for ethernet") Signed-off-by: Alifer Moraes Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts b/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts index 1a04d01acc18..77ab568fae67 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts @@ -264,7 +264,7 @@ phy-mode = "rgmii-id"; phy-reset-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; phy-reset-duration = <10>; - phy-reset-post-delay = <30>; + phy-reset-post-delay = <50>; phy-handle = <ðphy0>; fsl,magic-packet; status = "okay"; From e937cc1dd7966df33a478943817302502a164e25 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 6 Mar 2020 16:28:37 +0200 Subject: [PATCH 1504/4444] dmaengine: Add basic debugfs support Via the /sys/kernel/debug/dmaengine/summary users can get information about the DMA devices and the used channels. Example output on am654-evm with audio using two channels and after running dmatest on 4 channels: dma0 (285c0000.dma-controller): number of channels: 96 dma1 (31150000.dma-controller): number of channels: 267 dma1chan0 | 2b00000.mcasp:tx dma1chan1 | 2b00000.mcasp:rx dma1chan2 | in-use dma1chan3 | in-use dma1chan4 | in-use dma1chan5 | in-use For slave channels we can show the device and the channel name a given channel is requested. For non slave devices the only information we know is that the channel is in use. DMA drivers can implement the optional dbg_summary_show callback to provide controller specific information instead of the generic one. It is easy to extend the generic dmaengine_summary_show() to print additional information about the used channels. I have taken the idea from gpiolib and clk subsystems. Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20200306142839.17910-2-peter.ujfalusi@ti.com Signed-off-by: Vinod Koul --- drivers/dma/dmaengine.c | 76 ++++++++++++++++++++++++++++++++++++++- include/linux/dmaengine.h | 13 ++++++- 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index c3b1283b6d31..509abc8e8378 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -58,6 +58,65 @@ static DEFINE_IDA(dma_ida); static LIST_HEAD(dma_device_list); static long dmaengine_ref_count; +/* --- debugfs implementation --- */ +#ifdef CONFIG_DEBUG_FS +#include + +static void dmaengine_dbg_summary_show(struct seq_file *s, + struct dma_device *dma_dev) +{ + struct dma_chan *chan; + + list_for_each_entry(chan, &dma_dev->channels, device_node) { + if (chan->client_count) { + seq_printf(s, " %-13s| %s", dma_chan_name(chan), + chan->dbg_client_name ?: "in-use"); + + if (chan->router) + seq_printf(s, " (via router: %s)\n", + dev_name(chan->router->dev)); + else + seq_puts(s, "\n"); + } + } +} + +static int dmaengine_summary_show(struct seq_file *s, void *data) +{ + struct dma_device *dma_dev = NULL; + + mutex_lock(&dma_list_mutex); + list_for_each_entry(dma_dev, &dma_device_list, global_node) { + seq_printf(s, "dma%d (%s): number of channels: %u\n", + dma_dev->dev_id, dev_name(dma_dev->dev), + dma_dev->chancnt); + + if (dma_dev->dbg_summary_show) + dma_dev->dbg_summary_show(s, dma_dev); + else + dmaengine_dbg_summary_show(s, dma_dev); + + if (!list_is_last(&dma_dev->global_node, &dma_device_list)) + seq_puts(s, "\n"); + } + mutex_unlock(&dma_list_mutex); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(dmaengine_summary); + +static void __init dmaengine_debugfs_init(void) +{ + struct dentry *rootdir = debugfs_create_dir("dmaengine", NULL); + + /* /sys/kernel/debug/dmaengine/summary */ + debugfs_create_file("summary", 0444, rootdir, NULL, + &dmaengine_summary_fops); +} +#else +static inline void dmaengine_debugfs_init(void) { } +#endif /* DEBUG_FS */ + /* --- sysfs implementation --- */ #define DMA_SLAVE_NAME "slave" @@ -760,6 +819,11 @@ struct dma_chan *dma_request_chan(struct device *dev, const char *name) return chan ? chan : ERR_PTR(-EPROBE_DEFER); found: +#ifdef CONFIG_DEBUG_FS + chan->dbg_client_name = kasprintf(GFP_KERNEL, "%s:%s", dev_name(dev), + name); +#endif + chan->name = kasprintf(GFP_KERNEL, "dma:%s", name); if (!chan->name) return chan; @@ -837,6 +901,11 @@ void dma_release_channel(struct dma_chan *chan) chan->name = NULL; chan->slave = NULL; } + +#ifdef CONFIG_DEBUG_FS + kfree(chan->dbg_client_name); + chan->dbg_client_name = NULL; +#endif mutex_unlock(&dma_list_mutex); } EXPORT_SYMBOL_GPL(dma_release_channel); @@ -1559,6 +1628,11 @@ static int __init dma_bus_init(void) if (err) return err; - return class_register(&dma_devclass); + + err = class_register(&dma_devclass); + if (!err) + dmaengine_debugfs_init(); + + return err; } arch_initcall(dma_bus_init); diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index d3672f065a64..72920b5cf2d7 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -300,6 +300,8 @@ struct dma_router { * @chan_id: channel ID for sysfs * @dev: class device for sysfs * @name: backlink name for sysfs + * @dbg_client_name: slave name for debugfs in format: + * dev_name(requester's dev):channel name, for example: "2b00000.mcasp:tx" * @device_node: used to add this to the device chan list * @local: per-cpu pointer to a struct dma_chan_percpu * @client_count: how many clients are using this channel @@ -318,6 +320,9 @@ struct dma_chan { int chan_id; struct dma_chan_dev *dev; const char *name; +#ifdef CONFIG_DEBUG_FS + char *dbg_client_name; +#endif struct list_head device_node; struct dma_chan_percpu __percpu *local; @@ -806,7 +811,9 @@ struct dma_filter { * called and there are no further references to this structure. This * must be implemented to free resources however many existing drivers * do not and are therefore not safe to unbind while in use. - * + * @dbg_summary_show: optional routine to show contents in debugfs; default code + * will be used when this is omitted, but custom code can show extra, + * controller specific information. */ struct dma_device { struct kref ref; @@ -892,6 +899,10 @@ struct dma_device { struct dma_tx_state *txstate); void (*device_issue_pending)(struct dma_chan *chan); void (*device_release)(struct dma_device *dev); + /* debugfs support */ +#ifdef CONFIG_DEBUG_FS + void (*dbg_summary_show)(struct seq_file *s, struct dma_device *dev); +#endif }; static inline int dmaengine_slave_config(struct dma_chan *chan, From db8d9b4c9b303ede7e5b0d828ec8f7ae0d26d7ef Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 6 Mar 2020 16:28:38 +0200 Subject: [PATCH 1505/4444] dmaengine: ti: k3-udma: Implement custom dbg_summary_show for debugfs With the custom dbg_summary_show the driver can show useful information about the used channels. dma0 (285c0000.dma-controller): number of channels: 24 dma1 (31150000.dma-controller): number of channels: 84 dma1chan0 | 2b00000.mcasp:tx (MEM_TO_DEV, tchan16 [0x1010 -> 0xc400], PDMA[ ACC32 BURST ], TR mode) dma1chan1 | 2b00000.mcasp:rx (DEV_TO_MEM, rchan16 [0x4400 -> 0x9010], PDMA[ ACC32 BURST ], TR mode) dma1chan2 | 2ba0000.mcasp:tx (MEM_TO_DEV, tchan17 [0x1011 -> 0xc507], PDMA[ ACC32 BURST ], TR mode) dma1chan3 | 2ba0000.mcasp:rx (DEV_TO_MEM, rchan17 [0x4507 -> 0x9011], PDMA[ ACC32 BURST ], TR mode) dma1chan4 | in-use (MEM_TO_MEM, chan0 pair [0x1000 -> 0x9000], PSI-L Native, TR mode) dma1chan5 | in-use (MEM_TO_MEM, chan1 pair [0x1001 -> 0x9001], PSI-L Native, TR mode) dma1chan6 | in-use (MEM_TO_MEM, chan4 pair [0x1004 -> 0x9004], PSI-L Native, TR mode) dma1chan7 | in-use (MEM_TO_MEM, chan5 pair [0x1005 -> 0x9005], PSI-L Native, TR mode) Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20200306142839.17910-3-peter.ujfalusi@ti.com Signed-off-by: Vinod Koul --- drivers/dma/ti/k3-udma.c | 63 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index 205141494fc1..1e6aac87302d 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -3276,6 +3276,66 @@ static int udma_setup_resources(struct udma_dev *ud) return ch_count; } +#ifdef CONFIG_DEBUG_FS +static void udma_dbg_summary_show_chan(struct seq_file *s, + struct dma_chan *chan) +{ + struct udma_chan *uc = to_udma_chan(chan); + struct udma_chan_config *ucc = &uc->config; + + seq_printf(s, " %-13s| %s", dma_chan_name(chan), + chan->dbg_client_name ?: "in-use"); + seq_printf(s, " (%s, ", dmaengine_get_direction_text(uc->config.dir)); + + switch (uc->config.dir) { + case DMA_MEM_TO_MEM: + seq_printf(s, "chan%d pair [0x%04x -> 0x%04x], ", uc->tchan->id, + ucc->src_thread, ucc->dst_thread); + break; + case DMA_DEV_TO_MEM: + seq_printf(s, "rchan%d [0x%04x -> 0x%04x], ", uc->rchan->id, + ucc->src_thread, ucc->dst_thread); + break; + case DMA_MEM_TO_DEV: + seq_printf(s, "tchan%d [0x%04x -> 0x%04x], ", uc->tchan->id, + ucc->src_thread, ucc->dst_thread); + break; + default: + seq_printf(s, ")\n"); + return; + } + + if (ucc->ep_type == PSIL_EP_NATIVE) { + seq_printf(s, "PSI-L Native"); + if (ucc->metadata_size) { + seq_printf(s, "[%s", ucc->needs_epib ? " EPIB" : ""); + if (ucc->psd_size) + seq_printf(s, " PSDsize:%u", ucc->psd_size); + seq_printf(s, " ]"); + } + } else { + seq_printf(s, "PDMA"); + if (ucc->enable_acc32 || ucc->enable_burst) + seq_printf(s, "[%s%s ]", + ucc->enable_acc32 ? " ACC32" : "", + ucc->enable_burst ? " BURST" : ""); + } + + seq_printf(s, ", %s)\n", ucc->pkt_mode ? "Packet mode" : "TR mode"); +} + +static void udma_dbg_summary_show(struct seq_file *s, + struct dma_device *dma_dev) +{ + struct dma_chan *chan; + + list_for_each_entry(chan, &dma_dev->channels, device_node) { + if (chan->client_count) + udma_dbg_summary_show_chan(s, chan); + } +} +#endif /* CONFIG_DEBUG_FS */ + #define TI_UDMAC_BUSWIDTHS (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \ BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \ @@ -3362,6 +3422,9 @@ static int udma_probe(struct platform_device *pdev) ud->ddev.device_resume = udma_resume; ud->ddev.device_terminate_all = udma_terminate_all; ud->ddev.device_synchronize = udma_synchronize; +#ifdef CONFIG_DEBUG_FS + ud->ddev.dbg_summary_show = udma_dbg_summary_show; +#endif ud->ddev.device_free_chan_resources = udma_free_chan_resources; ud->ddev.src_addr_widths = TI_UDMAC_BUSWIDTHS; From 26cf132de6f79c06025706ddc61e045d591d404d Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 6 Mar 2020 16:28:39 +0200 Subject: [PATCH 1506/4444] dmaengine: Create debug directories for DMA devices Create a placeholder directory for each registered DMA device. DMA drivers can use the dmaengine_get_debugfs_root() call to get their debugfs root and can populate with custom files to aim debugging. Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20200306142839.17910-4-peter.ujfalusi@ti.com Signed-off-by: Vinod Koul --- drivers/dma/dmaengine.c | 28 +++++++++++++++++++++++++++- drivers/dma/dmaengine.h | 16 ++++++++++++++++ include/linux/dmaengine.h | 1 + 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 509abc8e8378..5a442752e07d 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -62,6 +62,22 @@ static long dmaengine_ref_count; #ifdef CONFIG_DEBUG_FS #include +static struct dentry *rootdir; + +static void dmaengine_debug_register(struct dma_device *dma_dev) +{ + dma_dev->dbg_dev_root = debugfs_create_dir(dev_name(dma_dev->dev), + rootdir); + if (IS_ERR(dma_dev->dbg_dev_root)) + dma_dev->dbg_dev_root = NULL; +} + +static void dmaengine_debug_unregister(struct dma_device *dma_dev) +{ + debugfs_remove_recursive(dma_dev->dbg_dev_root); + dma_dev->dbg_dev_root = NULL; +} + static void dmaengine_dbg_summary_show(struct seq_file *s, struct dma_device *dma_dev) { @@ -107,7 +123,7 @@ DEFINE_SHOW_ATTRIBUTE(dmaengine_summary); static void __init dmaengine_debugfs_init(void) { - struct dentry *rootdir = debugfs_create_dir("dmaengine", NULL); + rootdir = debugfs_create_dir("dmaengine", NULL); /* /sys/kernel/debug/dmaengine/summary */ debugfs_create_file("summary", 0444, rootdir, NULL, @@ -115,6 +131,12 @@ static void __init dmaengine_debugfs_init(void) } #else static inline void dmaengine_debugfs_init(void) { } +static inline int dmaengine_debug_register(struct dma_device *dma_dev) +{ + return 0; +} + +static inline void dmaengine_debug_unregister(struct dma_device *dma_dev) { } #endif /* DEBUG_FS */ /* --- sysfs implementation --- */ @@ -1265,6 +1287,8 @@ int dma_async_device_register(struct dma_device *device) dma_channel_rebalance(); mutex_unlock(&dma_list_mutex); + dmaengine_debug_register(device); + return 0; err_out: @@ -1298,6 +1322,8 @@ void dma_async_device_unregister(struct dma_device *device) { struct dma_chan *chan, *n; + dmaengine_debug_unregister(device); + list_for_each_entry_safe(chan, n, &device->channels, device_node) __dma_async_device_channel_unregister(device, chan); diff --git a/drivers/dma/dmaengine.h b/drivers/dma/dmaengine.h index e8a320c9e57c..1bfbd64b1371 100644 --- a/drivers/dma/dmaengine.h +++ b/drivers/dma/dmaengine.h @@ -182,4 +182,20 @@ dmaengine_desc_callback_valid(struct dmaengine_desc_callback *cb) struct dma_chan *dma_get_slave_channel(struct dma_chan *chan); struct dma_chan *dma_get_any_slave_channel(struct dma_device *device); +#ifdef CONFIG_DEBUG_FS +#include + +static inline struct dentry * +dmaengine_get_debugfs_root(struct dma_device *dma_dev) { + return dma_dev->dbg_dev_root; +} +#else +struct dentry; +static inline struct dentry * +dmaengine_get_debugfs_root(struct dma_device *dma_dev) +{ + return NULL; +} +#endif /* CONFIG_DEBUG_FS */ + #endif diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 72920b5cf2d7..21065c04c4ac 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -902,6 +902,7 @@ struct dma_device { /* debugfs support */ #ifdef CONFIG_DEBUG_FS void (*dbg_summary_show)(struct seq_file *s, struct dma_device *dev); + struct dentry *dbg_dev_root; #endif }; From 0c1cb8b00c9fbe8671ec99e0b271fca8cc2af11d Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Mon, 2 Mar 2020 16:30:46 +0100 Subject: [PATCH 1507/4444] ARM: dts: add bus to rockchip amba nodenames A test with the command below gives for example this error: arch/arm/boot/dts/rk3188-bqedison2qc.dt.yaml: amba: $nodename:0: 'amba' does not match '^(bus|soc|axi|ahb|apb)(@[0-9a-f]+)?$' AMBA is a open standard for the connection and management of functional blocks in a SoC. It's compatible with 'simple-bus', so fix this error by adding 'bus' to all Rockchip 'amba' nodes. make ARCH=arm dtbs_check DT_SCHEMA_FILES=~/.local/lib/python3.5/site-packages/dtschema/ schemas/simple-bus.yaml Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200302153047.17101-1-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3036.dtsi | 2 +- arch/arm/boot/dts/rk322x.dtsi | 2 +- arch/arm/boot/dts/rk3288.dtsi | 2 +- arch/arm/boot/dts/rk3xxx.dtsi | 2 +- arch/arm/boot/dts/rv1108.dtsi | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index bc53f0ca0f25..2226f0d70604 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -54,7 +54,7 @@ }; }; - amba { + amba: bus { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index 166f56e639a2..8ad44213f0dc 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -95,7 +95,7 @@ }; }; - amba { + amba: bus { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 039e8aa70d2d..8bcb4a51682e 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -155,7 +155,7 @@ }; }; - amba { + amba: bus { compatible = "simple-bus"; #address-cells = <2>; #size-cells = <2>; diff --git a/arch/arm/boot/dts/rk3xxx.dtsi b/arch/arm/boot/dts/rk3xxx.dtsi index 241f43e29c77..9438332b8a18 100644 --- a/arch/arm/boot/dts/rk3xxx.dtsi +++ b/arch/arm/boot/dts/rk3xxx.dtsi @@ -32,7 +32,7 @@ spi1 = &spi1; }; - amba { + amba: bus { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/rv1108.dtsi b/arch/arm/boot/dts/rv1108.dtsi index 8f8607ed721e..fda16f97605a 100644 --- a/arch/arm/boot/dts/rv1108.dtsi +++ b/arch/arm/boot/dts/rv1108.dtsi @@ -85,7 +85,7 @@ #clock-cells = <0>; }; - amba { + amba: bus { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; From b2411befed603011826b8783c370a086b5cee163 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Mon, 2 Mar 2020 16:30:47 +0100 Subject: [PATCH 1508/4444] arm64: dts: add bus to rockchip amba nodenames A test with the command below gives for example this error: arch/arm64/boot/dts/rockchip/rk3399-evb.dt.yaml: amba: $nodename:0: 'amba' does not match '^(bus|soc|axi|ahb|apb)(@[0-9a-f]+)?$' AMBA is a open standard for the connection and management of functional blocks in a SoC. It's compatible with 'simple-bus', so fix this error by adding 'bus' to all Rockchip 'amba' nodes. make ARCH=arm64 dtbs_check DT_SCHEMA_FILES=~/.local/lib/python3.5/site-packages/dtschema/ schemas/simple-bus.yaml Signed-off-by: Johan Jonker Link: https://lore.kernel.org/r/20200302153047.17101-2-jbx6244@gmail.com Signed-off-by: Heiko Stuebner --- arch/arm64/boot/dts/rockchip/px30.dtsi | 2 +- arch/arm64/boot/dts/rockchip/rk3308.dtsi | 2 +- arch/arm64/boot/dts/rockchip/rk3328.dtsi | 2 +- arch/arm64/boot/dts/rockchip/rk3368.dtsi | 2 +- arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 6aed865fb7b3..60de8e9c421b 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -703,7 +703,7 @@ clock-names = "pclk", "timer"; }; - amba { + amba: bus { compatible = "simple-bus"; #address-cells = <2>; #size-cells = <2>; diff --git a/arch/arm64/boot/dts/rockchip/rk3308.dtsi b/arch/arm64/boot/dts/rockchip/rk3308.dtsi index 3bd5bc86086b..ac43bc3f7031 100644 --- a/arch/arm64/boot/dts/rockchip/rk3308.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3308.dtsi @@ -513,7 +513,7 @@ status = "disabled"; }; - amba { + amba: bus { compatible = "simple-bus"; #address-cells = <2>; #size-cells = <2>; diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi index 2aefb38f7368..7abbc8dc1bc2 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi @@ -142,7 +142,7 @@ }; }; - amba { + amba: bus { compatible = "simple-bus"; #address-cells = <2>; #size-cells = <2>; diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi index a0df61c61925..2079e877a320 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi @@ -136,7 +136,7 @@ }; }; - amba { + amba: bus { compatible = "simple-bus"; #address-cells = <2>; #size-cells = <2>; diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi index cd5415d7e559..28c7ee540439 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi @@ -197,7 +197,7 @@ #clock-cells = <0>; }; - amba { + amba: bus { compatible = "simple-bus"; #address-cells = <2>; #size-cells = <2>; From 7c4a4d088283e02cc04252e88dd08b5cdf54e70f Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Tue, 10 Mar 2020 15:18:02 -0700 Subject: [PATCH 1509/4444] dmaengine: idxd: Merge definition of dsa_batch_desc into dsa_hw_desc We don't need a special structure just for batch descriptors. The layout matches the general form for other descriptors. Merge the desc_list_addr field into the union of other aliases for the the third quadword in the structure. Create a union to alias "xfer_size" with "desc_count". Signed-off-by: Tony Luck Acked-by: Dave Jiang Link: https://lore.kernel.org/r/158387868208.35922.5895104426944263789.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul --- include/uapi/linux/idxd.h | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/include/uapi/linux/idxd.h b/include/uapi/linux/idxd.h index 849ef1515d04..1f412fbf561b 100644 --- a/include/uapi/linux/idxd.h +++ b/include/uapi/linux/idxd.h @@ -83,21 +83,6 @@ enum dsa_completion_status { #define DSA_COMP_STATUS_MASK 0x7f #define DSA_COMP_STATUS_WRITE 0x80 -struct dsa_batch_desc { - uint32_t pasid:20; - uint32_t rsvd:11; - uint32_t priv:1; - uint32_t flags:24; - uint32_t opcode:8; - uint64_t completion_addr; - uint64_t desc_list_addr; - uint64_t rsvd1; - uint32_t desc_count; - uint16_t interrupt_handle; - uint16_t rsvd2; - uint8_t rsvd3[24]; -} __attribute__((packed)); - struct dsa_hw_desc { uint32_t pasid:20; uint32_t rsvd:11; @@ -109,6 +94,7 @@ struct dsa_hw_desc { uint64_t src_addr; uint64_t rdback_addr; uint64_t pattern; + uint64_t desc_list_addr; }; union { uint64_t dst_addr; @@ -116,7 +102,10 @@ struct dsa_hw_desc { uint64_t src2_addr; uint64_t comp_pattern; }; - uint32_t xfer_size; + union { + uint32_t xfer_size; + uint32_t desc_count; + }; uint16_t int_handle; uint16_t rsvd1; union { From a1fcaf07ec718bb1f11e29e952c9a4cb733d57a5 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Tue, 10 Mar 2020 10:50:30 -0700 Subject: [PATCH 1510/4444] dmaengine: idxd: reflect shadow copy of traffic class programming The traffic class are set to -1 at initialization until the user programs them. If the user choose not to, the driver will program appropriate defaults. The driver also needs to update the shadowed copies of the values after doing the programming. Fixes: c52ca478233c ("dmaengine: idxd: add configuration component of driver") Reported-by: Yixin Zhang Signed-off-by: Dave Jiang Link: https://lore.kernel.org/r/158386263076.10898.4586509576813094559.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul --- drivers/dma/idxd/device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c index ada69e722f84..f6f49f0f6fae 100644 --- a/drivers/dma/idxd/device.c +++ b/drivers/dma/idxd/device.c @@ -584,11 +584,11 @@ static void idxd_group_flags_setup(struct idxd_device *idxd) struct idxd_group *group = &idxd->groups[i]; if (group->tc_a == -1) - group->grpcfg.flags.tc_a = 0; + group->tc_a = group->grpcfg.flags.tc_a = 0; else group->grpcfg.flags.tc_a = group->tc_a; if (group->tc_b == -1) - group->grpcfg.flags.tc_b = 1; + group->tc_b = group->grpcfg.flags.tc_b = 1; else group->grpcfg.flags.tc_b = group->tc_b; group->grpcfg.flags.use_token_limit = group->use_token_limit; From 91124ac61216ed29405d96a29ec914624b196a79 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Tue, 10 Mar 2020 10:51:09 -0700 Subject: [PATCH 1511/4444] dmaengine: idxd: remove global token limit check The global token_limit is not tied to group tokens_reserved and tokens_allowed parameters. Remove the check in order to allow independent configuration. Fixes: c52ca478233c ("dmaengine: idxd: add configuration component of driver") Reported-by: Yixin Zhang Signed-off-by: Dave Jiang Link: https://lore.kernel.org/r/158386266911.11066.7545764533072221536.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul --- drivers/dma/idxd/sysfs.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c index a74e99cb055d..65b08da41329 100644 --- a/drivers/dma/idxd/sysfs.c +++ b/drivers/dma/idxd/sysfs.c @@ -509,9 +509,6 @@ static ssize_t group_tokens_reserved_store(struct device *dev, if (idxd->state == IDXD_DEV_ENABLED) return -EPERM; - if (idxd->token_limit == 0) - return -EPERM; - if (val > idxd->max_tokens) return -EINVAL; @@ -557,8 +554,6 @@ static ssize_t group_tokens_allowed_store(struct device *dev, if (idxd->state == IDXD_DEV_ENABLED) return -EPERM; - if (idxd->token_limit == 0) - return -EPERM; if (val < 4 * group->num_engines || val > group->tokens_reserved + idxd->nr_tokens) return -EINVAL; From 3a5a8a27545ddd8bbdcc9241230a2eed4e81c931 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Mar 2020 08:16:06 +0100 Subject: [PATCH 1512/4444] dmaengine: ppc4xx: Use scnprintf() for avoiding potential buffer overflow Since snprintf() returns the would-be-output size instead of the actual output size, the succeeding calls may go beyond the given buffer limit. Fix it by replacing with scnprintf(). Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20200311071606.4485-1-tiwai@suse.de Signed-off-by: Vinod Koul --- drivers/dma/ppc4xx/adma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c index fbabd2e88a18..4db000d5f01c 100644 --- a/drivers/dma/ppc4xx/adma.c +++ b/drivers/dma/ppc4xx/adma.c @@ -4303,7 +4303,7 @@ static ssize_t devices_show(struct device_driver *dev, char *buf) for (i = 0; i < PPC440SPE_ADMA_ENGINES_NUM; i++) { if (ppc440spe_adma_devices[i] == -1) continue; - size += snprintf(buf + size, PAGE_SIZE - size, + size += scnprintf(buf + size, PAGE_SIZE - size, "PPC440SP(E)-ADMA.%d: %s\n", i, ppc_adma_errors[ppc440spe_adma_devices[i]]); } From 32a1671ff8e84f0dfff3a50d4b2091d25e91f5e2 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 4 Mar 2020 15:37:26 +0100 Subject: [PATCH 1513/4444] ARM: dts: exynos: Fix polarity of the LCD SPI bus on UniversalC210 board Recent changes in the SPI core and the SPI-GPIO driver revealed that the GPIO lines for the LD9040 LCD controller on the UniversalC210 board are defined incorrectly. Fix the polarity for those lines to match the old behavior and hardware requirements to fix LCD panel operation with recent kernels. Cc: # 5.0.x Signed-off-by: Marek Szyprowski Reviewed-by: Andrzej Hajda Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos4210-universal_c210.dts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/exynos4210-universal_c210.dts b/arch/arm/boot/dts/exynos4210-universal_c210.dts index a1bdf7830a87..9dda6bdb9253 100644 --- a/arch/arm/boot/dts/exynos4210-universal_c210.dts +++ b/arch/arm/boot/dts/exynos4210-universal_c210.dts @@ -115,7 +115,7 @@ gpio-sck = <&gpy3 1 GPIO_ACTIVE_HIGH>; gpio-mosi = <&gpy3 3 GPIO_ACTIVE_HIGH>; num-chipselects = <1>; - cs-gpios = <&gpy4 3 GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpy4 3 GPIO_ACTIVE_LOW>; lcd@0 { compatible = "samsung,ld9040"; @@ -124,8 +124,6 @@ vci-supply = <&ldo17_reg>; reset-gpios = <&gpy4 5 GPIO_ACTIVE_HIGH>; spi-max-frequency = <1200000>; - spi-cpol; - spi-cpha; power-on-delay = <10>; reset-delay = <10>; panel-width-mm = <90>; From ee22d0c5e88b82780f143e5bb449ad597b31f444 Mon Sep 17 00:00:00 2001 From: Vidya Sagar Date: Tue, 3 Mar 2020 23:40:48 +0530 Subject: [PATCH 1514/4444] soc/tegra: bpmp: Update ABI header Update the firmware header to support uninitialization of UPHY PLL when the PCIe controller is operating in endpoint mode and host cuts the PCIe reference clock. Signed-off-by: Vidya Sagar Signed-off-by: Lorenzo Pieralisi Acked-by: Thierry Reding --- include/soc/tegra/bpmp-abi.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/soc/tegra/bpmp-abi.h b/include/soc/tegra/bpmp-abi.h index cac6f610b3fe..8f8e73e5cd45 100644 --- a/include/soc/tegra/bpmp-abi.h +++ b/include/soc/tegra/bpmp-abi.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2014-2018, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2020, NVIDIA CORPORATION. All rights reserved. */ #ifndef _ABI_BPMP_ABI_H_ @@ -2119,6 +2119,7 @@ enum { CMD_UPHY_PCIE_LANE_MARGIN_STATUS = 2, CMD_UPHY_PCIE_EP_CONTROLLER_PLL_INIT = 3, CMD_UPHY_PCIE_CONTROLLER_STATE = 4, + CMD_UPHY_PCIE_EP_CONTROLLER_PLL_OFF = 5, CMD_UPHY_MAX, }; @@ -2151,6 +2152,11 @@ struct cmd_uphy_pcie_controller_state_request { uint8_t enable; } __ABI_PACKED; +struct cmd_uphy_ep_controller_pll_off_request { + /** @brief EP controller number, valid: 0, 4, 5 */ + uint8_t ep_controller; +} __ABI_PACKED; + /** * @ingroup UPHY * @brief Request with #MRQ_UPHY @@ -2165,6 +2171,7 @@ struct cmd_uphy_pcie_controller_state_request { * |CMD_UPHY_PCIE_LANE_MARGIN_STATUS | | * |CMD_UPHY_PCIE_EP_CONTROLLER_PLL_INIT |cmd_uphy_ep_controller_pll_init_request | * |CMD_UPHY_PCIE_CONTROLLER_STATE |cmd_uphy_pcie_controller_state_request | + * |CMD_UPHY_PCIE_EP_CONTROLLER_PLL_OFF |cmd_uphy_ep_controller_pll_off_request | * */ @@ -2178,6 +2185,7 @@ struct mrq_uphy_request { struct cmd_uphy_margin_control_request uphy_set_margin_control; struct cmd_uphy_ep_controller_pll_init_request ep_ctrlr_pll_init; struct cmd_uphy_pcie_controller_state_request controller_state; + struct cmd_uphy_ep_controller_pll_off_request ep_ctrlr_pll_off; } __UNION_ANON; } __ABI_PACKED; From 9f04d18b1edf1992e1dd606933839d725aec9b1f Mon Sep 17 00:00:00 2001 From: Vidya Sagar Date: Tue, 3 Mar 2020 23:40:49 +0530 Subject: [PATCH 1515/4444] dt-bindings: PCI: tegra: Add DT support for PCIe EP nodes in Tegra194 Add support for PCIe controllers that can operate in endpoint mode in Tegra194. Signed-off-by: Vidya Sagar Signed-off-by: Lorenzo Pieralisi Reviewed-by: Rob Herring Acked-by: Thierry Reding --- .../bindings/pci/nvidia,tegra194-pcie.txt | 125 ++++++++++++++---- 1 file changed, 99 insertions(+), 26 deletions(-) diff --git a/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt b/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt index b739f92da58e..faa3ef5adfbb 100644 --- a/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt +++ b/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt @@ -1,11 +1,11 @@ NVIDIA Tegra PCIe controller (Synopsys DesignWare Core based) -This PCIe host controller is based on the Synopsis Designware PCIe IP +This PCIe controller is based on the Synopsis Designware PCIe IP and thus inherits all the common properties defined in designware-pcie.txt. +Some of the controller instances are dual mode where in they can work either +in root port mode or endpoint mode but one at a time. Required properties: -- compatible: For Tegra19x, must contain "nvidia,tegra194-pcie". -- device_type: Must be "pci" - power-domains: A phandle to the node that controls power to the respective PCIe controller and a specifier name for the PCIe controller. Following are the specifiers for the different PCIe controllers @@ -32,6 +32,32 @@ Required properties: entry for each entry in the interrupt-names property. - interrupt-names: Must include the following entries: "intr": The Tegra interrupt that is asserted for controller interrupts +- clocks: Must contain an entry for each entry in clock-names. + See ../clocks/clock-bindings.txt for details. +- clock-names: Must include the following entries: + - core +- resets: Must contain an entry for each entry in reset-names. + See ../reset/reset.txt for details. +- reset-names: Must include the following entries: + - apb + - core +- phys: Must contain a phandle to P2U PHY for each entry in phy-names. +- phy-names: Must include an entry for each active lane. + "p2u-N": where N ranges from 0 to one less than the total number of lanes +- nvidia,bpmp: Must contain a pair of phandle to BPMP controller node followed + by controller-id. Following are the controller ids for each controller. + 0: C0 + 1: C1 + 2: C2 + 3: C3 + 4: C4 + 5: C5 +- vddio-pex-ctl-supply: Regulator supply for PCIe side band signals + +RC mode: +- compatible: Tegra19x must contain "nvidia,tegra194-pcie" +- device_type: Must be "pci" for RC mode +- interrupt-names: Must include the following entries: "msi": The Tegra interrupt that is asserted when an MSI is received - bus-range: Range of bus numbers associated with this controller - #address-cells: Address representation for root ports (must be 3) @@ -60,27 +86,15 @@ Required properties: - interrupt-map-mask and interrupt-map: Standard PCI IRQ mapping properties Please refer to the standard PCI bus binding document for a more detailed explanation. -- clocks: Must contain an entry for each entry in clock-names. - See ../clocks/clock-bindings.txt for details. -- clock-names: Must include the following entries: - - core -- resets: Must contain an entry for each entry in reset-names. - See ../reset/reset.txt for details. -- reset-names: Must include the following entries: - - apb - - core -- phys: Must contain a phandle to P2U PHY for each entry in phy-names. -- phy-names: Must include an entry for each active lane. - "p2u-N": where N ranges from 0 to one less than the total number of lanes -- nvidia,bpmp: Must contain a pair of phandle to BPMP controller node followed - by controller-id. Following are the controller ids for each controller. - 0: C0 - 1: C1 - 2: C2 - 3: C3 - 4: C4 - 5: C5 -- vddio-pex-ctl-supply: Regulator supply for PCIe side band signals + +EP mode: +In Tegra194, Only controllers C0, C4 & C5 support EP mode. +- compatible: Tegra19x must contain "nvidia,tegra194-pcie-ep" +- reg-names: Must include the following entries: + "addr_space": Used to map remote RC address space +- reset-gpios: Must contain a phandle to a GPIO controller followed by + GPIO that is being used as PERST input signal. Please refer to pci.txt + document. Optional properties: - pinctrl-names: A list of pinctrl state names. @@ -104,6 +118,8 @@ Optional properties: specified in microseconds - nvidia,aspm-l0s-entrance-latency-us: ASPM L0s entrance latency to be specified in microseconds + +RC mode: - vpcie3v3-supply: A phandle to the regulator node that supplies 3.3V to the slot if the platform has one such slot. (Ex:- x16 slot owned by C5 controller in p2972-0000 platform). @@ -111,11 +127,18 @@ Optional properties: if the platform has one such slot. (Ex:- x16 slot owned by C5 controller in p2972-0000 platform). +EP mode: +- nvidia,refclk-select-gpios: Must contain a phandle to a GPIO controller + followed by GPIO that is being used to enable REFCLK to controller from host + +NOTE:- On Tegra194's P2972-0000 platform, only C5 controller can be enabled to +operate in the endpoint mode because of the way the platform is designed. + Examples: ========= -Tegra194: --------- +Tegra194 RC mode: +----------------- pcie@14180000 { compatible = "nvidia,tegra194-pcie", "snps,dw-pcie"; @@ -169,3 +192,53 @@ Tegra194: <&p2u_hsio_5>; phy-names = "p2u-0", "p2u-1", "p2u-2", "p2u-3"; }; + +Tegra194 EP mode: +----------------- + + pcie_ep@141a0000 { + compatible = "nvidia,tegra194-pcie-ep", "snps,dw-pcie-ep"; + power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX8A>; + reg = <0x00 0x141a0000 0x0 0x00020000 /* appl registers (128K) */ + 0x00 0x3a040000 0x0 0x00040000 /* iATU_DMA reg space (256K) */ + 0x00 0x3a080000 0x0 0x00040000 /* DBI reg space (256K) */ + 0x1c 0x00000000 0x4 0x00000000>; /* Address Space (16G) */ + reg-names = "appl", "atu_dma", "dbi", "addr_space"; + + num-lanes = <8>; + num-ib-windows = <2>; + num-ob-windows = <8>; + + pinctrl-names = "default"; + pinctrl-0 = <&clkreq_c5_bi_dir_state>; + + clocks = <&bpmp TEGRA194_CLK_PEX1_CORE_5>; + clock-names = "core"; + + resets = <&bpmp TEGRA194_RESET_PEX1_CORE_5_APB>, + <&bpmp TEGRA194_RESET_PEX1_CORE_5>; + reset-names = "apb", "core"; + + interrupts = ; /* controller interrupt */ + interrupt-names = "intr"; + + nvidia,bpmp = <&bpmp 5>; + + nvidia,aspm-cmrt-us = <60>; + nvidia,aspm-pwr-on-t-us = <20>; + nvidia,aspm-l0s-entrance-latency-us = <3>; + + vddio-pex-ctl-supply = <&vdd_1v8ao>; + + reset-gpios = <&gpio TEGRA194_MAIN_GPIO(GG, 1) GPIO_ACTIVE_LOW>; + + nvidia,refclk-select-gpios = <&gpio_aon TEGRA194_AON_GPIO(AA, 5) + GPIO_ACTIVE_HIGH>; + + phys = <&p2u_nvhs_0>, <&p2u_nvhs_1>, <&p2u_nvhs_2>, + <&p2u_nvhs_3>, <&p2u_nvhs_4>, <&p2u_nvhs_5>, + <&p2u_nvhs_6>, <&p2u_nvhs_7>; + + phy-names = "p2u-0", "p2u-1", "p2u-2", "p2u-3", "p2u-4", + "p2u-5", "p2u-6", "p2u-7"; + }; From 97249a89c17e8f1288fed1ebc617ea2e9e88d501 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Fri, 28 Feb 2020 16:27:06 +0100 Subject: [PATCH 1516/4444] ASoC: Convert cirrus,cs42l51 to json-schema Convert cirrus,cs42l51 to yaml format. Signed-off-by: Benjamin Gaignard Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20200228152706.29749-1-benjamin.gaignard@st.com Signed-off-by: Mark Brown --- .../bindings/sound/cirrus,cs42l51.yaml | 69 +++++++++++++++++++ .../devicetree/bindings/sound/cs42l51.txt | 33 --------- 2 files changed, 69 insertions(+), 33 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml delete mode 100644 Documentation/devicetree/bindings/sound/cs42l51.txt diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml new file mode 100644 index 000000000000..efce847a3408 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/cirrus,cs42l51.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: CS42L51 audio codec DT bindings + +maintainers: + - Olivier Moysan + +properties: + compatible: + const: cirrus,cs42l51 + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 0 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: MCLK + + reset-gpios: + maxItems: 1 + + VL-supply: + description: phandle to voltage regulator of digital interface section + + VD-supply: + description: phandle to voltage regulator of digital internal section + + VA-supply: + description: phandle to voltage regulator of analog internal section + + VAHP-supply: + description: phandle to voltage regulator of headphone + +required: + - compatible + - reg + - "#sound-dai-cells" + +examples: + - | + #include + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + + cs42l51@4a { + compatible = "cirrus,cs42l51"; + reg = <0x4a>; + #sound-dai-cells = <0>; + clocks = <&mclk_prov>; + clock-names = "MCLK"; + VL-supply = <®_audio>; + VD-supply = <®_audio>; + VA-supply = <®_audio>; + VAHP-supply = <®_audio>; + reset-gpios = <&gpiog 9 GPIO_ACTIVE_LOW>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/sound/cs42l51.txt b/Documentation/devicetree/bindings/sound/cs42l51.txt deleted file mode 100644 index acbd68ddd2cb..000000000000 --- a/Documentation/devicetree/bindings/sound/cs42l51.txt +++ /dev/null @@ -1,33 +0,0 @@ -CS42L51 audio CODEC - -Required properties: - - - compatible : "cirrus,cs42l51" - - - reg : the I2C address of the device for I2C. - -Optional properties: - - VL-supply, VD-supply, VA-supply, VAHP-supply: power supplies for the device, - as covered in Documentation/devicetree/bindings/regulator/regulator.txt. - - - reset-gpios : GPIO specification for the reset pin. If specified, it will be - deasserted before starting the communication with the codec. - - - clocks : a list of phandles + clock-specifiers, one for each entry in - clock-names - - - clock-names : must contain "MCLK" - -Example: - -cs42l51: cs42l51@4a { - compatible = "cirrus,cs42l51"; - reg = <0x4a>; - clocks = <&mclk_prov>; - clock-names = "MCLK"; - VL-supply = <®_audio>; - VD-supply = <®_audio>; - VA-supply = <®_audio>; - VAHP-supply = <®_audio>; - reset-gpios = <&gpiog 9 GPIO_ACTIVE_LOW>; -}; From 8719b6d29d2851fa84c4074bb2e5adc022911ab8 Mon Sep 17 00:00:00 2001 From: afzal mohammed Date: Wed, 4 Mar 2020 06:20:48 +0530 Subject: [PATCH 1517/4444] s390/irq: replace setup_irq() by request_irq() request_irq() is preferred over setup_irq(). Invocations of setup_irq() occur after memory allocators are ready. Per tglx[1], setup_irq() existed in olden days when allocators were not ready by the time early interrupts were initialized. Hence replace setup_irq() by request_irq(). [1] https://lkml.kernel.org/r/alpine.DEB.2.20.1710191609480.1971@nanos Signed-off-by: afzal mohammed Message-Id: <20200304005049.5291-1-afzal.mohd.ma@gmail.com> [heiko.carstens@de.ibm.com: replace pr_err with panic] Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/kernel/irq.c | 8 ++------ drivers/s390/cio/airq.c | 8 ++------ drivers/s390/cio/cio.c | 8 ++------ 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 8371855042dc..da550cb8b31b 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -294,11 +294,6 @@ static irqreturn_t do_ext_interrupt(int irq, void *dummy) return IRQ_HANDLED; } -static struct irqaction external_interrupt = { - .name = "EXT", - .handler = do_ext_interrupt, -}; - void __init init_ext_interrupts(void) { int idx; @@ -308,7 +303,8 @@ void __init init_ext_interrupts(void) irq_set_chip_and_handler(EXT_INTERRUPT, &dummy_irq_chip, handle_percpu_irq); - setup_irq(EXT_INTERRUPT, &external_interrupt); + if (request_irq(EXT_INTERRUPT, do_ext_interrupt, 0, "EXT", NULL)) + panic("Failed to register EXT interrupt\n"); } static DEFINE_SPINLOCK(irq_subclass_lock); diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index 427b2e24a8ce..cb466ed7eb5e 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c @@ -105,16 +105,12 @@ static irqreturn_t do_airq_interrupt(int irq, void *dummy) return IRQ_HANDLED; } -static struct irqaction airq_interrupt = { - .name = "AIO", - .handler = do_airq_interrupt, -}; - void __init init_airq_interrupts(void) { irq_set_chip_and_handler(THIN_INTERRUPT, &dummy_irq_chip, handle_percpu_irq); - setup_irq(THIN_INTERRUPT, &airq_interrupt); + if (request_irq(THIN_INTERRUPT, do_airq_interrupt, 0, "AIO", NULL)) + panic("Failed to register AIO interrupt\n"); } static inline unsigned long iv_size(unsigned long bits) diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 18f5458f90e8..6d716db2a46a 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -563,16 +563,12 @@ static irqreturn_t do_cio_interrupt(int irq, void *dummy) return IRQ_HANDLED; } -static struct irqaction io_interrupt = { - .name = "I/O", - .handler = do_cio_interrupt, -}; - void __init init_cio_interrupts(void) { irq_set_chip_and_handler(IO_INTERRUPT, &dummy_irq_chip, handle_percpu_irq); - setup_irq(IO_INTERRUPT, &io_interrupt); + if (request_irq(IO_INTERRUPT, do_cio_interrupt, 0, "I/O", NULL)) + panic("Failed to register I/O interrupt\n"); } #ifdef CONFIG_CCW_CONSOLE From 76fb118083eaf63f506fcbe695c1b12a38971b7a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 10 Mar 2020 10:25:51 +0100 Subject: [PATCH 1518/4444] s390/irq: make init_ext_interrupts static Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/hw_irq.h | 1 - arch/s390/kernel/irq.c | 18 +++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/arch/s390/include/asm/hw_irq.h b/arch/s390/include/asm/hw_irq.h index adae176757ae..9078b5b6b837 100644 --- a/arch/s390/include/asm/hw_irq.h +++ b/arch/s390/include/asm/hw_irq.h @@ -7,6 +7,5 @@ void __init init_airq_interrupts(void); void __init init_cio_interrupts(void); -void __init init_ext_interrupts(void); #endif diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index da550cb8b31b..3514420f0259 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -95,14 +95,6 @@ static const struct irq_class irqclass_sub_desc[] = { {.irq = CPU_RST, .name = "RST", .desc = "[CPU] CPU Restart"}, }; -void __init init_IRQ(void) -{ - BUILD_BUG_ON(ARRAY_SIZE(irqclass_sub_desc) != NR_ARCH_IRQS); - init_cio_interrupts(); - init_airq_interrupts(); - init_ext_interrupts(); -} - void do_IRQ(struct pt_regs *regs, int irq) { struct pt_regs *old_regs; @@ -294,7 +286,7 @@ static irqreturn_t do_ext_interrupt(int irq, void *dummy) return IRQ_HANDLED; } -void __init init_ext_interrupts(void) +static void __init init_ext_interrupts(void) { int idx; @@ -307,6 +299,14 @@ void __init init_ext_interrupts(void) panic("Failed to register EXT interrupt\n"); } +void __init init_IRQ(void) +{ + BUILD_BUG_ON(ARRAY_SIZE(irqclass_sub_desc) != NR_ARCH_IRQS); + init_cio_interrupts(); + init_airq_interrupts(); + init_ext_interrupts(); +} + static DEFINE_SPINLOCK(irq_subclass_lock); static unsigned char irq_subclass_refcount[64]; From 1d49688d2bc6406d74566bca35b3d67201a906fc Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 10 Mar 2020 10:29:43 +0100 Subject: [PATCH 1519/4444] s390/traps: mark test_monitor_call __init Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/kernel/traps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index dc75588d7894..ff9cc4c3290e 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -271,7 +271,7 @@ void kernel_stack_overflow(struct pt_regs *regs) } NOKPROBE_SYMBOL(kernel_stack_overflow); -static void test_monitor_call(void) +static void __init test_monitor_call(void) { int val = 1; From bb533ec8bacd064ee273ca3305db97938c3331ae Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Tue, 10 Mar 2020 09:01:44 +0100 Subject: [PATCH 1520/4444] s390/config: do not select VIRTIO_CONSOLE via Kconfig select does not ensure that dependencies are also selected. Instead of selecting VIRTIO_CONSOLE from S390_GUEST we should rather add this to the defconfigs. So we update those as well. Reported-by: Michael S. Tsirkin Signed-off-by: Christian Borntraeger Signed-off-by: Vasily Gorbik --- arch/s390/Kconfig | 1 - arch/s390/configs/debug_defconfig | 1 + arch/s390/configs/defconfig | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index f4ff75ff62f2..334f3f2199e8 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -953,7 +953,6 @@ config S390_GUEST select TTY select VIRTUALIZATION select VIRTIO - select VIRTIO_CONSOLE help Enabling this option adds support for virtio based paravirtual device drivers on s390. diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig index 2e60c80395ab..4ca5c7499cce 100644 --- a/arch/s390/configs/debug_defconfig +++ b/arch/s390/configs/debug_defconfig @@ -532,6 +532,7 @@ CONFIG_INPUT_EVDEV=y # CONFIG_SERIO is not set CONFIG_LEGACY_PTY_COUNT=0 CONFIG_NULL_TTY=m +CONFIG_VIRTIO_CONSOLE=y CONFIG_HW_RANDOM_VIRTIO=m CONFIG_RAW_DRIVER=m CONFIG_HANGCHECK_TIMER=m diff --git a/arch/s390/configs/defconfig b/arch/s390/configs/defconfig index 25f799849582..c0950750fb50 100644 --- a/arch/s390/configs/defconfig +++ b/arch/s390/configs/defconfig @@ -528,6 +528,7 @@ CONFIG_INPUT_EVDEV=y # CONFIG_SERIO is not set CONFIG_LEGACY_PTY_COUNT=0 CONFIG_NULL_TTY=m +CONFIG_VIRTIO_CONSOLE=y CONFIG_HW_RANDOM_VIRTIO=m CONFIG_RAW_DRIVER=m CONFIG_HANGCHECK_TIMER=m From 46b5889cc2c54bac7d7e727a44d28a298df23cef Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 14 Jan 2020 10:09:52 +0100 Subject: [PATCH 1521/4444] mtd: implement proper partition handling Instead of collecting partitions in a flat list, create a hierarchy within the mtd_info structure: use a partitions list to keep track of the partitions of an MTD device (which might be itself a partition of another MTD device), a pointer to the parent device (NULL when the MTD device is the root one, not a partition). By also saving directly in mtd_info the offset of the partition, we can get rid of the mtd_part structure. While at it, be consistent in the naming of the mtd_info structures to ease the understanding of the new hierarchy: these structures are usually called 'mtd', unless there are multiple instances of the same structure. In this case, there is usually a parent/child bound so we will call them 'parent' and 'child'. Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200114090952.11232-1-miquel.raynal@bootlin.com --- drivers/mtd/mtdchar.c | 12 +- drivers/mtd/mtdcore.c | 250 ++++++++---- drivers/mtd/mtdpart.c | 693 +++++++++------------------------ include/linux/mtd/mtd.h | 125 +++++- include/linux/mtd/partitions.h | 1 - 5 files changed, 477 insertions(+), 604 deletions(-) diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index b841008a9eb7..c5935b2f9cd1 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -349,6 +349,7 @@ static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd, uint64_t start, uint32_t length, void __user *ptr, uint32_t __user *retp) { + struct mtd_info *master = mtd_get_master(mtd); struct mtd_file_info *mfi = file->private_data; struct mtd_oob_ops ops = {}; uint32_t retlen; @@ -360,7 +361,7 @@ static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd, if (length > 4096) return -EINVAL; - if (!mtd->_write_oob) + if (!master->_write_oob) return -EOPNOTSUPP; ops.ooblen = length; @@ -586,6 +587,7 @@ static int mtdchar_blkpg_ioctl(struct mtd_info *mtd, static int mtdchar_write_ioctl(struct mtd_info *mtd, struct mtd_write_req __user *argp) { + struct mtd_info *master = mtd_get_master(mtd); struct mtd_write_req req; struct mtd_oob_ops ops = {}; const void __user *usr_data, *usr_oob; @@ -597,9 +599,8 @@ static int mtdchar_write_ioctl(struct mtd_info *mtd, usr_data = (const void __user *)(uintptr_t)req.usr_data; usr_oob = (const void __user *)(uintptr_t)req.usr_oob; - if (!mtd->_write_oob) + if (!master->_write_oob) return -EOPNOTSUPP; - ops.mode = req.mode; ops.len = (size_t)req.len; ops.ooblen = (size_t)req.ooblen; @@ -635,6 +636,7 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) { struct mtd_file_info *mfi = file->private_data; struct mtd_info *mtd = mfi->mtd; + struct mtd_info *master = mtd_get_master(mtd); void __user *argp = (void __user *)arg; int ret = 0; struct mtd_info_user info; @@ -824,7 +826,7 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) { struct nand_oobinfo oi; - if (!mtd->ooblayout) + if (!master->ooblayout) return -EOPNOTSUPP; ret = get_oobinfo(mtd, &oi); @@ -918,7 +920,7 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) { struct nand_ecclayout_user *usrlay; - if (!mtd->ooblayout) + if (!master->ooblayout) return -EOPNOTSUPP; usrlay = kmalloc(sizeof(*usrlay), GFP_KERNEL); diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 5fac4355b9c2..2916674208b3 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -456,13 +456,14 @@ static int mtd_reboot_notifier(struct notifier_block *n, unsigned long state, int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit, struct mtd_pairing_info *info) { - int npairs = mtd_wunit_per_eb(mtd) / mtd_pairing_groups(mtd); + struct mtd_info *master = mtd_get_master(mtd); + int npairs = mtd_wunit_per_eb(master) / mtd_pairing_groups(master); if (wunit < 0 || wunit >= npairs) return -EINVAL; - if (mtd->pairing && mtd->pairing->get_info) - return mtd->pairing->get_info(mtd, wunit, info); + if (master->pairing && master->pairing->get_info) + return master->pairing->get_info(master, wunit, info); info->group = 0; info->pair = wunit; @@ -498,15 +499,16 @@ EXPORT_SYMBOL_GPL(mtd_wunit_to_pairing_info); int mtd_pairing_info_to_wunit(struct mtd_info *mtd, const struct mtd_pairing_info *info) { - int ngroups = mtd_pairing_groups(mtd); - int npairs = mtd_wunit_per_eb(mtd) / ngroups; + struct mtd_info *master = mtd_get_master(mtd); + int ngroups = mtd_pairing_groups(master); + int npairs = mtd_wunit_per_eb(master) / ngroups; if (!info || info->pair < 0 || info->pair >= npairs || info->group < 0 || info->group >= ngroups) return -EINVAL; - if (mtd->pairing && mtd->pairing->get_wunit) - return mtd->pairing->get_wunit(mtd, info); + if (master->pairing && master->pairing->get_wunit) + return mtd->pairing->get_wunit(master, info); return info->pair; } @@ -524,10 +526,12 @@ EXPORT_SYMBOL_GPL(mtd_pairing_info_to_wunit); */ int mtd_pairing_groups(struct mtd_info *mtd) { - if (!mtd->pairing || !mtd->pairing->ngroups) + struct mtd_info *master = mtd_get_master(mtd); + + if (!master->pairing || !master->pairing->ngroups) return 1; - return mtd->pairing->ngroups; + return master->pairing->ngroups; } EXPORT_SYMBOL_GPL(mtd_pairing_groups); @@ -587,6 +591,7 @@ static int mtd_nvmem_add(struct mtd_info *mtd) int add_mtd_device(struct mtd_info *mtd) { + struct mtd_info *master = mtd_get_master(mtd); struct mtd_notifier *not; int i, error; @@ -608,7 +613,7 @@ int add_mtd_device(struct mtd_info *mtd) (mtd->_read && mtd->_read_oob))) return -EINVAL; - if (WARN_ON((!mtd->erasesize || !mtd->_erase) && + if (WARN_ON((!mtd->erasesize || !master->_erase) && !(mtd->flags & MTD_NO_ERASE))) return -EINVAL; @@ -765,7 +770,8 @@ static void mtd_set_dev_defaults(struct mtd_info *mtd) pr_debug("mtd device won't show a device symlink in sysfs\n"); } - mtd->orig_flags = mtd->flags; + INIT_LIST_HEAD(&mtd->partitions); + mutex_init(&mtd->master.partitions_lock); } /** @@ -971,20 +977,26 @@ EXPORT_SYMBOL_GPL(get_mtd_device); int __get_mtd_device(struct mtd_info *mtd) { + struct mtd_info *master = mtd_get_master(mtd); int err; - if (!try_module_get(mtd->owner)) + if (!try_module_get(master->owner)) return -ENODEV; - if (mtd->_get_device) { - err = mtd->_get_device(mtd); + if (master->_get_device) { + err = master->_get_device(mtd); if (err) { - module_put(mtd->owner); + module_put(master->owner); return err; } } - mtd->usecount++; + + while (mtd->parent) { + mtd->usecount++; + mtd = mtd->parent; + } + return 0; } EXPORT_SYMBOL_GPL(__get_mtd_device); @@ -1038,13 +1050,18 @@ EXPORT_SYMBOL_GPL(put_mtd_device); void __put_mtd_device(struct mtd_info *mtd) { - --mtd->usecount; - BUG_ON(mtd->usecount < 0); + struct mtd_info *master = mtd_get_master(mtd); - if (mtd->_put_device) - mtd->_put_device(mtd); + while (mtd->parent) { + --mtd->usecount; + BUG_ON(mtd->usecount < 0); + mtd = mtd->parent; + } - module_put(mtd->owner); + if (master->_put_device) + master->_put_device(master); + + module_put(master->owner); } EXPORT_SYMBOL_GPL(__put_mtd_device); @@ -1055,9 +1072,13 @@ EXPORT_SYMBOL_GPL(__put_mtd_device); */ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr) { + struct mtd_info *master = mtd_get_master(mtd); + u64 mst_ofs = mtd_get_master_ofs(mtd, 0); + int ret; + instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN; - if (!mtd->erasesize || !mtd->_erase) + if (!mtd->erasesize || !master->_erase) return -ENOTSUPP; if (instr->addr >= mtd->size || instr->len > mtd->size - instr->addr) @@ -1069,7 +1090,14 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr) return 0; ledtrig_mtd_activity(); - return mtd->_erase(mtd, instr); + + instr->addr += mst_ofs; + ret = master->_erase(master, instr); + if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) + instr->fail_addr -= mst_ofs; + + instr->addr -= mst_ofs; + return ret; } EXPORT_SYMBOL_GPL(mtd_erase); @@ -1079,30 +1107,36 @@ EXPORT_SYMBOL_GPL(mtd_erase); int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, void **virt, resource_size_t *phys) { + struct mtd_info *master = mtd_get_master(mtd); + *retlen = 0; *virt = NULL; if (phys) *phys = 0; - if (!mtd->_point) + if (!master->_point) return -EOPNOTSUPP; if (from < 0 || from >= mtd->size || len > mtd->size - from) return -EINVAL; if (!len) return 0; - return mtd->_point(mtd, from, len, retlen, virt, phys); + + from = mtd_get_master_ofs(mtd, from); + return master->_point(master, from, len, retlen, virt, phys); } EXPORT_SYMBOL_GPL(mtd_point); /* We probably shouldn't allow XIP if the unpoint isn't a NULL */ int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len) { - if (!mtd->_unpoint) + struct mtd_info *master = mtd_get_master(mtd); + + if (!master->_unpoint) return -EOPNOTSUPP; if (from < 0 || from >= mtd->size || len > mtd->size - from) return -EINVAL; if (!len) return 0; - return mtd->_unpoint(mtd, from, len); + return master->_unpoint(master, mtd_get_master_ofs(mtd, from), len); } EXPORT_SYMBOL_GPL(mtd_unpoint); @@ -1129,6 +1163,25 @@ unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len, } EXPORT_SYMBOL_GPL(mtd_get_unmapped_area); +static void mtd_update_ecc_stats(struct mtd_info *mtd, struct mtd_info *master, + const struct mtd_ecc_stats *old_stats) +{ + struct mtd_ecc_stats diff; + + if (master == mtd) + return; + + diff = master->ecc_stats; + diff.failed -= old_stats->failed; + diff.corrected -= old_stats->corrected; + + while (mtd->parent) { + mtd->ecc_stats.failed += diff.failed; + mtd->ecc_stats.corrected += diff.corrected; + mtd = mtd->parent; + } +} + int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { @@ -1171,8 +1224,10 @@ EXPORT_SYMBOL_GPL(mtd_write); int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { + struct mtd_info *master = mtd_get_master(mtd); + *retlen = 0; - if (!mtd->_panic_write) + if (!master->_panic_write) return -EOPNOTSUPP; if (to < 0 || to >= mtd->size || len > mtd->size - to) return -EINVAL; @@ -1183,7 +1238,8 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, if (!mtd->oops_panic_write) mtd->oops_panic_write = true; - return mtd->_panic_write(mtd, to, len, retlen, buf); + return master->_panic_write(master, mtd_get_master_ofs(mtd, to), len, + retlen, buf); } EXPORT_SYMBOL_GPL(mtd_panic_write); @@ -1222,7 +1278,10 @@ static int mtd_check_oob_ops(struct mtd_info *mtd, loff_t offs, int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) { + struct mtd_info *master = mtd_get_master(mtd); + struct mtd_ecc_stats old_stats = master->ecc_stats; int ret_code; + ops->retlen = ops->oobretlen = 0; ret_code = mtd_check_oob_ops(mtd, from, ops); @@ -1232,14 +1291,17 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) ledtrig_mtd_activity(); /* Check the validity of a potential fallback on mtd->_read */ - if (!mtd->_read_oob && (!mtd->_read || ops->oobbuf)) + if (!master->_read_oob && (!master->_read || ops->oobbuf)) return -EOPNOTSUPP; - if (mtd->_read_oob) - ret_code = mtd->_read_oob(mtd, from, ops); + from = mtd_get_master_ofs(mtd, from); + if (master->_read_oob) + ret_code = master->_read_oob(master, from, ops); else - ret_code = mtd->_read(mtd, from, ops->len, &ops->retlen, - ops->datbuf); + ret_code = master->_read(master, from, ops->len, &ops->retlen, + ops->datbuf); + + mtd_update_ecc_stats(mtd, master, &old_stats); /* * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics @@ -1258,6 +1320,7 @@ EXPORT_SYMBOL_GPL(mtd_read_oob); int mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) { + struct mtd_info *master = mtd_get_master(mtd); int ret; ops->retlen = ops->oobretlen = 0; @@ -1272,14 +1335,16 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to, ledtrig_mtd_activity(); /* Check the validity of a potential fallback on mtd->_write */ - if (!mtd->_write_oob && (!mtd->_write || ops->oobbuf)) + if (!master->_write_oob && (!master->_write || ops->oobbuf)) return -EOPNOTSUPP; - if (mtd->_write_oob) - return mtd->_write_oob(mtd, to, ops); + to = mtd_get_master_ofs(mtd, to); + + if (master->_write_oob) + return master->_write_oob(master, to, ops); else - return mtd->_write(mtd, to, ops->len, &ops->retlen, - ops->datbuf); + return master->_write(master, to, ops->len, &ops->retlen, + ops->datbuf); } EXPORT_SYMBOL_GPL(mtd_write_oob); @@ -1302,15 +1367,17 @@ EXPORT_SYMBOL_GPL(mtd_write_oob); int mtd_ooblayout_ecc(struct mtd_info *mtd, int section, struct mtd_oob_region *oobecc) { + struct mtd_info *master = mtd_get_master(mtd); + memset(oobecc, 0, sizeof(*oobecc)); - if (!mtd || section < 0) + if (!master || section < 0) return -EINVAL; - if (!mtd->ooblayout || !mtd->ooblayout->ecc) + if (!master->ooblayout || !master->ooblayout->ecc) return -ENOTSUPP; - return mtd->ooblayout->ecc(mtd, section, oobecc); + return master->ooblayout->ecc(master, section, oobecc); } EXPORT_SYMBOL_GPL(mtd_ooblayout_ecc); @@ -1334,15 +1401,17 @@ EXPORT_SYMBOL_GPL(mtd_ooblayout_ecc); int mtd_ooblayout_free(struct mtd_info *mtd, int section, struct mtd_oob_region *oobfree) { + struct mtd_info *master = mtd_get_master(mtd); + memset(oobfree, 0, sizeof(*oobfree)); - if (!mtd || section < 0) + if (!master || section < 0) return -EINVAL; - if (!mtd->ooblayout || !mtd->ooblayout->free) + if (!master->ooblayout || !master->ooblayout->free) return -ENOTSUPP; - return mtd->ooblayout->free(mtd, section, oobfree); + return master->ooblayout->free(master, section, oobfree); } EXPORT_SYMBOL_GPL(mtd_ooblayout_free); @@ -1651,60 +1720,69 @@ EXPORT_SYMBOL_GPL(mtd_ooblayout_count_eccbytes); int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, struct otp_info *buf) { - if (!mtd->_get_fact_prot_info) + struct mtd_info *master = mtd_get_master(mtd); + + if (!master->_get_fact_prot_info) return -EOPNOTSUPP; if (!len) return 0; - return mtd->_get_fact_prot_info(mtd, len, retlen, buf); + return master->_get_fact_prot_info(master, len, retlen, buf); } EXPORT_SYMBOL_GPL(mtd_get_fact_prot_info); int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { + struct mtd_info *master = mtd_get_master(mtd); + *retlen = 0; - if (!mtd->_read_fact_prot_reg) + if (!master->_read_fact_prot_reg) return -EOPNOTSUPP; if (!len) return 0; - return mtd->_read_fact_prot_reg(mtd, from, len, retlen, buf); + return master->_read_fact_prot_reg(master, from, len, retlen, buf); } EXPORT_SYMBOL_GPL(mtd_read_fact_prot_reg); int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, struct otp_info *buf) { - if (!mtd->_get_user_prot_info) + struct mtd_info *master = mtd_get_master(mtd); + + if (!master->_get_user_prot_info) return -EOPNOTSUPP; if (!len) return 0; - return mtd->_get_user_prot_info(mtd, len, retlen, buf); + return master->_get_user_prot_info(master, len, retlen, buf); } EXPORT_SYMBOL_GPL(mtd_get_user_prot_info); int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { + struct mtd_info *master = mtd_get_master(mtd); + *retlen = 0; - if (!mtd->_read_user_prot_reg) + if (!master->_read_user_prot_reg) return -EOPNOTSUPP; if (!len) return 0; - return mtd->_read_user_prot_reg(mtd, from, len, retlen, buf); + return master->_read_user_prot_reg(master, from, len, retlen, buf); } EXPORT_SYMBOL_GPL(mtd_read_user_prot_reg); int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, u_char *buf) { + struct mtd_info *master = mtd_get_master(mtd); int ret; *retlen = 0; - if (!mtd->_write_user_prot_reg) + if (!master->_write_user_prot_reg) return -EOPNOTSUPP; if (!len) return 0; - ret = mtd->_write_user_prot_reg(mtd, to, len, retlen, buf); + ret = master->_write_user_prot_reg(master, to, len, retlen, buf); if (ret) return ret; @@ -1718,80 +1796,105 @@ EXPORT_SYMBOL_GPL(mtd_write_user_prot_reg); int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len) { - if (!mtd->_lock_user_prot_reg) + struct mtd_info *master = mtd_get_master(mtd); + + if (!master->_lock_user_prot_reg) return -EOPNOTSUPP; if (!len) return 0; - return mtd->_lock_user_prot_reg(mtd, from, len); + return master->_lock_user_prot_reg(master, from, len); } EXPORT_SYMBOL_GPL(mtd_lock_user_prot_reg); /* Chip-supported device locking */ int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { - if (!mtd->_lock) + struct mtd_info *master = mtd_get_master(mtd); + + if (!master->_lock) return -EOPNOTSUPP; if (ofs < 0 || ofs >= mtd->size || len > mtd->size - ofs) return -EINVAL; if (!len) return 0; - return mtd->_lock(mtd, ofs, len); + return master->_lock(master, mtd_get_master_ofs(mtd, ofs), len); } EXPORT_SYMBOL_GPL(mtd_lock); int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { - if (!mtd->_unlock) + struct mtd_info *master = mtd_get_master(mtd); + + if (!master->_unlock) return -EOPNOTSUPP; if (ofs < 0 || ofs >= mtd->size || len > mtd->size - ofs) return -EINVAL; if (!len) return 0; - return mtd->_unlock(mtd, ofs, len); + return master->_unlock(master, mtd_get_master_ofs(mtd, ofs), len); } EXPORT_SYMBOL_GPL(mtd_unlock); int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) { - if (!mtd->_is_locked) + struct mtd_info *master = mtd_get_master(mtd); + + if (!master->_is_locked) return -EOPNOTSUPP; if (ofs < 0 || ofs >= mtd->size || len > mtd->size - ofs) return -EINVAL; if (!len) return 0; - return mtd->_is_locked(mtd, ofs, len); + return master->_is_locked(master, mtd_get_master_ofs(mtd, ofs), len); } EXPORT_SYMBOL_GPL(mtd_is_locked); int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs) { + struct mtd_info *master = mtd_get_master(mtd); + if (ofs < 0 || ofs >= mtd->size) return -EINVAL; - if (!mtd->_block_isreserved) + if (!master->_block_isreserved) return 0; - return mtd->_block_isreserved(mtd, ofs); + return master->_block_isreserved(master, mtd_get_master_ofs(mtd, ofs)); } EXPORT_SYMBOL_GPL(mtd_block_isreserved); int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs) { + struct mtd_info *master = mtd_get_master(mtd); + if (ofs < 0 || ofs >= mtd->size) return -EINVAL; - if (!mtd->_block_isbad) + if (!master->_block_isbad) return 0; - return mtd->_block_isbad(mtd, ofs); + return master->_block_isbad(master, mtd_get_master_ofs(mtd, ofs)); } EXPORT_SYMBOL_GPL(mtd_block_isbad); int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs) { - if (!mtd->_block_markbad) + struct mtd_info *master = mtd_get_master(mtd); + int ret; + + if (!master->_block_markbad) return -EOPNOTSUPP; if (ofs < 0 || ofs >= mtd->size) return -EINVAL; if (!(mtd->flags & MTD_WRITEABLE)) return -EROFS; - return mtd->_block_markbad(mtd, ofs); + + ret = master->_block_markbad(master, mtd_get_master_ofs(mtd, ofs)); + if (ret) + return ret; + + while (mtd->parent) { + mtd->ecc_stats.badblocks++; + mtd = mtd->parent; + } + + return 0; } EXPORT_SYMBOL_GPL(mtd_block_markbad); @@ -1841,12 +1944,17 @@ static int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen) { + struct mtd_info *master = mtd_get_master(mtd); + *retlen = 0; if (!(mtd->flags & MTD_WRITEABLE)) return -EROFS; - if (!mtd->_writev) + + if (!master->_writev) return default_mtd_writev(mtd, vecs, count, to, retlen); - return mtd->_writev(mtd, vecs, count, to, retlen); + + return master->_writev(master, vecs, count, + mtd_get_master_ofs(mtd, to), retlen); } EXPORT_SYMBOL_GPL(mtd_writev); diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 7328c066c5ba..3f6025684f58 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -20,339 +20,52 @@ #include "mtdcore.h" -/* Our partition linked list */ -static LIST_HEAD(mtd_partitions); -static DEFINE_MUTEX(mtd_partitions_mutex); - -/** - * struct mtd_part - our partition node structure - * - * @mtd: struct holding partition details - * @parent: parent mtd - flash device or another partition - * @offset: partition offset relative to the *flash device* - */ -struct mtd_part { - struct mtd_info mtd; - struct mtd_info *parent; - uint64_t offset; - struct list_head list; -}; - -/* - * Given a pointer to the MTD object in the mtd_part structure, we can retrieve - * the pointer to that structure. - */ -static inline struct mtd_part *mtd_to_part(const struct mtd_info *mtd) -{ - return container_of(mtd, struct mtd_part, mtd); -} - -static u64 part_absolute_offset(struct mtd_info *mtd) -{ - struct mtd_part *part = mtd_to_part(mtd); - - if (!mtd_is_partition(mtd)) - return 0; - - return part_absolute_offset(part->parent) + part->offset; -} - /* * MTD methods which simply translate the effective address and pass through * to the _real_ device. */ -static int part_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) +static inline void free_partition(struct mtd_info *mtd) { - struct mtd_part *part = mtd_to_part(mtd); - struct mtd_ecc_stats stats; - int res; - - stats = part->parent->ecc_stats; - res = part->parent->_read(part->parent, from + part->offset, len, - retlen, buf); - if (unlikely(mtd_is_eccerr(res))) - mtd->ecc_stats.failed += - part->parent->ecc_stats.failed - stats.failed; - else - mtd->ecc_stats.corrected += - part->parent->ecc_stats.corrected - stats.corrected; - return res; + kfree(mtd->name); + kfree(mtd); } -static int part_point(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, void **virt, resource_size_t *phys) -{ - struct mtd_part *part = mtd_to_part(mtd); - - return part->parent->_point(part->parent, from + part->offset, len, - retlen, virt, phys); -} - -static int part_unpoint(struct mtd_info *mtd, loff_t from, size_t len) -{ - struct mtd_part *part = mtd_to_part(mtd); - - return part->parent->_unpoint(part->parent, from + part->offset, len); -} - -static int part_read_oob(struct mtd_info *mtd, loff_t from, - struct mtd_oob_ops *ops) -{ - struct mtd_part *part = mtd_to_part(mtd); - struct mtd_ecc_stats stats; - int res; - - stats = part->parent->ecc_stats; - res = part->parent->_read_oob(part->parent, from + part->offset, ops); - if (unlikely(mtd_is_eccerr(res))) - mtd->ecc_stats.failed += - part->parent->ecc_stats.failed - stats.failed; - else - mtd->ecc_stats.corrected += - part->parent->ecc_stats.corrected - stats.corrected; - return res; -} - -static int part_read_user_prot_reg(struct mtd_info *mtd, loff_t from, - size_t len, size_t *retlen, u_char *buf) -{ - struct mtd_part *part = mtd_to_part(mtd); - return part->parent->_read_user_prot_reg(part->parent, from, len, - retlen, buf); -} - -static int part_get_user_prot_info(struct mtd_info *mtd, size_t len, - size_t *retlen, struct otp_info *buf) -{ - struct mtd_part *part = mtd_to_part(mtd); - return part->parent->_get_user_prot_info(part->parent, len, retlen, - buf); -} - -static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, - size_t len, size_t *retlen, u_char *buf) -{ - struct mtd_part *part = mtd_to_part(mtd); - return part->parent->_read_fact_prot_reg(part->parent, from, len, - retlen, buf); -} - -static int part_get_fact_prot_info(struct mtd_info *mtd, size_t len, - size_t *retlen, struct otp_info *buf) -{ - struct mtd_part *part = mtd_to_part(mtd); - return part->parent->_get_fact_prot_info(part->parent, len, retlen, - buf); -} - -static int part_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - struct mtd_part *part = mtd_to_part(mtd); - return part->parent->_write(part->parent, to + part->offset, len, - retlen, buf); -} - -static int part_panic_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - struct mtd_part *part = mtd_to_part(mtd); - return part->parent->_panic_write(part->parent, to + part->offset, len, - retlen, buf); -} - -static int part_write_oob(struct mtd_info *mtd, loff_t to, - struct mtd_oob_ops *ops) -{ - struct mtd_part *part = mtd_to_part(mtd); - - return part->parent->_write_oob(part->parent, to + part->offset, ops); -} - -static int part_write_user_prot_reg(struct mtd_info *mtd, loff_t from, - size_t len, size_t *retlen, u_char *buf) -{ - struct mtd_part *part = mtd_to_part(mtd); - return part->parent->_write_user_prot_reg(part->parent, from, len, - retlen, buf); -} - -static int part_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, - size_t len) -{ - struct mtd_part *part = mtd_to_part(mtd); - return part->parent->_lock_user_prot_reg(part->parent, from, len); -} - -static int part_writev(struct mtd_info *mtd, const struct kvec *vecs, - unsigned long count, loff_t to, size_t *retlen) -{ - struct mtd_part *part = mtd_to_part(mtd); - return part->parent->_writev(part->parent, vecs, count, - to + part->offset, retlen); -} - -static int part_erase(struct mtd_info *mtd, struct erase_info *instr) -{ - struct mtd_part *part = mtd_to_part(mtd); - int ret; - - instr->addr += part->offset; - ret = part->parent->_erase(part->parent, instr); - if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) - instr->fail_addr -= part->offset; - instr->addr -= part->offset; - - return ret; -} - -static int part_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) -{ - struct mtd_part *part = mtd_to_part(mtd); - return part->parent->_lock(part->parent, ofs + part->offset, len); -} - -static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) -{ - struct mtd_part *part = mtd_to_part(mtd); - return part->parent->_unlock(part->parent, ofs + part->offset, len); -} - -static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) -{ - struct mtd_part *part = mtd_to_part(mtd); - return part->parent->_is_locked(part->parent, ofs + part->offset, len); -} - -static void part_sync(struct mtd_info *mtd) -{ - struct mtd_part *part = mtd_to_part(mtd); - part->parent->_sync(part->parent); -} - -static int part_suspend(struct mtd_info *mtd) -{ - struct mtd_part *part = mtd_to_part(mtd); - return part->parent->_suspend(part->parent); -} - -static void part_resume(struct mtd_info *mtd) -{ - struct mtd_part *part = mtd_to_part(mtd); - part->parent->_resume(part->parent); -} - -static int part_block_isreserved(struct mtd_info *mtd, loff_t ofs) -{ - struct mtd_part *part = mtd_to_part(mtd); - ofs += part->offset; - return part->parent->_block_isreserved(part->parent, ofs); -} - -static int part_block_isbad(struct mtd_info *mtd, loff_t ofs) -{ - struct mtd_part *part = mtd_to_part(mtd); - ofs += part->offset; - return part->parent->_block_isbad(part->parent, ofs); -} - -static int part_block_markbad(struct mtd_info *mtd, loff_t ofs) -{ - struct mtd_part *part = mtd_to_part(mtd); - int res; - - ofs += part->offset; - res = part->parent->_block_markbad(part->parent, ofs); - if (!res) - mtd->ecc_stats.badblocks++; - return res; -} - -static int part_get_device(struct mtd_info *mtd) -{ - struct mtd_part *part = mtd_to_part(mtd); - return part->parent->_get_device(part->parent); -} - -static void part_put_device(struct mtd_info *mtd) -{ - struct mtd_part *part = mtd_to_part(mtd); - part->parent->_put_device(part->parent); -} - -static int part_ooblayout_ecc(struct mtd_info *mtd, int section, - struct mtd_oob_region *oobregion) -{ - struct mtd_part *part = mtd_to_part(mtd); - - return mtd_ooblayout_ecc(part->parent, section, oobregion); -} - -static int part_ooblayout_free(struct mtd_info *mtd, int section, - struct mtd_oob_region *oobregion) -{ - struct mtd_part *part = mtd_to_part(mtd); - - return mtd_ooblayout_free(part->parent, section, oobregion); -} - -static const struct mtd_ooblayout_ops part_ooblayout_ops = { - .ecc = part_ooblayout_ecc, - .free = part_ooblayout_free, -}; - -static int part_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len) -{ - struct mtd_part *part = mtd_to_part(mtd); - - return part->parent->_max_bad_blocks(part->parent, - ofs + part->offset, len); -} - -static inline void free_partition(struct mtd_part *p) -{ - kfree(p->mtd.name); - kfree(p); -} - -static struct mtd_part *allocate_partition(struct mtd_info *parent, - const struct mtd_partition *part, int partno, - uint64_t cur_offset) +static struct mtd_info *allocate_partition(struct mtd_info *parent, + const struct mtd_partition *part, + int partno, uint64_t cur_offset) { int wr_alignment = (parent->flags & MTD_NO_ERASE) ? parent->writesize : parent->erasesize; - struct mtd_part *slave; + struct mtd_info *child, *master = mtd_get_master(parent); u32 remainder; char *name; u64 tmp; /* allocate the partition structure */ - slave = kzalloc(sizeof(*slave), GFP_KERNEL); + child = kzalloc(sizeof(*child), GFP_KERNEL); name = kstrdup(part->name, GFP_KERNEL); - if (!name || !slave) { + if (!name || !child) { printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n", parent->name); kfree(name); - kfree(slave); + kfree(child); return ERR_PTR(-ENOMEM); } /* set up the MTD object for this partition */ - slave->mtd.type = parent->type; - slave->mtd.flags = parent->orig_flags & ~part->mask_flags; - slave->mtd.orig_flags = slave->mtd.flags; - slave->mtd.size = part->size; - slave->mtd.writesize = parent->writesize; - slave->mtd.writebufsize = parent->writebufsize; - slave->mtd.oobsize = parent->oobsize; - slave->mtd.oobavail = parent->oobavail; - slave->mtd.subpage_sft = parent->subpage_sft; - slave->mtd.pairing = parent->pairing; + child->type = parent->type; + child->part.flags = parent->flags & ~part->mask_flags; + child->flags = child->part.flags; + child->size = part->size; + child->writesize = parent->writesize; + child->writebufsize = parent->writebufsize; + child->oobsize = parent->oobsize; + child->oobavail = parent->oobavail; + child->subpage_sft = parent->subpage_sft; - slave->mtd.name = name; - slave->mtd.owner = parent->owner; + child->name = name; + child->owner = parent->owner; /* NOTE: Historically, we didn't arrange MTDs as a tree out of * concern for showing the same data in multiple partitions. @@ -360,134 +73,76 @@ static struct mtd_part *allocate_partition(struct mtd_info *parent, * so the MTD_PARTITIONED_MASTER option allows that. The master * will have device nodes etc only if this is set, so make the * parent conditional on that option. Note, this is a way to - * distinguish between the master and the partition in sysfs. + * distinguish between the parent and its partitions in sysfs. */ - slave->mtd.dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) || mtd_is_partition(parent) ? - &parent->dev : - parent->dev.parent; - slave->mtd.dev.of_node = part->of_node; + child->dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) || mtd_is_partition(parent) ? + &parent->dev : parent->dev.parent; + child->dev.of_node = part->of_node; + child->parent = parent; + child->part.offset = part->offset; + INIT_LIST_HEAD(&child->partitions); - if (parent->_read) - slave->mtd._read = part_read; - if (parent->_write) - slave->mtd._write = part_write; - - if (parent->_panic_write) - slave->mtd._panic_write = part_panic_write; - - if (parent->_point && parent->_unpoint) { - slave->mtd._point = part_point; - slave->mtd._unpoint = part_unpoint; - } - - if (parent->_read_oob) - slave->mtd._read_oob = part_read_oob; - if (parent->_write_oob) - slave->mtd._write_oob = part_write_oob; - if (parent->_read_user_prot_reg) - slave->mtd._read_user_prot_reg = part_read_user_prot_reg; - if (parent->_read_fact_prot_reg) - slave->mtd._read_fact_prot_reg = part_read_fact_prot_reg; - if (parent->_write_user_prot_reg) - slave->mtd._write_user_prot_reg = part_write_user_prot_reg; - if (parent->_lock_user_prot_reg) - slave->mtd._lock_user_prot_reg = part_lock_user_prot_reg; - if (parent->_get_user_prot_info) - slave->mtd._get_user_prot_info = part_get_user_prot_info; - if (parent->_get_fact_prot_info) - slave->mtd._get_fact_prot_info = part_get_fact_prot_info; - if (parent->_sync) - slave->mtd._sync = part_sync; - if (!partno && !parent->dev.class && parent->_suspend && - parent->_resume) { - slave->mtd._suspend = part_suspend; - slave->mtd._resume = part_resume; - } - if (parent->_writev) - slave->mtd._writev = part_writev; - if (parent->_lock) - slave->mtd._lock = part_lock; - if (parent->_unlock) - slave->mtd._unlock = part_unlock; - if (parent->_is_locked) - slave->mtd._is_locked = part_is_locked; - if (parent->_block_isreserved) - slave->mtd._block_isreserved = part_block_isreserved; - if (parent->_block_isbad) - slave->mtd._block_isbad = part_block_isbad; - if (parent->_block_markbad) - slave->mtd._block_markbad = part_block_markbad; - if (parent->_max_bad_blocks) - slave->mtd._max_bad_blocks = part_max_bad_blocks; - - if (parent->_get_device) - slave->mtd._get_device = part_get_device; - if (parent->_put_device) - slave->mtd._put_device = part_put_device; - - slave->mtd._erase = part_erase; - slave->parent = parent; - slave->offset = part->offset; - - if (slave->offset == MTDPART_OFS_APPEND) - slave->offset = cur_offset; - if (slave->offset == MTDPART_OFS_NXTBLK) { + if (child->part.offset == MTDPART_OFS_APPEND) + child->part.offset = cur_offset; + if (child->part.offset == MTDPART_OFS_NXTBLK) { tmp = cur_offset; - slave->offset = cur_offset; + child->part.offset = cur_offset; remainder = do_div(tmp, wr_alignment); if (remainder) { - slave->offset += wr_alignment - remainder; + child->part.offset += wr_alignment - remainder; printk(KERN_NOTICE "Moving partition %d: " "0x%012llx -> 0x%012llx\n", partno, - (unsigned long long)cur_offset, (unsigned long long)slave->offset); + (unsigned long long)cur_offset, + child->part.offset); } } - if (slave->offset == MTDPART_OFS_RETAIN) { - slave->offset = cur_offset; - if (parent->size - slave->offset >= slave->mtd.size) { - slave->mtd.size = parent->size - slave->offset - - slave->mtd.size; + if (child->part.offset == MTDPART_OFS_RETAIN) { + child->part.offset = cur_offset; + if (parent->size - child->part.offset >= child->size) { + child->size = parent->size - child->part.offset - + child->size; } else { printk(KERN_ERR "mtd partition \"%s\" doesn't have enough space: %#llx < %#llx, disabled\n", - part->name, parent->size - slave->offset, - slave->mtd.size); + part->name, parent->size - child->part.offset, + child->size); /* register to preserve ordering */ goto out_register; } } - if (slave->mtd.size == MTDPART_SIZ_FULL) - slave->mtd.size = parent->size - slave->offset; + if (child->size == MTDPART_SIZ_FULL) + child->size = parent->size - child->part.offset; - printk(KERN_NOTICE "0x%012llx-0x%012llx : \"%s\"\n", (unsigned long long)slave->offset, - (unsigned long long)(slave->offset + slave->mtd.size), slave->mtd.name); + printk(KERN_NOTICE "0x%012llx-0x%012llx : \"%s\"\n", + child->part.offset, child->part.offset + child->size, + child->name); /* let's do some sanity checks */ - if (slave->offset >= parent->size) { + if (child->part.offset >= parent->size) { /* let's register it anyway to preserve ordering */ - slave->offset = 0; - slave->mtd.size = 0; + child->part.offset = 0; + child->size = 0; /* Initialize ->erasesize to make add_mtd_device() happy. */ - slave->mtd.erasesize = parent->erasesize; - + child->erasesize = parent->erasesize; printk(KERN_ERR"mtd: partition \"%s\" is out of reach -- disabled\n", part->name); goto out_register; } - if (slave->offset + slave->mtd.size > parent->size) { - slave->mtd.size = parent->size - slave->offset; + if (child->part.offset + child->size > parent->size) { + child->size = parent->size - child->part.offset; printk(KERN_WARNING"mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#llx\n", - part->name, parent->name, (unsigned long long)slave->mtd.size); + part->name, parent->name, child->size); } if (parent->numeraseregions > 1) { /* Deal with variable erase size stuff */ int i, max = parent->numeraseregions; - u64 end = slave->offset + slave->mtd.size; + u64 end = child->part.offset + child->size; struct mtd_erase_region_info *regions = parent->eraseregions; /* Find the first erase regions which is part of this * partition. */ - for (i = 0; i < max && regions[i].offset <= slave->offset; i++) + for (i = 0; i < max && regions[i].offset <= child->part.offset; + i++) ; /* The loop searched for the region _behind_ the first one */ if (i > 0) @@ -495,70 +150,68 @@ static struct mtd_part *allocate_partition(struct mtd_info *parent, /* Pick biggest erasesize */ for (; i < max && regions[i].offset < end; i++) { - if (slave->mtd.erasesize < regions[i].erasesize) { - slave->mtd.erasesize = regions[i].erasesize; - } + if (child->erasesize < regions[i].erasesize) + child->erasesize = regions[i].erasesize; } - BUG_ON(slave->mtd.erasesize == 0); + BUG_ON(child->erasesize == 0); } else { /* Single erase size */ - slave->mtd.erasesize = parent->erasesize; + child->erasesize = parent->erasesize; } /* - * Slave erasesize might differ from the master one if the master + * Child erasesize might differ from the parent one if the parent * exposes several regions with different erasesize. Adjust * wr_alignment accordingly. */ - if (!(slave->mtd.flags & MTD_NO_ERASE)) - wr_alignment = slave->mtd.erasesize; + if (!(child->flags & MTD_NO_ERASE)) + wr_alignment = child->erasesize; - tmp = part_absolute_offset(parent) + slave->offset; + tmp = mtd_get_master_ofs(child, 0); remainder = do_div(tmp, wr_alignment); - if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) { + if ((child->flags & MTD_WRITEABLE) && remainder) { /* Doesn't start on a boundary of major erase size */ /* FIXME: Let it be writable if it is on a boundary of * _minor_ erase size though */ - slave->mtd.flags &= ~MTD_WRITEABLE; + child->flags &= ~MTD_WRITEABLE; printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n", part->name); } - tmp = part_absolute_offset(parent) + slave->mtd.size; + tmp = mtd_get_master_ofs(child, 0) + child->size; remainder = do_div(tmp, wr_alignment); - if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) { - slave->mtd.flags &= ~MTD_WRITEABLE; + if ((child->flags & MTD_WRITEABLE) && remainder) { + child->flags &= ~MTD_WRITEABLE; printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n", part->name); } - mtd_set_ooblayout(&slave->mtd, &part_ooblayout_ops); - slave->mtd.ecc_step_size = parent->ecc_step_size; - slave->mtd.ecc_strength = parent->ecc_strength; - slave->mtd.bitflip_threshold = parent->bitflip_threshold; + child->ecc_step_size = parent->ecc_step_size; + child->ecc_strength = parent->ecc_strength; + child->bitflip_threshold = parent->bitflip_threshold; - if (parent->_block_isbad) { + if (master->_block_isbad) { uint64_t offs = 0; - while (offs < slave->mtd.size) { - if (mtd_block_isreserved(parent, offs + slave->offset)) - slave->mtd.ecc_stats.bbtblocks++; - else if (mtd_block_isbad(parent, offs + slave->offset)) - slave->mtd.ecc_stats.badblocks++; - offs += slave->mtd.erasesize; + while (offs < child->size) { + if (mtd_block_isreserved(child, offs)) + child->ecc_stats.bbtblocks++; + else if (mtd_block_isbad(child, offs)) + child->ecc_stats.badblocks++; + offs += child->erasesize; } } out_register: - return slave; + return child; } static ssize_t mtd_partition_offset_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mtd_info *mtd = dev_get_drvdata(dev); - struct mtd_part *part = mtd_to_part(mtd); - return snprintf(buf, PAGE_SIZE, "%llu\n", part->offset); + + return snprintf(buf, PAGE_SIZE, "%lld\n", mtd->part.offset); } static DEVICE_ATTR(offset, S_IRUGO, mtd_partition_offset_show, NULL); @@ -568,9 +221,9 @@ static const struct attribute *mtd_partition_attrs[] = { NULL }; -static int mtd_add_partition_attrs(struct mtd_part *new) +static int mtd_add_partition_attrs(struct mtd_info *new) { - int ret = sysfs_create_files(&new->mtd.dev.kobj, mtd_partition_attrs); + int ret = sysfs_create_files(&new->dev.kobj, mtd_partition_attrs); if (ret) printk(KERN_WARNING "mtd: failed to create partition attrs, err=%d\n", ret); @@ -580,8 +233,9 @@ static int mtd_add_partition_attrs(struct mtd_part *new) int mtd_add_partition(struct mtd_info *parent, const char *name, long long offset, long long length) { + struct mtd_info *master = mtd_get_master(parent); struct mtd_partition part; - struct mtd_part *new; + struct mtd_info *child; int ret = 0; /* the direct offset is expected */ @@ -600,28 +254,28 @@ int mtd_add_partition(struct mtd_info *parent, const char *name, part.size = length; part.offset = offset; - new = allocate_partition(parent, &part, -1, offset); - if (IS_ERR(new)) - return PTR_ERR(new); + child = allocate_partition(parent, &part, -1, offset); + if (IS_ERR(child)) + return PTR_ERR(child); - mutex_lock(&mtd_partitions_mutex); - list_add(&new->list, &mtd_partitions); - mutex_unlock(&mtd_partitions_mutex); + mutex_lock(&master->master.partitions_lock); + list_add_tail(&child->part.node, &parent->partitions); + mutex_unlock(&master->master.partitions_lock); - ret = add_mtd_device(&new->mtd); + ret = add_mtd_device(child); if (ret) goto err_remove_part; - mtd_add_partition_attrs(new); + mtd_add_partition_attrs(child); return 0; err_remove_part: - mutex_lock(&mtd_partitions_mutex); - list_del(&new->list); - mutex_unlock(&mtd_partitions_mutex); + mutex_lock(&master->master.partitions_lock); + list_del(&child->part.node); + mutex_unlock(&master->master.partitions_lock); - free_partition(new); + free_partition(child); return ret; } @@ -630,119 +284,142 @@ EXPORT_SYMBOL_GPL(mtd_add_partition); /** * __mtd_del_partition - delete MTD partition * - * @priv: internal MTD struct for partition to be deleted + * @priv: MTD structure to be deleted * * This function must be called with the partitions mutex locked. */ -static int __mtd_del_partition(struct mtd_part *priv) +static int __mtd_del_partition(struct mtd_info *mtd) { - struct mtd_part *child, *next; + struct mtd_info *child, *next; int err; - list_for_each_entry_safe(child, next, &mtd_partitions, list) { - if (child->parent == &priv->mtd) { - err = __mtd_del_partition(child); - if (err) - return err; - } + list_for_each_entry_safe(child, next, &mtd->partitions, part.node) { + err = __mtd_del_partition(child); + if (err) + return err; } - sysfs_remove_files(&priv->mtd.dev.kobj, mtd_partition_attrs); + sysfs_remove_files(&mtd->dev.kobj, mtd_partition_attrs); - err = del_mtd_device(&priv->mtd); + err = del_mtd_device(mtd); if (err) return err; - list_del(&priv->list); - free_partition(priv); + list_del(&child->part.node); + free_partition(mtd); return 0; } /* * This function unregisters and destroy all slave MTD objects which are - * attached to the given MTD object. + * attached to the given MTD object, recursively. */ -int del_mtd_partitions(struct mtd_info *mtd) +static int __del_mtd_partitions(struct mtd_info *mtd) { - struct mtd_part *slave, *next; + struct mtd_info *child, *next; + LIST_HEAD(tmp_list); int ret, err = 0; - mutex_lock(&mtd_partitions_mutex); - list_for_each_entry_safe(slave, next, &mtd_partitions, list) - if (slave->parent == mtd) { - ret = __mtd_del_partition(slave); - if (ret < 0) - err = ret; + list_for_each_entry_safe(child, next, &mtd->partitions, part.node) { + if (mtd_has_partitions(child)) + del_mtd_partitions(child); + + pr_info("Deleting %s MTD partition\n", child->name); + ret = del_mtd_device(child); + if (ret < 0) { + pr_err("Error when deleting partition \"%s\" (%d)\n", + child->name, ret); + err = ret; + continue; } - mutex_unlock(&mtd_partitions_mutex); + + list_del(&child->part.node); + free_partition(child); + } return err; } +int del_mtd_partitions(struct mtd_info *mtd) +{ + struct mtd_info *master = mtd_get_master(mtd); + int ret; + + pr_info("Deleting MTD partitions on \"%s\":\n", mtd->name); + + mutex_lock(&master->master.partitions_lock); + ret = __del_mtd_partitions(mtd); + mutex_unlock(&master->master.partitions_lock); + + return ret; +} + int mtd_del_partition(struct mtd_info *mtd, int partno) { - struct mtd_part *slave, *next; + struct mtd_info *child, *master = mtd_get_master(mtd); int ret = -EINVAL; - mutex_lock(&mtd_partitions_mutex); - list_for_each_entry_safe(slave, next, &mtd_partitions, list) - if ((slave->parent == mtd) && - (slave->mtd.index == partno)) { - ret = __mtd_del_partition(slave); + mutex_lock(&master->master.partitions_lock); + list_for_each_entry(child, &mtd->partitions, part.node) { + if (child->index == partno) { + ret = __mtd_del_partition(child); break; } - mutex_unlock(&mtd_partitions_mutex); + } + mutex_unlock(&master->master.partitions_lock); return ret; } EXPORT_SYMBOL_GPL(mtd_del_partition); /* - * This function, given a master MTD object and a partition table, creates - * and registers slave MTD objects which are bound to the master according to - * the partition definitions. + * This function, given a parent MTD object and a partition table, creates + * and registers the child MTD objects which are bound to the parent according + * to the partition definitions. * - * For historical reasons, this function's caller only registers the master + * For historical reasons, this function's caller only registers the parent * if the MTD_PARTITIONED_MASTER config option is set. */ -int add_mtd_partitions(struct mtd_info *master, +int add_mtd_partitions(struct mtd_info *parent, const struct mtd_partition *parts, int nbparts) { - struct mtd_part *slave; + struct mtd_info *child, *master = mtd_get_master(parent); uint64_t cur_offset = 0; int i, ret; - printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); + printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", + nbparts, parent->name); for (i = 0; i < nbparts; i++) { - slave = allocate_partition(master, parts + i, i, cur_offset); - if (IS_ERR(slave)) { - ret = PTR_ERR(slave); + child = allocate_partition(parent, parts + i, i, cur_offset); + if (IS_ERR(child)) { + ret = PTR_ERR(child); goto err_del_partitions; } - mutex_lock(&mtd_partitions_mutex); - list_add(&slave->list, &mtd_partitions); - mutex_unlock(&mtd_partitions_mutex); + mutex_lock(&master->master.partitions_lock); + list_add_tail(&child->part.node, &parent->partitions); + mutex_unlock(&master->master.partitions_lock); - ret = add_mtd_device(&slave->mtd); + ret = add_mtd_device(child); if (ret) { - mutex_lock(&mtd_partitions_mutex); - list_del(&slave->list); - mutex_unlock(&mtd_partitions_mutex); + mutex_lock(&master->master.partitions_lock); + list_del(&child->part.node); + mutex_unlock(&master->master.partitions_lock); - free_partition(slave); + free_partition(child); goto err_del_partitions; } - mtd_add_partition_attrs(slave); - /* Look for subpartitions */ - parse_mtd_partitions(&slave->mtd, parts[i].types, NULL); + mtd_add_partition_attrs(child); - cur_offset = slave->offset + slave->mtd.size; + /* Look for subpartitions */ + parse_mtd_partitions(child, parts[i].types, NULL); + + cur_offset = child->part.offset + child->size; } return 0; @@ -1023,29 +700,11 @@ void mtd_part_parser_cleanup(struct mtd_partitions *parts) } } -int mtd_is_partition(const struct mtd_info *mtd) -{ - struct mtd_part *part; - int ispart = 0; - - mutex_lock(&mtd_partitions_mutex); - list_for_each_entry(part, &mtd_partitions, list) - if (&part->mtd == mtd) { - ispart = 1; - break; - } - mutex_unlock(&mtd_partitions_mutex); - - return ispart; -} -EXPORT_SYMBOL_GPL(mtd_is_partition); - /* Returns the size of the entire flash chip */ uint64_t mtd_get_device_size(const struct mtd_info *mtd) { - if (!mtd_is_partition(mtd)) - return mtd->size; + struct mtd_info *master = mtd_get_master((struct mtd_info *)mtd); - return mtd_get_device_size(mtd_to_part(mtd)->parent); + return master->size; } EXPORT_SYMBOL_GPL(mtd_get_device_size); diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 249e8d9bfbcd..2d1f4a61f4ac 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -194,10 +195,43 @@ struct mtd_debug_info { const char *partid; }; +/** + * struct mtd_part - MTD partition specific fields + * + * @node: list node used to add an MTD partition to the parent partition list + * @offset: offset of the partition relatively to the parent offset + * @flags: original flags (before the mtdpart logic decided to tweak them based + * on flash constraints, like eraseblock/pagesize alignment) + * + * This struct is embedded in mtd_info and contains partition-specific + * properties/fields. + */ +struct mtd_part { + struct list_head node; + u64 offset; + u32 flags; +}; + +/** + * struct mtd_master - MTD master specific fields + * + * @partitions_lock: lock protecting accesses to the partition list. Protects + * not only the master partition list, but also all + * sub-partitions. + * @suspended: et to 1 when the device is suspended, 0 otherwise + * + * This struct is embedded in mtd_info and contains master-specific + * properties/fields. The master is the root MTD device from the MTD partition + * point of view. + */ +struct mtd_master { + struct mutex partitions_lock; + unsigned int suspended : 1; +}; + struct mtd_info { u_char type; uint32_t flags; - uint32_t orig_flags; /* Flags as before running mtd checks */ uint64_t size; // Total size of the MTD /* "Major" erase size for the device. Naïve users may take this @@ -339,8 +373,52 @@ struct mtd_info { int usecount; struct mtd_debug_info dbg; struct nvmem_device *nvmem; + + /* + * Parent device from the MTD partition point of view. + * + * MTD masters do not have any parent, MTD partitions do. The parent + * MTD device can itself be a partition. + */ + struct mtd_info *parent; + + /* List of partitions attached to this MTD device */ + struct list_head partitions; + + union { + struct mtd_part part; + struct mtd_master master; + }; }; +static inline struct mtd_info *mtd_get_master(struct mtd_info *mtd) +{ + while (mtd->parent) + mtd = mtd->parent; + + return mtd; +} + +static inline u64 mtd_get_master_ofs(struct mtd_info *mtd, u64 ofs) +{ + while (mtd->parent) { + ofs += mtd->part.offset; + mtd = mtd->parent; + } + + return ofs; +} + +static inline bool mtd_is_partition(const struct mtd_info *mtd) +{ + return mtd->parent; +} + +static inline bool mtd_has_partitions(const struct mtd_info *mtd) +{ + return !list_empty(&mtd->partitions); +} + int mtd_ooblayout_ecc(struct mtd_info *mtd, int section, struct mtd_oob_region *oobecc); int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte, @@ -392,13 +470,16 @@ static inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops) static inline int mtd_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len) { - if (!mtd->_max_bad_blocks) + struct mtd_info *master = mtd_get_master(mtd); + + if (!master->_max_bad_blocks) return -ENOTSUPP; if (mtd->size < (len + ofs) || ofs < 0) return -EINVAL; - return mtd->_max_bad_blocks(mtd, ofs, len); + return master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs), + len); } int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit, @@ -439,8 +520,10 @@ int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, static inline void mtd_sync(struct mtd_info *mtd) { - if (mtd->_sync) - mtd->_sync(mtd); + struct mtd_info *master = mtd_get_master(mtd); + + if (master->_sync) + master->_sync(master); } int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); @@ -452,13 +535,31 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs); static inline int mtd_suspend(struct mtd_info *mtd) { - return mtd->_suspend ? mtd->_suspend(mtd) : 0; + struct mtd_info *master = mtd_get_master(mtd); + int ret; + + if (master->master.suspended) + return 0; + + ret = master->_suspend ? master->_suspend(master) : 0; + if (ret) + return ret; + + master->master.suspended = 1; + return 0; } static inline void mtd_resume(struct mtd_info *mtd) { - if (mtd->_resume) - mtd->_resume(mtd); + struct mtd_info *master = mtd_get_master(mtd); + + if (!master->master.suspended) + return; + + if (master->_resume) + master->_resume(master); + + master->master.suspended = 0; } static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd) @@ -538,7 +639,9 @@ static inline loff_t mtd_wunit_to_offset(struct mtd_info *mtd, loff_t base, static inline int mtd_has_oob(const struct mtd_info *mtd) { - return mtd->_read_oob && mtd->_write_oob; + struct mtd_info *master = mtd_get_master((struct mtd_info *)mtd); + + return master->_read_oob && master->_write_oob; } static inline int mtd_type_is_nand(const struct mtd_info *mtd) @@ -548,7 +651,9 @@ static inline int mtd_type_is_nand(const struct mtd_info *mtd) static inline int mtd_can_have_bb(const struct mtd_info *mtd) { - return !!mtd->_block_isbad; + struct mtd_info *master = mtd_get_master((struct mtd_info *)mtd); + + return !!master->_block_isbad; } /* Kernel-side ioctl definitions */ diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h index 11cb0c50cd84..e545c050d3e8 100644 --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h @@ -105,7 +105,6 @@ extern void deregister_mtd_parser(struct mtd_part_parser *parser); module_driver(__mtd_part_parser, register_mtd_parser, \ deregister_mtd_parser) -int mtd_is_partition(const struct mtd_info *mtd); int mtd_add_partition(struct mtd_info *master, const char *name, long long offset, long long length); int mtd_del_partition(struct mtd_info *master, int partno); From 13a964665fc1bedcdab1015e999f7631ec928c88 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 8 Feb 2020 11:36:12 +0000 Subject: [PATCH 1522/4444] mtd: fix spelling mistake "BlockMultiplerBits" -> "BlockMultiplierBits" There is a spelling mistake (missing i) in pr_info messages. Fix these. Signed-off-by: Colin Ian King Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200208113612.817988-1-colin.king@canonical.com --- drivers/mtd/inftlmount.c | 2 +- drivers/mtd/nand/raw/diskonchip.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c index 54b176d4319f..af16d3485de0 100644 --- a/drivers/mtd/inftlmount.c +++ b/drivers/mtd/inftlmount.c @@ -130,7 +130,7 @@ static int find_boot_record(struct INFTLrecord *inftl) " NoOfBootImageBlocks = %d\n" " NoOfBinaryPartitions = %d\n" " NoOfBDTLPartitions = %d\n" - " BlockMultiplerBits = %d\n" + " BlockMultiplierBits = %d\n" " FormatFlgs = %d\n" " OsakVersion = 0x%x\n" " PercentUsed = %d\n", diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index c0e1a8ebe820..2833c49c1378 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -1169,7 +1169,7 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti " NoOfBootImageBlocks = %d\n" " NoOfBinaryPartitions = %d\n" " NoOfBDTLPartitions = %d\n" - " BlockMultiplerBits = %d\n" + " BlockMultiplierBits = %d\n" " FormatFlgs = %d\n" " OsakVersion = %d.%d.%d.%d\n" " PercentUsed = %d\n", From c0b66dce0ca8e628c73f673f368230a455ea6631 Mon Sep 17 00:00:00 2001 From: Vignesh Raghavendra Date: Thu, 27 Feb 2020 10:42:12 +0530 Subject: [PATCH 1523/4444] MAINTAINERS: Add staging branch for HyperBus Update HyperBus entry with branch used to stage patches under mtd.git. Also, add mailing list and patchwork queue information. Signed-off-by: Vignesh Raghavendra Acked-by: Miquel Raynal Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200227051212.15496-1-vigneshr@ti.com --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 6158a143a13e..abe66664d5f4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7770,6 +7770,9 @@ F: Documentation/ABI/testing/debugfs-hyperv HYPERBUS SUPPORT M: Vignesh Raghavendra +L: linux-mtd@lists.infradead.org +Q: http://patchwork.ozlabs.org/project/linux-mtd/list/ +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git cfi/next S: Supported F: drivers/mtd/hyperbus/ F: include/linux/mtd/hyperbus.h From 4da0ea71ea934af18db4c63396ba2af1a679ef02 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 28 Feb 2020 12:25:54 +0300 Subject: [PATCH 1524/4444] mtd: lpddr: Fix a double free in probe() This function is only called from lpddr_probe(). We free "lpddr" both here and in the caller, so it's a double free. The best place to free "lpddr" is in lpddr_probe() so let's delete this one. Fixes: 8dc004395d5e ("[MTD] LPDDR qinfo probing.") Signed-off-by: Dan Carpenter Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200228092554.o57igp3nqhyvf66t@kili.mountain --- drivers/mtd/lpddr/lpddr_cmds.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c index 1efc643c9871..9341a8a592e8 100644 --- a/drivers/mtd/lpddr/lpddr_cmds.c +++ b/drivers/mtd/lpddr/lpddr_cmds.c @@ -68,7 +68,6 @@ struct mtd_info *lpddr_cmdset(struct map_info *map) shared = kmalloc_array(lpddr->numchips, sizeof(struct flchip_shared), GFP_KERNEL); if (!shared) { - kfree(lpddr); kfree(mtd); return NULL; } From 2243af41115d0e36e6414df6dd2a0386e022d9f8 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Tue, 25 Feb 2020 02:58:34 +0300 Subject: [PATCH 1525/4444] memory: tegra: Correct debugfs clk rate-range on Tegra20 Correctly set clk rate-range if number of available timings is zero. This fixes noisy "invalid range [4294967295, 0]" error messages during boot. Fixes: 8209eefa3d37 ("memory: tegra: Implement EMC debugfs interface on Tegra20") Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/memory/tegra/tegra20-emc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/memory/tegra/tegra20-emc.c b/drivers/memory/tegra/tegra20-emc.c index 8ae474d9bfb9..b16715e9515d 100644 --- a/drivers/memory/tegra/tegra20-emc.c +++ b/drivers/memory/tegra/tegra20-emc.c @@ -628,6 +628,11 @@ static void tegra_emc_debugfs_init(struct tegra_emc *emc) emc->debugfs.max_rate = emc->timings[i].rate; } + if (!emc->num_timings) { + emc->debugfs.min_rate = clk_get_rate(emc->clk); + emc->debugfs.max_rate = emc->debugfs.min_rate; + } + err = clk_set_rate_range(emc->clk, emc->debugfs.min_rate, emc->debugfs.max_rate); if (err < 0) { From a53670e1a734ba56fac84cf2b93b838bd4a6b835 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Tue, 25 Feb 2020 02:58:35 +0300 Subject: [PATCH 1526/4444] memory: tegra: Correct debugfs clk rate-range on Tegra30 Correctly set clk rate-range if number of available timings is zero. This fixes noisy "invalid range [4294967295, 0]" error messages during boot. Fixes: 8cee32b40040 ("memory: tegra: Implement EMC debugfs interface on Tegra30") Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/memory/tegra/tegra30-emc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/memory/tegra/tegra30-emc.c b/drivers/memory/tegra/tegra30-emc.c index e3efd9529506..b42bdb667e85 100644 --- a/drivers/memory/tegra/tegra30-emc.c +++ b/drivers/memory/tegra/tegra30-emc.c @@ -1256,6 +1256,11 @@ static void tegra_emc_debugfs_init(struct tegra_emc *emc) emc->debugfs.max_rate = emc->timings[i].rate; } + if (!emc->num_timings) { + emc->debugfs.min_rate = clk_get_rate(emc->clk); + emc->debugfs.max_rate = emc->debugfs.min_rate; + } + err = clk_set_rate_range(emc->clk, emc->debugfs.min_rate, emc->debugfs.max_rate); if (err < 0) { From 141267bffd1dc19a76e4d50e3e4829f85a806875 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Tue, 25 Feb 2020 02:58:36 +0300 Subject: [PATCH 1527/4444] memory: tegra: Correct debugfs clk rate-range on Tegra124 Correctly set clk rate-range if number of available timings is zero. This fixes noisy "invalid range [4294967295, 0]" error messages during boot. Fixes: 6b9acd935546 ("memory: tegra: Refashion EMC debugfs interface on Tegra124") Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/memory/tegra/tegra124-emc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/memory/tegra/tegra124-emc.c b/drivers/memory/tegra/tegra124-emc.c index 21f05240682b..33b8216bac30 100644 --- a/drivers/memory/tegra/tegra124-emc.c +++ b/drivers/memory/tegra/tegra124-emc.c @@ -1158,6 +1158,11 @@ static void emc_debugfs_init(struct device *dev, struct tegra_emc *emc) emc->debugfs.max_rate = emc->timings[i].rate; } + if (!emc->num_timings) { + emc->debugfs.min_rate = clk_get_rate(emc->clk); + emc->debugfs.max_rate = emc->debugfs.min_rate; + } + err = clk_set_rate_range(emc->clk, emc->debugfs.min_rate, emc->debugfs.max_rate); if (err < 0) { From 7c2f66a960fccc165d0b6c594f40f0ad3edfc61f Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 12 Feb 2020 01:39:25 +0100 Subject: [PATCH 1528/4444] mtd: rawnand: ams-delta: Add module device tables In preparation for merging the driver with "gpio-nand", introduce module device tables where new device models can be accommodated as soon as respective support is added. Signed-off-by: Janusz Krzysztofik Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200212003929.6682-11-jmkrzyszt@gmail.com --- drivers/mtd/nand/raw/ams-delta.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 0c88e94e9b71..a493f1dc6677 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -370,11 +370,29 @@ static int ams_delta_cleanup(struct platform_device *pdev) return 0; } +static const struct of_device_id gpio_nand_of_id_table[] = { + { + /* sentinel */ + }, +}; +MODULE_DEVICE_TABLE(of, gpio_nand_of_id_table); + +static const struct platform_device_id gpio_nand_plat_id_table[] = { + { + .name = "ams-delta-nand", + }, { + /* sentinel */ + }, +}; +MODULE_DEVICE_TABLE(platform, gpio_nand_plat_id_table); + static struct platform_driver ams_delta_nand_driver = { .probe = ams_delta_init, .remove = ams_delta_cleanup, + .id_table = gpio_nand_plat_id_table, .driver = { .name = "ams-delta-nand", + .of_match_table = of_match_ptr(gpio_nand_of_id_table), }, }; From d1b1a8f73a21c7807b23144f41174b71a5a60a40 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 12 Feb 2020 01:39:26 +0100 Subject: [PATCH 1529/4444] mtd: rawnand: ams-delta: Support custom driver initialisation In preparation for extending the driver with custom I/O support, try to obtain device specific initialisation routine from a matching device table entry and run it as an additional step of device probe. Signed-off-by: Janusz Krzysztofik Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200212003929.6682-12-jmkrzyszt@gmail.com --- drivers/mtd/nand/raw/ams-delta.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index a493f1dc6677..60502edfbeab 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -230,6 +231,7 @@ static int ams_delta_init(struct platform_device *pdev) struct nand_chip *this; struct mtd_info *mtd; struct gpio_descs *data_gpiods; + int (*probe)(struct platform_device *pdev, struct ams_delta_nand *priv); int err = 0; if (pdata) { @@ -319,6 +321,15 @@ static int ams_delta_init(struct platform_device *pdev) priv->data_gpiods = data_gpiods; priv->data_in = true; + if (pdev->id_entry) + probe = (void *) pdev->id_entry->driver_data; + else + probe = of_device_get_match_data(&pdev->dev); + if (probe) + err = probe(pdev, priv); + if (err) + return err; + /* Initialize the NAND controller object embedded in ams_delta_nand. */ priv->base.ops = &ams_delta_ops; nand_controller_init(&priv->base); From edfd8d9c763f5f91cda663e89f34dccacd8eb586 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 12 Feb 2020 01:39:27 +0100 Subject: [PATCH 1530/4444] mtd: rawnand: ams-delta: Drop useless local variable For consistency with adjacent code patterns used in the driver probe function, store data GPIO array pointer directly in a respective field of the driver private structure instead of storing it intermediately in a local variable for error checking. Signed-off-by: Janusz Krzysztofik Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200212003929.6682-13-jmkrzyszt@gmail.com --- drivers/mtd/nand/raw/ams-delta.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 60502edfbeab..d8eef3dffa66 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -230,7 +230,6 @@ static int ams_delta_init(struct platform_device *pdev) struct ams_delta_nand *priv; struct nand_chip *this; struct mtd_info *mtd; - struct gpio_descs *data_gpiods; int (*probe)(struct platform_device *pdev, struct ams_delta_nand *priv); int err = 0; @@ -312,13 +311,12 @@ static int ams_delta_init(struct platform_device *pdev) } /* Request array of data pins, initialize them as input */ - data_gpiods = devm_gpiod_get_array(&pdev->dev, "data", GPIOD_IN); - if (IS_ERR(data_gpiods)) { - err = PTR_ERR(data_gpiods); + priv->data_gpiods = devm_gpiod_get_array(&pdev->dev, "data", GPIOD_IN); + if (IS_ERR(priv->data_gpiods)) { + err = PTR_ERR(priv->data_gpiods); dev_err(&pdev->dev, "data GPIO request failed: %d\n", err); return err; } - priv->data_gpiods = data_gpiods; priv->data_in = true; if (pdev->id_entry) From 2b1dcee304b67f3c4e7e2e910be90e36eef46050 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 12 Feb 2020 01:39:28 +0100 Subject: [PATCH 1531/4444] mtd: rawnand: ams-delta: Make the driver custom I/O ready In order to be merged with "gpio-nand", the driver must support custom (non-GPIO) I/O accessors. Allow platforms to omit data GPIO port as well as NWE pin info from device setup. For the driver to still work on such platform, custom I/O accessors as well as a custom probe function which initialises the driver private structure with those accessors must be added to the driver. Signed-off-by: Janusz Krzysztofik Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200212003929.6682-14-jmkrzyszt@gmail.com --- drivers/mtd/nand/raw/ams-delta.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index d8eef3dffa66..5a27170b2808 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -43,6 +43,9 @@ struct ams_delta_nand { bool data_in; unsigned int tRP; unsigned int tWP; + u8 (*io_read)(struct ams_delta_nand *this); + void (*io_write)(struct ams_delta_nand *this, + u8 byte); }; static void ams_delta_write_commit(struct ams_delta_nand *priv) @@ -116,18 +119,18 @@ static void ams_delta_write_buf(struct ams_delta_nand *priv, const u8 *buf, ams_delta_dir_output(priv, buf[i++]); while (i < len) - ams_delta_io_write(priv, buf[i++]); + priv->io_write(priv, buf[i++]); } static void ams_delta_read_buf(struct ams_delta_nand *priv, u8 *buf, int len) { int i; - if (!priv->data_in) + if (priv->data_gpiods && !priv->data_in) ams_delta_dir_input(priv); for (i = 0; i < len; i++) - buf[i] = ams_delta_io_read(priv); + buf[i] = priv->io_read(priv); } static void ams_delta_ctrl_cs(struct ams_delta_nand *priv, bool assert) @@ -289,7 +292,8 @@ static int ams_delta_init(struct platform_device *pdev) return err; } - priv->gpiod_nwe = devm_gpiod_get(&pdev->dev, "nwe", GPIOD_OUT_LOW); + priv->gpiod_nwe = devm_gpiod_get_optional(&pdev->dev, "nwe", + GPIOD_OUT_LOW); if (IS_ERR(priv->gpiod_nwe)) { err = PTR_ERR(priv->gpiod_nwe); dev_err(&pdev->dev, "NWE GPIO request failed (%d)\n", err); @@ -311,13 +315,24 @@ static int ams_delta_init(struct platform_device *pdev) } /* Request array of data pins, initialize them as input */ - priv->data_gpiods = devm_gpiod_get_array(&pdev->dev, "data", GPIOD_IN); + priv->data_gpiods = devm_gpiod_get_array_optional(&pdev->dev, "data", + GPIOD_IN); if (IS_ERR(priv->data_gpiods)) { err = PTR_ERR(priv->data_gpiods); dev_err(&pdev->dev, "data GPIO request failed: %d\n", err); return err; } - priv->data_in = true; + if (priv->data_gpiods) { + if (!priv->gpiod_nwe) { + dev_err(&pdev->dev, + "mandatory NWE pin not provided by platform\n"); + return -ENODEV; + } + + priv->io_read = ams_delta_io_read; + priv->io_write = ams_delta_io_write; + priv->data_in = true; + } if (pdev->id_entry) probe = (void *) pdev->id_entry->driver_data; @@ -328,6 +343,11 @@ static int ams_delta_init(struct platform_device *pdev) if (err) return err; + if (!priv->io_read || !priv->io_write) { + dev_err(&pdev->dev, "incomplete device configuration\n"); + return -ENODEV; + } + /* Initialize the NAND controller object embedded in ams_delta_nand. */ priv->base.ops = &ams_delta_ops; nand_controller_init(&priv->base); From 16d00cd612068965134a08c08a43355b4b4ac58f Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 12 Feb 2020 01:39:29 +0100 Subject: [PATCH 1532/4444] mtd: rawnand: ams-delta: Rename structures and functions to gpio_nand* Another step in preparation for merging the driver with "gpio-nand". Signed-off-by: Janusz Krzysztofik Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200212003929.6682-15-jmkrzyszt@gmail.com --- drivers/mtd/nand/raw/ams-delta.c | 86 ++++++++++++++++---------------- 1 file changed, 42 insertions(+), 44 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 5a27170b2808..d66dab25df20 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -29,7 +29,7 @@ /* * MTD structure for E3 (Delta) */ -struct ams_delta_nand { +struct gpio_nand { struct nand_controller base; struct nand_chip nand_chip; struct gpio_desc *gpiod_rdy; @@ -43,19 +43,18 @@ struct ams_delta_nand { bool data_in; unsigned int tRP; unsigned int tWP; - u8 (*io_read)(struct ams_delta_nand *this); - void (*io_write)(struct ams_delta_nand *this, - u8 byte); + u8 (*io_read)(struct gpio_nand *this); + void (*io_write)(struct gpio_nand *this, u8 byte); }; -static void ams_delta_write_commit(struct ams_delta_nand *priv) +static void gpio_nand_write_commit(struct gpio_nand *priv) { gpiod_set_value(priv->gpiod_nwe, 1); ndelay(priv->tWP); gpiod_set_value(priv->gpiod_nwe, 0); } -static void ams_delta_io_write(struct ams_delta_nand *priv, u8 byte) +static void gpio_nand_io_write(struct gpio_nand *priv, u8 byte) { struct gpio_descs *data_gpiods = priv->data_gpiods; DECLARE_BITMAP(values, BITS_PER_TYPE(byte)) = { byte, }; @@ -63,10 +62,10 @@ static void ams_delta_io_write(struct ams_delta_nand *priv, u8 byte) gpiod_set_raw_array_value(data_gpiods->ndescs, data_gpiods->desc, data_gpiods->info, values); - ams_delta_write_commit(priv); + gpio_nand_write_commit(priv); } -static void ams_delta_dir_output(struct ams_delta_nand *priv, u8 byte) +static void gpio_nand_dir_output(struct gpio_nand *priv, u8 byte) { struct gpio_descs *data_gpiods = priv->data_gpiods; DECLARE_BITMAP(values, BITS_PER_TYPE(byte)) = { byte, }; @@ -76,12 +75,12 @@ static void ams_delta_dir_output(struct ams_delta_nand *priv, u8 byte) gpiod_direction_output_raw(data_gpiods->desc[i], test_bit(i, values)); - ams_delta_write_commit(priv); + gpio_nand_write_commit(priv); priv->data_in = false; } -static u8 ams_delta_io_read(struct ams_delta_nand *priv) +static u8 gpio_nand_io_read(struct gpio_nand *priv) { u8 res; struct gpio_descs *data_gpiods = priv->data_gpiods; @@ -99,7 +98,7 @@ static u8 ams_delta_io_read(struct ams_delta_nand *priv) return res; } -static void ams_delta_dir_input(struct ams_delta_nand *priv) +static void gpio_nand_dir_input(struct gpio_nand *priv) { struct gpio_descs *data_gpiods = priv->data_gpiods; int i; @@ -110,68 +109,67 @@ static void ams_delta_dir_input(struct ams_delta_nand *priv) priv->data_in = true; } -static void ams_delta_write_buf(struct ams_delta_nand *priv, const u8 *buf, - int len) +static void gpio_nand_write_buf(struct gpio_nand *priv, const u8 *buf, int len) { int i = 0; if (len > 0 && priv->data_in) - ams_delta_dir_output(priv, buf[i++]); + gpio_nand_dir_output(priv, buf[i++]); while (i < len) priv->io_write(priv, buf[i++]); } -static void ams_delta_read_buf(struct ams_delta_nand *priv, u8 *buf, int len) +static void gpio_nand_read_buf(struct gpio_nand *priv, u8 *buf, int len) { int i; if (priv->data_gpiods && !priv->data_in) - ams_delta_dir_input(priv); + gpio_nand_dir_input(priv); for (i = 0; i < len; i++) buf[i] = priv->io_read(priv); } -static void ams_delta_ctrl_cs(struct ams_delta_nand *priv, bool assert) +static void gpio_nand_ctrl_cs(struct gpio_nand *priv, bool assert) { gpiod_set_value(priv->gpiod_nce, assert); } -static int ams_delta_exec_op(struct nand_chip *this, +static int gpio_nand_exec_op(struct nand_chip *this, const struct nand_operation *op, bool check_only) { - struct ams_delta_nand *priv = nand_get_controller_data(this); + struct gpio_nand *priv = nand_get_controller_data(this); const struct nand_op_instr *instr; int ret = 0; if (check_only) return 0; - ams_delta_ctrl_cs(priv, 1); + gpio_nand_ctrl_cs(priv, 1); for (instr = op->instrs; instr < op->instrs + op->ninstrs; instr++) { switch (instr->type) { case NAND_OP_CMD_INSTR: gpiod_set_value(priv->gpiod_cle, 1); - ams_delta_write_buf(priv, &instr->ctx.cmd.opcode, 1); + gpio_nand_write_buf(priv, &instr->ctx.cmd.opcode, 1); gpiod_set_value(priv->gpiod_cle, 0); break; case NAND_OP_ADDR_INSTR: gpiod_set_value(priv->gpiod_ale, 1); - ams_delta_write_buf(priv, instr->ctx.addr.addrs, + gpio_nand_write_buf(priv, instr->ctx.addr.addrs, instr->ctx.addr.naddrs); gpiod_set_value(priv->gpiod_ale, 0); break; case NAND_OP_DATA_IN_INSTR: - ams_delta_read_buf(priv, instr->ctx.data.buf.in, + gpio_nand_read_buf(priv, instr->ctx.data.buf.in, instr->ctx.data.len); break; case NAND_OP_DATA_OUT_INSTR: - ams_delta_write_buf(priv, instr->ctx.data.buf.out, + gpio_nand_write_buf(priv, instr->ctx.data.buf.out, instr->ctx.data.len); break; @@ -188,15 +186,15 @@ static int ams_delta_exec_op(struct nand_chip *this, break; } - ams_delta_ctrl_cs(priv, 0); + gpio_nand_ctrl_cs(priv, 0); return ret; } -static int ams_delta_setup_data_interface(struct nand_chip *this, int csline, +static int gpio_nand_setup_data_interface(struct nand_chip *this, int csline, const struct nand_data_interface *cf) { - struct ams_delta_nand *priv = nand_get_controller_data(this); + struct gpio_nand *priv = nand_get_controller_data(this); const struct nand_sdr_timings *sdr = nand_get_sdr_timings(cf); struct device *dev = &nand_to_mtd(this)->dev; @@ -217,23 +215,23 @@ static int ams_delta_setup_data_interface(struct nand_chip *this, int csline, return 0; } -static const struct nand_controller_ops ams_delta_ops = { - .exec_op = ams_delta_exec_op, - .setup_data_interface = ams_delta_setup_data_interface, +static const struct nand_controller_ops gpio_nand_ops = { + .exec_op = gpio_nand_exec_op, + .setup_data_interface = gpio_nand_setup_data_interface, }; /* * Main initialization routine */ -static int ams_delta_init(struct platform_device *pdev) +static int gpio_nand_probe(struct platform_device *pdev) { struct gpio_nand_platdata *pdata = dev_get_platdata(&pdev->dev); const struct mtd_partition *partitions = NULL; int num_partitions = 0; - struct ams_delta_nand *priv; + struct gpio_nand *priv; struct nand_chip *this; struct mtd_info *mtd; - int (*probe)(struct platform_device *pdev, struct ams_delta_nand *priv); + int (*probe)(struct platform_device *pdev, struct gpio_nand *priv); int err = 0; if (pdata) { @@ -242,7 +240,7 @@ static int ams_delta_init(struct platform_device *pdev) } /* Allocate memory for MTD device structure and private data */ - priv = devm_kzalloc(&pdev->dev, sizeof(struct ams_delta_nand), + priv = devm_kzalloc(&pdev->dev, sizeof(struct gpio_nand), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -329,8 +327,8 @@ static int ams_delta_init(struct platform_device *pdev) return -ENODEV; } - priv->io_read = ams_delta_io_read; - priv->io_write = ams_delta_io_write; + priv->io_read = gpio_nand_io_read; + priv->io_write = gpio_nand_io_write; priv->data_in = true; } @@ -348,8 +346,8 @@ static int ams_delta_init(struct platform_device *pdev) return -ENODEV; } - /* Initialize the NAND controller object embedded in ams_delta_nand. */ - priv->base.ops = &ams_delta_ops; + /* Initialize the NAND controller object embedded in gpio_nand. */ + priv->base.ops = &gpio_nand_ops; nand_controller_init(&priv->base); this->controller = &priv->base; @@ -385,9 +383,9 @@ err_nand_cleanup: /* * Clean up routine */ -static int ams_delta_cleanup(struct platform_device *pdev) +static int gpio_nand_remove(struct platform_device *pdev) { - struct ams_delta_nand *priv = platform_get_drvdata(pdev); + struct gpio_nand *priv = platform_get_drvdata(pdev); struct mtd_info *mtd = nand_to_mtd(&priv->nand_chip); /* Apply write protection */ @@ -415,9 +413,9 @@ static const struct platform_device_id gpio_nand_plat_id_table[] = { }; MODULE_DEVICE_TABLE(platform, gpio_nand_plat_id_table); -static struct platform_driver ams_delta_nand_driver = { - .probe = ams_delta_init, - .remove = ams_delta_cleanup, +static struct platform_driver gpio_nand_driver = { + .probe = gpio_nand_probe, + .remove = gpio_nand_remove, .id_table = gpio_nand_plat_id_table, .driver = { .name = "ams-delta-nand", @@ -425,7 +423,7 @@ static struct platform_driver ams_delta_nand_driver = { }, }; -module_platform_driver(ams_delta_nand_driver); +module_platform_driver(gpio_nand_driver); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Jonathan McDowell "); From 84234652595f8dc29a92a33a6ae504c7df2e11c8 Mon Sep 17 00:00:00 2001 From: Mason Yang Date: Mon, 17 Feb 2020 14:56:39 +0800 Subject: [PATCH 1533/4444] mtd: rawnand: Add support for Macronix NAND randomizer Macronix NANDs support randomizer operation for user data scrambled, which can be enabled with a SET_FEATURE. User data written to the NAND device without randomizer is still readable after randomizer function enabled. The penalty of randomizer are subpage accesses prohibited and more time period is needed in program operation and entering deep power-down mode. i.e., tPROG 300us to 340us(randomizer enabled) For more high-reliability concern, if subpage write not available with hardware ECC and then to enable randomizer is recommended by default. Driver checks byte 167 of Vendor Blocks in ONFI parameter page table to see if this high-reliability function is supported. By adding a new specific DT property in children nodes to enable randomizer function. Signed-off-by: Mason Yang Reviewed-by: Miquel Raynal Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/1581922600-25461-2-git-send-email-masonccyang@mxic.com.tw --- drivers/mtd/nand/raw/nand_macronix.c | 81 ++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/drivers/mtd/nand/raw/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c index 3ff7ce00cbdb..0a2fe25f2639 100644 --- a/drivers/mtd/nand/raw/nand_macronix.c +++ b/drivers/mtd/nand/raw/nand_macronix.c @@ -11,6 +11,19 @@ #define MACRONIX_READ_RETRY_BIT BIT(0) #define MACRONIX_NUM_READ_RETRY_MODES 6 +#define ONFI_FEATURE_ADDR_MXIC_RANDOMIZER 0xB0 +#define MACRONIX_RANDOMIZER_BIT BIT(1) +#define MACRONIX_RANDOMIZER_ENPGM BIT(0) +#define MACRONIX_RANDOMIZER_RANDEN BIT(1) +#define MACRONIX_RANDOMIZER_RANDOPT BIT(2) +#define MACRONIX_RANDOMIZER_MODE_ENTER \ + (MACRONIX_RANDOMIZER_ENPGM | \ + MACRONIX_RANDOMIZER_RANDEN | \ + MACRONIX_RANDOMIZER_RANDOPT) +#define MACRONIX_RANDOMIZER_MODE_EXIT \ + (MACRONIX_RANDOMIZER_RANDEN | \ + MACRONIX_RANDOMIZER_RANDOPT) + struct nand_onfi_vendor_macronix { u8 reserved; u8 reliability_func; @@ -29,15 +42,83 @@ static int macronix_nand_setup_read_retry(struct nand_chip *chip, int mode) return nand_set_features(chip, ONFI_FEATURE_ADDR_READ_RETRY, feature); } +static int macronix_nand_randomizer_check_enable(struct nand_chip *chip) +{ + u8 feature[ONFI_SUBFEATURE_PARAM_LEN]; + int ret; + + ret = nand_get_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER, + feature); + if (ret < 0) + return ret; + + if (feature[0]) + return feature[0]; + + feature[0] = MACRONIX_RANDOMIZER_MODE_ENTER; + ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER, + feature); + if (ret < 0) + return ret; + + /* RANDEN and RANDOPT OTP bits are programmed */ + feature[0] = 0x0; + ret = nand_prog_page_op(chip, 0, 0, feature, 1); + if (ret < 0) + return ret; + + ret = nand_get_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER, + feature); + if (ret < 0) + return ret; + + feature[0] &= MACRONIX_RANDOMIZER_MODE_EXIT; + ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER, + feature); + if (ret < 0) + return ret; + + return 0; +} + static void macronix_nand_onfi_init(struct nand_chip *chip) { struct nand_parameters *p = &chip->parameters; struct nand_onfi_vendor_macronix *mxic; + struct device_node *dn = nand_get_flash_node(chip); + int rand_otp = 0; + int ret; if (!p->onfi) return; + if (of_find_property(dn, "mxic,enable-randomizer-otp", NULL)) + rand_otp = 1; + mxic = (struct nand_onfi_vendor_macronix *)p->onfi->vendor; + /* Subpage write is prohibited in randomizer operatoin */ + if (rand_otp && chip->options & NAND_NO_SUBPAGE_WRITE && + mxic->reliability_func & MACRONIX_RANDOMIZER_BIT) { + if (p->supports_set_get_features) { + bitmap_set(p->set_feature_list, + ONFI_FEATURE_ADDR_MXIC_RANDOMIZER, 1); + bitmap_set(p->get_feature_list, + ONFI_FEATURE_ADDR_MXIC_RANDOMIZER, 1); + ret = macronix_nand_randomizer_check_enable(chip); + if (ret < 0) { + bitmap_clear(p->set_feature_list, + ONFI_FEATURE_ADDR_MXIC_RANDOMIZER, + 1); + bitmap_clear(p->get_feature_list, + ONFI_FEATURE_ADDR_MXIC_RANDOMIZER, + 1); + pr_info("Macronix NAND randomizer failed\n"); + } else { + pr_info("Macronix NAND randomizer enabled\n"); + } + } + } + if ((mxic->reliability_func & MACRONIX_READ_RETRY_BIT) == 0) return; From 7f274f411c76ecf87c6eef7ce263ddfe0962ba46 Mon Sep 17 00:00:00 2001 From: Mason Yang Date: Mon, 17 Feb 2020 14:56:40 +0800 Subject: [PATCH 1534/4444] dt-bindings: mtd: Document Macronix NAND device bindings Document the bindings used by the Macronix NAND device. Signed-off-by: Mason Yang Reviewed-by: Rob Herring [ Link: https://lore.kernel.org/linux-mtd/1581922600-25461-3-git-send-email-masonccyang@mxic.com.tw --- .../devicetree/bindings/mtd/nand-macronix.txt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/nand-macronix.txt diff --git a/Documentation/devicetree/bindings/mtd/nand-macronix.txt b/Documentation/devicetree/bindings/mtd/nand-macronix.txt new file mode 100644 index 000000000000..ffab28a2c4d1 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/nand-macronix.txt @@ -0,0 +1,27 @@ +Macronix NANDs Device Tree Bindings +----------------------------------- + +Macronix NANDs support randomizer operation for scrambling user data, +which can be enabled with a SET_FEATURE. The penalty when using the +randomizer are subpage accesses prohibited and more time period needed +for program operation, i.e., tPROG 300us to 340us (randomizer enabled). +Enabling the randomizer is a one time persistent and non reversible +operation. + +For more high-reliability concern, if subpage write is not available +with hardware ECC and not enabled at UBI level, then enabling the +randomizer is recommended by default by adding a new specific property +in children nodes. + +Required NAND chip properties in children mode: +- randomizer enable: should be "mxic,enable-randomizer-otp" + +Example: + + nand: nand-controller@unit-address { + + nand@0 { + reg = <0>; + mxic,enable-randomizer-otp; + }; + }; From 2148937501ee3d663e0010e519a553fea67ad103 Mon Sep 17 00:00:00 2001 From: Frieder Schrempf Date: Tue, 18 Feb 2020 10:05:14 +0000 Subject: [PATCH 1535/4444] mtd: spinand: Stop using spinand->oobbuf for buffering bad block markers For reading and writing the bad block markers, spinand->oobbuf is currently used as a buffer for the marker bytes. During the underlying read and write operations to actually get/set the content of the OOB area, the content of spinand->oobbuf is reused and changed by accessing it through spinand->oobbuf and/or spinand->databuf. This is a flaw in the original design of the SPI NAND core and at the latest from 13c15e07eedf ("mtd: spinand: Handle the case where PROGRAM LOAD does not reset the cache") on, it results in not having the bad block marker written at all, as the spinand->oobbuf is cleared to 0xff after setting the marker bytes to zero. To fix it, we now just store the two bytes for the marker on the stack and let the read/write operations copy it from/to the page buffer later. Fixes: 7529df465248 ("mtd: nand: Add core infrastructure to support SPI NANDs") Cc: stable@vger.kernel.org Signed-off-by: Frieder Schrempf Reviewed-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200218100432.32433-2-frieder.schrempf@kontron.de --- drivers/mtd/nand/spi/core.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index a9e9cbad942f..137d31dae3ce 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -570,18 +570,18 @@ static int spinand_mtd_write(struct mtd_info *mtd, loff_t to, static bool spinand_isbad(struct nand_device *nand, const struct nand_pos *pos) { struct spinand_device *spinand = nand_to_spinand(nand); + u8 marker[2] = { }; struct nand_page_io_req req = { .pos = *pos, - .ooblen = 2, + .ooblen = sizeof(marker), .ooboffs = 0, - .oobbuf.in = spinand->oobbuf, + .oobbuf.in = marker, .mode = MTD_OPS_RAW, }; - memset(spinand->oobbuf, 0, 2); spinand_select_target(spinand, pos->target); spinand_read_page(spinand, &req, false); - if (spinand->oobbuf[0] != 0xff || spinand->oobbuf[1] != 0xff) + if (marker[0] != 0xff || marker[1] != 0xff) return true; return false; @@ -605,11 +605,12 @@ static int spinand_mtd_block_isbad(struct mtd_info *mtd, loff_t offs) static int spinand_markbad(struct nand_device *nand, const struct nand_pos *pos) { struct spinand_device *spinand = nand_to_spinand(nand); + u8 marker[2] = { }; struct nand_page_io_req req = { .pos = *pos, .ooboffs = 0, - .ooblen = 2, - .oobbuf.out = spinand->oobbuf, + .ooblen = sizeof(marker), + .oobbuf.out = marker, }; int ret; @@ -624,7 +625,6 @@ static int spinand_markbad(struct nand_device *nand, const struct nand_pos *pos) spinand_erase_op(spinand, pos); - memset(spinand->oobbuf, 0, 2); return spinand_write_page(spinand, &req); } From 621a7b780bd8b7054647d53d5071961f2c9e0873 Mon Sep 17 00:00:00 2001 From: Frieder Schrempf Date: Tue, 18 Feb 2020 10:05:25 +0000 Subject: [PATCH 1536/4444] mtd: spinand: Explicitly use MTD_OPS_RAW to write the bad block marker to OOB When writing the bad block marker to the OOB area the access mode should be set to MTD_OPS_RAW as it is done for reading the marker. Currently this only works because req.mode is initialized to MTD_OPS_PLACE_OOB (0) and spinand_write_to_cache_op() checks for req.mode != MTD_OPS_AUTO_OOB. Fix this by explicitly setting req.mode to MTD_OPS_RAW. Fixes: 7529df465248 ("mtd: nand: Add core infrastructure to support SPI NANDs") Signed-off-by: Frieder Schrempf Reviewed-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200218100432.32433-3-frieder.schrempf@kontron.de --- drivers/mtd/nand/spi/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 137d31dae3ce..ee1eea857367 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -611,6 +611,7 @@ static int spinand_markbad(struct nand_device *nand, const struct nand_pos *pos) .ooboffs = 0, .ooblen = sizeof(marker), .oobbuf.out = marker, + .mode = MTD_OPS_RAW, }; int ret; From b645ad39d56846618704e463b24bb994c9585c7f Mon Sep 17 00:00:00 2001 From: Frieder Schrempf Date: Tue, 18 Feb 2020 10:05:35 +0000 Subject: [PATCH 1537/4444] mtd: spinand: Do not erase the block before writing a bad block marker Currently when marking a block, we use spinand_erase_op() to erase the block before writing the marker to the OOB area. Doing so without waiting for the operation to finish can lead to the marking failing silently and no bad block marker being written to the flash. In fact we don't need to do an erase at all before writing the BBM. The ECC is disabled for raw accesses to the OOB data and we don't need to work around any issues with chips reporting ECC errors as it is known to be the case for raw NAND. Fixes: 7529df465248 ("mtd: nand: Add core infrastructure to support SPI NANDs") Cc: stable@vger.kernel.org Signed-off-by: Frieder Schrempf Reviewed-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200218100432.32433-4-frieder.schrempf@kontron.de --- drivers/mtd/nand/spi/core.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index ee1eea857367..b6bb358b96ce 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -615,7 +615,6 @@ static int spinand_markbad(struct nand_device *nand, const struct nand_pos *pos) }; int ret; - /* Erase block before marking it bad. */ ret = spinand_select_target(spinand, pos->target); if (ret) return ret; @@ -624,8 +623,6 @@ static int spinand_markbad(struct nand_device *nand, const struct nand_pos *pos) if (ret) return ret; - spinand_erase_op(spinand, pos); - return spinand_write_page(spinand, &req); } From c6fbcb70132ffc66696a94dd3d8e6215c750254f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20Neusch=C3=A4fer?= Date: Sun, 23 Feb 2020 19:06:33 +0100 Subject: [PATCH 1538/4444] mtd: rawnand: Fix a typo ("manufecturer") MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonathan Neuschäfer Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200223180634.8736-1-j.neuschaefer@gmx.net --- include/linux/mtd/rawnand.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 4ab9bccfcde0..3c7c15aadcee 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1215,7 +1215,7 @@ static inline struct device_node *nand_get_flash_node(struct nand_chip *chip) * struct nand_flash_dev - NAND Flash Device ID Structure * @name: a human-readable name of the NAND chip * @dev_id: the device ID (the second byte of the full chip ID array) - * @mfr_id: manufecturer ID part of the full chip ID array (refers the same + * @mfr_id: manufacturer ID part of the full chip ID array (refers the same * memory address as ``id[0]``) * @dev_id: device ID part of the full chip ID array (refers the same memory * address as ``id[1]``) From 49f1c33076ca56871ffddc4800b04524204ea889 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 26 Feb 2020 16:27:22 -0600 Subject: [PATCH 1539/4444] mtd: rawnand: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Acked-by: Masahiro Yamada Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200226222722.GA18020@embeddedor --- drivers/mtd/nand/raw/denali.h | 2 +- drivers/mtd/nand/raw/marvell_nand.c | 2 +- drivers/mtd/nand/raw/meson_nand.c | 2 +- drivers/mtd/nand/raw/mtk_nand.c | 2 +- drivers/mtd/nand/raw/nand_hynix.c | 2 +- drivers/mtd/nand/raw/sunxi_nand.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/raw/denali.h b/drivers/mtd/nand/raw/denali.h index e5cdcda56d14..ac46eb7956ce 100644 --- a/drivers/mtd/nand/raw/denali.h +++ b/drivers/mtd/nand/raw/denali.h @@ -328,7 +328,7 @@ struct denali_chip { struct nand_chip chip; struct list_head node; unsigned int nsels; - struct denali_chip_sel sels[0]; + struct denali_chip_sel sels[]; }; /** diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index fb5abdcfb007..7082bef1c8a7 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -334,7 +334,7 @@ struct marvell_nand_chip { int addr_cyc; int selected_die; unsigned int nsels; - struct marvell_nand_chip_sel sels[0]; + struct marvell_nand_chip_sel sels[]; }; static inline struct marvell_nand_chip *to_marvell_nand(struct nand_chip *chip) diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c index 9f17b5b8efbf..f6fb5c0e6255 100644 --- a/drivers/mtd/nand/raw/meson_nand.c +++ b/drivers/mtd/nand/raw/meson_nand.c @@ -118,7 +118,7 @@ struct meson_nfc_nand_chip { u8 *data_buf; __le64 *info_buf; u32 nsels; - u8 sels[0]; + u8 sels[]; }; struct meson_nand_ecc { diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index b8305e39ab51..ef149e8b26d0 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -131,7 +131,7 @@ struct mtk_nfc_nand_chip { u32 spare_per_sector; int nsels; - u8 sels[0]; + u8 sels[]; /* nothing after this field */ }; diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c index 194e4227aefe..7caedaa5b9e5 100644 --- a/drivers/mtd/nand/raw/nand_hynix.c +++ b/drivers/mtd/nand/raw/nand_hynix.c @@ -26,7 +26,7 @@ struct hynix_read_retry { int nregs; const u8 *regs; - u8 values[0]; + u8 values[]; }; /** diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 37a4ac0dd85b..6ede3934a5f4 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -195,7 +195,7 @@ struct sunxi_nand_chip { u32 timing_cfg; u32 timing_ctl; int nsels; - struct sunxi_nand_chip_sel sels[0]; + struct sunxi_nand_chip_sel sels[]; }; static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand) From 7cd8c0adb489fde5cec2690a85517df74fa8abbb Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 27 Feb 2020 14:37:43 +0200 Subject: [PATCH 1540/4444] mtd: rawnand: gpmi: Use dma_request_chan() instead dma_request_slave_channel() dma_request_slave_channel() is a wrapper on top of dma_request_chan() eating up the error code. Use using dma_request_chan() directly to return the real error code. Signed-off-by: Peter Ujfalusi Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200227123749.24064-2-peter.ujfalusi@ti.com --- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index b9d5d55a5edb..53b00c841aec 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -1148,20 +1148,21 @@ static int acquire_dma_channels(struct gpmi_nand_data *this) { struct platform_device *pdev = this->pdev; struct dma_chan *dma_chan; + int ret = 0; /* request dma channel */ - dma_chan = dma_request_slave_channel(&pdev->dev, "rx-tx"); - if (!dma_chan) { - dev_err(this->dev, "Failed to request DMA channel.\n"); - goto acquire_err; + dma_chan = dma_request_chan(&pdev->dev, "rx-tx"); + if (IS_ERR(dma_chan)) { + ret = PTR_ERR(dma_chan); + if (ret != -EPROBE_DEFER) + dev_err(this->dev, "DMA channel request failed: %d\n", + ret); + release_dma_channels(this); + } else { + this->dma_chans[0] = dma_chan; } - this->dma_chans[0] = dma_chan; - return 0; - -acquire_err: - release_dma_channels(this); - return -EINVAL; + return ret; } static int gpmi_get_clks(struct gpmi_nand_data *this) From aafe30baf4ad131c22a0dc730298360a6e695ce3 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 27 Feb 2020 14:37:44 +0200 Subject: [PATCH 1541/4444] mtd: rawnand: marvell: Release DMA channel on error Release the DMA channel on errors after the channel has been successfully requested. Signed-off-by: Peter Ujfalusi Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200227123749.24064-3-peter.ujfalusi@ti.com --- drivers/mtd/nand/raw/marvell_nand.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index 7082bef1c8a7..f60d885f38bf 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -2751,8 +2751,10 @@ static int marvell_nfc_init_dma(struct marvell_nfc *nfc) } r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) - return -ENXIO; + if (!r) { + ret = -ENXIO; + goto release_channel; + } config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; @@ -2763,7 +2765,7 @@ static int marvell_nfc_init_dma(struct marvell_nfc *nfc) ret = dmaengine_slave_config(nfc->dma_chan, &config); if (ret < 0) { dev_err(nfc->dev, "Failed to configure DMA channel\n"); - return ret; + goto release_channel; } /* @@ -2773,12 +2775,20 @@ static int marvell_nfc_init_dma(struct marvell_nfc *nfc) * the provided buffer. */ nfc->dma_buf = kmalloc(MAX_CHUNK_SIZE, GFP_KERNEL | GFP_DMA); - if (!nfc->dma_buf) - return -ENOMEM; + if (!nfc->dma_buf) { + ret = -ENOMEM; + goto release_channel; + } nfc->use_dma = true; return 0; + +release_channel: + dma_release_channel(nfc->dma_chan); + nfc->dma_chan = NULL; + + return ret; } static void marvell_nfc_reset(struct marvell_nfc *nfc) @@ -2920,10 +2930,13 @@ static int marvell_nfc_probe(struct platform_device *pdev) ret = marvell_nand_chips_init(dev, nfc); if (ret) - goto unprepare_reg_clk; + goto release_dma; return 0; +release_dma: + if (nfc->use_dma) + dma_release_channel(nfc->dma_chan); unprepare_reg_clk: clk_disable_unprepare(nfc->reg_clk); unprepare_core_clk: From cf9e2389482179db6bfab41512a9c0b722540be8 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 27 Feb 2020 14:37:45 +0200 Subject: [PATCH 1542/4444] mtd: rawnand: marvell: Use dma_request_chan() instead dma_request_slave_channel() dma_request_slave_channel() is a wrapper on top of dma_request_chan() eating up the error code. Use using dma_request_chan() directly to return the real error code. Signed-off-by: Peter Ujfalusi Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200227123749.24064-4-peter.ujfalusi@ti.com --- drivers/mtd/nand/raw/marvell_nand.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index f60d885f38bf..179f0ca585f8 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -2743,11 +2743,14 @@ static int marvell_nfc_init_dma(struct marvell_nfc *nfc) if (ret) return ret; - nfc->dma_chan = dma_request_slave_channel(nfc->dev, "data"); - if (!nfc->dma_chan) { - dev_err(nfc->dev, - "Unable to request data DMA channel\n"); - return -ENODEV; + nfc->dma_chan = dma_request_chan(nfc->dev, "data"); + if (IS_ERR(nfc->dma_chan)) { + ret = PTR_ERR(nfc->dma_chan); + nfc->dma_chan = NULL; + if (ret != -EPROBE_DEFER) + dev_err(nfc->dev, "DMA channel request failed: %d\n", + ret); + return ret; } r = platform_get_resource(pdev, IORESOURCE_MEM, 0); From ac80c55b46754fbe0394cf404a9091b551f00e22 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 27 Feb 2020 14:37:46 +0200 Subject: [PATCH 1543/4444] mtd: rawnand: sunxi: Use dma_request_chan() instead dma_request_slave_channel() dma_request_slave_channel() is a wrapper on top of dma_request_chan() eating up the error code. By using dma_request_chan() directly the driver can support deferred probing against DMA. Signed-off-by: Peter Ujfalusi Acked-by: Maxime Ripard Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200227123749.24064-5-peter.ujfalusi@ti.com --- drivers/mtd/nand/raw/sunxi_nand.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 6ede3934a5f4..5f3e40b79fb1 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -2123,8 +2123,16 @@ static int sunxi_nfc_probe(struct platform_device *pdev) if (ret) goto out_ahb_reset_reassert; - nfc->dmac = dma_request_slave_channel(dev, "rxtx"); - if (nfc->dmac) { + nfc->dmac = dma_request_chan(dev, "rxtx"); + if (IS_ERR(nfc->dmac)) { + ret = PTR_ERR(nfc->dmac); + if (ret == -EPROBE_DEFER) + goto out_ahb_reset_reassert; + + /* Ignore errors to fall back to PIO mode */ + dev_warn(dev, "failed to request rxtx DMA channel: %d\n", ret); + nfc->dmac = NULL; + } else { struct dma_slave_config dmac_cfg = { }; dmac_cfg.src_addr = r->start + nfc->caps->reg_io_data; @@ -2138,9 +2146,6 @@ static int sunxi_nfc_probe(struct platform_device *pdev) if (nfc->caps->extra_mbus_conf) writel(readl(nfc->regs + NFC_REG_CTL) | NFC_DMA_TYPE_NORMAL, nfc->regs + NFC_REG_CTL); - - } else { - dev_warn(dev, "failed to request rxtx DMA channel\n"); } platform_set_drvdata(pdev, nfc); From 80c3012e127cf8f4c0601868b2c23b1caab20b44 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 27 Feb 2020 14:37:47 +0200 Subject: [PATCH 1544/4444] mtd: rawnand: qcom: Release resources on failure within qcom_nandc_alloc() In case when DMA channel request or alloc_bam_transaction() fails, dma_unmap_single() and any channels already requested should be released. Signed-off-by: Peter Ujfalusi Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200227123749.24064-6-peter.ujfalusi@ti.com --- drivers/mtd/nand/raw/qcom_nandc.c | 61 +++++++++++++++++-------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index 7bb9a7e8e1e7..ca21cb3836dc 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -2628,6 +2628,29 @@ static const struct nand_controller_ops qcom_nandc_ops = { .attach_chip = qcom_nand_attach_chip, }; +static void qcom_nandc_unalloc(struct qcom_nand_controller *nandc) +{ + if (nandc->props->is_bam) { + if (!dma_mapping_error(nandc->dev, nandc->reg_read_dma)) + dma_unmap_single(nandc->dev, nandc->reg_read_dma, + MAX_REG_RD * + sizeof(*nandc->reg_read_buf), + DMA_FROM_DEVICE); + + if (nandc->tx_chan) + dma_release_channel(nandc->tx_chan); + + if (nandc->rx_chan) + dma_release_channel(nandc->rx_chan); + + if (nandc->cmd_chan) + dma_release_channel(nandc->cmd_chan); + } else { + if (nandc->chan) + dma_release_channel(nandc->chan); + } +} + static int qcom_nandc_alloc(struct qcom_nand_controller *nandc) { int ret; @@ -2676,19 +2699,22 @@ static int qcom_nandc_alloc(struct qcom_nand_controller *nandc) nandc->tx_chan = dma_request_slave_channel(nandc->dev, "tx"); if (!nandc->tx_chan) { dev_err(nandc->dev, "failed to request tx channel\n"); - return -ENODEV; + ret = -ENODEV; + goto unalloc; } nandc->rx_chan = dma_request_slave_channel(nandc->dev, "rx"); if (!nandc->rx_chan) { dev_err(nandc->dev, "failed to request rx channel\n"); - return -ENODEV; + ret = -ENODEV; + goto unalloc; } nandc->cmd_chan = dma_request_slave_channel(nandc->dev, "cmd"); if (!nandc->cmd_chan) { dev_err(nandc->dev, "failed to request cmd channel\n"); - return -ENODEV; + ret = -ENODEV; + goto unalloc; } /* @@ -2702,7 +2728,8 @@ static int qcom_nandc_alloc(struct qcom_nand_controller *nandc) if (!nandc->bam_txn) { dev_err(nandc->dev, "failed to allocate bam transaction\n"); - return -ENOMEM; + ret = -ENOMEM; + goto unalloc; } } else { nandc->chan = dma_request_slave_channel(nandc->dev, "rxtx"); @@ -2720,29 +2747,9 @@ static int qcom_nandc_alloc(struct qcom_nand_controller *nandc) nandc->controller.ops = &qcom_nandc_ops; return 0; -} - -static void qcom_nandc_unalloc(struct qcom_nand_controller *nandc) -{ - if (nandc->props->is_bam) { - if (!dma_mapping_error(nandc->dev, nandc->reg_read_dma)) - dma_unmap_single(nandc->dev, nandc->reg_read_dma, - MAX_REG_RD * - sizeof(*nandc->reg_read_buf), - DMA_FROM_DEVICE); - - if (nandc->tx_chan) - dma_release_channel(nandc->tx_chan); - - if (nandc->rx_chan) - dma_release_channel(nandc->rx_chan); - - if (nandc->cmd_chan) - dma_release_channel(nandc->cmd_chan); - } else { - if (nandc->chan) - dma_release_channel(nandc->chan); - } +unalloc: + qcom_nandc_unalloc(nandc); + return ret; } /* one time setup of a few nand controller registers */ From 92f0f8efbd4ad8fac2e3e902eff3c67da65f08cc Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 27 Feb 2020 14:37:48 +0200 Subject: [PATCH 1545/4444] mtd: rawnand: qcom: Use dma_request_chan() instead dma_request_slave_channel() dma_request_slave_channel() is a wrapper on top of dma_request_chan() eating up the error code. Use using dma_request_chan() directly to return the real error code. Signed-off-by: Peter Ujfalusi Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200227123749.24064-7-peter.ujfalusi@ti.com --- drivers/mtd/nand/raw/qcom_nandc.c | 50 ++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index ca21cb3836dc..5b11c7061497 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -2696,24 +2696,36 @@ static int qcom_nandc_alloc(struct qcom_nand_controller *nandc) return -EIO; } - nandc->tx_chan = dma_request_slave_channel(nandc->dev, "tx"); - if (!nandc->tx_chan) { - dev_err(nandc->dev, "failed to request tx channel\n"); - ret = -ENODEV; + nandc->tx_chan = dma_request_chan(nandc->dev, "tx"); + if (IS_ERR(nandc->tx_chan)) { + ret = PTR_ERR(nandc->tx_chan); + nandc->tx_chan = NULL; + if (ret != -EPROBE_DEFER) + dev_err(nandc->dev, + "tx DMA channel request failed: %d\n", + ret); goto unalloc; } - nandc->rx_chan = dma_request_slave_channel(nandc->dev, "rx"); - if (!nandc->rx_chan) { - dev_err(nandc->dev, "failed to request rx channel\n"); - ret = -ENODEV; + nandc->rx_chan = dma_request_chan(nandc->dev, "rx"); + if (IS_ERR(nandc->rx_chan)) { + ret = PTR_ERR(nandc->rx_chan); + nandc->rx_chan = NULL; + if (ret != -EPROBE_DEFER) + dev_err(nandc->dev, + "rx DMA channel request failed: %d\n", + ret); goto unalloc; } - nandc->cmd_chan = dma_request_slave_channel(nandc->dev, "cmd"); - if (!nandc->cmd_chan) { - dev_err(nandc->dev, "failed to request cmd channel\n"); - ret = -ENODEV; + nandc->cmd_chan = dma_request_chan(nandc->dev, "cmd"); + if (IS_ERR(nandc->cmd_chan)) { + ret = PTR_ERR(nandc->cmd_chan); + nandc->cmd_chan = NULL; + if (ret != -EPROBE_DEFER) + dev_err(nandc->dev, + "cmd DMA channel request failed: %d\n", + ret); goto unalloc; } @@ -2732,11 +2744,15 @@ static int qcom_nandc_alloc(struct qcom_nand_controller *nandc) goto unalloc; } } else { - nandc->chan = dma_request_slave_channel(nandc->dev, "rxtx"); - if (!nandc->chan) { - dev_err(nandc->dev, - "failed to request slave channel\n"); - return -ENODEV; + nandc->chan = dma_request_chan(nandc->dev, "rxtx"); + if (IS_ERR(nandc->chan)) { + ret = PTR_ERR(nandc->chan); + nandc->chan = NULL; + if (ret != -EPROBE_DEFER) + dev_err(nandc->dev, + "rxtx DMA channel request failed: %d\n", + ret); + return ret; } } From b35f79aa461e965514e7d437c6704679552f4818 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 27 Feb 2020 14:37:49 +0200 Subject: [PATCH 1546/4444] mtd: rawnand: stm32_fmc2: Use dma_request_chan() instead dma_request_slave_channel() dma_request_slave_channel() is a wrapper on top of dma_request_chan() eating up the error code. Use using dma_request_chan() directly and inform user of error in case the DMA request failed. Signed-off-by: Peter Ujfalusi Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200227123749.24064-8-peter.ujfalusi@ti.com --- drivers/mtd/nand/raw/stm32_fmc2_nand.c | 44 ++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c index 3ba73f18841f..b6d45cd911ae 100644 --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c @@ -1606,15 +1606,36 @@ static int stm32_fmc2_setup_interface(struct nand_chip *chip, int chipnr, /* DMA configuration */ static int stm32_fmc2_dma_setup(struct stm32_fmc2_nfc *fmc2) { - int ret; + int ret = 0; - fmc2->dma_tx_ch = dma_request_slave_channel(fmc2->dev, "tx"); - fmc2->dma_rx_ch = dma_request_slave_channel(fmc2->dev, "rx"); - fmc2->dma_ecc_ch = dma_request_slave_channel(fmc2->dev, "ecc"); + fmc2->dma_tx_ch = dma_request_chan(fmc2->dev, "tx"); + if (IS_ERR(fmc2->dma_tx_ch)) { + ret = PTR_ERR(fmc2->dma_tx_ch); + if (ret != -ENODEV) + dev_err(fmc2->dev, + "failed to request tx DMA channel: %d\n", ret); + fmc2->dma_tx_ch = NULL; + goto err_dma; + } - if (!fmc2->dma_tx_ch || !fmc2->dma_rx_ch || !fmc2->dma_ecc_ch) { - dev_warn(fmc2->dev, "DMAs not defined in the device tree, polling mode is used\n"); - return 0; + fmc2->dma_rx_ch = dma_request_chan(fmc2->dev, "rx"); + if (IS_ERR(fmc2->dma_rx_ch)) { + ret = PTR_ERR(fmc2->dma_rx_ch); + if (ret != -ENODEV) + dev_err(fmc2->dev, + "failed to request rx DMA channel: %d\n", ret); + fmc2->dma_rx_ch = NULL; + goto err_dma; + } + + fmc2->dma_ecc_ch = dma_request_chan(fmc2->dev, "ecc"); + if (IS_ERR(fmc2->dma_ecc_ch)) { + ret = PTR_ERR(fmc2->dma_ecc_ch); + if (ret != -ENODEV) + dev_err(fmc2->dev, + "failed to request ecc DMA channel: %d\n", ret); + fmc2->dma_ecc_ch = NULL; + goto err_dma; } ret = sg_alloc_table(&fmc2->dma_ecc_sg, FMC2_MAX_SG, GFP_KERNEL); @@ -1635,6 +1656,15 @@ static int stm32_fmc2_dma_setup(struct stm32_fmc2_nfc *fmc2) init_completion(&fmc2->dma_ecc_complete); return 0; + +err_dma: + if (ret == -ENODEV) { + dev_warn(fmc2->dev, + "DMAs not defined in the DT, polling mode is used\n"); + ret = 0; + } + + return ret; } /* NAND callbacks setup */ From e015d72f321e8b54aa3aef680e85dcd87f912703 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Mon, 2 Mar 2020 15:45:09 -0300 Subject: [PATCH 1547/4444] mtd: rawnand: ingenic: Add dependency on MIPS || COMPILE_TEST This driver has no arch-specific instructions but is only ever useful on MIPS; so disable this driver if we're not compiling for MIPS, unless the driver is compile-tested. Signed-off-by: Paul Cercueil Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200302184509.10666-1-paul@crapouillou.net --- drivers/mtd/nand/raw/ingenic/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/raw/ingenic/Kconfig b/drivers/mtd/nand/raw/ingenic/Kconfig index e30feb56b650..96c5ae8b1bbc 100644 --- a/drivers/mtd/nand/raw/ingenic/Kconfig +++ b/drivers/mtd/nand/raw/ingenic/Kconfig @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config MTD_NAND_JZ4780 tristate "JZ4780 NAND controller" + depends on MIPS || COMPILE_TEST depends on JZ4780_NEMC help Enables support for NAND Flash connected to the NEMC on JZ4780 SoC From 92270086b7e5ada7ab381c06cc3da2e95ed17088 Mon Sep 17 00:00:00 2001 From: Mason Yang Date: Tue, 3 Mar 2020 15:21:21 +0800 Subject: [PATCH 1548/4444] mtd: rawnand: Add support for manufacturer specific lock/unlock operation Add nand_lock() & nand_unlock() for manufacturer specific lock & unlock operation while the device supports Block Portection function. Signed-off-by: Mason Yang Reviewed-by: Miquel Raynal Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/1583220084-10890-2-git-send-email-masonccyang@mxic.com.tw --- drivers/mtd/nand/raw/nand_base.c | 36 ++++++++++++++++++++++++++++++-- include/linux/mtd/rawnand.h | 5 +++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index a3ed6c54963e..a13b91aa3780 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -4365,6 +4365,38 @@ static void nand_shutdown(struct mtd_info *mtd) nand_suspend(mtd); } +/** + * nand_lock - [MTD Interface] Lock the NAND flash + * @mtd: MTD device structure + * @ofs: offset byte address + * @len: number of bytes to lock (must be a multiple of block/page size) + */ +static int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + + if (!chip->lock_area) + return -ENOTSUPP; + + return chip->lock_area(chip, ofs, len); +} + +/** + * nand_unlock - [MTD Interface] Unlock the NAND flash + * @mtd: MTD device structure + * @ofs: offset byte address + * @len: number of bytes to unlock (must be a multiple of block/page size) + */ +static int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + + if (!chip->unlock_area) + return -ENOTSUPP; + + return chip->unlock_area(chip, ofs, len); +} + /* Set default functions */ static void nand_set_defaults(struct nand_chip *chip) { @@ -5791,8 +5823,8 @@ static int nand_scan_tail(struct nand_chip *chip) mtd->_read_oob = nand_read_oob; mtd->_write_oob = nand_write_oob; mtd->_sync = nand_sync; - mtd->_lock = NULL; - mtd->_unlock = NULL; + mtd->_lock = nand_lock; + mtd->_unlock = nand_unlock; mtd->_suspend = nand_suspend; mtd->_resume = nand_resume; mtd->_reboot = nand_shutdown; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 3c7c15aadcee..49ed50fb44ab 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1077,6 +1077,8 @@ struct nand_legacy { * @manufacturer: [INTERN] Contains manufacturer information * @manufacturer.desc: [INTERN] Contains manufacturer's description * @manufacturer.priv: [INTERN] Contains manufacturer private information + * @lock_area: [REPLACEABLE] specific NAND chip lock operation + * @unlock_area: [REPLACEABLE] specific NAND chip unlock operation */ struct nand_chip { @@ -1136,6 +1138,9 @@ struct nand_chip { const struct nand_manufacturer *desc; void *priv; } manufacturer; + + int (*lock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len); + int (*unlock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len); }; extern const struct mtd_ooblayout_ops nand_ooblayout_sp_ops; From 03a539c7a118427a6609a26461358c56ac8f3a06 Mon Sep 17 00:00:00 2001 From: Mason Yang Date: Tue, 3 Mar 2020 15:21:22 +0800 Subject: [PATCH 1549/4444] mtd: rawnand: Macronix: Add support for block protection Macronix AC/AD series support using SET_FEATURES to change block protection and unprotection. Block protection support can be checked with GET_FEATURES. Signed-off-by: Mason Yang Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/1583220084-10890-3-git-send-email-masonccyang@mxic.com.tw --- drivers/mtd/nand/raw/nand_macronix.c | 72 ++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/drivers/mtd/nand/raw/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c index 0a2fe25f2639..fbe2fff0cf1b 100644 --- a/drivers/mtd/nand/raw/nand_macronix.c +++ b/drivers/mtd/nand/raw/nand_macronix.c @@ -11,6 +11,10 @@ #define MACRONIX_READ_RETRY_BIT BIT(0) #define MACRONIX_NUM_READ_RETRY_MODES 6 +#define ONFI_FEATURE_ADDR_MXIC_PROTECTION 0xA0 +#define MXIC_BLOCK_PROTECTION_ALL_LOCK 0x38 +#define MXIC_BLOCK_PROTECTION_ALL_UNLOCK 0x0 + #define ONFI_FEATURE_ADDR_MXIC_RANDOMIZER 0xB0 #define MACRONIX_RANDOMIZER_BIT BIT(1) #define MACRONIX_RANDOMIZER_ENPGM BIT(0) @@ -172,6 +176,73 @@ static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip) ONFI_FEATURE_ADDR_TIMING_MODE, 1); } +/* + * Macronix NAND supports Block Protection by Protectoin(PT) pin; + * active high at power-on which protects the entire chip even the #WP is + * disabled. Lock/unlock protection area can be partition according to + * protection bits, i.e. upper 1/2 locked, upper 1/4 locked and so on. + */ +static int mxic_nand_lock(struct nand_chip *chip, loff_t ofs, uint64_t len) +{ + u8 feature[ONFI_SUBFEATURE_PARAM_LEN]; + int ret; + + feature[0] = MXIC_BLOCK_PROTECTION_ALL_LOCK; + nand_select_target(chip, 0); + ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION, + feature); + nand_deselect_target(chip); + if (ret) + pr_err("%s all blocks failed\n", __func__); + + return ret; +} + +static int mxic_nand_unlock(struct nand_chip *chip, loff_t ofs, uint64_t len) +{ + u8 feature[ONFI_SUBFEATURE_PARAM_LEN]; + int ret; + + feature[0] = MXIC_BLOCK_PROTECTION_ALL_UNLOCK; + nand_select_target(chip, 0); + ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION, + feature); + nand_deselect_target(chip); + if (ret) + pr_err("%s all blocks failed\n", __func__); + + return ret; +} + +static void macronix_nand_block_protection_support(struct nand_chip *chip) +{ + u8 feature[ONFI_SUBFEATURE_PARAM_LEN]; + int ret; + + bitmap_set(chip->parameters.get_feature_list, + ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1); + + feature[0] = MXIC_BLOCK_PROTECTION_ALL_UNLOCK; + nand_select_target(chip, 0); + ret = nand_get_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION, + feature); + nand_deselect_target(chip); + if (ret || feature[0] != MXIC_BLOCK_PROTECTION_ALL_LOCK) { + if (ret) + pr_err("Block protection check failed\n"); + + bitmap_clear(chip->parameters.get_feature_list, + ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1); + return; + } + + bitmap_set(chip->parameters.set_feature_list, + ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1); + + chip->lock_area = mxic_nand_lock; + chip->unlock_area = mxic_nand_unlock; +} + static int macronix_nand_init(struct nand_chip *chip) { if (nand_is_slc(chip)) @@ -179,6 +250,7 @@ static int macronix_nand_init(struct nand_chip *chip) macronix_nand_fix_broken_get_timings(chip); macronix_nand_onfi_init(chip); + macronix_nand_block_protection_support(chip); return 0; } From 397deafc02e1b91668fa1ee95fdd52d14fa82135 Mon Sep 17 00:00:00 2001 From: Piotr Sroka Date: Mon, 10 Feb 2020 10:55:25 +0100 Subject: [PATCH 1550/4444] mtd: rawnand: cadence: get meta data size from registers Add checking size of BCH meta data size in capabilities registers instead of using fixed value. BCH meta data is used to keep data from NAND flash OOB area. Signed-off-by: Piotr Sroka Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/1581328530-29966-1-git-send-email-piotrs@cadence.com --- .../mtd/nand/raw/cadence-nand-controller.c | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c index f6c7102a1e32..5063a8b493a4 100644 --- a/drivers/mtd/nand/raw/cadence-nand-controller.c +++ b/drivers/mtd/nand/raw/cadence-nand-controller.c @@ -30,7 +30,6 @@ * Generic mode is used for executing rest of commands. */ -#define MAX_OOB_SIZE_PER_SECTOR 32 #define MAX_ADDRESS_CYC 6 #define MAX_ERASE_ADDRESS_CYC 3 #define MAX_DATA_SIZE 0xFFFC @@ -190,6 +189,7 @@ /* BCH Engine identification register 3. */ #define BCH_CFG_3 0x844 +#define BCH_CFG_3_METADATA_SIZE GENMASK(23, 16) /* Ready/Busy# line status. */ #define RBN_SETINGS 0x1004 @@ -499,6 +499,7 @@ struct cdns_nand_ctrl { unsigned long assigned_cs; struct list_head chips; + u8 bch_metadata_size; }; struct cdns_nand_chip { @@ -1077,6 +1078,14 @@ static int cadence_nand_read_bch_caps(struct cdns_nand_ctrl *cdns_ctrl) int max_step_size = 0, nstrengths, i; u32 reg; + reg = readl_relaxed(cdns_ctrl->reg + BCH_CFG_3); + cdns_ctrl->bch_metadata_size = FIELD_GET(BCH_CFG_3_METADATA_SIZE, reg); + if (cdns_ctrl->bch_metadata_size < 4) { + dev_err(cdns_ctrl->dev, + "Driver needs at least 4 bytes of BCH meta data\n"); + return -EIO; + } + reg = readl_relaxed(cdns_ctrl->reg + BCH_CFG_0); cdns_ctrl->ecc_strengths[0] = FIELD_GET(BCH_CFG_0_CORR_CAP_0, reg); cdns_ctrl->ecc_strengths[1] = FIELD_GET(BCH_CFG_0_CORR_CAP_1, reg); @@ -1170,7 +1179,8 @@ static int cadence_nand_hw_init(struct cdns_nand_ctrl *cdns_ctrl) writel_relaxed(0xFFFFFFFF, cdns_ctrl->reg + INTR_STATUS); cadence_nand_get_caps(cdns_ctrl); - cadence_nand_read_bch_caps(cdns_ctrl); + if (cadence_nand_read_bch_caps(cdns_ctrl)) + return -EIO; /* * Set IO width access to 8. @@ -2587,7 +2597,6 @@ int cadence_nand_attach_chip(struct nand_chip *chip) struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); u32 ecc_size = cdns_chip->sector_count * chip->ecc.bytes; struct mtd_info *mtd = nand_to_mtd(chip); - u32 max_oob_data_size; int ret; if (chip->options & NAND_BUSWIDTH_16) { @@ -2628,10 +2637,8 @@ int cadence_nand_attach_chip(struct nand_chip *chip) cdns_chip->avail_oob_size = mtd->oobsize - ecc_size; - max_oob_data_size = MAX_OOB_SIZE_PER_SECTOR; - - if (cdns_chip->avail_oob_size > max_oob_data_size) - cdns_chip->avail_oob_size = max_oob_data_size; + if (cdns_chip->avail_oob_size > cdns_ctrl->bch_metadata_size) + cdns_chip->avail_oob_size = cdns_ctrl->bch_metadata_size; if ((cdns_chip->avail_oob_size + cdns_chip->bbm_len + ecc_size) > mtd->oobsize) From e4578af0354176ff6b4ae78b9998b4f479f7c31c Mon Sep 17 00:00:00 2001 From: Piotr Sroka Date: Mon, 10 Feb 2020 10:55:26 +0100 Subject: [PATCH 1551/4444] mtd: rawnand: cadence: fix the calculation of the avaialble OOB size The value of cdns_chip->sector_count is not known at the moment of the derivation of ecc_size, leading to a zero value. Fix this by assigning ecc_size later in the code. Fixes: ec4ba01e894d ("mtd: rawnand: Add new Cadence NAND driver to MTD subsystem") Cc: stable@vger.kernel.org Signed-off-by: Piotr Sroka Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/1581328530-29966-2-git-send-email-piotrs@cadence.com --- drivers/mtd/nand/raw/cadence-nand-controller.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c index 5063a8b493a4..2ebfd0934739 100644 --- a/drivers/mtd/nand/raw/cadence-nand-controller.c +++ b/drivers/mtd/nand/raw/cadence-nand-controller.c @@ -2595,7 +2595,7 @@ int cadence_nand_attach_chip(struct nand_chip *chip) { struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); - u32 ecc_size = cdns_chip->sector_count * chip->ecc.bytes; + u32 ecc_size; struct mtd_info *mtd = nand_to_mtd(chip); int ret; @@ -2634,6 +2634,7 @@ int cadence_nand_attach_chip(struct nand_chip *chip) /* Error correction configuration. */ cdns_chip->sector_size = chip->ecc.size; cdns_chip->sector_count = mtd->writesize / cdns_chip->sector_size; + ecc_size = cdns_chip->sector_count * chip->ecc.bytes; cdns_chip->avail_oob_size = mtd->oobsize - ecc_size; From 9bf1903bed7a2e84f5a8deedb38f7e0ac5e8bfc6 Mon Sep 17 00:00:00 2001 From: Piotr Sroka Date: Mon, 10 Feb 2020 10:55:27 +0100 Subject: [PATCH 1552/4444] mtd: rawnand: cadence: change bad block marker size Increase bad block marker size from one byte to two bytes. Bad block marker is handled by skip bytes feature of HPNFC. Controller expects this value to be an even number. Fixes: ec4ba01e894d ("mtd: rawnand: Add new Cadence NAND driver to MTD subsystem") Cc: stable@vger.kernel.org Signed-off-by: Piotr Sroka Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/1581328530-29966-3-git-send-email-piotrs@cadence.com --- drivers/mtd/nand/raw/cadence-nand-controller.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c index 2ebfd0934739..5c1bbb05ab51 100644 --- a/drivers/mtd/nand/raw/cadence-nand-controller.c +++ b/drivers/mtd/nand/raw/cadence-nand-controller.c @@ -2612,12 +2612,9 @@ int cadence_nand_attach_chip(struct nand_chip *chip) chip->options |= NAND_NO_SUBPAGE_WRITE; cdns_chip->bbm_offs = chip->badblockpos; - if (chip->options & NAND_BUSWIDTH_16) { - cdns_chip->bbm_offs &= ~0x01; - cdns_chip->bbm_len = 2; - } else { - cdns_chip->bbm_len = 1; - } + cdns_chip->bbm_offs &= ~0x01; + /* this value should be even number */ + cdns_chip->bbm_len = 2; ret = nand_ecc_choose_conf(chip, &cdns_ctrl->ecc_caps, From 0d7d6c8183aadb1dcc13f415941404a7913b46b3 Mon Sep 17 00:00:00 2001 From: Piotr Sroka Date: Mon, 10 Feb 2020 10:55:28 +0100 Subject: [PATCH 1553/4444] mtd: rawnand: cadence: reinit completion before executing a new command Reing the completion object before executing CDMA command to make sure the 'done' flag is OK. Fixes: ec4ba01e894d ("mtd: rawnand: Add new Cadence NAND driver to MTD subsystem") Cc: stable@vger.kernel.org Signed-off-by: Piotr Sroka Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/1581328530-29966-4-git-send-email-piotrs@cadence.com --- drivers/mtd/nand/raw/cadence-nand-controller.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c index 5c1bbb05ab51..efddc5c68afb 100644 --- a/drivers/mtd/nand/raw/cadence-nand-controller.c +++ b/drivers/mtd/nand/raw/cadence-nand-controller.c @@ -998,6 +998,7 @@ static int cadence_nand_cdma_send(struct cdns_nand_ctrl *cdns_ctrl, return status; cadence_nand_reset_irq(cdns_ctrl); + reinit_completion(&cdns_ctrl->complete); writel_relaxed((u32)cdns_ctrl->dma_cdma_desc, cdns_ctrl->reg + CMD_REG2); From cdc6aba6719b9d7d85c6d411a43345ee12223268 Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Wed, 22 Jan 2020 16:33:11 -0500 Subject: [PATCH 1554/4444] dt: bindings: brcmnand: Add support for flash-edu Adding support for EBI DMA unit (EDU). Signed-off-by: Kamal Dasu Reviewed-by: Rob Herring Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200122213313.35820-2-kdasu.kdev@gmail.com --- .../devicetree/bindings/mtd/brcm,brcmnand.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt index 82156dc8f304..05651a654c66 100644 --- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt @@ -35,11 +35,11 @@ Required properties: (optional) NAND flash cache range (if at non-standard offset) - reg-names : a list of the names corresponding to the previous register ranges. Should contain "nand" and (optionally) - "flash-dma" and/or "nand-cache". -- interrupts : The NAND CTLRDY interrupt and (if Flash DMA is available) - FLASH_DMA_DONE -- interrupt-names : May be "nand_ctlrdy" or "flash_dma_done", if broken out as - individual interrupts. + "flash-dma" or "flash-edu" and/or "nand-cache". +- interrupts : The NAND CTLRDY interrupt, (if Flash DMA is available) + FLASH_DMA_DONE and if EDU is avaialble and used FLASH_EDU_DONE +- interrupt-names : May be "nand_ctlrdy" or "flash_dma_done" or "flash_edu_done", + if broken out as individual interrupts. May be "nand", if the SoC has the individual NAND interrupts multiplexed behind another custom piece of hardware From 634088e2621310d2473e4ec3b69843e32d5cee20 Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Wed, 22 Jan 2020 16:33:12 -0500 Subject: [PATCH 1555/4444] arch: mips: brcm: Add 7425 flash-edu support Nand controller v5.0 and v6.0 have nand edu blocks that enable dma nand flash transfers. This allows for faster read and write access. Signed-off-by: Kamal Dasu Acked-by: Paul Burton Reviewed-by: Florian Fainelli Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200122213313.35820-3-kdasu.kdev@gmail.com --- arch/mips/boot/dts/brcm/bcm7425.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/boot/dts/brcm/bcm7425.dtsi b/arch/mips/boot/dts/brcm/bcm7425.dtsi index 410e61ebaf9e..aa0b2d39c902 100644 --- a/arch/mips/boot/dts/brcm/bcm7425.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7425.dtsi @@ -403,8 +403,8 @@ compatible = "brcm,brcmnand-v5.0", "brcm,brcmnand"; #address-cells = <1>; #size-cells = <0>; - reg-names = "nand"; - reg = <0x41b800 0x400>; + reg-names = "nand", "flash-edu"; + reg = <0x41b800 0x400>, <0x41bc00 0x24>; interrupt-parent = <&hif_l2_intc>; interrupts = <24>; status = "disabled"; From a5d53ad26a8b441325eb9de8e9bb816584ebca7c Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Wed, 22 Jan 2020 16:33:13 -0500 Subject: [PATCH 1556/4444] mtd: rawnand: brcmnand: Add support for flash-edu for dma transfers Legacy mips soc platforms that have controller v5.0 and 6.0 use flash-edu block for dma transfers. This change adds support for nand dma transfers using the EDU block. Signed-off-by: Kamal Dasu Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200122213313.35820-4-kdasu.kdev@gmail.com --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 293 ++++++++++++++++++++++- 1 file changed, 287 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 44518dada75b..e4e3ceeac38f 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -102,6 +102,45 @@ struct brcm_nand_dma_desc { #define NAND_CTRL_RDY (INTFC_CTLR_READY | INTFC_FLASH_READY) #define NAND_POLL_STATUS_TIMEOUT_MS 100 +#define EDU_CMD_WRITE 0x00 +#define EDU_CMD_READ 0x01 +#define EDU_STATUS_ACTIVE BIT(0) +#define EDU_ERR_STATUS_ERRACK BIT(0) +#define EDU_DONE_MASK GENMASK(1, 0) + +#define EDU_CONFIG_MODE_NAND BIT(0) +#define EDU_CONFIG_SWAP_BYTE BIT(1) +#ifdef CONFIG_CPU_BIG_ENDIAN +#define EDU_CONFIG_SWAP_CFG EDU_CONFIG_SWAP_BYTE +#else +#define EDU_CONFIG_SWAP_CFG 0 +#endif + +/* edu registers */ +enum edu_reg { + EDU_CONFIG = 0, + EDU_DRAM_ADDR, + EDU_EXT_ADDR, + EDU_LENGTH, + EDU_CMD, + EDU_STOP, + EDU_STATUS, + EDU_DONE, + EDU_ERR_STATUS, +}; + +static const u16 edu_regs[] = { + [EDU_CONFIG] = 0x00, + [EDU_DRAM_ADDR] = 0x04, + [EDU_EXT_ADDR] = 0x08, + [EDU_LENGTH] = 0x0c, + [EDU_CMD] = 0x10, + [EDU_STOP] = 0x14, + [EDU_STATUS] = 0x18, + [EDU_DONE] = 0x1c, + [EDU_ERR_STATUS] = 0x20, +}; + /* flash_dma registers */ enum flash_dma_reg { FLASH_DMA_REVISION = 0, @@ -167,6 +206,8 @@ enum { BRCMNAND_HAS_WP = BIT(3), }; +struct brcmnand_host; + struct brcmnand_controller { struct device *dev; struct nand_controller controller; @@ -185,17 +226,32 @@ struct brcmnand_controller { int cmd_pending; bool dma_pending; + bool edu_pending; struct completion done; struct completion dma_done; + struct completion edu_done; /* List of NAND hosts (one for each chip-select) */ struct list_head host_list; + /* EDU info, per-transaction */ + const u16 *edu_offsets; + void __iomem *edu_base; + int edu_irq; + int edu_count; + u64 edu_dram_addr; + u32 edu_ext_addr; + u32 edu_cmd; + u32 edu_config; + /* flash_dma reg */ const u16 *flash_dma_offsets; struct brcm_nand_dma_desc *dma_desc; dma_addr_t dma_pa; + int (*dma_trans)(struct brcmnand_host *host, u64 addr, u32 *buf, + u32 len, u8 dma_cmd); + /* in-memory cache of the FLASH_CACHE, used only for some commands */ u8 flash_cache[FC_BYTES]; @@ -216,6 +272,7 @@ struct brcmnand_controller { u32 nand_cs_nand_xor; u32 corr_stat_threshold; u32 flash_dma_mode; + u32 flash_edu_mode; bool pio_poll_mode; }; @@ -657,6 +714,22 @@ static inline void brcmnand_write_fc(struct brcmnand_controller *ctrl, __raw_writel(val, ctrl->nand_fc + word * 4); } +static inline void edu_writel(struct brcmnand_controller *ctrl, + enum edu_reg reg, u32 val) +{ + u16 offs = ctrl->edu_offsets[reg]; + + brcmnand_writel(val, ctrl->edu_base + offs); +} + +static inline u32 edu_readl(struct brcmnand_controller *ctrl, + enum edu_reg reg) +{ + u16 offs = ctrl->edu_offsets[reg]; + + return brcmnand_readl(ctrl->edu_base + offs); +} + static void brcmnand_clear_ecc_addr(struct brcmnand_controller *ctrl) { @@ -926,6 +999,16 @@ static inline bool has_flash_dma(struct brcmnand_controller *ctrl) return ctrl->flash_dma_base; } +static inline bool has_edu(struct brcmnand_controller *ctrl) +{ + return ctrl->edu_base; +} + +static inline bool use_dma(struct brcmnand_controller *ctrl) +{ + return has_flash_dma(ctrl) || has_edu(ctrl); +} + static inline void disable_ctrl_irqs(struct brcmnand_controller *ctrl) { if (ctrl->pio_poll_mode) @@ -1299,6 +1382,52 @@ static int write_oob_to_regs(struct brcmnand_controller *ctrl, int i, return tbytes; } +static void brcmnand_edu_init(struct brcmnand_controller *ctrl) +{ + /* initialize edu */ + edu_writel(ctrl, EDU_ERR_STATUS, 0); + edu_readl(ctrl, EDU_ERR_STATUS); + edu_writel(ctrl, EDU_DONE, 0); + edu_writel(ctrl, EDU_DONE, 0); + edu_writel(ctrl, EDU_DONE, 0); + edu_writel(ctrl, EDU_DONE, 0); + edu_readl(ctrl, EDU_DONE); +} + +/* edu irq */ +static irqreturn_t brcmnand_edu_irq(int irq, void *data) +{ + struct brcmnand_controller *ctrl = data; + + if (ctrl->edu_count) { + ctrl->edu_count--; + while (!(edu_readl(ctrl, EDU_DONE) & EDU_DONE_MASK)) + udelay(1); + edu_writel(ctrl, EDU_DONE, 0); + edu_readl(ctrl, EDU_DONE); + } + + if (ctrl->edu_count) { + ctrl->edu_dram_addr += FC_BYTES; + ctrl->edu_ext_addr += FC_BYTES; + + edu_writel(ctrl, EDU_DRAM_ADDR, (u32)ctrl->edu_dram_addr); + edu_readl(ctrl, EDU_DRAM_ADDR); + edu_writel(ctrl, EDU_EXT_ADDR, ctrl->edu_ext_addr); + edu_readl(ctrl, EDU_EXT_ADDR); + + mb(); /* flush previous writes */ + edu_writel(ctrl, EDU_CMD, ctrl->edu_cmd); + edu_readl(ctrl, EDU_CMD); + + return IRQ_HANDLED; + } + + complete(&ctrl->edu_done); + + return IRQ_HANDLED; +} + static irqreturn_t brcmnand_ctlrdy_irq(int irq, void *data) { struct brcmnand_controller *ctrl = data; @@ -1307,6 +1436,16 @@ static irqreturn_t brcmnand_ctlrdy_irq(int irq, void *data) if (ctrl->dma_pending) return IRQ_HANDLED; + /* check if you need to piggy back on the ctrlrdy irq */ + if (ctrl->edu_pending) { + if (irq == ctrl->irq && ((int)ctrl->edu_irq >= 0)) + /* Discard interrupts while using dedicated edu irq */ + return IRQ_HANDLED; + + /* no registered edu irq, call handler */ + return brcmnand_edu_irq(irq, data); + } + complete(&ctrl->done); return IRQ_HANDLED; } @@ -1644,6 +1783,81 @@ static void brcmnand_write_buf(struct nand_chip *chip, const uint8_t *buf, } } +/** + * Kick EDU engine + */ +static int brcmnand_edu_trans(struct brcmnand_host *host, u64 addr, u32 *buf, + u32 len, u8 cmd) +{ + struct brcmnand_controller *ctrl = host->ctrl; + unsigned long timeo = msecs_to_jiffies(200); + int ret = 0; + int dir = (cmd == CMD_PAGE_READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE); + u8 edu_cmd = (cmd == CMD_PAGE_READ ? EDU_CMD_READ : EDU_CMD_WRITE); + unsigned int trans = len >> FC_SHIFT; + dma_addr_t pa; + + pa = dma_map_single(ctrl->dev, buf, len, dir); + if (dma_mapping_error(ctrl->dev, pa)) { + dev_err(ctrl->dev, "unable to map buffer for EDU DMA\n"); + return -ENOMEM; + } + + ctrl->edu_pending = true; + ctrl->edu_dram_addr = pa; + ctrl->edu_ext_addr = addr; + ctrl->edu_cmd = edu_cmd; + ctrl->edu_count = trans; + + edu_writel(ctrl, EDU_DRAM_ADDR, (u32)ctrl->edu_dram_addr); + edu_readl(ctrl, EDU_DRAM_ADDR); + edu_writel(ctrl, EDU_EXT_ADDR, ctrl->edu_ext_addr); + edu_readl(ctrl, EDU_EXT_ADDR); + edu_writel(ctrl, EDU_LENGTH, FC_BYTES); + edu_readl(ctrl, EDU_LENGTH); + + /* Start edu engine */ + mb(); /* flush previous writes */ + edu_writel(ctrl, EDU_CMD, ctrl->edu_cmd); + edu_readl(ctrl, EDU_CMD); + + if (wait_for_completion_timeout(&ctrl->edu_done, timeo) <= 0) { + dev_err(ctrl->dev, + "timeout waiting for EDU; status %#x, error status %#x\n", + edu_readl(ctrl, EDU_STATUS), + edu_readl(ctrl, EDU_ERR_STATUS)); + } + + dma_unmap_single(ctrl->dev, pa, len, dir); + + /* for program page check NAND status */ + if (((brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS) & + INTFC_FLASH_STATUS) & NAND_STATUS_FAIL) && + edu_cmd == EDU_CMD_WRITE) { + dev_info(ctrl->dev, "program failed at %llx\n", + (unsigned long long)addr); + ret = -EIO; + } + + /* Make sure the EDU status is clean */ + if (edu_readl(ctrl, EDU_STATUS) & EDU_STATUS_ACTIVE) + dev_warn(ctrl->dev, "EDU still active: %#x\n", + edu_readl(ctrl, EDU_STATUS)); + + if (unlikely(edu_readl(ctrl, EDU_ERR_STATUS) & EDU_ERR_STATUS_ERRACK)) { + dev_warn(ctrl->dev, "EDU RBUS error at addr %llx\n", + (unsigned long long)addr); + ret = -EIO; + } + + ctrl->edu_pending = false; + brcmnand_edu_init(ctrl); + edu_writel(ctrl, EDU_STOP, 0); /* force stop */ + edu_readl(ctrl, EDU_STOP); + + return ret; +} + /** * Construct a FLASH_DMA descriptor as part of a linked list. You must know the * following ahead of time: @@ -1850,9 +2064,11 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip, try_dmaread: brcmnand_clear_ecc_addr(ctrl); - if (has_flash_dma(ctrl) && !oob && flash_dma_buf_ok(buf)) { - err = brcmnand_dma_trans(host, addr, buf, trans * FC_BYTES, - CMD_PAGE_READ); + if (ctrl->dma_trans && !oob && flash_dma_buf_ok(buf)) { + err = ctrl->dma_trans(host, addr, buf, + trans * FC_BYTES, + CMD_PAGE_READ); + if (err) { if (mtd_is_bitflip_or_eccerr(err)) err_addr = addr; @@ -1988,10 +2204,12 @@ static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip, for (i = 0; i < ctrl->max_oob; i += 4) oob_reg_write(ctrl, i, 0xffffffff); - if (has_flash_dma(ctrl) && !oob && flash_dma_buf_ok(buf)) { - if (brcmnand_dma_trans(host, addr, (u32 *)buf, - mtd->writesize, CMD_PROGRAM_PAGE)) + if (use_dma(ctrl) && !oob && flash_dma_buf_ok(buf)) { + if (ctrl->dma_trans(host, addr, (u32 *)buf, mtd->writesize, + CMD_PROGRAM_PAGE)) + ret = -EIO; + goto out; } @@ -2494,6 +2712,8 @@ static int brcmnand_suspend(struct device *dev) if (has_flash_dma(ctrl)) ctrl->flash_dma_mode = flash_dma_readl(ctrl, FLASH_DMA_MODE); + else if (has_edu(ctrl)) + ctrl->edu_config = edu_readl(ctrl, EDU_CONFIG); return 0; } @@ -2508,6 +2728,14 @@ static int brcmnand_resume(struct device *dev) flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0); } + if (has_edu(ctrl)) + ctrl->edu_config = edu_readl(ctrl, EDU_CONFIG); + else { + edu_writel(ctrl, EDU_CONFIG, ctrl->edu_config); + edu_readl(ctrl, EDU_CONFIG); + brcmnand_edu_init(ctrl); + } + brcmnand_write_reg(ctrl, BRCMNAND_CS_SELECT, ctrl->nand_cs_nand_select); brcmnand_write_reg(ctrl, BRCMNAND_CS_XOR, ctrl->nand_cs_nand_xor); brcmnand_write_reg(ctrl, BRCMNAND_CORR_THRESHOLD, @@ -2553,6 +2781,49 @@ MODULE_DEVICE_TABLE(of, brcmnand_of_match); /*********************************************************************** * Platform driver setup (per controller) ***********************************************************************/ +static int brcmnand_edu_setup(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct brcmnand_controller *ctrl = dev_get_drvdata(&pdev->dev); + struct resource *res; + int ret; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "flash-edu"); + if (res) { + ctrl->edu_base = devm_ioremap_resource(dev, res); + if (IS_ERR(ctrl->edu_base)) + return PTR_ERR(ctrl->edu_base); + + ctrl->edu_offsets = edu_regs; + + edu_writel(ctrl, EDU_CONFIG, EDU_CONFIG_MODE_NAND | + EDU_CONFIG_SWAP_CFG); + edu_readl(ctrl, EDU_CONFIG); + + /* initialize edu */ + brcmnand_edu_init(ctrl); + + ctrl->edu_irq = platform_get_irq_optional(pdev, 1); + if (ctrl->edu_irq < 0) { + dev_warn(dev, + "FLASH EDU enabled, using ctlrdy irq\n"); + } else { + ret = devm_request_irq(dev, ctrl->edu_irq, + brcmnand_edu_irq, 0, + "brcmnand-edu", ctrl); + if (ret < 0) { + dev_err(ctrl->dev, "can't allocate IRQ %d: error %d\n", + ctrl->edu_irq, ret); + return ret; + } + + dev_info(dev, "FLASH EDU enabled using irq %u\n", + ctrl->edu_irq); + } + } + + return 0; +} int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) { @@ -2578,6 +2849,7 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) init_completion(&ctrl->done); init_completion(&ctrl->dma_done); + init_completion(&ctrl->edu_done); nand_controller_init(&ctrl->controller); ctrl->controller.ops = &brcmnand_controller_ops; INIT_LIST_HEAD(&ctrl->host_list); @@ -2675,6 +2947,15 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) } dev_info(dev, "enabling FLASH_DMA\n"); + /* set flash dma transfer function to call */ + ctrl->dma_trans = brcmnand_dma_trans; + } else { + ret = brcmnand_edu_setup(pdev); + if (ret < 0) + goto err; + + /* set edu transfer function to call */ + ctrl->dma_trans = brcmnand_edu_trans; } /* Disable automatic device ID config, direct addressing */ From 96f5b4fa567040360dc57fd39b8e1a85a3e0132a Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 10 Mar 2020 20:50:07 +0800 Subject: [PATCH 1557/4444] f2fs: fix to account compressed inode correctly stat_inc_compr_inode() needs to check FI_COMPRESSED_FILE flag, so in f2fs_disable_compressed_file(), we should call stat_dec_compr_inode() before clearing FI_COMPRESSED_FILE flag. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 760a05f98ac7..23013d3b59ba 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3824,8 +3824,8 @@ static inline u64 f2fs_disable_compressed_file(struct inode *inode) return fi->i_compr_blocks; fi->i_flags &= ~F2FS_COMPR_FL; - clear_inode_flag(inode, FI_COMPRESSED_FILE); stat_dec_compr_inode(inode); + clear_inode_flag(inode, FI_COMPRESSED_FILE); return 0; } From 6cfdf15fdbff85acbaa92920bee88f37ca0404ba Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 10 Mar 2020 20:50:08 +0800 Subject: [PATCH 1558/4444] f2fs: fix to check dirty pages during compressed inode conversion Compressed cluster can be generated during dirty data writeback, if there is dirty pages on compressed inode, it needs to disable converting compressed inode to non-compressed one. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 23013d3b59ba..dbca4c6a7aaf 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3820,6 +3820,8 @@ static inline u64 f2fs_disable_compressed_file(struct inode *inode) if (!f2fs_compressed_file(inode)) return 0; + if (get_dirty_pages(inode)) + return 1; if (fi->i_compr_blocks) return fi->i_compr_blocks; From 2536ac6872e5265b4d9d263122cee02e3d5cae1d Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 10 Mar 2020 20:50:09 +0800 Subject: [PATCH 1559/4444] f2fs: allow to clear F2FS_COMPR_FL flag If regular inode has no compressed cluster, allow using 'chattr -c' to remove its compress flag, recovering it to a non-compressed file. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 07f636732199..afc9a1a5a884 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1817,10 +1817,10 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask) } if ((iflags ^ masked_flags) & F2FS_COMPR_FL) { - if (S_ISREG(inode->i_mode) && - (masked_flags & F2FS_COMPR_FL || i_size_read(inode) || - F2FS_HAS_BLOCKS(inode))) - return -EINVAL; + if (S_ISREG(inode->i_mode) && (masked_flags & F2FS_COMPR_FL)) { + if (f2fs_disable_compressed_file(inode)) + return -EINVAL; + } if (iflags & F2FS_NOCOMP_FL) return -EINVAL; if (iflags & F2FS_COMPR_FL) { From da180322582bd9db07f29e6d4a2d170afde0703f Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Sat, 25 Jan 2020 00:20:09 +0100 Subject: [PATCH 1560/4444] ARM: dts: sunxi: Fix DE2 clocks register range As it can be seen from DE2 manual, clock range is 0x10000. Fix it. Signed-off-by: Jernej Skrabec Fixes: 73f122c82775 ("ARM: dts: sun8i: a83t: Add display pipeline") Fixes: 05a43a262d03 ("ARM: dts: sun8i: r40: Add HDMI pipeline") Fixes: 21b299209330 ("ARM: sun8i: v3s: add device nodes for DE2 display pipeline") Fixes: d8c6f1f0295c ("ARM: sun8i: h3/h5: add DE2 CCU device node for H3") [wens@csie.org: added fixes tags] Signed-off-by: Chen-Yu Tsai --- arch/arm/boot/dts/sun8i-a83t.dtsi | 2 +- arch/arm/boot/dts/sun8i-r40.dtsi | 2 +- arch/arm/boot/dts/sun8i-v3s.dtsi | 2 +- arch/arm/boot/dts/sunxi-h3-h5.dtsi | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi index 53c2b6a836f2..92c69534d1e5 100644 --- a/arch/arm/boot/dts/sun8i-a83t.dtsi +++ b/arch/arm/boot/dts/sun8i-a83t.dtsi @@ -314,7 +314,7 @@ display_clocks: clock@1000000 { compatible = "allwinner,sun8i-a83t-de2-clk"; - reg = <0x01000000 0x100000>; + reg = <0x01000000 0x10000>; clocks = <&ccu CLK_BUS_DE>, <&ccu CLK_PLL_DE>; clock-names = "bus", diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi index d5442b5b6fd2..b2dd00a8eb9d 100644 --- a/arch/arm/boot/dts/sun8i-r40.dtsi +++ b/arch/arm/boot/dts/sun8i-r40.dtsi @@ -136,7 +136,7 @@ display_clocks: clock@1000000 { compatible = "allwinner,sun8i-r40-de2-clk", "allwinner,sun8i-h3-de2-clk"; - reg = <0x01000000 0x100000>; + reg = <0x01000000 0x10000>; clocks = <&ccu CLK_BUS_DE>, <&ccu CLK_DE>; clock-names = "bus", diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi index 81ea50838cd5..e5312869c0d2 100644 --- a/arch/arm/boot/dts/sun8i-v3s.dtsi +++ b/arch/arm/boot/dts/sun8i-v3s.dtsi @@ -105,7 +105,7 @@ display_clocks: clock@1000000 { compatible = "allwinner,sun8i-v3s-de2-clk"; - reg = <0x01000000 0x100000>; + reg = <0x01000000 0x10000>; clocks = <&ccu CLK_BUS_DE>, <&ccu CLK_DE>; clock-names = "bus", diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi index ed3908849111..d5516019e0f6 100644 --- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi +++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi @@ -114,7 +114,7 @@ display_clocks: clock@1000000 { /* compatible is in per SoC .dtsi file */ - reg = <0x01000000 0x100000>; + reg = <0x01000000 0x10000>; clocks = <&ccu CLK_BUS_DE>, <&ccu CLK_DE>; clock-names = "bus", From 3e9a1a8b7f811de3eb1445d72f68766b704ad17c Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Sat, 25 Jan 2020 00:20:10 +0100 Subject: [PATCH 1561/4444] arm64: dts: allwinner: a64: Fix display clock register range Register range of display clocks is 0x10000, as it can be seen from DE2 documentation. Fix it. Signed-off-by: Jernej Skrabec Fixes: 2c796fc8f5dbd ("arm64: dts: allwinner: a64: add necessary device tree nodes for DE2 CCU") [wens@csie.org: added fixes tag] Signed-off-by: Chen-Yu Tsai --- arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index 990de71ca048..8571f4aeaeb8 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -264,7 +264,7 @@ display_clocks: clock@0 { compatible = "allwinner,sun50i-a64-de2-clk"; - reg = <0x0 0x100000>; + reg = <0x0 0x10000>; clocks = <&ccu CLK_BUS_DE>, <&ccu CLK_DE>; clock-names = "bus", From dbf72a8c014728691f95a3fc9a463f9bdeb8c3fb Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Sat, 25 Jan 2020 00:20:13 +0100 Subject: [PATCH 1562/4444] ARM: dts: sun8i: a83t: Add device node for rotation core Allwinner A83T contains rotation core. Add a node for it. Signed-off-by: Jernej Skrabec Signed-off-by: Chen-Yu Tsai --- arch/arm/boot/dts/sun8i-a83t.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi index 92c69534d1e5..ff29458235ee 100644 --- a/arch/arm/boot/dts/sun8i-a83t.dtsi +++ b/arch/arm/boot/dts/sun8i-a83t.dtsi @@ -324,6 +324,17 @@ #reset-cells = <1>; }; + rotate: rotate@1020000 { + compatible = "allwinner,sun8i-a83t-de2-rotate"; + reg = <0x1020000 0x10000>; + interrupts = ; + clocks = <&display_clocks CLK_BUS_ROT>, + <&display_clocks CLK_ROT>; + clock-names = "bus", + "mod"; + resets = <&display_clocks RST_ROT>; + }; + mixer0: mixer@1100000 { compatible = "allwinner,sun8i-a83t-de2-mixer-0"; reg = <0x01100000 0x100000>; From 048cdfceebb762ccbec7a11e1f1fb1c170c1e669 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Sat, 25 Jan 2020 00:20:14 +0100 Subject: [PATCH 1563/4444] arm64: dts: allwinner: a64: add node for rotation core Allwinner A64 contains rotation core compatible to A83T. Add a node for it. Signed-off-by: Jernej Skrabec Signed-off-by: Chen-Yu Tsai --- arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index 8571f4aeaeb8..31143fe64d91 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -274,6 +274,18 @@ #reset-cells = <1>; }; + rotate: rotate@20000 { + compatible = "allwinner,sun50i-a64-de2-rotate", + "allwinner,sun8i-a83t-de2-rotate"; + reg = <0x20000 0x10000>; + interrupts = ; + clocks = <&display_clocks CLK_BUS_ROT>, + <&display_clocks CLK_ROT>; + clock-names = "bus", + "mod"; + resets = <&display_clocks RST_ROT>; + }; + mixer0: mixer@100000 { compatible = "allwinner,sun50i-a64-de2-mixer-0"; reg = <0x100000 0x100000>; From 103ae95513803102d2a2c91458cfac5dfbaad124 Mon Sep 17 00:00:00 2001 From: tangbin Date: Wed, 11 Mar 2020 22:46:46 +0800 Subject: [PATCH 1564/4444] ASoC: zte: zx-tdm: remove redundant variables dev In this function, the variable 'dev' is assigned to '&pdev->dev', but in the following code, all the assignments to 'struce device' are used '&pdev->dev' instead of 'dev',except 'zx_tdm->dev'. So,the variable 'dev' in this function is redundant and can be replaced by '&pdev->dev' as elsewhere. Signed-off-by: tangbin Link: https://lore.kernel.org/r/20200311144646.11292-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/zte/zx-tdm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/zte/zx-tdm.c b/sound/soc/zte/zx-tdm.c index 0e5a05b25a77..4f787185d630 100644 --- a/sound/soc/zte/zx-tdm.c +++ b/sound/soc/zte/zx-tdm.c @@ -371,7 +371,6 @@ static struct snd_soc_dai_driver zx_tdm_dai = { static int zx_tdm_probe(struct platform_device *pdev) { - struct device *dev = &pdev->dev; struct of_phandle_args out_args; unsigned int dma_reg_offset; struct zx_tdm_info *zx_tdm; @@ -384,7 +383,7 @@ static int zx_tdm_probe(struct platform_device *pdev) if (!zx_tdm) return -ENOMEM; - zx_tdm->dev = dev; + zx_tdm->dev = &pdev->dev; zx_tdm->dai_wclk = devm_clk_get(&pdev->dev, "wclk"); if (IS_ERR(zx_tdm->dai_wclk)) { From 9032cdd96a2d4b0ef2f43499328f8a68050be2ec Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Fri, 17 Jan 2020 18:03:52 +0100 Subject: [PATCH 1565/4444] ASoC: dt-bindings: stm32: convert spdfirx to json-schema Convert the STM32 SPDIFRX bindings to DT schema format using json-schema. Signed-off-by: Olivier Moysan Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20200117170352.16040-1-olivier.moysan@st.com Signed-off-by: Mark Brown --- .../bindings/sound/st,stm32-spdifrx.txt | 56 ------------- .../bindings/sound/st,stm32-spdifrx.yaml | 80 +++++++++++++++++++ 2 files changed, 80 insertions(+), 56 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml diff --git a/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt deleted file mode 100644 index 33826f2459fa..000000000000 --- a/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt +++ /dev/null @@ -1,56 +0,0 @@ -STMicroelectronics STM32 S/PDIF receiver (SPDIFRX). - -The SPDIFRX peripheral, is designed to receive an S/PDIF flow compliant with -IEC-60958 and IEC-61937. - -Required properties: - - compatible: should be "st,stm32h7-spdifrx" - - reg: cpu DAI IP base address and size - - clocks: must contain an entry for kclk (used as S/PDIF signal reference) - - clock-names: must contain "kclk" - - interrupts: cpu DAI interrupt line - - dmas: DMA specifiers for audio data DMA and iec control flow DMA - See STM32 DMA bindings, Documentation/devicetree/bindings/dma/stm32-dma.txt - - dma-names: two dmas have to be defined, "rx" and "rx-ctrl" - -Optional properties: - - resets: Reference to a reset controller asserting the SPDIFRX - -The device node should contain one 'port' child node with one child 'endpoint' -node, according to the bindings defined in Documentation/devicetree/bindings/ -graph.txt. - -Example: -spdifrx: spdifrx@40004000 { - compatible = "st,stm32h7-spdifrx"; - reg = <0x40004000 0x400>; - clocks = <&rcc SPDIFRX_CK>; - clock-names = "kclk"; - interrupts = <97>; - dmas = <&dmamux1 2 93 0x400 0x0>, - <&dmamux1 3 94 0x400 0x0>; - dma-names = "rx", "rx-ctrl"; - pinctrl-0 = <&spdifrx_pins>; - pinctrl-names = "default"; - - spdifrx_port: port { - cpu_endpoint: endpoint { - remote-endpoint = <&codec_endpoint>; - }; - }; -}; - -spdif_in: spdif-in { - compatible = "linux,spdif-dir"; - - codec_port: port { - codec_endpoint: endpoint { - remote-endpoint = <&cpu_endpoint>; - }; - }; -}; - -soundcard { - compatible = "audio-graph-card"; - dais = <&spdifrx_port>; -}; diff --git a/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml new file mode 100644 index 000000000000..b7f7dc452231 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml @@ -0,0 +1,80 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/st,stm32-spdifrx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectronics STM32 S/PDIF receiver (SPDIFRX) + +maintainers: + - Olivier Moysan + +description: | + The SPDIFRX peripheral, is designed to receive an S/PDIF flow compliant with + IEC-60958 and IEC-61937. + +properties: + compatible: + enum: + - st,stm32h7-spdifrx + + "#sound-dai-cells": + const: 0 + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: kclk + + interrupts: + maxItems: 1 + + dmas: + items: + - description: audio data capture DMA + - description: IEC status bits capture DMA + + dma-names: + items: + - const: rx + - const: rx-ctrl + + resets: + maxItems: 1 + +required: + - compatible + - "#sound-dai-cells" + - reg + - clocks + - clock-names + - interrupts + - dmas + - dma-names + +additionalProperties: false + +examples: + - | + #include + #include + spdifrx: spdifrx@40004000 { + compatible = "st,stm32h7-spdifrx"; + #sound-dai-cells = <0>; + reg = <0x40004000 0x400>; + clocks = <&rcc SPDIF_K>; + clock-names = "kclk"; + interrupts = ; + dmas = <&dmamux1 2 93 0x400 0x0>, + <&dmamux1 3 94 0x400 0x0>; + dma-names = "rx", "rx-ctrl"; + pinctrl-0 = <&spdifrx_pins>; + pinctrl-names = "default"; + }; + +... From 583b53ece0b0268c542a1eafadb62e3d4b0aab8c Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Mon, 9 Mar 2020 00:51:43 +0300 Subject: [PATCH 1566/4444] power: supply: bq27xxx_battery: Silence deferred-probe error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver fails to probe with -EPROBE_DEFER if battery's power supply (charger driver) isn't ready yet and this results in a bit noisy error message in KMSG during kernel's boot up. Let's silence the harmless error message. Signed-off-by: Dmitry Osipenko Reviewed-by: Andrew F. Davis Reviewed-by: Pali Rohár Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq27xxx_battery.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c index 195c18c2f426..664e50103eaa 100644 --- a/drivers/power/supply/bq27xxx_battery.c +++ b/drivers/power/supply/bq27xxx_battery.c @@ -1885,7 +1885,10 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) di->bat = power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg); if (IS_ERR(di->bat)) { - dev_err(di->dev, "failed to register battery\n"); + if (PTR_ERR(di->bat) == -EPROBE_DEFER) + dev_dbg(di->dev, "failed to register battery, deferring probe\n"); + else + dev_err(di->dev, "failed to register battery\n"); return PTR_ERR(di->bat); } From 9027f6111ca40dcc703e1cf6129a73703ae299b7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Mar 2020 10:08:18 +0100 Subject: [PATCH 1567/4444] power: twl4030: Use scnprintf() for avoiding potential buffer overflow Since snprintf() returns the would-be-output size instead of the actual output size, the succeeding calls may go beyond the given buffer limit. Fix it by replacing with scnprintf(). Signed-off-by: Takashi Iwai Signed-off-by: Sebastian Reichel --- drivers/power/supply/twl4030_charger.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/twl4030_charger.c b/drivers/power/supply/twl4030_charger.c index 648ab80288c9..1bc49b2e12e8 100644 --- a/drivers/power/supply/twl4030_charger.c +++ b/drivers/power/supply/twl4030_charger.c @@ -726,10 +726,10 @@ twl4030_bci_mode_show(struct device *dev, for (i = 0; i < ARRAY_SIZE(modes); i++) if (mode == i) - len += snprintf(buf+len, PAGE_SIZE-len, + len += scnprintf(buf+len, PAGE_SIZE-len, "[%s] ", modes[i]); else - len += snprintf(buf+len, PAGE_SIZE-len, + len += scnprintf(buf+len, PAGE_SIZE-len, "%s ", modes[i]); buf[len-1] = '\n'; return len; From 6cdd5b09cbe67365c42aee539f6fd00f2ecfdaab Mon Sep 17 00:00:00 2001 From: Sherry Zong Date: Mon, 9 Mar 2020 16:18:44 +0800 Subject: [PATCH 1568/4444] power: reset: sc27xx: Power off the external subsystems' connection When powering off the whole system, we should power off some external subsystems' connection firstly, otherwise some external subsystems will hold some power and result in powering down abnormally. Signed-off-by: Sherry Zong Signed-off-by: Baolin Wang Signed-off-by: Sebastian Reichel --- drivers/power/reset/sc27xx-poweroff.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/power/reset/sc27xx-poweroff.c b/drivers/power/reset/sc27xx-poweroff.c index 29fb08b8faa0..2bedd4c58ddc 100644 --- a/drivers/power/reset/sc27xx-poweroff.c +++ b/drivers/power/reset/sc27xx-poweroff.c @@ -13,6 +13,8 @@ #define SC27XX_PWR_PD_HW 0xc2c #define SC27XX_PWR_OFF_EN BIT(0) +#define SC27XX_SLP_CTRL 0xdf0 +#define SC27XX_LDO_XTL_EN BIT(3) static struct regmap *regmap; @@ -40,6 +42,9 @@ static struct syscore_ops poweroff_syscore_ops = { static void sc27xx_poweroff_do_poweroff(void) { + /* Disable the external subsys connection's power firstly */ + regmap_write(regmap, SC27XX_SLP_CTRL, SC27XX_LDO_XTL_EN); + regmap_write(regmap, SC27XX_PWR_PD_HW, SC27XX_PWR_OFF_EN); } From 274afbc3ad33136962d66447e89d02e3c142a30a Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Mon, 9 Mar 2020 16:18:45 +0800 Subject: [PATCH 1569/4444] power: reset: sc27xx: Change to use cpu_down() To allow the SC27XX driver can be built as a module, and the freeze_secondary_cpus() symbol is not exported, thus we can change to use the exported cpu_down() API to shut down other cpus to avoid racing, which is same as the freeze_secondary_cpus(). Signed-off-by: Baolin Wang Signed-off-by: Sebastian Reichel --- drivers/power/reset/sc27xx-poweroff.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/power/reset/sc27xx-poweroff.c b/drivers/power/reset/sc27xx-poweroff.c index 2bedd4c58ddc..91b5eceeb810 100644 --- a/drivers/power/reset/sc27xx-poweroff.c +++ b/drivers/power/reset/sc27xx-poweroff.c @@ -29,10 +29,13 @@ static struct regmap *regmap; */ static void sc27xx_poweroff_shutdown(void) { -#ifdef CONFIG_PM_SLEEP_SMP - int cpu = smp_processor_id(); +#ifdef CONFIG_HOTPLUG_CPU + int cpu; - freeze_secondary_cpus(cpu); + for_each_online_cpu(cpu) { + if (cpu != smp_processor_id()) + cpu_down(cpu); + } #endif } From f78c55e3b4806974f7d590b2aab8683232b7bd25 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Mon, 9 Mar 2020 16:18:46 +0800 Subject: [PATCH 1570/4444] power: reset: sc27xx: Allow the SC27XX poweroff driver building into a module Change the config to 'tristate' and use module_platform_driver() to allow the SC27XX poweroff driver building into a module, as well as adding some mudule information. Signed-off-by: Baolin Wang Signed-off-by: Sebastian Reichel --- drivers/power/reset/Kconfig | 2 +- drivers/power/reset/sc27xx-poweroff.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index 513efe8e7628..890380302080 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -248,7 +248,7 @@ config SYSCON_REBOOT_MODE action according to the mode. config POWER_RESET_SC27XX - bool "Spreadtrum SC27xx PMIC power-off driver" + tristate "Spreadtrum SC27xx PMIC power-off driver" depends on MFD_SC27XX_PMIC || COMPILE_TEST help This driver supports powering off a system through diff --git a/drivers/power/reset/sc27xx-poweroff.c b/drivers/power/reset/sc27xx-poweroff.c index 91b5eceeb810..69863074daf6 100644 --- a/drivers/power/reset/sc27xx-poweroff.c +++ b/drivers/power/reset/sc27xx-poweroff.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -71,4 +72,8 @@ static struct platform_driver sc27xx_poweroff_driver = { .name = "sc27xx-poweroff", }, }; -builtin_platform_driver(sc27xx_poweroff_driver); +module_platform_driver(sc27xx_poweroff_driver); + +MODULE_DESCRIPTION("Power off driver for SC27XX PMIC Device"); +MODULE_AUTHOR("Baolin Wang "); +MODULE_LICENSE("GPL v2"); From 5bcdf1009f1bf49f05812c5c33e948edd8845fe1 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 10 Mar 2020 17:54:52 +0000 Subject: [PATCH 1571/4444] arm64: dts: msm8916: Add fastrpc node Add fastrpc device node for adsp with one compute bank. Tested-by: Loic Poulain Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20200310175452.7503-1-srinivas.kandagatla@linaro.org Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/msm8916.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index be7e57fc4480..a88a15f2352b 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -1130,6 +1130,20 @@ qcom,remote-pid = <1>; label = "hexagon"; + + fastrpc { + compatible = "qcom,fastrpc"; + qcom,smd-channels = "fastrpcsmd-apps-dsp"; + label = "adsp"; + + #address-cells = <1>; + #size-cells = <0>; + + cb@1{ + compatible = "qcom,fastrpc-compute-cb"; + reg = <1>; + }; + }; }; }; From 5febf6d6ae4d488a5dc388c46d96c17f9556238f Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 24 Feb 2020 10:14:06 -0600 Subject: [PATCH 1572/4444] scsi: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Link: https://lore.kernel.org/r/20200224161406.GA21454@embeddedor Reviewed-by: Lee Duncan Reviewed-by: Satish Kharat Signed-off-by: Gustavo A. R. Silva Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/vnic_devcmd.h | 2 +- drivers/scsi/ipr.h | 6 +++--- drivers/scsi/isci/sas.h | 2 +- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 2 +- drivers/scsi/mvsas/mv_sas.h | 2 +- drivers/scsi/mvumi.h | 4 ++-- drivers/scsi/pmcraid.h | 2 +- drivers/scsi/snic/vnic_devcmd.h | 2 +- drivers/scsi/stex.c | 2 +- include/scsi/iscsi_if.h | 10 +++++----- include/scsi/scsi_bsg_iscsi.h | 2 +- include/scsi/scsi_device.h | 4 ++-- include/scsi/scsi_host.h | 2 +- include/scsi/scsi_ioctl.h | 2 +- include/scsi/srp.h | 8 ++++---- include/uapi/scsi/scsi_bsg_fc.h | 2 +- 16 files changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/fnic/vnic_devcmd.h b/drivers/scsi/fnic/vnic_devcmd.h index c5dde556dc7c..c20d30e36dfc 100644 --- a/drivers/scsi/fnic/vnic_devcmd.h +++ b/drivers/scsi/fnic/vnic_devcmd.h @@ -442,7 +442,7 @@ struct vnic_devcmd_notify { struct vnic_devcmd_provinfo { u8 oui[3]; u8 type; - u8 data[0]; + u8 data[]; }; /* diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index a67baeb36d1f..fd3929a19ab5 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -451,12 +451,12 @@ struct ipr_config_table_hdr64 { struct ipr_config_table { struct ipr_config_table_hdr hdr; - struct ipr_config_table_entry dev[0]; + struct ipr_config_table_entry dev[]; }__attribute__((packed, aligned (4))); struct ipr_config_table64 { struct ipr_config_table_hdr64 hdr64; - struct ipr_config_table_entry64 dev[0]; + struct ipr_config_table_entry64 dev[]; }__attribute__((packed, aligned (8))); struct ipr_config_table_entry_wrapper { @@ -792,7 +792,7 @@ struct ipr_mode_page28 { struct ipr_mode_page_hdr hdr; u8 num_entries; u8 entry_length; - struct ipr_dev_bus_entry bus[0]; + struct ipr_dev_bus_entry bus[]; }__attribute__((packed)); struct ipr_mode_page24 { diff --git a/drivers/scsi/isci/sas.h b/drivers/scsi/isci/sas.h index dc26b4aea99e..15d8f3631ab7 100644 --- a/drivers/scsi/isci/sas.h +++ b/drivers/scsi/isci/sas.h @@ -201,7 +201,7 @@ struct smp_req { u8 func; /* byte 1 */ u8 alloc_resp_len; /* byte 2 */ u8 req_len; /* byte 3 */ - u8 req_data[0]; + u8 req_data[]; } __packed; /* diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index c597d544eb39..778d5e6ce385 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -207,7 +207,7 @@ struct fw_event_work { u8 ignore; u16 event; struct kref refcount; - char event_data[0] __aligned(4); + char event_data[] __aligned(4); }; static void fw_event_work_free(struct kref *r) diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h index 519edc796691..327fdd5ee962 100644 --- a/drivers/scsi/mvsas/mv_sas.h +++ b/drivers/scsi/mvsas/mv_sas.h @@ -394,7 +394,7 @@ struct mvs_info { dma_addr_t bulk_buffer_dma1; #define TRASH_BUCKET_SIZE 0x20000 void *dma_pool; - struct mvs_slot_info slot_info[0]; + struct mvs_slot_info slot_info[]; }; struct mvs_prv_info{ diff --git a/drivers/scsi/mvumi.h b/drivers/scsi/mvumi.h index ec8cc2207536..60d5691fc4ab 100644 --- a/drivers/scsi/mvumi.h +++ b/drivers/scsi/mvumi.h @@ -130,7 +130,7 @@ enum { struct mvumi_hotplug_event { u16 size; u8 dummy[2]; - u8 bitmap[0]; + u8 bitmap[]; }; struct mvumi_driver_event { @@ -290,7 +290,7 @@ struct mvumi_rsp_frame { struct mvumi_ob_data { struct list_head list; - unsigned char data[0]; + unsigned char data[]; }; struct version_info { diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h index a4f7eb8f50a3..15c962108075 100644 --- a/drivers/scsi/pmcraid.h +++ b/drivers/scsi/pmcraid.h @@ -623,7 +623,7 @@ struct pmcraid_aen_msg { u32 hostno; u32 length; u8 reserved[8]; - u8 data[0]; + u8 data[]; }; /* Controller state event message type */ diff --git a/drivers/scsi/snic/vnic_devcmd.h b/drivers/scsi/snic/vnic_devcmd.h index d81b4f0ceaaa..0e0fa38f8d90 100644 --- a/drivers/scsi/snic/vnic_devcmd.h +++ b/drivers/scsi/snic/vnic_devcmd.h @@ -208,7 +208,7 @@ struct vnic_devcmd_notify { struct vnic_devcmd_provinfo { u8 oui[3]; u8 type; - u8 data[0]; + u8 data[]; }; /* diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 33287b6bdf0e..d4f10c0d813c 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -236,7 +236,7 @@ struct req_msg { u8 data_dir; u8 payload_sz; /* payload size in 4-byte, not used */ u8 cdb[STEX_CDB_LENGTH]; - u32 variable[0]; + u32 variable[]; }; struct status_msg { diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index 92b11c7e0b4f..b0e240b10bf9 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -311,7 +311,7 @@ enum iscsi_param_type { struct iscsi_param_info { uint32_t len; /* Actual length of the param value */ uint16_t param; /* iscsi param */ - uint8_t value[0]; /* length sized value follows */ + uint8_t value[]; /* length sized value follows */ } __packed; struct iscsi_iface_param_info { @@ -320,7 +320,7 @@ struct iscsi_iface_param_info { uint16_t param; /* iscsi param value */ uint8_t iface_type; /* IPv4 or IPv6 */ uint8_t param_type; /* iscsi_param_type */ - uint8_t value[0]; /* length sized value follows */ + uint8_t value[]; /* length sized value follows */ } __packed; /* @@ -697,7 +697,7 @@ enum iscsi_flashnode_param { struct iscsi_flashnode_param_info { uint32_t len; /* Actual length of the param */ uint16_t param; /* iscsi param value */ - uint8_t value[0]; /* length sized value follows */ + uint8_t value[]; /* length sized value follows */ } __packed; enum iscsi_discovery_parent_type { @@ -815,7 +815,7 @@ struct iscsi_stats { * up to ISCSI_STATS_CUSTOM_MAX */ uint32_t custom_length; - struct iscsi_stats_custom custom[0] + struct iscsi_stats_custom custom[] __attribute__ ((aligned (sizeof(uint64_t)))); }; @@ -946,7 +946,7 @@ struct iscsi_offload_host_stats { * up to ISCSI_HOST_STATS_CUSTOM_MAX */ uint32_t custom_length; - struct iscsi_host_stats_custom custom[0] + struct iscsi_host_stats_custom custom[] __aligned(sizeof(uint64_t)); }; diff --git a/include/scsi/scsi_bsg_iscsi.h b/include/scsi/scsi_bsg_iscsi.h index fa0c820a1663..6b8128005af8 100644 --- a/include/scsi/scsi_bsg_iscsi.h +++ b/include/scsi/scsi_bsg_iscsi.h @@ -52,7 +52,7 @@ struct iscsi_bsg_host_vendor { uint64_t vendor_id; /* start of vendor command area */ - uint32_t vendor_cmd[0]; + uint32_t vendor_cmd[]; }; /* Response: diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index f146a4557787..579e24c92f2f 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -230,7 +230,7 @@ struct scsi_device { struct mutex state_mutex; enum scsi_device_state sdev_state; struct task_struct *quiesced_by; - unsigned long sdev_data[0]; + unsigned long sdev_data[]; } __attribute__((aligned(sizeof(unsigned long)))); #define to_scsi_device(d) \ @@ -314,7 +314,7 @@ struct scsi_target { char scsi_level; enum scsi_target_state state; void *hostdata; /* available to low-level driver */ - unsigned long starget_data[0]; /* for the transport */ + unsigned long starget_data[]; /* for the transport */ /* starget_data must be the last element!!!! */ } __attribute__((aligned(sizeof(unsigned long)))); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 7464394e7d01..822e8cda8d9b 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -683,7 +683,7 @@ struct Scsi_Host { * and also because some compilers (m68k) don't automatically force * alignment to a long boundary. */ - unsigned long hostdata[0] /* Used for storage of host specific stuff */ + unsigned long hostdata[] /* Used for storage of host specific stuff */ __attribute__ ((aligned (sizeof(unsigned long)))); }; diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h index 4fe69d863b5d..b465799f4d2d 100644 --- a/include/scsi/scsi_ioctl.h +++ b/include/scsi/scsi_ioctl.h @@ -27,7 +27,7 @@ struct scsi_device; typedef struct scsi_ioctl_command { unsigned int inlen; unsigned int outlen; - unsigned char data[0]; + unsigned char data[]; } Scsi_Ioctl_Command; typedef struct scsi_idlun { diff --git a/include/scsi/srp.h b/include/scsi/srp.h index 9220758d5087..177d8026e96f 100644 --- a/include/scsi/srp.h +++ b/include/scsi/srp.h @@ -109,7 +109,7 @@ struct srp_direct_buf { struct srp_indirect_buf { struct srp_direct_buf table_desc; __be32 len; - struct srp_direct_buf desc_list[0]; + struct srp_direct_buf desc_list[]; } __attribute__((packed)); /* Immediate data buffer descriptor as defined in SRP2. */ @@ -244,7 +244,7 @@ struct srp_cmd { u8 reserved4; u8 add_cdb_len; u8 cdb[16]; - u8 add_data[0]; + u8 add_data[]; }; enum { @@ -274,7 +274,7 @@ struct srp_rsp { __be32 data_in_res_cnt; __be32 sense_data_len; __be32 resp_data_len; - u8 data[0]; + u8 data[]; } __attribute__((packed)); struct srp_cred_req { @@ -306,7 +306,7 @@ struct srp_aer_req { struct scsi_lun lun; __be32 sense_data_len; u32 reserved3; - u8 sense_data[0]; + u8 sense_data[]; } __attribute__((packed)); struct srp_aer_rsp { diff --git a/include/uapi/scsi/scsi_bsg_fc.h b/include/uapi/scsi/scsi_bsg_fc.h index 3ae65e93235c..7f5930801f72 100644 --- a/include/uapi/scsi/scsi_bsg_fc.h +++ b/include/uapi/scsi/scsi_bsg_fc.h @@ -209,7 +209,7 @@ struct fc_bsg_host_vendor { __u64 vendor_id; /* start of vendor command area */ - __u32 vendor_cmd[0]; + __u32 vendor_cmd[]; }; /* Response: From ed830385a2b1fbfcd1d08744b00587df5592162b Mon Sep 17 00:00:00 2001 From: Brian King Date: Wed, 26 Feb 2020 19:45:43 -0600 Subject: [PATCH 1573/4444] scsi: ibmvfc: Avoid loss of all paths during SVC node reboot When an SVC node goes down as part of a node reboot, its WWPNs are moved to the remaining node. When the node is back online, its WWPNs are moved back. The result is that the WWPN moves from one NPort_ID to another, then back again. The ibmvfc driver was forcing the old port to be removed, but not sending an implicit logout. When the WWPN showed up at the new location, the PLOGI failed as there was already a login established for the old scsi id. The patch below fixes this by ensuring we always send an implicit logout for any scsi id associated with an rport prior to calling fc_remote_port_delete. Link: https://lore.kernel.org/r/1582767943-16611-1-git-send-email-brking@linux.vnet.ibm.com Signed-off-by: Brian King Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi/ibmvfc.c | 217 ++++++++++++++++++++++++++------- drivers/scsi/ibmvscsi/ibmvfc.h | 3 +- 2 files changed, 178 insertions(+), 42 deletions(-) diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index df897df5cafe..84dd8c5145c8 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -133,6 +133,7 @@ static void ibmvfc_tgt_send_prli(struct ibmvfc_target *); static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *); static void ibmvfc_tgt_query_target(struct ibmvfc_target *); static void ibmvfc_npiv_logout(struct ibmvfc_host *); +static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *); static const char *unknown_error = "unknown error"; @@ -413,22 +414,44 @@ static const char *ibmvfc_get_fc_type(u16 status) * @tgt: ibmvfc target struct * @action: action to perform * + * Returns: + * 0 if action changed / non-zero if not changed **/ -static void ibmvfc_set_tgt_action(struct ibmvfc_target *tgt, +static int ibmvfc_set_tgt_action(struct ibmvfc_target *tgt, enum ibmvfc_target_action action) { + int rc = -EINVAL; + switch (tgt->action) { - case IBMVFC_TGT_ACTION_DEL_RPORT: - if (action == IBMVFC_TGT_ACTION_DELETED_RPORT) + case IBMVFC_TGT_ACTION_LOGOUT_RPORT: + if (action == IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT || + action == IBMVFC_TGT_ACTION_DEL_RPORT) { tgt->action = action; + rc = 0; + } + break; + case IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT: + if (action == IBMVFC_TGT_ACTION_DEL_RPORT) { + tgt->action = action; + rc = 0; + } + break; + case IBMVFC_TGT_ACTION_DEL_RPORT: + if (action == IBMVFC_TGT_ACTION_DELETED_RPORT) { + tgt->action = action; + rc = 0; + } case IBMVFC_TGT_ACTION_DELETED_RPORT: break; default: - if (action == IBMVFC_TGT_ACTION_DEL_RPORT) + if (action >= IBMVFC_TGT_ACTION_LOGOUT_RPORT) tgt->add_rport = 0; tgt->action = action; + rc = 0; break; } + + return rc; } /** @@ -536,6 +559,19 @@ static void ibmvfc_reinit_host(struct ibmvfc_host *vhost) wake_up(&vhost->work_wait_q); } +/** + * ibmvfc_del_tgt - Schedule cleanup and removal of the target + * @tgt: ibmvfc target struct + * @job_step: job step to perform + * + **/ +static void ibmvfc_del_tgt(struct ibmvfc_target *tgt) +{ + if (!ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_RPORT)) + tgt->job_step = ibmvfc_tgt_implicit_logout_and_del; + wake_up(&tgt->vhost->work_wait_q); +} + /** * ibmvfc_link_down - Handle a link down event from the adapter * @vhost: ibmvfc host struct @@ -550,7 +586,7 @@ static void ibmvfc_link_down(struct ibmvfc_host *vhost, ENTER; scsi_block_requests(vhost->host); list_for_each_entry(tgt, &vhost->targets, queue) - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); ibmvfc_set_host_state(vhost, state); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_TGT_DEL); vhost->events_to_log |= IBMVFC_AE_LINKDOWN; @@ -583,7 +619,7 @@ static void ibmvfc_init_host(struct ibmvfc_host *vhost) vhost->async_crq.cur = 0; list_for_each_entry(tgt, &vhost->targets, queue) - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); scsi_block_requests(vhost->host); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT); vhost->job_step = ibmvfc_npiv_login; @@ -1500,7 +1536,7 @@ static void ibmvfc_relogin(struct scsi_device *sdev) list_for_each_entry(tgt, &vhost->targets, queue) { if (rport == tgt->rport) { - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); break; } } @@ -2686,7 +2722,7 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, if (tgt->need_login && be64_to_cpu(crq->event) == IBMVFC_AE_ELS_LOGO) tgt->logo_rcvd = 1; if (!tgt->need_login || be64_to_cpu(crq->event) == IBMVFC_AE_ELS_PLOGI) { - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); ibmvfc_reinit_host(vhost); } } @@ -3220,8 +3256,8 @@ static void ibmvfc_tasklet(void *data) static void ibmvfc_init_tgt(struct ibmvfc_target *tgt, void (*job_step) (struct ibmvfc_target *)) { - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT); - tgt->job_step = job_step; + if (!ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT)) + tgt->job_step = job_step; wake_up(&tgt->vhost->work_wait_q); } @@ -3237,7 +3273,7 @@ static int ibmvfc_retry_tgt_init(struct ibmvfc_target *tgt, void (*job_step) (struct ibmvfc_target *)) { if (++tgt->init_retries > IBMVFC_MAX_TGT_INIT_RETRIES) { - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); wake_up(&tgt->vhost->work_wait_q); return 0; } else @@ -3312,13 +3348,13 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt) tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR; tgt->add_rport = 1; } else - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); } else if (prli_rsp[index].retry) ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli); else - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); } else - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); break; case IBMVFC_MAD_DRIVER_FAILED: break; @@ -3335,7 +3371,7 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt) else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli); else - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); tgt_log(tgt, level, "Process Login failed: %s (%x:%x) rc=0x%02X\n", ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), @@ -3434,7 +3470,7 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt) if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi); else - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); tgt_log(tgt, level, "Port Login failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), @@ -3515,15 +3551,38 @@ static void ibmvfc_tgt_implicit_logout_done(struct ibmvfc_event *evt) break; } - if (vhost->action == IBMVFC_HOST_ACTION_TGT_INIT) - ibmvfc_init_tgt(tgt, ibmvfc_tgt_send_plogi); - else if (vhost->action == IBMVFC_HOST_ACTION_QUERY_TGTS && - tgt->scsi_id != tgt->new_scsi_id) - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_init_tgt(tgt, ibmvfc_tgt_send_plogi); kref_put(&tgt->kref, ibmvfc_release_tgt); wake_up(&vhost->work_wait_q); } +/** + * __ibmvfc_tgt_get_implicit_logout_evt - Allocate and init an event for implicit logout + * @tgt: ibmvfc target struct + * + * Returns: + * Allocated and initialized ibmvfc_event struct + **/ +static struct ibmvfc_event *__ibmvfc_tgt_get_implicit_logout_evt(struct ibmvfc_target *tgt, + void (*done) (struct ibmvfc_event *)) +{ + struct ibmvfc_implicit_logout *mad; + struct ibmvfc_host *vhost = tgt->vhost; + struct ibmvfc_event *evt; + + kref_get(&tgt->kref); + evt = ibmvfc_get_event(vhost); + ibmvfc_init_event(evt, done, IBMVFC_MAD_FORMAT); + evt->tgt = tgt; + mad = &evt->iu.implicit_logout; + memset(mad, 0, sizeof(*mad)); + mad->common.version = cpu_to_be32(1); + mad->common.opcode = cpu_to_be32(IBMVFC_IMPLICIT_LOGOUT); + mad->common.length = cpu_to_be16(sizeof(*mad)); + mad->old_scsi_id = cpu_to_be64(tgt->scsi_id); + return evt; +} + /** * ibmvfc_tgt_implicit_logout - Initiate an Implicit Logout for specified target * @tgt: ibmvfc target struct @@ -3531,24 +3590,15 @@ static void ibmvfc_tgt_implicit_logout_done(struct ibmvfc_event *evt) **/ static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt) { - struct ibmvfc_implicit_logout *mad; struct ibmvfc_host *vhost = tgt->vhost; struct ibmvfc_event *evt; if (vhost->discovery_threads >= disc_threads) return; - kref_get(&tgt->kref); - evt = ibmvfc_get_event(vhost); vhost->discovery_threads++; - ibmvfc_init_event(evt, ibmvfc_tgt_implicit_logout_done, IBMVFC_MAD_FORMAT); - evt->tgt = tgt; - mad = &evt->iu.implicit_logout; - memset(mad, 0, sizeof(*mad)); - mad->common.version = cpu_to_be32(1); - mad->common.opcode = cpu_to_be32(IBMVFC_IMPLICIT_LOGOUT); - mad->common.length = cpu_to_be16(sizeof(*mad)); - mad->old_scsi_id = cpu_to_be64(tgt->scsi_id); + evt = __ibmvfc_tgt_get_implicit_logout_evt(tgt, + ibmvfc_tgt_implicit_logout_done); ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT); if (ibmvfc_send_event(evt, vhost, default_timeout)) { @@ -3559,6 +3609,53 @@ static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt) tgt_dbg(tgt, "Sent Implicit Logout\n"); } +/** + * ibmvfc_tgt_implicit_logout_and_del_done - Completion handler for Implicit Logout MAD + * @evt: ibmvfc event struct + * + **/ +static void ibmvfc_tgt_implicit_logout_and_del_done(struct ibmvfc_event *evt) +{ + struct ibmvfc_target *tgt = evt->tgt; + struct ibmvfc_host *vhost = evt->vhost; + struct ibmvfc_passthru_mad *mad = &evt->xfer_iu->passthru; + u32 status = be16_to_cpu(mad->common.status); + + vhost->discovery_threads--; + ibmvfc_free_event(evt); + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + + tgt_dbg(tgt, "Implicit Logout %s\n", (status == IBMVFC_MAD_SUCCESS) ? "succeeded" : "failed"); + kref_put(&tgt->kref, ibmvfc_release_tgt); + wake_up(&vhost->work_wait_q); +} + +/** + * ibmvfc_tgt_implicit_logout_and_del - Initiate an Implicit Logout for specified target + * @tgt: ibmvfc target struct + * + **/ +static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *tgt) +{ + struct ibmvfc_host *vhost = tgt->vhost; + struct ibmvfc_event *evt; + + if (vhost->discovery_threads >= disc_threads) + return NULL; + + vhost->discovery_threads++; + evt = __ibmvfc_tgt_get_implicit_logout_evt(tgt, + ibmvfc_tgt_implicit_logout_and_del_done); + + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT); + if (ibmvfc_send_event(evt, vhost, default_timeout)) { + vhost->discovery_threads--; + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + kref_put(&tgt->kref, ibmvfc_release_tgt); + } else + tgt_dbg(tgt, "Sent Implicit Logout\n"); +} + /** * ibmvfc_adisc_needs_plogi - Does device need PLOGI? * @mad: ibmvfc passthru mad struct @@ -3600,13 +3697,13 @@ static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt) case IBMVFC_MAD_SUCCESS: tgt_dbg(tgt, "ADISC succeeded\n"); if (ibmvfc_adisc_needs_plogi(mad, tgt)) - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); break; case IBMVFC_MAD_DRIVER_FAILED: break; case IBMVFC_MAD_FAILED: default: - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); fc_reason = (be32_to_cpu(mad->fc_iu.response[1]) & 0x00ff0000) >> 16; fc_explain = (be32_to_cpu(mad->fc_iu.response[1]) & 0x0000ff00) >> 8; tgt_info(tgt, "ADISC failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", @@ -3799,9 +3896,8 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt) switch (status) { case IBMVFC_MAD_SUCCESS: tgt_dbg(tgt, "Query Target succeeded\n"); - tgt->new_scsi_id = be64_to_cpu(rsp->scsi_id); if (be64_to_cpu(rsp->scsi_id) != tgt->scsi_id) - ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout); + ibmvfc_del_tgt(tgt); else ibmvfc_init_tgt(tgt, ibmvfc_tgt_adisc); break; @@ -3815,11 +3911,11 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt) if ((be16_to_cpu(rsp->status) & IBMVFC_FABRIC_MAPPED) == IBMVFC_FABRIC_MAPPED && be16_to_cpu(rsp->error) == IBMVFC_UNABLE_TO_PERFORM_REQ && be16_to_cpu(rsp->fc_explain) == IBMVFC_PORT_NAME_NOT_REG) - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_query_target); else - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); tgt_log(tgt, level, "Query Target failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), @@ -3896,7 +3992,6 @@ static int ibmvfc_alloc_target(struct ibmvfc_host *vhost, u64 scsi_id) tgt = mempool_alloc(vhost->tgt_pool, GFP_NOIO); memset(tgt, 0, sizeof(*tgt)); tgt->scsi_id = scsi_id; - tgt->new_scsi_id = scsi_id; tgt->vhost = vhost; tgt->need_login = 1; tgt->cancel_key = vhost->task_set++; @@ -4188,6 +4283,25 @@ static int ibmvfc_dev_init_to_do(struct ibmvfc_host *vhost) return 0; } +/** + * ibmvfc_dev_logo_to_do - Is there target logout work to do? + * @vhost: ibmvfc host struct + * + * Returns: + * 1 if work to do / 0 if not + **/ +static int ibmvfc_dev_logo_to_do(struct ibmvfc_host *vhost) +{ + struct ibmvfc_target *tgt; + + list_for_each_entry(tgt, &vhost->targets, queue) { + if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT || + tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT) + return 1; + } + return 0; +} + /** * __ibmvfc_work_to_do - Is there task level work to do? (no locking) * @vhost: ibmvfc host struct @@ -4217,11 +4331,20 @@ static int __ibmvfc_work_to_do(struct ibmvfc_host *vhost) if (tgt->action == IBMVFC_TGT_ACTION_INIT_WAIT) return 0; return 1; + case IBMVFC_HOST_ACTION_TGT_DEL: + case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: + if (vhost->discovery_threads == disc_threads) + return 0; + list_for_each_entry(tgt, &vhost->targets, queue) + if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT) + return 1; + list_for_each_entry(tgt, &vhost->targets, queue) + if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT) + return 0; + return 1; case IBMVFC_HOST_ACTION_LOGO: case IBMVFC_HOST_ACTION_INIT: case IBMVFC_HOST_ACTION_ALLOC_TGTS: - case IBMVFC_HOST_ACTION_TGT_DEL: - case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: case IBMVFC_HOST_ACTION_QUERY: case IBMVFC_HOST_ACTION_RESET: case IBMVFC_HOST_ACTION_REENABLE: @@ -4390,6 +4513,18 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) break; case IBMVFC_HOST_ACTION_TGT_DEL: case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: + list_for_each_entry(tgt, &vhost->targets, queue) { + if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT) { + tgt->job_step(tgt); + break; + } + } + + if (ibmvfc_dev_logo_to_do(vhost)) { + spin_unlock_irqrestore(vhost->host->host_lock, flags); + return; + } + list_for_each_entry(tgt, &vhost->targets, queue) { if (tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) { tgt_dbg(tgt, "Deleting rport\n"); diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index 7da89f4d26b2..907889f1fa9d 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -596,6 +596,8 @@ enum ibmvfc_target_action { IBMVFC_TGT_ACTION_NONE = 0, IBMVFC_TGT_ACTION_INIT, IBMVFC_TGT_ACTION_INIT_WAIT, + IBMVFC_TGT_ACTION_LOGOUT_RPORT, + IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT, IBMVFC_TGT_ACTION_DEL_RPORT, IBMVFC_TGT_ACTION_DELETED_RPORT, }; @@ -604,7 +606,6 @@ struct ibmvfc_target { struct list_head queue; struct ibmvfc_host *vhost; u64 scsi_id; - u64 new_scsi_id; struct fc_rport *rport; int target_id; enum ibmvfc_target_action action; From bef18d308a2215eff8c3411a23d7f34604ce56c3 Mon Sep 17 00:00:00 2001 From: Sagar Biradar Date: Wed, 12 Feb 2020 16:29:31 -0800 Subject: [PATCH 1574/4444] scsi: aacraid: Disabling TM path and only processing IOP reset Fixes the occasional adapter panic when sg_reset is issued with -d, -t, -b and -H flags. Removal of command type HBA_IU_TYPE_SCSI_TM_REQ in aac_hba_send since iu_type, request_id and fib_flags are not populated. Device and target reset handlers are made to send TMF commands only when reset_state is 0. Link: https://lore.kernel.org/r/1581553771-25796-1-git-send-email-Sagar.Biradar@microchip.com Reviewed-by: Sagar Biradar Signed-off-by: Sagar Biradar Signed-off-by: Balsundar P Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/commsup.c | 2 +- drivers/scsi/aacraid/linit.c | 34 +++++++++++++++++++++++++--------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index bb14a05f6d77..4725e4c763cf 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -729,7 +729,7 @@ int aac_hba_send(u8 command, struct fib *fibptr, fib_callback callback, hbacmd->request_id = cpu_to_le32((((u32)(fibptr - dev->fibs)) << 2) + 1); fibptr->flags |= FIB_CONTEXT_FLAG_SCSI_CMD; - } else if (command != HBA_IU_TYPE_SCSI_TM_REQ) + } else return -EINVAL; diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index d0d1f3072c0c..b1d133de29ab 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -733,7 +733,11 @@ static int aac_eh_abort(struct scsi_cmnd* cmd) status = aac_hba_send(HBA_IU_TYPE_SCSI_TM_REQ, fib, (fib_callback) aac_hba_callback, (void *) cmd); - + if (status != -EINPROGRESS) { + aac_fib_complete(fib); + aac_fib_free(fib); + return ret; + } /* Wait up to 15 secs for completion */ for (count = 0; count < 15; ++count) { if (cmd->SCp.sent_command) { @@ -912,11 +916,11 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd) info = &aac->hba_map[bus][cid]; - if (info->devtype != AAC_DEVTYPE_NATIVE_RAW && - info->reset_state > 0) + if (!(info->devtype == AAC_DEVTYPE_NATIVE_RAW && + !(info->reset_state > 0))) return FAILED; - pr_err("%s: Host adapter reset request. SCSI hang ?\n", + pr_err("%s: Host device reset request. SCSI hang ?\n", AAC_DRIVERNAME); fib = aac_fib_alloc(aac); @@ -931,7 +935,12 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd) status = aac_hba_send(command, fib, (fib_callback) aac_tmf_callback, (void *) info); - + if (status != -EINPROGRESS) { + info->reset_state = 0; + aac_fib_complete(fib); + aac_fib_free(fib); + return ret; + } /* Wait up to 15 seconds for completion */ for (count = 0; count < 15; ++count) { if (info->reset_state == 0) { @@ -970,11 +979,11 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd) info = &aac->hba_map[bus][cid]; - if (info->devtype != AAC_DEVTYPE_NATIVE_RAW && - info->reset_state > 0) + if (!(info->devtype == AAC_DEVTYPE_NATIVE_RAW && + !(info->reset_state > 0))) return FAILED; - pr_err("%s: Host adapter reset request. SCSI hang ?\n", + pr_err("%s: Host target reset request. SCSI hang ?\n", AAC_DRIVERNAME); fib = aac_fib_alloc(aac); @@ -991,6 +1000,13 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd) (fib_callback) aac_tmf_callback, (void *) info); + if (status != -EINPROGRESS) { + info->reset_state = 0; + aac_fib_complete(fib); + aac_fib_free(fib); + return ret; + } + /* Wait up to 15 seconds for completion */ for (count = 0; count < 15; ++count) { if (info->reset_state <= 0) { @@ -1043,7 +1059,7 @@ static int aac_eh_bus_reset(struct scsi_cmnd* cmd) } } - pr_err("%s: Host adapter reset request. SCSI hang ?\n", AAC_DRIVERNAME); + pr_err("%s: Host bus reset request. SCSI hang ?\n", AAC_DRIVERNAME); /* * Check the health of the controller From cc6b32ee3b914d3036a4d364fd4918b48fc034eb Mon Sep 17 00:00:00 2001 From: Frank Mayhar Date: Thu, 27 Feb 2020 14:59:45 -0500 Subject: [PATCH 1575/4444] scsi: iscsi: Add support for asynchronous iSCSI session destruction iSCSI session destruction can be arbitrarily slow, since it might require network operations and serialization inside the SCSI layer. This patch adds a new user event to trigger the destruction work asynchronously, releasing the rx_queue_mutex as soon as the operation is queued and before it is performed. This change allows other operations to run in other sessions in the meantime, removing one of the major iSCSI bottlenecks for us. To prevent the session from being used after the destruction request, we remove it immediately from the sesslist. This simplifies the locking required during the asynchronous removal. Link: https://lore.kernel.org/r/20200227195945.761719-1-krisman@collabora.com Co-developed-by: Gabriel Krisman Bertazi Co-developed-by: Khazhismel Kumykov Reviewed-by: Lee Duncan Signed-off-by: Gabriel Krisman Bertazi Signed-off-by: Frank Mayhar Signed-off-by: Khazhismel Kumykov Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_iscsi.c | 38 +++++++++++++++++++++++++++++ include/scsi/iscsi_if.h | 1 + include/scsi/scsi_transport_iscsi.h | 1 + 3 files changed, 40 insertions(+) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index f3f0ecdb09a2..17a45716a0fe 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -95,6 +95,8 @@ static DECLARE_WORK(stop_conn_work, stop_conn_work_fn); static atomic_t iscsi_session_nr; /* sysfs session id for next new session */ static struct workqueue_struct *iscsi_eh_timer_workq; +static struct workqueue_struct *iscsi_destroy_workq; + static DEFINE_IDA(iscsi_sess_ida); /* * list of registered transports and lock that must @@ -1615,6 +1617,7 @@ static struct sock *nls; static DEFINE_MUTEX(rx_queue_mutex); static LIST_HEAD(sesslist); +static LIST_HEAD(sessdestroylist); static DEFINE_SPINLOCK(sesslock); static LIST_HEAD(connlist); static LIST_HEAD(connlist_err); @@ -2035,6 +2038,14 @@ static void __iscsi_unbind_session(struct work_struct *work) ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n"); } +static void __iscsi_destroy_session(struct work_struct *work) +{ + struct iscsi_cls_session *session = + container_of(work, struct iscsi_cls_session, destroy_work); + + session->transport->destroy_session(session); +} + struct iscsi_cls_session * iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport, int dd_size) @@ -2057,6 +2068,7 @@ iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport, INIT_WORK(&session->block_work, __iscsi_block_session); INIT_WORK(&session->unbind_work, __iscsi_unbind_session); INIT_WORK(&session->scan_work, iscsi_scan_session); + INIT_WORK(&session->destroy_work, __iscsi_destroy_session); spin_lock_init(&session->lock); /* this is released in the dev's release function */ @@ -3631,6 +3643,23 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) else transport->destroy_session(session); break; + case ISCSI_UEVENT_DESTROY_SESSION_ASYNC: + session = iscsi_session_lookup(ev->u.d_session.sid); + if (!session) + err = -EINVAL; + else if (iscsi_session_has_conns(ev->u.d_session.sid)) + err = -EBUSY; + else { + unsigned long flags; + + /* Prevent this session from being found again */ + spin_lock_irqsave(&sesslock, flags); + list_move(&session->sess_list, &sessdestroylist); + spin_unlock_irqrestore(&sesslock, flags); + + queue_work(iscsi_destroy_workq, &session->destroy_work); + } + break; case ISCSI_UEVENT_UNBIND_SESSION: session = iscsi_session_lookup(ev->u.d_session.sid); if (session) @@ -4676,8 +4705,16 @@ static __init int iscsi_transport_init(void) goto release_nls; } + iscsi_destroy_workq = create_singlethread_workqueue("iscsi_destroy"); + if (!iscsi_destroy_workq) { + err = -ENOMEM; + goto destroy_wq; + } + return 0; +destroy_wq: + destroy_workqueue(iscsi_eh_timer_workq); release_nls: netlink_kernel_release(nls); unregister_flashnode_bus: @@ -4699,6 +4736,7 @@ unregister_transport_class: static void __exit iscsi_transport_exit(void) { + destroy_workqueue(iscsi_destroy_workq); destroy_workqueue(iscsi_eh_timer_workq); netlink_kernel_release(nls); bus_unregister(&iscsi_flashnode_bus); diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index b0e240b10bf9..5225a23f2d0e 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -60,6 +60,7 @@ enum iscsi_uevent_e { ISCSI_UEVENT_LOGOUT_FLASHNODE_SID = UEVENT_BASE + 30, ISCSI_UEVENT_SET_CHAP = UEVENT_BASE + 31, ISCSI_UEVENT_GET_HOST_STATS = UEVENT_BASE + 32, + ISCSI_UEVENT_DESTROY_SESSION_ASYNC = UEVENT_BASE + 33, /* up events */ ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1, diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 2129dc9e2dec..fa8814245796 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -226,6 +226,7 @@ struct iscsi_cls_session { struct work_struct unblock_work; struct work_struct scan_work; struct work_struct unbind_work; + struct work_struct destroy_work; /* recovery fields */ int recovery_tmo; From 5848fe960b080b1e731b467b6e026de841c65234 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 7 Mar 2020 21:01:15 -0800 Subject: [PATCH 1576/4444] scsi: fusion: fix if-statement empty body warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When driver debugging is not enabled, change the debug print macros to use the no_printk() macro. This fixes a gcc warning when -Wextra is set: ../drivers/message/fusion/mptlan.c:266:39: warning: suggest braces around empty body in an ‘else’ statement [-Wempty-body] I have verified that there is very little object code change (with gcc 7.5.0). There are a few changes like: cmp %a,%b jl $1 to cmp %b,%a jg $1 Link: https://lore.kernel.org/r/ff9df31b-c4c1-c942-1cbf-18039e084c8e@infradead.org Cc: Bart Van Assche Cc: "James E.J. Bottomley" Cc: "Martin K. Petersen" Cc: linux-scsi@vger.kernel.org Cc: MPT-FusionLinux.pdl@broadcom.com Cc: Suganath Prabu Subramani Cc: Chaitra P B Cc: Sathya Prakash Reviewed-by: Bart van Assche Reviewed-by: Hannes Reinecke Signed-off-by: Randy Dunlap Signed-off-by: Martin K. Petersen --- drivers/message/fusion/mptlan.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h index 8a24494f8c4d..a1ec7e84d6fe 100644 --- a/drivers/message/fusion/mptlan.h +++ b/drivers/message/fusion/mptlan.h @@ -64,6 +64,7 @@ #include #include #include +#include #include #include #include @@ -111,13 +112,13 @@ MODULE_DESCRIPTION(LANAME); #ifdef MPT_LAN_IO_DEBUG #define dioprintk(x) printk x #else -#define dioprintk(x) +#define dioprintk(x) no_printk x #endif #ifdef MPT_LAN_DEBUG #define dlprintk(x) printk x #else -#define dlprintk(x) +#define dlprintk(x) no_printk x #endif #define NETDEV_TO_LANPRIV_PTR(d) ((struct mpt_lan_priv *)netdev_priv(d)) From b893eb0141cb4b896b275d00bea2deb64f6f1eac Mon Sep 17 00:00:00 2001 From: Brian King Date: Mon, 2 Mar 2020 08:39:21 -0600 Subject: [PATCH 1577/4444] scsi: ibmvfc: Fix NULL return compiler warning Fix up a compiler warning introduced via 54b04c99d02e Link: https://lore.kernel.org/r/1583159961-15903-1-git-send-email-brking@linux.vnet.ibm.com Fixes: 54b04c99d02e ("scsi: ibmvfc: Avoid loss of all paths during SVC node reboot") Signed-off-by: Brian King Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi/ibmvfc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 84dd8c5145c8..7da9e060b270 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -3641,7 +3641,7 @@ static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *tgt) struct ibmvfc_event *evt; if (vhost->discovery_threads >= disc_threads) - return NULL; + return; vhost->discovery_threads++; evt = __ibmvfc_tgt_get_implicit_logout_evt(tgt, From 47d054580a75b7d14d275a76146ce2f41bc16a81 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Mon, 2 Mar 2020 21:53:46 +0800 Subject: [PATCH 1578/4444] scsi: ufs-mediatek: fix HOST_PA_TACTIVATE quirk for Samsung UFS Devices Device quirk "UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE" is enabled for all Samsung devices by default currently. However MediaTek UFS host requires different host PA_TACTIVATE configuration. Hence clear this quirk first and then apply vendor-specific value in vops callback. Link: https://lore.kernel.org/r/20200302135346.16797-1-stanley.chu@mediatek.com Reviewed-by: Avri Altman Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-mediatek.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index de650822c9d9..3b0e575d7460 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -533,8 +533,10 @@ static int ufs_mtk_apply_dev_quirks(struct ufs_hba *hba) struct ufs_dev_info *dev_info = &hba->dev_info; u16 mid = dev_info->wmanufacturerid; - if (mid == UFS_VENDOR_SAMSUNG) + if (mid == UFS_VENDOR_SAMSUNG) { + hba->dev_quirks &= ~UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE; ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 6); + } /* * Decide waiting time before gating reference clock and From 779dfcf6435b9ad612a630f0cae41adedbc0190b Mon Sep 17 00:00:00 2001 From: Phong Tran Date: Mon, 9 Mar 2020 22:53:19 +0700 Subject: [PATCH 1579/4444] scsi: aacraid: clean up warning cast-function-type Make the aacraid driver -Wcast-function-type clean Report by: https://github.com/KSPP/linux/issues/20 drivers/scsi/aacraid/aachba.c:813:23: warning: cast between incompatible function types from 'int (*)(struct scsi_cmnd *)' to 'void (*)(struct scsi_cmnd *)' [-Wcast-function-type] Link: https://lore.kernel.org/r/20200309155319.12658-1-tranmanphong@gmail.com Reviewed-by: Bart van Assche Reviewed-by: Kees Cook Signed-off-by: Phong Tran Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/aachba.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 474d48eb1348..eb72ac8136c3 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -798,6 +798,11 @@ static int aac_probe_container_callback1(struct scsi_cmnd * scsicmd) return 0; } +static void aac_probe_container_scsi_done(struct scsi_cmnd *scsi_cmnd) +{ + aac_probe_container_callback1(scsi_cmnd); +} + int aac_probe_container(struct aac_dev *dev, int cid) { struct scsi_cmnd *scsicmd = kmalloc(sizeof(*scsicmd), GFP_KERNEL); @@ -810,7 +815,7 @@ int aac_probe_container(struct aac_dev *dev, int cid) return -ENOMEM; } scsicmd->list.next = NULL; - scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))aac_probe_container_callback1; + scsicmd->scsi_done = aac_probe_container_scsi_done; scsicmd->device = scsidev; scsidev->sdev_state = 0; From 598a90f2002c4c4daee24d76d24e8270c7075eef Mon Sep 17 00:00:00 2001 From: Rajan Shanmugavelu Date: Wed, 12 Feb 2020 17:29:28 -0800 Subject: [PATCH 1580/4444] scsi: qla2xxx: add ring buffer for tracing debug logs Having this log in a ring buffer helps to diagnose qla2xxx driver and firmware issues instead of having to reproduce the problem with extended_logging enabled. This saves cycles and helps when it is hard to reproduce problem. Link: https://lore.kernel.org/r/1581557368-32080-1-git-send-email-rajan.shanmugavelu@oracle.com Reviewed-by: Joe Jin Acked-by: Himanshu Madhani Signed-off-by: Rajan Shanmugavelu Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_dbg.c | 23 +++++++++++++++++--- include/trace/events/qla.h | 39 ++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 include/trace/events/qla.h diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 88a56e8480f7..f301a8048b2f 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -73,6 +73,8 @@ #include "qla_def.h" #include +#define CREATE_TRACE_POINTS +#include static uint32_t ql_dbg_offset = 0x800; @@ -2537,15 +2539,30 @@ ql_dbg(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...) { va_list va; struct va_format vaf; - - if (!ql_mask_match(level)) - return; + char pbuf[64]; va_start(va, fmt); vaf.fmt = fmt; vaf.va = &va; + if (!ql_mask_match(level)) { + if (vha != NULL) { + const struct pci_dev *pdev = vha->hw->pdev; + /* : Message */ + snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x:%ld: ", + QL_MSGHDR, dev_name(&(pdev->dev)), id, + vha->host_no); + } else { + snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ", + QL_MSGHDR, "0000:00:00.0", id); + } + pbuf[sizeof(pbuf) - 1] = 0; + trace_ql_dbg_log(pbuf, &vaf); + va_end(va); + return; + } + if (vha != NULL) { const struct pci_dev *pdev = vha->hw->pdev; /* : Message */ diff --git a/include/trace/events/qla.h b/include/trace/events/qla.h new file mode 100644 index 000000000000..b71f680968eb --- /dev/null +++ b/include/trace/events/qla.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#if !defined(_TRACE_QLA_H_) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_QLA_H_ + +#include + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM qla + +#define QLA_MSG_MAX 256 + +DECLARE_EVENT_CLASS(qla_log_event, + TP_PROTO(const char *buf, + struct va_format *vaf), + + TP_ARGS(buf, vaf), + + TP_STRUCT__entry( + __string(buf, buf) + __dynamic_array(char, msg, QLA_MSG_MAX) + ), + TP_fast_assign( + __assign_str(buf, buf); + vsnprintf(__get_str(msg), QLA_MSG_MAX, vaf->fmt, *vaf->va); + ), + + TP_printk("%s %s", __get_str(buf), __get_str(msg)) +); + +DEFINE_EVENT(qla_log_event, ql_dbg_log, + TP_PROTO(const char *buf, struct va_format *vaf), + TP_ARGS(buf, vaf) +); + +#endif /* _TRACE_QLA_H */ + +#define TRACE_INCLUDE_FILE qla + +#include From 31df2fd54cafdadadb20c60e80461c9b08b2ff56 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:34 +0100 Subject: [PATCH 1581/4444] scsi: docs: Add an empty index file for SCSI documents In preparation for adding the SCSI documents to the documentation body, add an empty index for it. The next patches should be adding contents to it, as files get converted to ReST format. Link: https://lore.kernel.org/r/4d8c1b7ebe5898ac4a8265ca5e5a9552da3b426f.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/index.rst | 1 + Documentation/scsi/index.rst | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 Documentation/scsi/index.rst diff --git a/Documentation/index.rst b/Documentation/index.rst index e99d0bd2589d..d39fd2c9f1ce 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -130,6 +130,7 @@ needed). bpf/index usb/index PCI/index + scsi/index misc-devices/index mic/index scheduler/index diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst new file mode 100644 index 000000000000..16baf8b0f11f --- /dev/null +++ b/Documentation/scsi/index.rst @@ -0,0 +1,10 @@ +.. SPDX-License-Identifier: GPL-2.0 + +==================== +Linux SCSI Subsystem +==================== + +.. toctree:: + :maxdepth: 1 + + From 7f877908df42d58468980d89a7f130ab30c83afd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:35 +0100 Subject: [PATCH 1582/4444] scsi: docs: include SCSI Transport SRP diagram at the doc body Instead of having a separate makefile, and be alone, group it at the SCSI documentation and make it being built as part of docs makefile. Link: https://lore.kernel.org/r/419c455fb40c9a1e85cc9a654a7fdb07aeeccf71.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/index.rst | 2 +- Documentation/scsi/scsi_transport_srp/Makefile | 7 ------- Documentation/scsi/scsi_transport_srp/figures.rst | 6 ++++++ 3 files changed, 7 insertions(+), 8 deletions(-) delete mode 100644 Documentation/scsi/scsi_transport_srp/Makefile create mode 100644 Documentation/scsi/scsi_transport_srp/figures.rst diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index 16baf8b0f11f..3ef7ad65372a 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -7,4 +7,4 @@ Linux SCSI Subsystem .. toctree:: :maxdepth: 1 - + scsi_transport_srp/figures diff --git a/Documentation/scsi/scsi_transport_srp/Makefile b/Documentation/scsi/scsi_transport_srp/Makefile deleted file mode 100644 index 5f6b567e955c..000000000000 --- a/Documentation/scsi/scsi_transport_srp/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: rport_state_diagram.svg rport_state_diagram.png - -rport_state_diagram.svg: rport_state_diagram.dot - dot -Tsvg -o $@ $< - -rport_state_diagram.png: rport_state_diagram.dot - dot -Tpng -o $@ $< diff --git a/Documentation/scsi/scsi_transport_srp/figures.rst b/Documentation/scsi/scsi_transport_srp/figures.rst new file mode 100644 index 000000000000..6c8f8dd6301b --- /dev/null +++ b/Documentation/scsi/scsi_transport_srp/figures.rst @@ -0,0 +1,6 @@ +.. SPDX-License-Identifier: GPL-2.0 + +SCSI RDMA (SRP) transport class diagram +======================================= + +.. kernel-figure:: rport_state_diagram.dot From f76576777a03bdd02bc8e5e71838c187051b17a0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:36 +0100 Subject: [PATCH 1583/4444] scsi: docs: convert 53c700.txt to ReST Link: https://lore.kernel.org/r/a2e5116b70564f36b4fc7f1f1e5da1e693d7dadb.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/{53c700.txt => 53c700.rst} | 61 +++++++++---------- Documentation/scsi/index.rst | 2 + MAINTAINERS | 2 +- 3 files changed, 33 insertions(+), 32 deletions(-) rename Documentation/scsi/{53c700.txt => 53c700.rst} (75%) diff --git a/Documentation/scsi/53c700.txt b/Documentation/scsi/53c700.rst similarity index 75% rename from Documentation/scsi/53c700.txt rename to Documentation/scsi/53c700.rst index e31aceb6df15..53a0e9f9c198 100644 --- a/Documentation/scsi/53c700.txt +++ b/Documentation/scsi/53c700.rst @@ -1,3 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0 + +======================= +The 53c700 Driver Notes +======================= + General Description =================== @@ -16,9 +22,9 @@ fill in to get the driver working. Compile Time Flags ================== -A compile time flag is: +A compile time flag is:: -CONFIG_53C700_LE_ON_BE + CONFIG_53C700_LE_ON_BE define if the chipset must be supported in little endian mode on a big endian architecture (used for the 700 on parisc). @@ -51,9 +57,11 @@ consistent with the best operation of the chip (although some choose to drive it off the CPU or bus clock rather than going to the expense of an extra clock chip). The best operation clock speeds are: -53c700 - 25MHz -53c700-66 - 50MHz -53c710 - 40Mhz +========= ===== +53c700 25MHz +53c700-66 50MHz +53c710 40Mhz +========= ===== Writing Your Glue Driver ======================== @@ -69,7 +77,7 @@ parameters that matter to you (see below), plumb the NCR_700_intr routine into the interrupt line and call NCR_700_detect with the host template and the new parameters as arguments. You should also call the relevant request_*_region function and place the register base -address into the `base' pointer of the host parameters. +address into the 'base' pointer of the host parameters. In the release routine, you must free the NCR_700_Host_Parameters that you allocated, call the corresponding release_*_region and free the @@ -78,7 +86,7 @@ interrupt. Handling Interrupts ------------------- -In general, you should just plumb the card's interrupt line in with +In general, you should just plumb the card's interrupt line in with request_irq(irq, NCR_700_intr, , , host); @@ -95,41 +103,32 @@ Settable NCR_700_Host_Parameters The following are a list of the user settable parameters: clock: (MANDATORY) - -Set to the clock speed of the chip in MHz. + Set to the clock speed of the chip in MHz. base: (MANDATORY) - -set to the base of the io or mem region for the register set. On 64 -bit architectures this is only 32 bits wide, so the registers must be -mapped into the low 32 bits of memory. + Set to the base of the io or mem region for the register set. On 64 + bit architectures this is only 32 bits wide, so the registers must be + mapped into the low 32 bits of memory. pci_dev: (OPTIONAL) - -set to the PCI board device. Leave NULL for a non-pci board. This is -used for the pci_alloc_consistent() and pci_map_*() functions. + Set to the PCI board device. Leave NULL for a non-pci board. This is + used for the pci_alloc_consistent() and pci_map_*() functions. dmode_extra: (OPTIONAL, 53c710 only) - -extra flags for the DMODE register. These are used to control bus -output pins on the 710. The settings should be a combination of -DMODE_FC1 and DMODE_FC2. What these pins actually do is entirely up -to the board designer. Usually it is safe to ignore this setting. + Extra flags for the DMODE register. These are used to control bus + output pins on the 710. The settings should be a combination of + DMODE_FC1 and DMODE_FC2. What these pins actually do is entirely up + to the board designer. Usually it is safe to ignore this setting. differential: (OPTIONAL) - -set to 1 if the chip drives a differential bus. + Set to 1 if the chip drives a differential bus. force_le_on_be: (OPTIONAL, only if CONFIG_53C700_LE_ON_BE is set) - -set to 1 if the chip is operating in little endian mode on a big -endian architecture. + Set to 1 if the chip is operating in little endian mode on a big + endian architecture. chip710: (OPTIONAL) - -set to 1 if the chip is a 53c710. + Set to 1 if the chip is a 53c710. burst_disable: (OPTIONAL, 53c710 only) - -disable 8 byte bursting for DMA transfers. - + Disable 8 byte bursting for DMA transfers. diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index 3ef7ad65372a..99efc77c3ac2 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -7,4 +7,6 @@ Linux SCSI Subsystem .. toctree:: :maxdepth: 1 + 53c700 + scsi_transport_srp/figures diff --git a/MAINTAINERS b/MAINTAINERS index 38fe2f3f7b6f..2bcab7c4cf3a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9386,7 +9386,7 @@ LASI 53c700 driver for PARISC M: "James E.J. Bottomley" L: linux-scsi@vger.kernel.org S: Maintained -F: Documentation/scsi/53c700.txt +F: Documentation/scsi/53c700.rst F: drivers/scsi/53c700* LEAKING_ADDRESSES From dd9cc1447ad39ddf09224357396d5e5175fb44dc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:37 +0100 Subject: [PATCH 1584/4444] scsi: docs: convert aacraid.txt to ReST Link: https://lore.kernel.org/r/67c60ad88777c91937d49771e2a3f48cbf353e4c.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- .../scsi/{aacraid.txt => aacraid.rst} | 59 ++++++++++++++----- Documentation/scsi/index.rst | 1 + MAINTAINERS | 2 +- drivers/scsi/Kconfig | 2 +- 4 files changed, 46 insertions(+), 18 deletions(-) rename Documentation/scsi/{aacraid.txt => aacraid.rst} (83%) diff --git a/Documentation/scsi/aacraid.txt b/Documentation/scsi/aacraid.rst similarity index 83% rename from Documentation/scsi/aacraid.txt rename to Documentation/scsi/aacraid.rst index 30f643f611b2..1904674b94f3 100644 --- a/Documentation/scsi/aacraid.txt +++ b/Documentation/scsi/aacraid.rst @@ -1,7 +1,11 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=================================== AACRAID Driver for Linux (take two) +=================================== Introduction -------------------------- +============ The aacraid driver adds support for Adaptec (http://www.adaptec.com) RAID controllers. This is a major rewrite from the original Adaptec supplied driver. It has significantly cleaned up both the code @@ -9,8 +13,11 @@ and the running binary size (the module is less than half the size of the original). Supported Cards/Chipsets -------------------------- +======================== + + =================== ======= ======================================= PCI ID (pci.ids) OEM Product + =================== ======= ======================================= 9005:0285:9005:0285 Adaptec 2200S (Vulcan) 9005:0285:9005:0286 Adaptec 2120S (Crusader) 9005:0285:9005:0287 Adaptec 2200S (Vulcan-2m) @@ -117,34 +124,54 @@ Supported Cards/Chipsets 9005:0285:108e:0286 SUN STK RAID INT (Cougar) 9005:0285:108e:0287 SUN STK RAID EXT (Prometheus) 9005:0285:108e:7aae SUN STK RAID EM (Narvi) + =================== ======= ======================================= People -------------------------- -Alan Cox -Christoph Hellwig (updates for new-style PCI probing and SCSI host registration, - small cleanups/fixes) -Matt Domsch (revision ioctl, adapter messages) -Deanna Bonds (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers - added new ioctls, changed scsi interface to use new error handler, - increased the number of fibs and outstanding commands to a container) +====== + +Alan Cox + +Christoph Hellwig + +- updates for new-style PCI probing and SCSI host registration, + small cleanups/fixes + +Matt Domsch + +- revision ioctl, adapter messages + +Deanna Bonds + +- non-DASD support, PAE fibs and 64 bit, added new adaptec controllers + added new ioctls, changed scsi interface to use new error handler, + increased the number of fibs and outstanding commands to a container +- fixed 64bit and 64G memory model, changed confusing naming convention + where fibs that go to the hardware are consistently called hw_fibs and + not just fibs like the name of the driver tracking structure + +Mark Salyzyn + +- Fixed panic issues and added some new product ids for upcoming hbas. +- Performance tuning, card failover and bug mitigations. - (fixed 64bit and 64G memory model, changed confusing naming convention - where fibs that go to the hardware are consistently called hw_fibs and - not just fibs like the name of the driver tracking structure) -Mark Salyzyn Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations. Achim Leubner -Original Driver +- Original Driver + ------------------------- + Adaptec Unix OEM Product Group Mailing List -------------------------- +============ + linux-scsi@vger.kernel.org (Interested parties troll here) Also note this is very different to Brian's original driver so don't expect him to support it. + Adaptec does support this driver. Contact Adaptec tech support or aacraid@adaptec.com Original by Brian Boerner February 2001 + Rewritten by Alan Cox, November 2001 diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index 99efc77c3ac2..2e0429d1a7a5 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -8,5 +8,6 @@ Linux SCSI Subsystem :maxdepth: 1 53c700 + aacraid scsi_transport_srp/figures diff --git a/MAINTAINERS b/MAINTAINERS index 2bcab7c4cf3a..3251b768fec0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -236,7 +236,7 @@ M: Adaptec OEM Raid Solutions L: linux-scsi@vger.kernel.org W: http://www.adaptec.com/ S: Supported -F: Documentation/scsi/aacraid.txt +F: Documentation/scsi/aacraid.rst F: drivers/scsi/aacraid/ ABI/API diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 2b882b96e0d4..a153444318fb 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -421,7 +421,7 @@ config SCSI_AACRAID help This driver supports a variety of Dell, HP, Adaptec, IBM and ICP storage products. For a list of supported products, refer - to . + to . To compile this driver as a module, choose M here: the module will be called aacraid. From cb3224089417af6c1f6526303c0c7bd1c76652e8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:38 +0100 Subject: [PATCH 1585/4444] scsi: docs: convert advansys.txt to ReST Link: https://lore.kernel.org/r/3c697a046e641c81cdfd0784f037d41d54766931.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- .../scsi/{advansys.txt => advansys.rst} | 129 +++++++++++------- Documentation/scsi/index.rst | 1 + MAINTAINERS | 2 +- 3 files changed, 81 insertions(+), 51 deletions(-) rename Documentation/scsi/{advansys.txt => advansys.rst} (73%) diff --git a/Documentation/scsi/advansys.txt b/Documentation/scsi/advansys.rst similarity index 73% rename from Documentation/scsi/advansys.txt rename to Documentation/scsi/advansys.rst index 4a3db62b7424..e0367e179696 100644 --- a/Documentation/scsi/advansys.txt +++ b/Documentation/scsi/advansys.rst @@ -1,3 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0 + +===================== +AdvanSys Driver Notes +===================== + AdvanSys (Advanced System Products, Inc.) manufactures the following RISC-based, Bus-Mastering, Fast (10 Mhz) and Ultra (20 Mhz) Narrow (8-bit transfer) SCSI Host Adapters for the ISA, EISA, VL, and PCI @@ -12,50 +18,51 @@ adapter detected. The number of CDBs used by the driver can be lowered in the BIOS by changing the 'Host Queue Size' adapter setting. Laptop Products: - ABP-480 - Bus-Master CardBus (16 CDB) + - ABP-480 - Bus-Master CardBus (16 CDB) Connectivity Products: - ABP510/5150 - Bus-Master ISA (240 CDB) - ABP5140 - Bus-Master ISA PnP (16 CDB) - ABP5142 - Bus-Master ISA PnP with floppy (16 CDB) - ABP902/3902 - Bus-Master PCI (16 CDB) - ABP3905 - Bus-Master PCI (16 CDB) - ABP915 - Bus-Master PCI (16 CDB) - ABP920 - Bus-Master PCI (16 CDB) - ABP3922 - Bus-Master PCI (16 CDB) - ABP3925 - Bus-Master PCI (16 CDB) - ABP930 - Bus-Master PCI (16 CDB) - ABP930U - Bus-Master PCI Ultra (16 CDB) - ABP930UA - Bus-Master PCI Ultra (16 CDB) - ABP960 - Bus-Master PCI MAC/PC (16 CDB) - ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB) + - ABP510/5150 - Bus-Master ISA (240 CDB) + - ABP5140 - Bus-Master ISA PnP (16 CDB) + - ABP5142 - Bus-Master ISA PnP with floppy (16 CDB) + - ABP902/3902 - Bus-Master PCI (16 CDB) + - ABP3905 - Bus-Master PCI (16 CDB) + - ABP915 - Bus-Master PCI (16 CDB) + - ABP920 - Bus-Master PCI (16 CDB) + - ABP3922 - Bus-Master PCI (16 CDB) + - ABP3925 - Bus-Master PCI (16 CDB) + - ABP930 - Bus-Master PCI (16 CDB) + - ABP930U - Bus-Master PCI Ultra (16 CDB) + - ABP930UA - Bus-Master PCI Ultra (16 CDB) + - ABP960 - Bus-Master PCI MAC/PC (16 CDB) + - ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB) Single Channel Products: - ABP542 - Bus-Master ISA with floppy (240 CDB) - ABP742 - Bus-Master EISA (240 CDB) - ABP842 - Bus-Master VL (240 CDB) - ABP940 - Bus-Master PCI (240 CDB) - ABP940U - Bus-Master PCI Ultra (240 CDB) - ABP940UA/3940UA - Bus-Master PCI Ultra (240 CDB) - ABP970 - Bus-Master PCI MAC/PC (240 CDB) - ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB) - ABP3960UA - Bus-Master PCI MAC/PC Ultra (240 CDB) - ABP940UW/3940UW - Bus-Master PCI Ultra-Wide (253 CDB) - ABP970UW - Bus-Master PCI MAC/PC Ultra-Wide (253 CDB) - ABP3940U2W - Bus-Master PCI LVD/Ultra2-Wide (253 CDB) + - ABP542 - Bus-Master ISA with floppy (240 CDB) + - ABP742 - Bus-Master EISA (240 CDB) + - ABP842 - Bus-Master VL (240 CDB) + - ABP940 - Bus-Master PCI (240 CDB) + - ABP940U - Bus-Master PCI Ultra (240 CDB) + - ABP940UA/3940UA - Bus-Master PCI Ultra (240 CDB) + - ABP970 - Bus-Master PCI MAC/PC (240 CDB) + - ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB) + - ABP3960UA - Bus-Master PCI MAC/PC Ultra (240 CDB) + - ABP940UW/3940UW - Bus-Master PCI Ultra-Wide (253 CDB) + - ABP970UW - Bus-Master PCI MAC/PC Ultra-Wide (253 CDB) + - ABP3940U2W - Bus-Master PCI LVD/Ultra2-Wide (253 CDB) Multi-Channel Products: - ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel) - ABP852 - Dual Channel Bus-Master VL (240 CDB Per Channel) - ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel) - ABP950UW - Dual Channel Bus-Master PCI Ultra-Wide (253 CDB Per Channel) - ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel) - ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel) - ABP980UA/3980UA - Four Channel Bus-Master PCI Ultra (16 CDB Per Chan.) - ABP3950U2W - Bus-Master PCI LVD/Ultra2-Wide and Ultra-Wide (253 CDB) - ABP3950U3W - Bus-Master PCI Dual LVD2/Ultra3-Wide (253 CDB) + - ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel) + - ABP852 - Dual Channel Bus-Master VL (240 CDB Per Channel) + - ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel) + - ABP950UW - Dual Channel Bus-Master PCI Ultra-Wide (253 CDB Per Channel) + - ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel) + - ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel) + - ABP980UA/3980UA - Four Channel Bus-Master PCI Ultra (16 CDB Per Chan.) + - ABP3950U2W - Bus-Master PCI LVD/Ultra2-Wide and Ultra-Wide (253 CDB) + - ABP3950U3W - Bus-Master PCI Dual LVD2/Ultra3-Wide (253 CDB) Driver Compile Time Options and Debugging +========================================= The following constants can be defined in the source file. @@ -88,26 +95,30 @@ The following constants can be defined in the source file. first three hex digits of the pseudo I/O Port must be set to 'deb' and the fourth hex digit specifies the debug level: 0 - F. The following command line will look for an adapter at 0x330 - and set the debug level to 2. + and set the debug level to 2:: linux advansys=0x330,0,0,0,0xdeb2 If the driver is built as a loadable module this variable can be defined when the driver is loaded. The following insmod command - will set the debug level to one. + will set the debug level to one:: insmod advansys.o asc_dbglvl=1 Debugging Message Levels: - 0: Errors Only - 1: High-Level Tracing - 2-N: Verbose Tracing + + + ==== ================== + 0 Errors Only + 1 High-Level Tracing + 2-N Verbose Tracing + ==== ================== To enable debug output to console, please make sure that: a. System and kernel logging is enabled (syslogd, klogd running). b. Kernel messages are routed to console output. Check - /etc/syslog.conf for an entry similar to this: + /etc/syslog.conf for an entry similar to this:: kern.* /dev/console @@ -120,8 +131,11 @@ The following constants can be defined in the source file. Alternatively you can enable printk() to console with this program. However, this is not the 'official' way to do this. + Debug output is logged in /var/log/messages. + :: + main() { syscall(103, 7, 0, 0); @@ -144,11 +158,11 @@ The following constants can be defined in the source file. Statistics are only available for kernels greater than or equal to v1.3.0 with the CONFIG_PROC_FS (/proc) file system configured. - AdvanSys SCSI adapter files have the following path name format: + AdvanSys SCSI adapter files have the following path name format:: /proc/scsi/advansys/{0,1,2,3,...} - This information can be displayed with cat. For example: + This information can be displayed with cat. For example:: cat /proc/scsi/advansys/0 @@ -156,6 +170,7 @@ The following constants can be defined in the source file. contain adapter and device configuration information. Driver LILO Option +================== If init/main.c is modified as described in the 'Directions for Adding the AdvanSys Driver to Linux' section (B.4.) above, the driver will @@ -167,17 +182,30 @@ affects searching for ISA and VL boards. Examples: 1. Eliminate I/O port scanning: - boot: linux advansys= - or - boot: linux advansys=0x0 + + boot:: + + linux advansys= + + or:: + + boot: linux advansys=0x0 + 2. Limit I/O port scanning to one I/O port: - boot: linux advansys=0x110 + + boot:: + + linux advansys=0x110 + 3. Limit I/O port scanning to four I/O ports: - boot: linux advansys=0x110,0x210,0x230,0x330 + + boot:: + + linux advansys=0x110,0x210,0x230,0x330 For a loadable module the same effect can be achieved by setting the 'asc_iopflag' variable and 'asc_ioport' array when loading -the driver, e.g. +the driver, e.g.:: insmod advansys.o asc_iopflag=1 asc_ioport=0x110,0x330 @@ -187,6 +215,7 @@ the 'Driver Compile Time Options and Debugging' section above for more information. Credits (Chronological Order) +============================= Bob Frey wrote the AdvanSys SCSI driver and maintained it up to 3.3F. He continues to answer questions diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index 2e0429d1a7a5..df526a0ceccf 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -9,5 +9,6 @@ Linux SCSI Subsystem 53c700 aacraid + advansys scsi_transport_srp/figures diff --git a/MAINTAINERS b/MAINTAINERS index 3251b768fec0..abaac06fa0c5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -540,7 +540,7 @@ M: Matthew Wilcox M: Hannes Reinecke L: linux-scsi@vger.kernel.org S: Maintained -F: Documentation/scsi/advansys.txt +F: Documentation/scsi/advansys.rst F: drivers/scsi/advansys.c ADXL34X THREE-AXIS DIGITAL ACCELEROMETER DRIVER (ADXL345/ADXL346) From 94b5530f1fb8e468ca0a4117f2bb0fbdca550df1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:39 +0100 Subject: [PATCH 1586/4444] scsi: docs: convert aha152x.txt to ReST Link: https://lore.kernel.org/r/097cfcc7f25343676a1fedcefed7e3b91b41b4df.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- .../scsi/{aha152x.txt => aha152x.rst} | 75 ++++++++++++------- Documentation/scsi/index.rst | 1 + Documentation/scsi/scsi-parameters.txt | 2 +- drivers/scsi/Kconfig | 2 +- drivers/scsi/aha152x.c | 4 +- 5 files changed, 53 insertions(+), 31 deletions(-) rename Documentation/scsi/{aha152x.txt => aha152x.rst} (76%) diff --git a/Documentation/scsi/aha152x.txt b/Documentation/scsi/aha152x.rst similarity index 76% rename from Documentation/scsi/aha152x.txt rename to Documentation/scsi/aha152x.rst index 94848734ac66..7012b5c46d5d 100644 --- a/Documentation/scsi/aha152x.txt +++ b/Documentation/scsi/aha152x.rst @@ -1,7 +1,12 @@ -$Id: README.aha152x,v 1.2 1999/12/25 15:32:30 fischer Exp fischer $ -Adaptec AHA-1520/1522 SCSI driver for Linux (aha152x) +.. SPDX-License-Identifier: GPL-2.0 +.. include:: + +===================================================== +Adaptec AHA-1520/1522 SCSI driver for Linux (aha152x) +===================================================== + +Copyright |copy| 1993-1999 Jürgen Fischer -Copyright 1993-1999 Jürgen Fischer TC1550 patches by Luuk van Dijk (ldz@xs4all.nl) @@ -14,8 +19,10 @@ less polling loops), has slightly higher throughput (at least on my ancient test box; a i486/33Mhz/20MB). -CONFIGURATION ARGUMENTS: +Configuration Arguments +======================= +============ ======================================== ====================== IOPORT base io address (0x340/0x140) IRQ interrupt level (9-12; default 11) SCSI_ID scsi id of controller (0-7; default 7) @@ -25,31 +32,38 @@ SYNCHRONOUS enable synchronous transfers (0/1; default 1 [on]) DELAY: bus reset delay (default 100) EXT_TRANS: enable extended translation (0/1: default 0 [off]) (see NOTES) +============ ======================================== ====================== -COMPILE TIME CONFIGURATION (go into AHA152X in drivers/scsi/Makefile): +Compile Time Configuration +========================== --DAUTOCONF - use configuration the controller reports (AHA-152x only) +(go into AHA152X in drivers/scsi/Makefile): --DSKIP_BIOSTEST - Don't test for BIOS signature (AHA-1510 or disabled BIOS) +- DAUTOCONF + use configuration the controller reports (AHA-152x only) --DSETUP0="{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY, EXT_TRANS }" - override for the first controller +- DSKIP_BIOSTEST + Don't test for BIOS signature (AHA-1510 or disabled BIOS) --DSETUP1="{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY, EXT_TRANS }" - override for the second controller +- DSETUP0="{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY, EXT_TRANS }" + override for the first controller --DAHA152X_DEBUG - enable debugging output +- DSETUP1="{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY, EXT_TRANS }" + override for the second controller --DAHA152X_STAT - enable some statistics +- DAHA152X_DEBUG + enable debugging output + +- DAHA152X_STAT + enable some statistics -LILO COMMAND LINE OPTIONS: +LILO Command Line Options +========================= -aha152x=[,[,[,[,[,[, [,[,[,[,[,[,[, [,[,[,[,[,[,[,1GB: + - take current geometry from the partition table - (using scsicam_bios_param and accept only `valid' geometries, + (using scsicam_bios_param and accept only 'valid' geometries, ie. either (C/32/64) or (C/63/255)). This can be extended translation even if it's not enabled in the driver. @@ -161,7 +181,8 @@ geometry right in most cases: disks. -REFERENCES USED: +References Used +=============== "AIC-6260 SCSI Chip Specification", Adaptec Corporation. @@ -177,7 +198,7 @@ REFERENCES USED: Drew Eckhardt (drew@cs.colorado.edu) - Eric Youngdale (eric@andante.org) + Eric Youngdale (eric@andante.org) special thanks to Eric Youngdale for the free(!) supplying the documentation on the chip. diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index df526a0ceccf..8404e991b588 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -10,5 +10,6 @@ Linux SCSI Subsystem 53c700 aacraid advansys + aha152x scsi_transport_srp/figures diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt index 25a4b4cf04a6..064d6dfcac26 100644 --- a/Documentation/scsi/scsi-parameters.txt +++ b/Documentation/scsi/scsi-parameters.txt @@ -16,7 +16,7 @@ parameters may be changed at runtime by the command See header of drivers/scsi/advansys.c. aha152x= [HW,SCSI] - See Documentation/scsi/aha152x.txt. + See Documentation/scsi/aha152x.rst. aha1542= [HW,SCSI] Format: [,,[,]] diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index a153444318fb..18af62594bc0 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -383,7 +383,7 @@ config SCSI_AHA152X It is explained in section 3.3 of the SCSI-HOWTO, available from . You might also want to - read the file . + read the file . To compile this driver as a module, choose M here: the module will be called aha152x. diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index eb466c2e1839..90f97df1c42a 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -220,7 +220,7 @@ * ************************************************************************** - see Documentation/scsi/aha152x.txt for configuration details + see Documentation/scsi/aha152x.rst for configuration details **************************************************************************/ @@ -1249,7 +1249,7 @@ static int aha152x_biosparam(struct scsi_device *sdev, struct block_device *bdev "aha152x: unable to verify geometry for disk with >1GB.\n" " Using default translation. Please verify yourself.\n" " Perhaps you need to enable extended translation in the driver.\n" - " See Documentation/scsi/aha152x.txt for details.\n"); + " See Documentation/scsi/aha152x.rst for details.\n"); } } else { info_array[0] = info[0]; From 520a44d4dfe15ac6a0c1b79b13cc548af51467b7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:40 +0100 Subject: [PATCH 1587/4444] scsi: docs: convert aic79xx.txt to ReST Link: https://lore.kernel.org/r/e8a40337a2173f028c9ac569d3d71fd880f4fab5.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/aic79xx.rst | 593 +++++++++++++++++++++++++ Documentation/scsi/aic79xx.txt | 497 --------------------- Documentation/scsi/index.rst | 1 + Documentation/scsi/scsi-parameters.txt | 2 +- drivers/scsi/aic7xxx/Kconfig.aic79xx | 2 +- 5 files changed, 596 insertions(+), 499 deletions(-) create mode 100644 Documentation/scsi/aic79xx.rst delete mode 100644 Documentation/scsi/aic79xx.txt diff --git a/Documentation/scsi/aic79xx.rst b/Documentation/scsi/aic79xx.rst new file mode 100644 index 000000000000..071ff5111a4f --- /dev/null +++ b/Documentation/scsi/aic79xx.rst @@ -0,0 +1,593 @@ +.. SPDX-License-Identifier: GPL-2.0 +.. include:: + +=================================== +Adaptec Ultra320 Family Manager Set +=================================== + +README for The Linux Operating System + +.. The following information is available in this file: + + 1. Supported Hardware + 2. Version History + 3. Command Line Options + 4. Additional Notes + 5. Contacting Adaptec + + +1. Supported Hardware +===================== + + The following Adaptec SCSI Host Adapters are supported by this + driver set. + + ============= ========================================= + Ultra320 ASIC Description + ============= ========================================= + AIC-7901A Single Channel 64-bit PCI-X 133MHz to + Ultra320 SCSI ASIC + AIC-7901B Single Channel 64-bit PCI-X 133MHz to + Ultra320 SCSI ASIC with Retained Training + AIC-7902A4 Dual Channel 64-bit PCI-X 133MHz to + Ultra320 SCSI ASIC + AIC-7902B Dual Channel 64-bit PCI-X 133MHz to + Ultra320 SCSI ASIC with Retained Training + ============= ========================================= + + ========================== ===================================== ============ + Ultra320 Adapters Description ASIC + ========================== ===================================== ============ + Adaptec SCSI Card 39320 Dual Channel 64-bit PCI-X 133MHz to 7902A4/7902B + Ultra320 SCSI Card (one external + 68-pin, two internal 68-pin) + Adaptec SCSI Card 39320A Dual Channel 64-bit PCI-X 133MHz to 7902B + Ultra320 SCSI Card (one external + 68-pin, two internal 68-pin) + Adaptec SCSI Card 39320D Dual Channel 64-bit PCI-X 133MHz to 7902A4 + Ultra320 SCSI Card (two external VHDC + and one internal 68-pin) + Adaptec SCSI Card 39320D Dual Channel 64-bit PCI-X 133MHz to 7902A4 + Ultra320 SCSI Card (two external VHDC + and one internal 68-pin) based on the + AIC-7902B ASIC + Adaptec SCSI Card 29320 Single Channel 64-bit PCI-X 133MHz to 7901A + Ultra320 SCSI Card (one external + 68-pin, two internal 68-pin, one + internal 50-pin) + Adaptec SCSI Card 29320A Single Channel 64-bit PCI-X 133MHz to 7901B + Ultra320 SCSI Card (one external + 68-pin, two internal 68-pin, one + internal 50-pin) + Adaptec SCSI Card 29320LP Single Channel 64-bit Low Profile 7901A + PCI-X 133MHz to Ultra320 SCSI Card + (One external VHDC, one internal + 68-pin) + Adaptec SCSI Card 29320ALP Single Channel 64-bit Low Profile 7901B + PCI-X 133MHz to Ultra320 SCSI Card + (One external VHDC, one internal + 68-pin) + ========================== ===================================== ============ + +2. Version History +================== + + + * 3.0 (December 1st, 2005) + - Updated driver to use SCSI transport class infrastructure + - Upported sequencer and core fixes from adaptec released + version 2.0.15 of the driver. + + * 1.3.11 (July 11, 2003) + - Fix several deadlock issues. + - Add 29320ALP and 39320B Id's. + + * 1.3.10 (June 3rd, 2003) + - Align the SCB_TAG field on a 16byte boundary. This avoids + SCB corruption on some PCI-33 busses. + - Correct non-zero luns on Rev B. hardware. + - Update for change in 2.5.X SCSI proc FS interface. + - When negotiation async via an 8bit WDTR message, send + an SDTR with an offset of 0 to be sure the target + knows we are async. This works around a firmware defect + in the Quantum Atlas 10K. + - Implement controller suspend and resume. + - Clear PCI error state during driver attach so that we + don't disable memory mapped I/O due to a stray write + by some other driver probe that occurred before we + claimed the controller. + + * 1.3.9 (May 22nd, 2003) + - Fix compiler errors. + - Remove S/G splitting for segments that cross a 4GB boundary. + This is guaranteed not to happen in Linux. + - Add support for scsi_report_device_reset() found in + 2.5.X kernels. + - Add 7901B support. + - Simplify handling of the packetized lun Rev A workaround. + - Correct and simplify handling of the ignore wide residue + message. The previous code would fail to report a residual + if the transaction data length was even and we received + an IWR message. + + * 1.3.8 (April 29th, 2003) + - Fix types accessed via the command line interface code. + - Perform a few firmware optimizations. + - Fix "Unexpected PKT busfree" errors. + - Use a sequencer interrupt to notify the host of + commands with bad status. We defer the notification + until there are no outstanding selections to ensure + that the host is interrupted for as short a time as + possible. + - Remove pre-2.2.X support. + - Add support for new 2.5.X interrupt API. + - Correct big-endian architecture support. + + * 1.3.7 (April 16th, 2003) + - Use del_timer_sync() to ensure that no timeouts + are pending during controller shutdown. + - For pre-2.5.X kernels, carefully adjust our segment + list size to avoid SCSI malloc pool fragmentation. + - Cleanup channel display in our /proc output. + - Workaround duplicate device entries in the mid-layer + device list during add-single-device. + + * 1.3.6 (March 28th, 2003) + - Correct a double free in the Domain Validation code. + - Correct a reference to free'ed memory during controller + shutdown. + - Reset the bus on an SE->LVD change. This is required + to reset our transceivers. + + * 1.3.5 (March 24th, 2003) + - Fix a few register window mode bugs. + - Include read streaming in the PPR flags we display in + diagnostics as well as /proc. + - Add PCI hot plug support for 2.5.X kernels. + - Correct default precompensation value for RevA hardware. + - Fix Domain Validation thread shutdown. + - Add a firmware workaround to make the LED blink + brighter during packetized operations on the H2A4. + - Correct /proc display of user read streaming settings. + - Simplify driver locking by releasing the io_request_lock + upon driver entry from the mid-layer. + - Cleanup command line parsing and move much of this code + to aiclib. + + * 1.3.4 (February 28th, 2003) + - Correct a race condition in our error recovery handler. + - Allow Test Unit Ready commands to take a full 5 seconds + during Domain Validation. + + * 1.3.2 (February 19th, 2003) + - Correct a Rev B. regression due to the GEM318 + compatibility fix included in 1.3.1. + + * 1.3.1 (February 11th, 2003) + - Add support for the 39320A. + - Improve recovery for certain PCI-X errors. + - Fix handling of LQ/DATA/LQ/DATA for the + same write transaction that can occur without + interveining training. + - Correct compatibility issues with the GEM318 + enclosure services device. + - Correct data corruption issue that occurred under + high tag depth write loads. + - Adapt to a change in the 2.5.X daemonize() API. + - Correct a "Missing case in ahd_handle_scsiint" panic. + + * 1.3.0 (January 21st, 2003) + - Full regression testing for all U320 products completed. + - Added abort and target/lun reset error recovery handler and + interrupt coalescing. + + * 1.2.0 (November 14th, 2002) + - Added support for Domain Validation + - Add support for the Hewlett-Packard version of the 39320D + and AIC-7902 adapters. + + Support for previous adapters has not been fully tested and should + only be used at the customer's own risk. + + * 1.1.1 (September 24th, 2002) + - Added support for the Linux 2.5.X kernel series + + * 1.1.0 (September 17th, 2002) + - Added support for four additional SCSI products: + ASC-39320, ASC-29320, ASC-29320LP, AIC-7901. + + * 1.0.0 (May 30th, 2002) + - Initial driver release. + + * 2.1. Software/Hardware Features + - Support for the SPI-4 "Ultra320" standard: + - 320MB/s transfer rates + - Packetized SCSI Protocol at 160MB/s and 320MB/s + - Quick Arbitration Selection (QAS) + - Retained Training Information (Rev B. ASIC only) + - Interrupt Coalescing + - Initiator Mode (target mode not currently + supported) + - Support for the PCI-X standard up to 133MHz + - Support for the PCI v2.2 standard + - Domain Validation + + * 2.2. Operating System Support: + - Redhat Linux 7.2, 7.3, 8.0, Advanced Server 2.1 + - SuSE Linux 7.3, 8.0, 8.1, Enterprise Server 7 + - only Intel and AMD x86 supported at this time + - >4GB memory configurations supported. + + Refer to the User's Guide for more details on this. + +3. Command Line Options +======================= + + .. Warning:: + + ALTERING OR ADDING THESE DRIVER PARAMETERS + INCORRECTLY CAN RENDER YOUR SYSTEM INOPERABLE. + USE THEM WITH CAUTION. + + Put a .conf file in the /etc/modprobe.d/ directory and add/edit a + line containing ``options aic79xx aic79xx=[command[,command...]]`` where + ``command`` is one or more of the following: + + +verbose + :Definition: enable additional informative messages during driver operation. + :Possible Values: This option is a flag + :Default Value: disabled + +debug:[value] + :Definition: Enables various levels of debugging information + The bit definitions for the debugging mask can + be found in drivers/scsi/aic7xxx/aic79xx.h under + the "Debug" heading. + :Possible Values: 0x0000 = no debugging, 0xffff = full debugging + :Default Value: 0x0000 + +no_reset + :Definition: Do not reset the bus during the initial probe + phase + :Possible Values: This option is a flag + :Default Value: disabled + +extended + :Definition: Force extended translation on the controller + :Possible Values: This option is a flag + :Default Value: disabled + +periodic_otag + :Definition: Send an ordered tag periodically to prevent + tag starvation. Needed for some older devices + :Possible Values: This option is a flag + :Default Value: disabled + +reverse_scan + :Definition: Probe the scsi bus in reverse order, starting with target 15 + :Possible Values: This option is a flag + :Default Value: disabled + +global_tag_depth + :Definition: Global tag depth for all targets on all busses. + This option sets the default tag depth which + may be selectively overridden vi the tag_info + option. + + :Possible Values: 1 - 253 + :Default Value: 32 + +tag_info:{{value[,value...]}[,{value[,value...]}...]} + :Definition: Set the per-target tagged queue depth on a + per controller basis. Both controllers and targets + may be omitted indicating that they should retain + the default tag depth. + + :Possible Values: 1 - 253 + :Default Value: 32 + + Examples: + + + :: + + tag_info:{{16,32,32,64,8,8,,32,32,32,32,32,32,32,32,32} + + On Controller 0 + + - specifies a tag depth of 16 for target 0 + - specifies a tag depth of 64 for target 3 + - specifies a tag depth of 8 for targets 4 and 5 + - leaves target 6 at the default + - specifies a tag depth of 32 for targets 1,2,7-15 + + All other targets retain the default depth. + + :: + + tag_info:{{},{32,,32}} + + On Controller 1 + + - specifies a tag depth of 32 for targets 0 and 2 + + All other targets retain the default depth. + + +rd_strm: {rd_strm_bitmask[,rd_strm_bitmask...]} + :Definition: Enable read streaming on a per target basis. + The rd_strm_bitmask is a 16 bit hex value in which + each bit represents a target. Setting the target's + bit to '1' enables read streaming for that + target. Controllers may be omitted indicating that + they should retain the default read streaming setting. + + Examples: + + :: + + rd_strm:{0x0041} + + On Controller 0 + + - enables read streaming for targets 0 and 6. + - disables read streaming for targets 1-5,7-15. + + All other targets retain the default read + streaming setting. + + :: + + rd_strm:{0x0023,,0xFFFF} + + On Controller 0 + + - enables read streaming for targets 1,2, and 5. + - disables read streaming for targets 3,4,6-15. + + On Controller 2 + + - enables read streaming for all targets. + + All other targets retain the default read + streaming setting. + + :Possible Values: 0x0000 - 0xffff + :Default Value: 0x0000 + +dv: {value[,value...]} + :Definition: Set Domain Validation Policy on a per-controller basis. + Controllers may be omitted indicating that + they should retain the default read streaming setting. + + :Possible Values: + + ==== =============================== + < 0 Use setting from serial EEPROM. + 0 Disable DV + > 0 Enable DV + ==== =============================== + + :Default Value: DV Serial EEPROM configuration setting. + + Example: + + :: + + dv:{-1,0,,1,1,0} + + - On Controller 0 leave DV at its default setting. + - On Controller 1 disable DV. + - Skip configuration on Controller 2. + - On Controllers 3 and 4 enable DV. + - On Controller 5 disable DV. + +seltime:[value] + :Definition: Specifies the selection timeout value + :Possible Values: 0 = 256ms, 1 = 128ms, 2 = 64ms, 3 = 32ms + :Default Value: 0 + +.. Warning: + + The following three options should only be changed at + the direction of a technical support representative. + + +precomp: {value[,value...]} + :Definition: Set IO Cell precompensation value on a per-controller basis. + Controllers may be omitted indicating that + they should retain the default precompensation setting. + + :Possible Values: 0 - 7 + :Default Value: Varies based on chip revision + + Examples: + + :: + + precomp:{0x1} + + On Controller 0 set precompensation to 1. + + :: + + precomp:{1,,7} + + - On Controller 0 set precompensation to 1. + - On Controller 2 set precompensation to 8. + +slewrate: {value[,value...]} + :Definition: Set IO Cell slew rate on a per-controller basis. + Controllers may be omitted indicating that + they should retain the default slew rate setting. + + :Possible Values: 0 - 15 + :Default Value: Varies based on chip revision + + Examples: + + :: + + slewrate:{0x1} + + - On Controller 0 set slew rate to 1. + + :: + + slewrate :{1,,8} + + - On Controller 0 set slew rate to 1. + - On Controller 2 set slew rate to 8. + +amplitude: {value[,value...]} + :Definition: Set IO Cell signal amplitude on a per-controller basis. + Controllers may be omitted indicating that + they should retain the default read streaming setting. + + :Possible Values: 1 - 7 + :Default Value: Varies based on chip revision + + Examples: + + :: + + amplitude:{0x1} + + On Controller 0 set amplitude to 1. + + :: + + amplitude :{1,,7} + + - On Controller 0 set amplitude to 1. + - On Controller 2 set amplitude to 7. + +Example:: + + options aic79xx aic79xx=verbose,rd_strm:{{0x0041}} + +enables verbose output in the driver and turns read streaming on +for targets 0 and 6 of Controller 0. + +4. Additional Notes +=================== + +4.1. Known/Unresolved or FYI Issues +----------------------------------- + + * Under SuSE Linux Enterprise 7, the driver may fail to operate + correctly due to a problem with PCI interrupt routing in the + Linux kernel. Please contact SuSE for an updated Linux + kernel. + +4.2. Third-Party Compatibility Issues +------------------------------------- + + * Adaptec only supports Ultra320 hard drives running + the latest firmware available. Please check with + your hard drive manufacturer to ensure you have the + latest version. + +4.3. Operating System or Technology Limitations +----------------------------------------------- + + * PCI Hot Plug is untested and may cause the operating system + to stop responding. + * Luns that are not numbered contiguously starting with 0 might not + be automatically probed during system startup. This is a limitation + of the OS. Please contact your Linux vendor for instructions on + manually probing non-contiguous luns. + * Using the Driver Update Disk version of this package during OS + installation under RedHat might result in two versions of this + driver being installed into the system module directory. This + might cause problems with the /sbin/mkinitrd program and/or + other RPM packages that try to install system modules. The best + way to correct this once the system is running is to install + the latest RPM package version of this driver, available from + http://www.adaptec.com. + + +5. Adaptec Customer Support +=========================== + + A Technical Support Identification (TSID) Number is required for + Adaptec technical support. + + - The 12-digit TSID can be found on the white barcode-type label + included inside the box with your product. The TSID helps us + provide more efficient service by accurately identifying your + product and support status. + + Support Options + - Search the Adaptec Support Knowledgebase (ASK) at + http://ask.adaptec.com for articles, troubleshooting tips, and + frequently asked questions about your product. + - For support via Email, submit your question to Adaptec's + Technical Support Specialists at http://ask.adaptec.com/. + + North America + - Visit our Web site at http://www.adaptec.com/. + - For information about Adaptec's support options, call + 408-957-2550, 24 hours a day, 7 days a week. + - To speak with a Technical Support Specialist, + + * For hardware products, call 408-934-7274, + Monday to Friday, 3:00 am to 5:00 pm, PDT. + * For RAID and Fibre Channel products, call 321-207-2000, + Monday to Friday, 3:00 am to 5:00 pm, PDT. + + To expedite your service, have your computer with you. + - To order Adaptec products, including accessories and cables, + call 408-957-7274. To order cables online go to + http://www.adaptec.com/buy-cables/. + + Europe + - Visit our Web site at http://www.adaptec.com/en-US/_common/world_index. + - To speak with a Technical Support Specialist, call, or email, + + * German: +49 89 4366 5522, Monday-Friday, 9:00-17:00 CET, + http://ask-de.adaptec.com/. + * French: +49 89 4366 5533, Monday-Friday, 9:00-17:00 CET, + http://ask-fr.adaptec.com/. + * English: +49 89 4366 5544, Monday-Friday, 9:00-17:00 GMT, + http://ask.adaptec.com/. + + - You can order Adaptec cables online at + http://www.adaptec.com/buy-cables/. + + Japan + - Visit our web site at http://www.adaptec.co.jp/. + - To speak with a Technical Support Specialist, call + +81 3 5308 6120, Monday-Friday, 9:00 a.m. to 12:00 p.m., + 1:00 p.m. to 6:00 p.m. + +Copyright |copy| 2003 Adaptec Inc. 691 S. Milpitas Blvd., Milpitas CA 95035 USA. +All rights reserved. + +You are permitted to redistribute, use and modify this README file in whole +or in part in conjunction with redistribution of software governed by the +General Public License, provided that the following conditions are met: + +1. Redistributions of README file must retain the above copyright + notice, this list of conditions, and the following disclaimer, + without modification. +2. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. +3. Modifications or new contributions must be attributed in a copyright + notice identifying the author ("Contributor") and added below the + original copyright notice. The copyright notice is for purposes of + identifying contributors and should not be deemed as permission to alter + the permissions given by Adaptec. + +THIS README FILE IS PROVIDED BY ADAPTEC AND CONTRIBUTORS ``AS IS`` AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ANY +WARRANTIES OF NON-INFRINGEMENT OR THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +ADAPTEC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS README +FILE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Documentation/scsi/aic79xx.txt b/Documentation/scsi/aic79xx.txt deleted file mode 100644 index e2d3273000d4..000000000000 --- a/Documentation/scsi/aic79xx.txt +++ /dev/null @@ -1,497 +0,0 @@ -==================================================================== -= Adaptec Ultra320 Family Manager Set = -= = -= README for = -= The Linux Operating System = -==================================================================== - -The following information is available in this file: - - 1. Supported Hardware - 2. Version History - 3. Command Line Options - 4. Additional Notes - 5. Contacting Adaptec - - -1. Supported Hardware - - The following Adaptec SCSI Host Adapters are supported by this - driver set. - - Ultra320 ASIC Description - ---------------------------------------------------------------- - AIC-7901A Single Channel 64-bit PCI-X 133MHz to - Ultra320 SCSI ASIC - AIC-7901B Single Channel 64-bit PCI-X 133MHz to - Ultra320 SCSI ASIC with Retained Training - AIC-7902A4 Dual Channel 64-bit PCI-X 133MHz to - Ultra320 SCSI ASIC - AIC-7902B Dual Channel 64-bit PCI-X 133MHz to - Ultra320 SCSI ASIC with Retained Training - - Ultra320 Adapters Description ASIC - -------------------------------------------------------------------------- - Adaptec SCSI Card 39320 Dual Channel 64-bit PCI-X 133MHz to 7902A4/7902B - Ultra320 SCSI Card (one external - 68-pin, two internal 68-pin) - Adaptec SCSI Card 39320A Dual Channel 64-bit PCI-X 133MHz to 7902B - Ultra320 SCSI Card (one external - 68-pin, two internal 68-pin) - Adaptec SCSI Card 39320D Dual Channel 64-bit PCI-X 133MHz to 7902A4 - Ultra320 SCSI Card (two external VHDC - and one internal 68-pin) - Adaptec SCSI Card 39320D Dual Channel 64-bit PCI-X 133MHz to 7902A4 - Ultra320 SCSI Card (two external VHDC - and one internal 68-pin) based on the - AIC-7902B ASIC - Adaptec SCSI Card 29320 Single Channel 64-bit PCI-X 133MHz to 7901A - Ultra320 SCSI Card (one external - 68-pin, two internal 68-pin, one - internal 50-pin) - Adaptec SCSI Card 29320A Single Channel 64-bit PCI-X 133MHz to 7901B - Ultra320 SCSI Card (one external - 68-pin, two internal 68-pin, one - internal 50-pin) - Adaptec SCSI Card 29320LP Single Channel 64-bit Low Profile 7901A - PCI-X 133MHz to Ultra320 SCSI Card - (One external VHDC, one internal - 68-pin) - Adaptec SCSI Card 29320ALP Single Channel 64-bit Low Profile 7901B - PCI-X 133MHz to Ultra320 SCSI Card - (One external VHDC, one internal - 68-pin) -2. Version History - - 3.0 (December 1st, 2005) - - Updated driver to use SCSI transport class infrastructure - - Upported sequencer and core fixes from adaptec released - version 2.0.15 of the driver. - - 1.3.11 (July 11, 2003) - - Fix several deadlock issues. - - Add 29320ALP and 39320B Id's. - - 1.3.10 (June 3rd, 2003) - - Align the SCB_TAG field on a 16byte boundary. This avoids - SCB corruption on some PCI-33 busses. - - Correct non-zero luns on Rev B. hardware. - - Update for change in 2.5.X SCSI proc FS interface. - - When negotiation async via an 8bit WDTR message, send - an SDTR with an offset of 0 to be sure the target - knows we are async. This works around a firmware defect - in the Quantum Atlas 10K. - - Implement controller suspend and resume. - - Clear PCI error state during driver attach so that we - don't disable memory mapped I/O due to a stray write - by some other driver probe that occurred before we - claimed the controller. - - 1.3.9 (May 22nd, 2003) - - Fix compiler errors. - - Remove S/G splitting for segments that cross a 4GB boundary. - This is guaranteed not to happen in Linux. - - Add support for scsi_report_device_reset() found in - 2.5.X kernels. - - Add 7901B support. - - Simplify handling of the packetized lun Rev A workaround. - - Correct and simplify handling of the ignore wide residue - message. The previous code would fail to report a residual - if the transaction data length was even and we received - an IWR message. - - 1.3.8 (April 29th, 2003) - - Fix types accessed via the command line interface code. - - Perform a few firmware optimizations. - - Fix "Unexpected PKT busfree" errors. - - Use a sequencer interrupt to notify the host of - commands with bad status. We defer the notification - until there are no outstanding selections to ensure - that the host is interrupted for as short a time as - possible. - - Remove pre-2.2.X support. - - Add support for new 2.5.X interrupt API. - - Correct big-endian architecture support. - - 1.3.7 (April 16th, 2003) - - Use del_timer_sync() to ensure that no timeouts - are pending during controller shutdown. - - For pre-2.5.X kernels, carefully adjust our segment - list size to avoid SCSI malloc pool fragmentation. - - Cleanup channel display in our /proc output. - - Workaround duplicate device entries in the mid-layer - device list during add-single-device. - - 1.3.6 (March 28th, 2003) - - Correct a double free in the Domain Validation code. - - Correct a reference to free'ed memory during controller - shutdown. - - Reset the bus on an SE->LVD change. This is required - to reset our transceivers. - - 1.3.5 (March 24th, 2003) - - Fix a few register window mode bugs. - - Include read streaming in the PPR flags we display in - diagnostics as well as /proc. - - Add PCI hot plug support for 2.5.X kernels. - - Correct default precompensation value for RevA hardware. - - Fix Domain Validation thread shutdown. - - Add a firmware workaround to make the LED blink - brighter during packetized operations on the H2A4. - - Correct /proc display of user read streaming settings. - - Simplify driver locking by releasing the io_request_lock - upon driver entry from the mid-layer. - - Cleanup command line parsing and move much of this code - to aiclib. - - 1.3.4 (February 28th, 2003) - - Correct a race condition in our error recovery handler. - - Allow Test Unit Ready commands to take a full 5 seconds - during Domain Validation. - - 1.3.2 (February 19th, 2003) - - Correct a Rev B. regression due to the GEM318 - compatibility fix included in 1.3.1. - - 1.3.1 (February 11th, 2003) - - Add support for the 39320A. - - Improve recovery for certain PCI-X errors. - - Fix handling of LQ/DATA/LQ/DATA for the - same write transaction that can occur without - interveining training. - - Correct compatibility issues with the GEM318 - enclosure services device. - - Correct data corruption issue that occurred under - high tag depth write loads. - - Adapt to a change in the 2.5.X daemonize() API. - - Correct a "Missing case in ahd_handle_scsiint" panic. - - 1.3.0 (January 21st, 2003) - - Full regression testing for all U320 products completed. - - Added abort and target/lun reset error recovery handler and - interrupt coalescing. - - 1.2.0 (November 14th, 2002) - - Added support for Domain Validation - - Add support for the Hewlett-Packard version of the 39320D - and AIC-7902 adapters. - Support for previous adapters has not been fully tested and should - only be used at the customer's own risk. - - 1.1.1 (September 24th, 2002) - - Added support for the Linux 2.5.X kernel series - - 1.1.0 (September 17th, 2002) - - Added support for four additional SCSI products: - ASC-39320, ASC-29320, ASC-29320LP, AIC-7901. - - 1.0.0 (May 30th, 2002) - - Initial driver release. - - 2.1. Software/Hardware Features - - Support for the SPI-4 "Ultra320" standard: - - 320MB/s transfer rates - - Packetized SCSI Protocol at 160MB/s and 320MB/s - - Quick Arbitration Selection (QAS) - - Retained Training Information (Rev B. ASIC only) - - Interrupt Coalescing - - Initiator Mode (target mode not currently - supported) - - Support for the PCI-X standard up to 133MHz - - Support for the PCI v2.2 standard - - Domain Validation - - 2.2. Operating System Support: - - Redhat Linux 7.2, 7.3, 8.0, Advanced Server 2.1 - - SuSE Linux 7.3, 8.0, 8.1, Enterprise Server 7 - - only Intel and AMD x86 supported at this time - - >4GB memory configurations supported. - - Refer to the User's Guide for more details on this. - -3. Command Line Options - - WARNING: ALTERING OR ADDING THESE DRIVER PARAMETERS - INCORRECTLY CAN RENDER YOUR SYSTEM INOPERABLE. - USE THEM WITH CAUTION. - - Put a .conf file in the /etc/modprobe.d/ directory and add/edit a - line containing 'options aic79xx aic79xx=[command[,command...]]' where - 'command' is one or more of the following: - ----------------------------------------------------------------- - Option: verbose - Definition: enable additional informative messages during - driver operation. - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: debug:[value] - Definition: Enables various levels of debugging information - The bit definitions for the debugging mask can - be found in drivers/scsi/aic7xxx/aic79xx.h under - the "Debug" heading. - Possible Values: 0x0000 = no debugging, 0xffff = full debugging - Default Value: 0x0000 - ----------------------------------------------------------------- - Option: no_reset - Definition: Do not reset the bus during the initial probe - phase - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: extended - Definition: Force extended translation on the controller - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: periodic_otag - Definition: Send an ordered tag periodically to prevent - tag starvation. Needed for some older devices - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: reverse_scan - Definition: Probe the scsi bus in reverse order, starting - with target 15 - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: global_tag_depth - Definition: Global tag depth for all targets on all busses. - This option sets the default tag depth which - may be selectively overridden vi the tag_info - option. - Possible Values: 1 - 253 - Default Value: 32 - ----------------------------------------------------------------- - Option: tag_info:{{value[,value...]}[,{value[,value...]}...]} - Definition: Set the per-target tagged queue depth on a - per controller basis. Both controllers and targets - may be omitted indicating that they should retain - the default tag depth. - Examples: tag_info:{{16,32,32,64,8,8,,32,32,32,32,32,32,32,32,32} - On Controller 0 - specifies a tag depth of 16 for target 0 - specifies a tag depth of 64 for target 3 - specifies a tag depth of 8 for targets 4 and 5 - leaves target 6 at the default - specifies a tag depth of 32 for targets 1,2,7-15 - All other targets retain the default depth. - - tag_info:{{},{32,,32}} - On Controller 1 - specifies a tag depth of 32 for targets 0 and 2 - All other targets retain the default depth. - - Possible Values: 1 - 253 - Default Value: 32 - ----------------------------------------------------------------- - Option: rd_strm: {rd_strm_bitmask[,rd_strm_bitmask...]} - Definition: Enable read streaming on a per target basis. - The rd_strm_bitmask is a 16 bit hex value in which - each bit represents a target. Setting the target's - bit to '1' enables read streaming for that - target. Controllers may be omitted indicating that - they should retain the default read streaming setting. - Example: rd_strm:{0x0041} - On Controller 0 - enables read streaming for targets 0 and 6. - disables read streaming for targets 1-5,7-15. - All other targets retain the default read - streaming setting. - Example: rd_strm:{0x0023,,0xFFFF} - On Controller 0 - enables read streaming for targets 1,2, and 5. - disables read streaming for targets 3,4,6-15. - On Controller 2 - enables read streaming for all targets. - All other targets retain the default read - streaming setting. - - Possible Values: 0x0000 - 0xffff - Default Value: 0x0000 - ----------------------------------------------------------------- - Option: dv: {value[,value...]} - Definition: Set Domain Validation Policy on a per-controller basis. - Controllers may be omitted indicating that - they should retain the default read streaming setting. - Example: dv:{-1,0,,1,1,0} - On Controller 0 leave DV at its default setting. - On Controller 1 disable DV. - Skip configuration on Controller 2. - On Controllers 3 and 4 enable DV. - On Controller 5 disable DV. - - Possible Values: < 0 Use setting from serial EEPROM. - 0 Disable DV - > 0 Enable DV - Default Value: DV Serial EEPROM configuration setting. - ----------------------------------------------------------------- - Option: seltime:[value] - Definition: Specifies the selection timeout value - Possible Values: 0 = 256ms, 1 = 128ms, 2 = 64ms, 3 = 32ms - Default Value: 0 - ----------------------------------------------------------------- - - *** The following three options should only be changed at *** - *** the direction of a technical support representative. *** - - ----------------------------------------------------------------- - Option: precomp: {value[,value...]} - Definition: Set IO Cell precompensation value on a per-controller - basis. - Controllers may be omitted indicating that - they should retain the default precompensation setting. - Example: precomp:{0x1} - On Controller 0 set precompensation to 1. - Example: precomp:{1,,7} - On Controller 0 set precompensation to 1. - On Controller 2 set precompensation to 8. - - Possible Values: 0 - 7 - Default Value: Varies based on chip revision - ----------------------------------------------------------------- - Option: slewrate: {value[,value...]} - Definition: Set IO Cell slew rate on a per-controller basis. - Controllers may be omitted indicating that - they should retain the default slew rate setting. - Example: slewrate:{0x1} - On Controller 0 set slew rate to 1. - Example: slewrate :{1,,8} - On Controller 0 set slew rate to 1. - On Controller 2 set slew rate to 8. - - Possible Values: 0 - 15 - Default Value: Varies based on chip revision - ----------------------------------------------------------------- - Option: amplitude: {value[,value...]} - Definition: Set IO Cell signal amplitude on a per-controller basis. - Controllers may be omitted indicating that - they should retain the default read streaming setting. - Example: amplitude:{0x1} - On Controller 0 set amplitude to 1. - Example: amplitude :{1,,7} - On Controller 0 set amplitude to 1. - On Controller 2 set amplitude to 7. - - Possible Values: 1 - 7 - Default Value: Varies based on chip revision - ----------------------------------------------------------------- - - Example: 'options aic79xx aic79xx=verbose,rd_strm:{{0x0041}}' - enables verbose output in the driver and turns read streaming on - for targets 0 and 6 of Controller 0. - -4. Additional Notes - - 4.1. Known/Unresolved or FYI Issues - - * Under SuSE Linux Enterprise 7, the driver may fail to operate - correctly due to a problem with PCI interrupt routing in the - Linux kernel. Please contact SuSE for an updated Linux - kernel. - - 4.2. Third-Party Compatibility Issues - - * Adaptec only supports Ultra320 hard drives running - the latest firmware available. Please check with - your hard drive manufacturer to ensure you have the - latest version. - - 4.3. Operating System or Technology Limitations - - * PCI Hot Plug is untested and may cause the operating system - to stop responding. - * Luns that are not numbered contiguously starting with 0 might not - be automatically probed during system startup. This is a limitation - of the OS. Please contact your Linux vendor for instructions on - manually probing non-contiguous luns. - * Using the Driver Update Disk version of this package during OS - installation under RedHat might result in two versions of this - driver being installed into the system module directory. This - might cause problems with the /sbin/mkinitrd program and/or - other RPM packages that try to install system modules. The best - way to correct this once the system is running is to install - the latest RPM package version of this driver, available from - http://www.adaptec.com. - - -5. Adaptec Customer Support - - A Technical Support Identification (TSID) Number is required for - Adaptec technical support. - - The 12-digit TSID can be found on the white barcode-type label - included inside the box with your product. The TSID helps us - provide more efficient service by accurately identifying your - product and support status. - - Support Options - - Search the Adaptec Support Knowledgebase (ASK) at - http://ask.adaptec.com for articles, troubleshooting tips, and - frequently asked questions about your product. - - For support via Email, submit your question to Adaptec's - Technical Support Specialists at http://ask.adaptec.com/. - - North America - - Visit our Web site at http://www.adaptec.com/. - - For information about Adaptec's support options, call - 408-957-2550, 24 hours a day, 7 days a week. - - To speak with a Technical Support Specialist, - * For hardware products, call 408-934-7274, - Monday to Friday, 3:00 am to 5:00 pm, PDT. - * For RAID and Fibre Channel products, call 321-207-2000, - Monday to Friday, 3:00 am to 5:00 pm, PDT. - To expedite your service, have your computer with you. - - To order Adaptec products, including accessories and cables, - call 408-957-7274. To order cables online go to - http://www.adaptec.com/buy-cables/. - - Europe - - Visit our Web site at http://www.adaptec.com/en-US/_common/world_index. - - To speak with a Technical Support Specialist, call, or email, - * German: +49 89 4366 5522, Monday-Friday, 9:00-17:00 CET, - http://ask-de.adaptec.com/. - * French: +49 89 4366 5533, Monday-Friday, 9:00-17:00 CET, - http://ask-fr.adaptec.com/. - * English: +49 89 4366 5544, Monday-Friday, 9:00-17:00 GMT, - http://ask.adaptec.com/. - - You can order Adaptec cables online at - http://www.adaptec.com/buy-cables/. - - Japan - - Visit our web site at http://www.adaptec.co.jp/. - - To speak with a Technical Support Specialist, call - +81 3 5308 6120, Monday-Friday, 9:00 a.m. to 12:00 p.m., - 1:00 p.m. to 6:00 p.m. - -------------------------------------------------------------------- -/* - * Copyright (c) 2003 Adaptec Inc. 691 S. Milpitas Blvd., Milpitas CA 95035 USA. - * All rights reserved. - * - * You are permitted to redistribute, use and modify this README file in whole - * or in part in conjunction with redistribution of software governed by the - * General Public License, provided that the following conditions are met: - * 1. Redistributions of README file must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * 3. Modifications or new contributions must be attributed in a copyright - * notice identifying the author ("Contributor") and added below the - * original copyright notice. The copyright notice is for purposes of - * identifying contributors and should not be deemed as permission to alter - * the permissions given by Adaptec. - * - * THIS README FILE IS PROVIDED BY ADAPTEC AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ANY - * WARRANTIES OF NON-INFRINGEMENT OR THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * ADAPTEC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS README - * FILE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index 8404e991b588..b7fdfc0cb956 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -11,5 +11,6 @@ Linux SCSI Subsystem aacraid advansys aha152x + aic79xx scsi_transport_srp/figures diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt index 064d6dfcac26..8ed9c662a1d4 100644 --- a/Documentation/scsi/scsi-parameters.txt +++ b/Documentation/scsi/scsi-parameters.txt @@ -25,7 +25,7 @@ parameters may be changed at runtime by the command See Documentation/scsi/aic7xxx.txt. aic79xx= [HW,SCSI] - See Documentation/scsi/aic79xx.txt. + See Documentation/scsi/aic79xx.rst. atascsi= [HW,SCSI] See drivers/scsi/atari_scsi.c. diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx index 16743fb9eead..d4c50b8fce29 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic79xx +++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx @@ -32,7 +32,7 @@ config AIC79XX_CMDS_PER_DEVICE on some devices. The upper bound is 253. 0 disables tagged queueing. Per device tag depth can be controlled via the kernel command line - "tag_info" option. See Documentation/scsi/aic79xx.txt for details. + "tag_info" option. See Documentation/scsi/aic79xx.rst for details. config AIC79XX_RESET_DELAY_MS int "Initial bus reset delay in milli-seconds" From cff7c4a596e3498f52ac9c1277b4bc7d7a18e5d7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:41 +0100 Subject: [PATCH 1588/4444] scsi: docs: convert aic7xxx.txt to ReST Link: https://lore.kernel.org/r/dc2b1ffe4bf64cfc4b32328740704a30e8d38a79.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/aic7xxx.rst | 458 +++++++++++++++++++++++++ Documentation/scsi/aic7xxx.txt | 394 --------------------- Documentation/scsi/index.rst | 1 + Documentation/scsi/scsi-parameters.txt | 2 +- drivers/scsi/aic7xxx/Kconfig.aic7xxx | 2 +- 5 files changed, 461 insertions(+), 396 deletions(-) create mode 100644 Documentation/scsi/aic7xxx.rst delete mode 100644 Documentation/scsi/aic7xxx.txt diff --git a/Documentation/scsi/aic7xxx.rst b/Documentation/scsi/aic7xxx.rst new file mode 100644 index 000000000000..bad0e5567b21 --- /dev/null +++ b/Documentation/scsi/aic7xxx.rst @@ -0,0 +1,458 @@ +.. SPDX-License-Identifier: GPL-2.0 +.. include:: + +======================================================== +Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v7.0 +======================================================== + +README for The Linux Operating System + +The following information is available in this file: + + 1. Supported Hardware + 2. Version History + 3. Command Line Options + 4. Contacting Adaptec + +1. Supported Hardware +===================== + + The following Adaptec SCSI Chips and Host Adapters are supported by + the aic7xxx driver. + + ======== ===== ========= ======== ========= ===== =============== + Chip MIPS Host Bus MaxSync MaxWidth SCBs Notes + ======== ===== ========= ======== ========= ===== =============== + aic7770 10 EISA/VL 10MHz 16Bit 4 1 + aic7850 10 PCI/32 10MHz 8Bit 3 + aic7855 10 PCI/32 10MHz 8Bit 3 + aic7856 10 PCI/32 10MHz 8Bit 3 + aic7859 10 PCI/32 20MHz 8Bit 3 + aic7860 10 PCI/32 20MHz 8Bit 3 + aic7870 10 PCI/32 10MHz 16Bit 16 + aic7880 10 PCI/32 20MHz 16Bit 16 + aic7890 20 PCI/32 40MHz 16Bit 16 3 4 5 6 7 8 + aic7891 20 PCI/64 40MHz 16Bit 16 3 4 5 6 7 8 + aic7892 20 PCI/64-66 80MHz 16Bit 16 3 4 5 6 7 8 + aic7895 15 PCI/32 20MHz 16Bit 16 2 3 4 5 + aic7895C 15 PCI/32 20MHz 16Bit 16 2 3 4 5 8 + aic7896 20 PCI/32 40MHz 16Bit 16 2 3 4 5 6 7 8 + aic7897 20 PCI/64 40MHz 16Bit 16 2 3 4 5 6 7 8 + aic7899 20 PCI/64-66 80MHz 16Bit 16 2 3 4 5 6 7 8 + ======== ===== ========= ======== ========= ===== =============== + + 1. Multiplexed Twin Channel Device - One controller servicing two + busses. + 2. Multi-function Twin Channel Device - Two controllers on one chip. + 3. Command Channel Secondary DMA Engine - Allows scatter gather list + and SCB prefetch. + 4. 64 Byte SCB Support - Allows disconnected, untagged request table + for all possible target/lun combinations. + 5. Block Move Instruction Support - Doubles the speed of certain + sequencer operations. + 6. 'Bayonet' style Scatter Gather Engine - Improves S/G prefetch + performance. + 7. Queuing Registers - Allows queuing of new transactions without + pausing the sequencer. + 8. Multiple Target IDs - Allows the controller to respond to selection + as a target on multiple SCSI IDs. + + ============== ======= =========== =============== =============== ========= + Controller Chip Host-Bus Int-Connectors Ext-Connectors Notes + ============== ======= =========== =============== =============== ========= + AHA-274X[A] aic7770 EISA SE-50M SE-HD50F + AHA-274X[A]W aic7770 EISA SE-HD68F SE-HD68F + SE-50M + AHA-274X[A]T aic7770 EISA 2 X SE-50M SE-HD50F + AHA-2842 aic7770 VL SE-50M SE-HD50F + AHA-2940AU aic7860 PCI/32 SE-50M SE-HD50F + AVA-2902I aic7860 PCI/32 SE-50M + AVA-2902E aic7860 PCI/32 SE-50M + AVA-2906 aic7856 PCI/32 SE-50M SE-DB25F + APC-7850 aic7850 PCI/32 SE-50M 1 + AVA-2940 aic7860 PCI/32 SE-50M + AHA-2920B aic7860 PCI/32 SE-50M + AHA-2930B aic7860 PCI/32 SE-50M + AHA-2920C aic7856 PCI/32 SE-50M SE-HD50F + AHA-2930C aic7860 PCI/32 SE-50M + AHA-2930C aic7860 PCI/32 SE-50M + AHA-2910C aic7860 PCI/32 SE-50M + AHA-2915C aic7860 PCI/32 SE-50M + AHA-2940AU/CN aic7860 PCI/32 SE-50M SE-HD50F + AHA-2944W aic7870 PCI/32 HVD-HD68F HVD-HD68F + HVD-50M + AHA-3940W aic7870 PCI/32 2 X SE-HD68F SE-HD68F 2 + AHA-2940UW aic7880 PCI/32 SE-HD68F + SE-50M SE-HD68F + AHA-2940U aic7880 PCI/32 SE-50M SE-HD50F + AHA-2940D aic7880 PCI/32 + aHA-2940 A/T aic7880 PCI/32 + AHA-2940D A/T aic7880 PCI/32 + AHA-3940UW aic7880 PCI/32 2 X SE-HD68F SE-HD68F 3 + AHA-3940UWD aic7880 PCI/32 2 X SE-HD68F 2 X SE-VHD68F 3 + AHA-3940U aic7880 PCI/32 2 X SE-50M SE-HD50F 3 + AHA-2944UW aic7880 PCI/32 HVD-HD68F HVD-HD68F + HVD-50M + AHA-3944UWD aic7880 PCI/32 2 X HVD-HD68F 2 X HVD-VHD68F 3 + AHA-4944UW aic7880 PCI/32 + AHA-2930UW aic7880 PCI/32 + AHA-2940UW Pro aic7880 PCI/32 SE-HD68F SE-HD68F 4 + SE-50M + AHA-2940UW/CN aic7880 PCI/32 + AHA-2940UDual aic7895 PCI/32 + AHA-2940UWDual aic7895 PCI/32 + AHA-3940UWD aic7895 PCI/32 + AHA-3940AUW aic7895 PCI/32 + AHA-3940AUWD aic7895 PCI/32 + AHA-3940AU aic7895 PCI/32 + AHA-3944AUWD aic7895 PCI/32 2 X HVD-HD68F 2 X HVD-VHD68F + AHA-2940U2B aic7890 PCI/32 LVD-HD68F LVD-HD68F + AHA-2940U2 OEM aic7891 PCI/64 + AHA-2940U2W aic7890 PCI/32 LVD-HD68F LVD-HD68F + SE-HD68F + SE-50M + AHA-2950U2B aic7891 PCI/64 LVD-HD68F LVD-HD68F + AHA-2930U2 aic7890 PCI/32 LVD-HD68F SE-HD50F + SE-50M + AHA-3950U2B aic7897 PCI/64 + AHA-3950U2D aic7897 PCI/64 + AHA-29160 aic7892 PCI/64-66 + AHA-29160 CPQ aic7892 PCI/64-66 + AHA-29160N aic7892 PCI/32 LVD-HD68F SE-HD50F + SE-50M + AHA-29160LP aic7892 PCI/64-66 + AHA-19160 aic7892 PCI/64-66 + AHA-29150LP aic7892 PCI/64-66 + AHA-29130LP aic7892 PCI/64-66 + AHA-3960D aic7899 PCI/64-66 2 X LVD-HD68F 2 X LVD-VHD68F + LVD-50M + AHA-3960D CPQ aic7899 PCI/64-66 2 X LVD-HD68F 2 X LVD-VHD68F + LVD-50M + AHA-39160 aic7899 PCI/64-66 2 X LVD-HD68F 2 X LVD-VHD68F + LVD-50M + ============== ======= =========== =============== =============== ========= + + 1. No BIOS support + 2. DEC21050 PCI-PCI bridge with multiple controller chips on secondary bus + 3. DEC2115X PCI-PCI bridge with multiple controller chips on secondary bus + 4. All three SCSI connectors may be used simultaneously without + SCSI "stub" effects. + +2. Version History +================== + + * 7.0 (4th August, 2005) + - Updated driver to use SCSI transport class infrastructure + - Upported sequencer and core fixes from last adaptec released + version of the driver. + + * 6.2.36 (June 3rd, 2003) + - Correct code that disables PCI parity error checking. + - Correct and simplify handling of the ignore wide residue + message. The previous code would fail to report a residual + if the transaction data length was even and we received + an IWR message. + - Add support for the 2.5.X EISA framework. + - Update for change in 2.5.X SCSI proc FS interface. + - Correct Domain Validation command-line option parsing. + - When negotiation async via an 8bit WDTR message, send + an SDTR with an offset of 0 to be sure the target + knows we are async. This works around a firmware defect + in the Quantum Atlas 10K. + - Clear PCI error state during driver attach so that we + don't disable memory mapped I/O due to a stray write + by some other driver probe that occurred before we + claimed the controller. + + * 6.2.35 (May 14th, 2003) + - Fix a few GCC 3.3 compiler warnings. + - Correct operation on EISA Twin Channel controller. + - Add support for 2.5.X's scsi_report_device_reset(). + + * 6.2.34 (May 5th, 2003) + - Fix locking regression introduced in 6.2.29 that + could cause a lock order reversal between the io_request_lock + and our per-softc lock. This was only possible on RH9, + SuSE, and kernel.org 2.4.X kernels. + + * 6.2.33 (April 30th, 2003) + - Dynamically disable PCI parity error reporting after + 10 errors are reported to the user. These errors are + the result of some other device issuing PCI transactions + with bad parity. Once the user has been informed of the + problem, continuing to report the errors just degrades + our performance. + + * 6.2.32 (March 28th, 2003) + - Dynamically sized S/G lists to avoid SCSI malloc + pool fragmentation and SCSI mid-layer deadlock. + + * 6.2.28 (January 20th, 2003) + - Domain Validation Fixes + - Add ability to disable PCI parity error checking. + - Enhanced Memory Mapped I/O probe + + * 6.2.20 (November 7th, 2002) + - Added Domain Validation. + +3. Command Line Options +======================= + + + .. Warning:: + + ALTERING OR ADDING THESE DRIVER PARAMETERS + INCORRECTLY CAN RENDER YOUR SYSTEM INOPERABLE. + USE THEM WITH CAUTION. + + Put a .conf file in the /etc/modprobe.d directory and add/edit a + line containing ``options aic7xxx aic7xxx=[command[,command...]]`` where + ``command`` is one or more of the following: + +verbose + + :Definition: enable additional informative messages during driver operation. + :Possible Values: This option is a flag + :Default Value: disabled + + +debug:[value] + + :Definition: Enables various levels of debugging information + :Possible Values: 0x0000 = no debugging, 0xffff = full debugging + :Default Value: 0x0000 + +no_probe + +probe_eisa_vl + + :Definition: Do not probe for EISA/VLB controllers. + This is a toggle. If the driver is compiled + to not probe EISA/VLB controllers by default, + specifying "no_probe" will enable this probing. + If the driver is compiled to probe EISA/VLB + controllers by default, specifying "no_probe" + will disable this probing. + + :Possible Values: This option is a toggle + :Default Value: EISA/VLB probing is disabled by default. + +pci_parity + + :Definition: Toggles the detection of PCI parity errors. + On many motherboards with VIA chipsets, + PCI parity is not generated correctly on the + PCI bus. It is impossible for the hardware to + differentiate between these "spurious" parity + errors and real parity errors. The symptom of + this problem is a stream of the message:: + + "scsi0: Data Parity Error Detected during address or write data phase" + + output by the driver. + + :Possible Values: This option is a toggle + :Default Value: PCI Parity Error reporting is disabled + +no_reset + + :Definition: Do not reset the bus during the initial probe + phase + + :Possible Values: This option is a flag + :Default Value: disabled + +extended + + :Definition: Force extended translation on the controller + :Possible Values: This option is a flag + :Default Value: disabled + +periodic_otag + + :Definition: Send an ordered tag periodically to prevent + tag starvation. Needed for some older devices + + :Possible Values: This option is a flag + :Default Value: disabled + +reverse_scan + + :Definition: Probe the scsi bus in reverse order, starting + with target 15 + + :Possible Values: This option is a flag + :Default Value: disabled + +global_tag_depth:[value] + + :Definition: Global tag depth for all targets on all busses. + This option sets the default tag depth which + may be selectively overridden vi the tag_info + option. + + :Possible Values: 1 - 253 + :Default Value: 32 + +tag_info:{{value[,value...]}[,{value[,value...]}...]} + + :Definition: Set the per-target tagged queue depth on a + per controller basis. Both controllers and targets + may be omitted indicating that they should retain + the default tag depth. + + :Possible Values: 1 - 253 + :Default Value: 32 + + Examples: + + :: + + tag_info:{{16,32,32,64,8,8,,32,32,32,32,32,32,32,32,32} + + On Controller 0: + + - specifies a tag depth of 16 for target 0 + - specifies a tag depth of 64 for target 3 + - specifies a tag depth of 8 for targets 4 and 5 + - leaves target 6 at the default + - specifies a tag depth of 32 for targets 1,2,7-15 + - All other targets retain the default depth. + + :: + + tag_info:{{},{32,,32}} + + On Controller 1: + + - specifies a tag depth of 32 for targets 0 and 2 + - All other targets retain the default depth. + +seltime:[value] + + :Definition: Specifies the selection timeout value + :Possible Values: 0 = 256ms, 1 = 128ms, 2 = 64ms, 3 = 32ms + :Default Value: 0 + +dv: {value[,value...]} + + :Definition: Set Domain Validation Policy on a per-controller basis. + Controllers may be omitted indicating that + they should retain the default read streaming setting. + + :Possible Values: + + ==== =============================== + < 0 Use setting from serial EEPROM. + 0 Disable DV + > 0 Enable DV + ==== =============================== + + + :Default Value: SCSI-Select setting on controllers with a SCSI Select + option for DV. Otherwise, on for controllers supporting + U160 speeds and off for all other controller types. + + Example: + + :: + + dv:{-1,0,,1,1,0} + + - On Controller 0 leave DV at its default setting. + - On Controller 1 disable DV. + - Skip configuration on Controller 2. + - On Controllers 3 and 4 enable DV. + - On Controller 5 disable DV. + +Example:: + + options aic7xxx aic7xxx=verbose,no_probe,tag_info:{{},{,,10}},seltime:1 + +enables verbose logging, Disable EISA/VLB probing, +and set tag depth on Controller 1/Target 2 to 10 tags. + +4. Adaptec Customer Support +=========================== + + A Technical Support Identification (TSID) Number is required for + Adaptec technical support. + + - The 12-digit TSID can be found on the white barcode-type label + included inside the box with your product. The TSID helps us + provide more efficient service by accurately identifying your + product and support status. + + Support Options + - Search the Adaptec Support Knowledgebase (ASK) at + http://ask.adaptec.com for articles, troubleshooting tips, and + frequently asked questions about your product. + - For support via Email, submit your question to Adaptec's + Technical Support Specialists at http://ask.adaptec.com/. + + North America + - Visit our Web site at http://www.adaptec.com/. + - For information about Adaptec's support options, call + 408-957-2550, 24 hours a day, 7 days a week. + - To speak with a Technical Support Specialist, + + * For hardware products, call 408-934-7274, + Monday to Friday, 3:00 am to 5:00 pm, PDT. + * For RAID and Fibre Channel products, call 321-207-2000, + Monday to Friday, 3:00 am to 5:00 pm, PDT. + + To expedite your service, have your computer with you. + - To order Adaptec products, including accessories and cables, + call 408-957-7274. To order cables online go to + http://www.adaptec.com/buy-cables/. + + Europe + - Visit our Web site at http://www.adaptec.com/en-US/_common/world_index. + - To speak with a Technical Support Specialist, call, or email, + + * German: +49 89 4366 5522, Monday-Friday, 9:00-17:00 CET, + http://ask-de.adaptec.com/. + * French: +49 89 4366 5533, Monday-Friday, 9:00-17:00 CET, + http://ask-fr.adaptec.com/. + * English: +49 89 4366 5544, Monday-Friday, 9:00-17:00 GMT, + http://ask.adaptec.com/. + + - You can order Adaptec cables online at + http://www.adaptec.com/buy-cables/. + + Japan + - Visit our web site at http://www.adaptec.co.jp/. + - To speak with a Technical Support Specialist, call + +81 3 5308 6120, Monday-Friday, 9:00 a.m. to 12:00 p.m., + 1:00 p.m. to 6:00 p.m. + +Copyright |copy| 2003 Adaptec Inc. 691 S. Milpitas Blvd., Milpitas CA 95035 USA. + +All rights reserved. + +You are permitted to redistribute, use and modify this README file in whole +or in part in conjunction with redistribution of software governed by the +General Public License, provided that the following conditions are met: + +1. Redistributions of README file must retain the above copyright + notice, this list of conditions, and the following disclaimer, + without modification. +2. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. +3. Modifications or new contributions must be attributed in a copyright + notice identifying the author ("Contributor") and added below the + original copyright notice. The copyright notice is for purposes of + identifying contributors and should not be deemed as permission to alter + the permissions given by Adaptec. + +THIS README FILE IS PROVIDED BY ADAPTEC AND CONTRIBUTORS ``AS IS`` AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ANY +WARRANTIES OF NON-INFRINGEMENT OR THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +ADAPTEC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS README +FILE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Documentation/scsi/aic7xxx.txt b/Documentation/scsi/aic7xxx.txt deleted file mode 100644 index 7c5d0223d444..000000000000 --- a/Documentation/scsi/aic7xxx.txt +++ /dev/null @@ -1,394 +0,0 @@ -==================================================================== -= Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v7.0 = -= README for = -= The Linux Operating System = -==================================================================== - -The following information is available in this file: - - 1. Supported Hardware - 2. Version History - 3. Command Line Options - 4. Contacting Adaptec - -1. Supported Hardware - - The following Adaptec SCSI Chips and Host Adapters are supported by - the aic7xxx driver. - - Chip MIPS Host Bus MaxSync MaxWidth SCBs Notes - --------------------------------------------------------------- - aic7770 10 EISA/VL 10MHz 16Bit 4 1 - aic7850 10 PCI/32 10MHz 8Bit 3 - aic7855 10 PCI/32 10MHz 8Bit 3 - aic7856 10 PCI/32 10MHz 8Bit 3 - aic7859 10 PCI/32 20MHz 8Bit 3 - aic7860 10 PCI/32 20MHz 8Bit 3 - aic7870 10 PCI/32 10MHz 16Bit 16 - aic7880 10 PCI/32 20MHz 16Bit 16 - aic7890 20 PCI/32 40MHz 16Bit 16 3 4 5 6 7 8 - aic7891 20 PCI/64 40MHz 16Bit 16 3 4 5 6 7 8 - aic7892 20 PCI/64-66 80MHz 16Bit 16 3 4 5 6 7 8 - aic7895 15 PCI/32 20MHz 16Bit 16 2 3 4 5 - aic7895C 15 PCI/32 20MHz 16Bit 16 2 3 4 5 8 - aic7896 20 PCI/32 40MHz 16Bit 16 2 3 4 5 6 7 8 - aic7897 20 PCI/64 40MHz 16Bit 16 2 3 4 5 6 7 8 - aic7899 20 PCI/64-66 80MHz 16Bit 16 2 3 4 5 6 7 8 - - 1. Multiplexed Twin Channel Device - One controller servicing two - busses. - 2. Multi-function Twin Channel Device - Two controllers on one chip. - 3. Command Channel Secondary DMA Engine - Allows scatter gather list - and SCB prefetch. - 4. 64 Byte SCB Support - Allows disconnected, untagged request table - for all possible target/lun combinations. - 5. Block Move Instruction Support - Doubles the speed of certain - sequencer operations. - 6. `Bayonet' style Scatter Gather Engine - Improves S/G prefetch - performance. - 7. Queuing Registers - Allows queuing of new transactions without - pausing the sequencer. - 8. Multiple Target IDs - Allows the controller to respond to selection - as a target on multiple SCSI IDs. - - Controller Chip Host-Bus Int-Connectors Ext-Connectors Notes - -------------------------------------------------------------------------- - AHA-274X[A] aic7770 EISA SE-50M SE-HD50F - AHA-274X[A]W aic7770 EISA SE-HD68F SE-HD68F - SE-50M - AHA-274X[A]T aic7770 EISA 2 X SE-50M SE-HD50F - AHA-2842 aic7770 VL SE-50M SE-HD50F - AHA-2940AU aic7860 PCI/32 SE-50M SE-HD50F - AVA-2902I aic7860 PCI/32 SE-50M - AVA-2902E aic7860 PCI/32 SE-50M - AVA-2906 aic7856 PCI/32 SE-50M SE-DB25F - APC-7850 aic7850 PCI/32 SE-50M 1 - AVA-2940 aic7860 PCI/32 SE-50M - AHA-2920B aic7860 PCI/32 SE-50M - AHA-2930B aic7860 PCI/32 SE-50M - AHA-2920C aic7856 PCI/32 SE-50M SE-HD50F - AHA-2930C aic7860 PCI/32 SE-50M - AHA-2930C aic7860 PCI/32 SE-50M - AHA-2910C aic7860 PCI/32 SE-50M - AHA-2915C aic7860 PCI/32 SE-50M - AHA-2940AU/CN aic7860 PCI/32 SE-50M SE-HD50F - AHA-2944W aic7870 PCI/32 HVD-HD68F HVD-HD68F - HVD-50M - AHA-3940W aic7870 PCI/32 2 X SE-HD68F SE-HD68F 2 - AHA-2940UW aic7880 PCI/32 SE-HD68F - SE-50M SE-HD68F - AHA-2940U aic7880 PCI/32 SE-50M SE-HD50F - AHA-2940D aic7880 PCI/32 - aHA-2940 A/T aic7880 PCI/32 - AHA-2940D A/T aic7880 PCI/32 - AHA-3940UW aic7880 PCI/32 2 X SE-HD68F SE-HD68F 3 - AHA-3940UWD aic7880 PCI/32 2 X SE-HD68F 2 X SE-VHD68F 3 - AHA-3940U aic7880 PCI/32 2 X SE-50M SE-HD50F 3 - AHA-2944UW aic7880 PCI/32 HVD-HD68F HVD-HD68F - HVD-50M - AHA-3944UWD aic7880 PCI/32 2 X HVD-HD68F 2 X HVD-VHD68F 3 - AHA-4944UW aic7880 PCI/32 - AHA-2930UW aic7880 PCI/32 - AHA-2940UW Pro aic7880 PCI/32 SE-HD68F SE-HD68F 4 - SE-50M - AHA-2940UW/CN aic7880 PCI/32 - AHA-2940UDual aic7895 PCI/32 - AHA-2940UWDual aic7895 PCI/32 - AHA-3940UWD aic7895 PCI/32 - AHA-3940AUW aic7895 PCI/32 - AHA-3940AUWD aic7895 PCI/32 - AHA-3940AU aic7895 PCI/32 - AHA-3944AUWD aic7895 PCI/32 2 X HVD-HD68F 2 X HVD-VHD68F - AHA-2940U2B aic7890 PCI/32 LVD-HD68F LVD-HD68F - AHA-2940U2 OEM aic7891 PCI/64 - AHA-2940U2W aic7890 PCI/32 LVD-HD68F LVD-HD68F - SE-HD68F - SE-50M - AHA-2950U2B aic7891 PCI/64 LVD-HD68F LVD-HD68F - AHA-2930U2 aic7890 PCI/32 LVD-HD68F SE-HD50F - SE-50M - AHA-3950U2B aic7897 PCI/64 - AHA-3950U2D aic7897 PCI/64 - AHA-29160 aic7892 PCI/64-66 - AHA-29160 CPQ aic7892 PCI/64-66 - AHA-29160N aic7892 PCI/32 LVD-HD68F SE-HD50F - SE-50M - AHA-29160LP aic7892 PCI/64-66 - AHA-19160 aic7892 PCI/64-66 - AHA-29150LP aic7892 PCI/64-66 - AHA-29130LP aic7892 PCI/64-66 - AHA-3960D aic7899 PCI/64-66 2 X LVD-HD68F 2 X LVD-VHD68F - LVD-50M - AHA-3960D CPQ aic7899 PCI/64-66 2 X LVD-HD68F 2 X LVD-VHD68F - LVD-50M - AHA-39160 aic7899 PCI/64-66 2 X LVD-HD68F 2 X LVD-VHD68F - LVD-50M - - 1. No BIOS support - 2. DEC21050 PCI-PCI bridge with multiple controller chips on secondary bus - 3. DEC2115X PCI-PCI bridge with multiple controller chips on secondary bus - 4. All three SCSI connectors may be used simultaneously without - SCSI "stub" effects. - -2. Version History - 7.0 (4th August, 2005) - - Updated driver to use SCSI transport class infrastructure - - Upported sequencer and core fixes from last adaptec released - version of the driver. - 6.2.36 (June 3rd, 2003) - - Correct code that disables PCI parity error checking. - - Correct and simplify handling of the ignore wide residue - message. The previous code would fail to report a residual - if the transaction data length was even and we received - an IWR message. - - Add support for the 2.5.X EISA framework. - - Update for change in 2.5.X SCSI proc FS interface. - - Correct Domain Validation command-line option parsing. - - When negotiation async via an 8bit WDTR message, send - an SDTR with an offset of 0 to be sure the target - knows we are async. This works around a firmware defect - in the Quantum Atlas 10K. - - Clear PCI error state during driver attach so that we - don't disable memory mapped I/O due to a stray write - by some other driver probe that occurred before we - claimed the controller. - - 6.2.35 (May 14th, 2003) - - Fix a few GCC 3.3 compiler warnings. - - Correct operation on EISA Twin Channel controller. - - Add support for 2.5.X's scsi_report_device_reset(). - - 6.2.34 (May 5th, 2003) - - Fix locking regression introduced in 6.2.29 that - could cause a lock order reversal between the io_request_lock - and our per-softc lock. This was only possible on RH9, - SuSE, and kernel.org 2.4.X kernels. - - 6.2.33 (April 30th, 2003) - - Dynamically disable PCI parity error reporting after - 10 errors are reported to the user. These errors are - the result of some other device issuing PCI transactions - with bad parity. Once the user has been informed of the - problem, continuing to report the errors just degrades - our performance. - - 6.2.32 (March 28th, 2003) - - Dynamically sized S/G lists to avoid SCSI malloc - pool fragmentation and SCSI mid-layer deadlock. - - 6.2.28 (January 20th, 2003) - - Domain Validation Fixes - - Add ability to disable PCI parity error checking. - - Enhanced Memory Mapped I/O probe - - 6.2.20 (November 7th, 2002) - - Added Domain Validation. - -3. Command Line Options - - WARNING: ALTERING OR ADDING THESE DRIVER PARAMETERS - INCORRECTLY CAN RENDER YOUR SYSTEM INOPERABLE. - USE THEM WITH CAUTION. - - Put a .conf file in the /etc/modprobe.d directory and add/edit a - line containing 'options aic7xxx aic7xxx=[command[,command...]]' where - 'command' is one or more of the following: - ----------------------------------------------------------------- - Option: verbose - Definition: enable additional informative messages during - driver operation. - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: debug:[value] - Definition: Enables various levels of debugging information - Possible Values: 0x0000 = no debugging, 0xffff = full debugging - Default Value: 0x0000 - ----------------------------------------------------------------- - Option: no_probe - Option: probe_eisa_vl - Definition: Do not probe for EISA/VLB controllers. - This is a toggle. If the driver is compiled - to not probe EISA/VLB controllers by default, - specifying "no_probe" will enable this probing. - If the driver is compiled to probe EISA/VLB - controllers by default, specifying "no_probe" - will disable this probing. - Possible Values: This option is a toggle - Default Value: EISA/VLB probing is disabled by default. - ----------------------------------------------------------------- - Option: pci_parity - Definition: Toggles the detection of PCI parity errors. - On many motherboards with VIA chipsets, - PCI parity is not generated correctly on the - PCI bus. It is impossible for the hardware to - differentiate between these "spurious" parity - errors and real parity errors. The symptom of - this problem is a stream of the message: - "scsi0: Data Parity Error Detected during address or write data phase" - output by the driver. - Possible Values: This option is a toggle - Default Value: PCI Parity Error reporting is disabled - ----------------------------------------------------------------- - Option: no_reset - Definition: Do not reset the bus during the initial probe - phase - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: extended - Definition: Force extended translation on the controller - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: periodic_otag - Definition: Send an ordered tag periodically to prevent - tag starvation. Needed for some older devices - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: reverse_scan - Definition: Probe the scsi bus in reverse order, starting - with target 15 - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: global_tag_depth:[value] - Definition: Global tag depth for all targets on all busses. - This option sets the default tag depth which - may be selectively overridden vi the tag_info - option. - Possible Values: 1 - 253 - Default Value: 32 - ----------------------------------------------------------------- - Option: tag_info:{{value[,value...]}[,{value[,value...]}...]} - Definition: Set the per-target tagged queue depth on a - per controller basis. Both controllers and targets - may be omitted indicating that they should retain - the default tag depth. - Examples: tag_info:{{16,32,32,64,8,8,,32,32,32,32,32,32,32,32,32} - On Controller 0 - specifies a tag depth of 16 for target 0 - specifies a tag depth of 64 for target 3 - specifies a tag depth of 8 for targets 4 and 5 - leaves target 6 at the default - specifies a tag depth of 32 for targets 1,2,7-15 - All other targets retain the default depth. - - tag_info:{{},{32,,32}} - On Controller 1 - specifies a tag depth of 32 for targets 0 and 2 - All other targets retain the default depth. - - Possible Values: 1 - 253 - Default Value: 32 - ----------------------------------------------------------------- - Option: seltime:[value] - Definition: Specifies the selection timeout value - Possible Values: 0 = 256ms, 1 = 128ms, 2 = 64ms, 3 = 32ms - Default Value: 0 - ----------------------------------------------------------------- - Option: dv: {value[,value...]} - Definition: Set Domain Validation Policy on a per-controller basis. - Controllers may be omitted indicating that - they should retain the default read streaming setting. - Example: dv:{-1,0,,1,1,0} - On Controller 0 leave DV at its default setting. - On Controller 1 disable DV. - Skip configuration on Controller 2. - On Controllers 3 and 4 enable DV. - On Controller 5 disable DV. - - Possible Values: < 0 Use setting from serial EEPROM. - 0 Disable DV - > 0 Enable DV - - Default Value: SCSI-Select setting on controllers with a SCSI Select - option for DV. Otherwise, on for controllers supporting - U160 speeds and off for all other controller types. - ----------------------------------------------------------------- - - Example: - 'options aic7xxx aic7xxx=verbose,no_probe,tag_info:{{},{,,10}},seltime:1' - enables verbose logging, Disable EISA/VLB probing, - and set tag depth on Controller 1/Target 2 to 10 tags. - -4. Adaptec Customer Support - - A Technical Support Identification (TSID) Number is required for - Adaptec technical support. - - The 12-digit TSID can be found on the white barcode-type label - included inside the box with your product. The TSID helps us - provide more efficient service by accurately identifying your - product and support status. - - Support Options - - Search the Adaptec Support Knowledgebase (ASK) at - http://ask.adaptec.com for articles, troubleshooting tips, and - frequently asked questions about your product. - - For support via Email, submit your question to Adaptec's - Technical Support Specialists at http://ask.adaptec.com/. - - North America - - Visit our Web site at http://www.adaptec.com/. - - For information about Adaptec's support options, call - 408-957-2550, 24 hours a day, 7 days a week. - - To speak with a Technical Support Specialist, - * For hardware products, call 408-934-7274, - Monday to Friday, 3:00 am to 5:00 pm, PDT. - * For RAID and Fibre Channel products, call 321-207-2000, - Monday to Friday, 3:00 am to 5:00 pm, PDT. - To expedite your service, have your computer with you. - - To order Adaptec products, including accessories and cables, - call 408-957-7274. To order cables online go to - http://www.adaptec.com/buy-cables/. - - Europe - - Visit our Web site at http://www.adaptec.com/en-US/_common/world_index. - - To speak with a Technical Support Specialist, call, or email, - * German: +49 89 4366 5522, Monday-Friday, 9:00-17:00 CET, - http://ask-de.adaptec.com/. - * French: +49 89 4366 5533, Monday-Friday, 9:00-17:00 CET, - http://ask-fr.adaptec.com/. - * English: +49 89 4366 5544, Monday-Friday, 9:00-17:00 GMT, - http://ask.adaptec.com/. - - You can order Adaptec cables online at - http://www.adaptec.com/buy-cables/. - - Japan - - Visit our web site at http://www.adaptec.co.jp/. - - To speak with a Technical Support Specialist, call - +81 3 5308 6120, Monday-Friday, 9:00 a.m. to 12:00 p.m., - 1:00 p.m. to 6:00 p.m. - -------------------------------------------------------------------- -/* - * Copyright (c) 2003 Adaptec Inc. 691 S. Milpitas Blvd., Milpitas CA 95035 USA. - * All rights reserved. - * - * You are permitted to redistribute, use and modify this README file in whole - * or in part in conjunction with redistribution of software governed by the - * General Public License, provided that the following conditions are met: - * 1. Redistributions of README file must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * 3. Modifications or new contributions must be attributed in a copyright - * notice identifying the author ("Contributor") and added below the - * original copyright notice. The copyright notice is for purposes of - * identifying contributors and should not be deemed as permission to alter - * the permissions given by Adaptec. - * - * THIS README FILE IS PROVIDED BY ADAPTEC AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ANY - * WARRANTIES OF NON-INFRINGEMENT OR THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * ADAPTEC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS README - * FILE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index b7fdfc0cb956..c0b66763515f 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -12,5 +12,6 @@ Linux SCSI Subsystem advansys aha152x aic79xx + aic7xxx scsi_transport_srp/figures diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt index 8ed9c662a1d4..266fd3b2398a 100644 --- a/Documentation/scsi/scsi-parameters.txt +++ b/Documentation/scsi/scsi-parameters.txt @@ -22,7 +22,7 @@ parameters may be changed at runtime by the command Format: [,,[,]] aic7xxx= [HW,SCSI] - See Documentation/scsi/aic7xxx.txt. + See Documentation/scsi/aic7xxx.rst. aic79xx= [HW,SCSI] See Documentation/scsi/aic79xx.rst. diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx index 3546b8cc401f..9d027549d698 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx +++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx @@ -37,7 +37,7 @@ config AIC7XXX_CMDS_PER_DEVICE on some devices. The upper bound is 253. 0 disables tagged queueing. Per device tag depth can be controlled via the kernel command line - "tag_info" option. See Documentation/scsi/aic7xxx.txt for details. + "tag_info" option. See Documentation/scsi/aic7xxx.rst for details. config AIC7XXX_RESET_DELAY_MS int "Initial bus reset delay in milli-seconds" From 6e5a663d8e5c6a39ba0a98058ee94796e835fb98 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:42 +0100 Subject: [PATCH 1589/4444] scsi: docs: convert bfa.txt to ReST Link: https://lore.kernel.org/r/6660d0f83ddae2ab8efb31c39f9c220fc132e9d4.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/{bfa.txt => bfa.rst} | 28 +++++++++++++++++-------- Documentation/scsi/index.rst | 1 + 2 files changed, 20 insertions(+), 9 deletions(-) rename Documentation/scsi/{bfa.txt => bfa.rst} (72%) diff --git a/Documentation/scsi/bfa.txt b/Documentation/scsi/bfa.rst similarity index 72% rename from Documentation/scsi/bfa.txt rename to Documentation/scsi/bfa.rst index 3cc4d80d6092..3abc0411857d 100644 --- a/Documentation/scsi/bfa.txt +++ b/Documentation/scsi/bfa.rst @@ -1,5 +1,8 @@ -Linux driver for Brocade FC/FCOE adapters +.. SPDX-License-Identifier: GPL-2.0 +========================================= +Linux driver for Brocade FC/FCOE adapters +========================================= Supported Hardware ------------------ @@ -7,8 +10,9 @@ Supported Hardware bfa 3.0.2.2 driver supports all Brocade FC/FCOE adapters. Below is a list of adapter models with corresponding PCIIDs. - PCIID Model - + =================== =========================================== + PCIID Model + =================== =========================================== 1657:0013:1657:0014 425 4Gbps dual port FC HBA 1657:0013:1657:0014 825 8Gbps PCIe dual port FC HBA 1657:0013:103c:1742 HP 82B 8Gbps PCIedual port FC HBA @@ -26,6 +30,7 @@ adapter models with corresponding PCIIDs. 1657:0022:1657:0024 1860 16Gbps FC HBA 1657:0022:1657:0022 1860 10Gbps CNA - FCOE + =================== =========================================== Firmware download @@ -37,9 +42,11 @@ http://www.brocade.com/services-support/drivers-downloads/adapters/Linux.page and then click following respective util package link: - Version Link - + ========= ======================================================= + Version Link + ========= ======================================================= v3.0.0.0 Linux Adapter Firmware package for RHEL 6.2, SLES 11SP2 + ========= ======================================================= Configuration & Management utility download @@ -52,9 +59,11 @@ http://www.brocade.com/services-support/drivers-downloads/adapters/Linux.page and then click following respective util package link - Version Link - + ========= ======================================================= + Version Link + ========= ======================================================= v3.0.2.0 Linux Adapter Firmware package for RHEL 6.2, SLES 11SP2 + ========= ======================================================= Documentation @@ -69,10 +78,11 @@ http://www.brocade.com/services-support/drivers-downloads/adapters/Linux.page and use the following inbox and out-of-box driver version mapping to find the corresponding documentation: + ============= ================== Inbox Version Out-of-box Version - + ============= ================== v3.0.2.2 v3.0.0.0 - + ============= ================== Support ------- diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index c0b66763515f..1e37227f3536 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -13,5 +13,6 @@ Linux SCSI Subsystem aha152x aic79xx aic7xxx + bfa scsi_transport_srp/figures From 1d4f8dfe2d976d49e6d9065643f106b1750f3445 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:43 +0100 Subject: [PATCH 1590/4444] scsi: docs: convert bnx2fc.txt to ReST Link: https://lore.kernel.org/r/f239116bd2c36f6fc8deb62e325bb8161da04270.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/{bnx2fc.txt => bnx2fc.rst} | 18 ++++++++++++------ Documentation/scsi/index.rst | 1 + 2 files changed, 13 insertions(+), 6 deletions(-) rename Documentation/scsi/{bnx2fc.txt => bnx2fc.rst} (91%) diff --git a/Documentation/scsi/bnx2fc.txt b/Documentation/scsi/bnx2fc.rst similarity index 91% rename from Documentation/scsi/bnx2fc.txt rename to Documentation/scsi/bnx2fc.rst index 80823556d62f..2fef2dff80c7 100644 --- a/Documentation/scsi/bnx2fc.txt +++ b/Documentation/scsi/bnx2fc.rst @@ -1,3 +1,6 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=========================== Operating FCoE using bnx2fc =========================== Broadcom FCoE offload through bnx2fc is full stateful hardware offload that @@ -24,6 +27,7 @@ Driver Usage Model: 2. Configure the interfaces on which bnx2fc driver has to operate on. Here are the steps to configure: + a. cd /etc/fcoe b. copy cfg-ethx to cfg-eth5 if FCoE has to be enabled on eth5. c. Repeat this for all the interfaces where FCoE has to be enabled. @@ -39,8 +43,10 @@ discovery and log into the targets. 5. "Symbolic Name" in 'fcoeadm -i' output would display if bnx2fc has claimed the interface. -Eg: -[root@bh2 ~]# fcoeadm -i + +Eg:: + + [root@bh2 ~]# fcoeadm -i Description: NetXtreme II BCM57712 10 Gigabit Ethernet Revision: 01 Manufacturer: Broadcom Corporation @@ -60,16 +66,16 @@ Eg: State: Online 6. Verify the vlan discovery is performed by running ifconfig and notice -.-fcoe interfaces are automatically created. + .-fcoe interfaces are automatically created. Refer to fcoeadm manpage for more information on fcoeadm operations to create/destroy interfaces or to display lun/target information. -NOTE: +NOTE ==== ** Broadcom FCoE capable devices implement a DCBX/LLDP client on-chip. Only one LLDP client is allowed per interface. For proper operation all host software based DCBX/LLDP clients (e.g. lldpad) must be disabled. To disable lldpad on a -given interface, run the following command: +given interface, run the following command:: -lldptool set-lldp -i adminStatus=disabled + lldptool set-lldp -i adminStatus=disabled diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index 1e37227f3536..d453fb3f1f7d 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -14,5 +14,6 @@ Linux SCSI Subsystem aic79xx aic7xxx bfa + bnx2fc scsi_transport_srp/figures From 977b899ce3cc4c5ca6776f1a62d7817f49c7581f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:44 +0100 Subject: [PATCH 1591/4444] scsi: docs: convert BusLogic.txt to ReST Link: https://lore.kernel.org/r/750629b6a5233c85c5391c44d126606b8aabefc8.1583136624.git.mchehab+huawei@kernel.org Acked-by: Khalid Aziz Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- .../scsi/{BusLogic.txt => BusLogic.rst} | 89 +++++++++++++------ Documentation/scsi/index.rst | 1 + drivers/scsi/BusLogic.c | 2 +- drivers/scsi/Kconfig | 2 +- 4 files changed, 67 insertions(+), 27 deletions(-) rename Documentation/scsi/{BusLogic.txt => BusLogic.rst} (93%) diff --git a/Documentation/scsi/BusLogic.txt b/Documentation/scsi/BusLogic.rst similarity index 93% rename from Documentation/scsi/BusLogic.txt rename to Documentation/scsi/BusLogic.rst index 48e982cd6fe7..b60169812358 100644 --- a/Documentation/scsi/BusLogic.txt +++ b/Documentation/scsi/BusLogic.rst @@ -1,6 +1,11 @@ - BusLogic MultiMaster and FlashPoint SCSI Driver for Linux +.. SPDX-License-Identifier: GPL-2.0 + +========================================================= +BusLogic MultiMaster and FlashPoint SCSI Driver for Linux +========================================================= Version 2.0.15 for Linux 2.0 + Version 2.1.15 for Linux 2.1 PRODUCTION RELEASE @@ -8,13 +13,16 @@ 17 August 1998 Leonard N. Zubkoff + Dandelion Digital + lnz@dandelion.com Copyright 1995-1998 by Leonard N. Zubkoff - INTRODUCTION +Introduction +============ BusLogic, Inc. designed and manufactured a variety of high performance SCSI host adapters which share a common programming interface across a diverse @@ -86,9 +94,11 @@ Contact information for offices in Europe and Japan is available on the Web site. - DRIVER FEATURES +Driver Features +=============== -o Configuration Reporting and Testing +Configuration Reporting and Testing +----------------------------------- During system initialization, the driver reports extensively on the host adapter hardware configuration, including the synchronous transfer parameters @@ -130,7 +140,8 @@ o Configuration Reporting and Testing The status of Wide Negotiation, Disconnect/Reconnect, and Tagged Queuing are reported as "Enabled", Disabled", or a sequence of "Y" and "N" letters. -o Performance Features +Performance Features +-------------------- BusLogic SCSI Host Adapters directly implement SCSI-2 Tagged Queuing, and so support has been included in the driver to utilize tagged queuing with any @@ -150,7 +161,8 @@ o Performance Features queue depth of 1 is selected. Tagged queuing is also disabled for individual target devices if disconnect/reconnect is disabled for that device. -o Robustness Features +Robustness Features +------------------- The driver implements extensive error recovery procedures. When the higher level parts of the SCSI subsystem request that a timed out command be reset, @@ -174,7 +186,8 @@ o Robustness Features lock up or crash, and thereby allowing a clean shutdown and restart after the offending component is removed. -o PCI Configuration Support +PCI Configuration Support +------------------------- On PCI systems running kernels compiled with PCI BIOS support enabled, this driver will interrogate the PCI configuration space and use the I/O port @@ -184,19 +197,22 @@ o PCI Configuration Support used to disable the ISA compatible I/O port entirely as it is not necessary. The ISA compatible I/O port is disabled by default on the BT-948/958/958D. -o /proc File System Support +/proc File System Support +------------------------- Copies of the host adapter configuration information together with updated data transfer and error recovery statistics are available through the /proc/scsi/BusLogic/ interface. -o Shared Interrupts Support +Shared Interrupts Support +------------------------- On systems that support shared interrupts, any number of BusLogic Host Adapters may share the same interrupt request channel. - SUPPORTED HOST ADAPTERS +Supported Host Adapters +======================= The following list comprises the supported BusLogic SCSI Host Adapters as of the date of this document. It is recommended that anyone purchasing a BusLogic @@ -205,6 +221,7 @@ that it is or will be supported. FlashPoint Series PCI Host Adapters: +======================= ============================================= FlashPoint LT (BT-930) Ultra SCSI-3 FlashPoint LT (BT-930R) Ultra SCSI-3 with RAIDPlus FlashPoint LT (BT-920) Ultra SCSI-3 (BT-930 without BIOS) @@ -214,15 +231,19 @@ FlashPoint LW (BT-950) Wide Ultra SCSI-3 FlashPoint LW (BT-950R) Wide Ultra SCSI-3 with RAIDPlus FlashPoint DW (BT-952) Dual Channel Wide Ultra SCSI-3 FlashPoint DW (BT-952R) Dual Channel Wide Ultra SCSI-3 with RAIDPlus +======================= ============================================= MultiMaster "W" Series Host Adapters: +======= === ============================== BT-948 PCI Ultra SCSI-3 BT-958 PCI Wide Ultra SCSI-3 BT-958D PCI Wide Differential Ultra SCSI-3 +======= === ============================== MultiMaster "C" Series Host Adapters: +======== ==== ============================== BT-946C PCI Fast SCSI-2 BT-956C PCI Wide Fast SCSI-2 BT-956CD PCI Wide Differential Fast SCSI-2 @@ -232,9 +253,11 @@ BT-757C EISA Wide Fast SCSI-2 BT-757CD EISA Wide Differential Fast SCSI-2 BT-545C ISA Fast SCSI-2 BT-540CF ISA Fast SCSI-2 +======== ==== ============================== MultiMaster "S" Series Host Adapters: +======= ==== ============================== BT-445S VLB Fast SCSI-2 BT-747S EISA Fast SCSI-2 BT-747D EISA Differential Fast SCSI-2 @@ -244,11 +267,14 @@ BT-545S ISA Fast SCSI-2 BT-542D ISA Differential Fast SCSI-2 BT-742A EISA SCSI-2 (742A revision H) BT-542B ISA SCSI-2 (542B revision H) +======= ==== ============================== MultiMaster "A" Series Host Adapters: +======= ==== ============================== BT-742A EISA SCSI-2 (742A revisions A - G) BT-542B ISA SCSI-2 (542B revisions A - G) +======= ==== ============================== AMI FastDisk Host Adapters that are true BusLogic MultiMaster clones are also supported by this driver. @@ -260,9 +286,11 @@ list. The retail kit includes the bare board and manual as well as cabling and driver media and documentation that are not provided with bare boards. - FLASHPOINT INSTALLATION NOTES +FlashPoint Installation Notes +============================= -o RAIDPlus Support +RAIDPlus Support +---------------- FlashPoint Host Adapters now include RAIDPlus, Mylex's bootable software RAID. RAIDPlus is not supported on Linux, and there are no plans to support @@ -273,7 +301,8 @@ o RAIDPlus Support than RAIDPlus, so there is little impetus to include RAIDPlus support in the BusLogic driver. -o Enabling UltraSCSI Transfers +Enabling UltraSCSI Transfers +---------------------------- FlashPoint Host Adapters ship with their configuration set to "Factory Default" settings that are conservative and do not allow for UltraSCSI speed @@ -287,12 +316,14 @@ o Enabling UltraSCSI Transfers the "Optimum Performance" settings are loaded. - BT-948/958/958D INSTALLATION NOTES +BT-948/958/958D Installation Notes +================================== The BT-948/958/958D PCI Ultra SCSI Host Adapters have some features which may require attention in some circumstances when installing Linux. -o PCI I/O Port Assignments +PCI I/O Port Assignments +------------------------ When configured to factory default settings, the BT-948/958/958D will only recognize the PCI I/O port assignments made by the motherboard's PCI BIOS. @@ -312,7 +343,8 @@ o PCI I/O Port Assignments possible future I/O port conflicts. The older BT-946C/956C/956CD also have this configuration option, but the factory default setting is "Primary". -o PCI Slot Scanning Order +PCI Slot Scanning Order +----------------------- In systems with multiple BusLogic PCI Host Adapters, the order in which the PCI slots are scanned may appear reversed with the BT-948/958/958D as @@ -339,7 +371,8 @@ o PCI Slot Scanning Order so as to recognize the host adapters in the same order as they are enumerated by the host adapter's BIOS. -o Enabling UltraSCSI Transfers +Enabling UltraSCSI Transfers +---------------------------- The BT-948/958/958D ship with their configuration set to "Factory Default" settings that are conservative and do not allow for UltraSCSI speed to be @@ -353,7 +386,8 @@ o Enabling UltraSCSI Transfers "Optimum Performance" settings are loaded. - DRIVER OPTIONS +Driver Options +============== BusLogic Driver Options may be specified either via the Linux Kernel Command Line or via the Loadable Kernel Module Installation Facility. Driver Options @@ -520,30 +554,34 @@ The following examples demonstrate setting the Queue Depth for Target Devices Devices on the second host adapter to 31, and the Bus Settle Time on the second host adapter to 30 seconds. -Linux Kernel Command Line: +Linux Kernel Command Line:: linux BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30 -LILO Linux Boot Loader (in /etc/lilo.conf): +LILO Linux Boot Loader (in /etc/lilo.conf):: append = "BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30" -INSMOD Loadable Kernel Module Installation Facility: +INSMOD Loadable Kernel Module Installation Facility:: insmod BusLogic.o \ 'BusLogic="QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"' -NOTE: Module Utilities 2.1.71 or later is required for correct parsing + +.. Note:: + + Module Utilities 2.1.71 or later is required for correct parsing of driver options containing commas. - DRIVER INSTALLATION +Driver Installation +=================== This distribution was prepared for Linux kernel version 2.0.35, but should be compatible with 2.0.4 or any later 2.0 series kernel. To install the new BusLogic SCSI driver, you may use the following commands, -replacing "/usr/src" with wherever you keep your Linux kernel source tree: +replacing "/usr/src" with wherever you keep your Linux kernel source tree:: cd /usr/src tar -xvzf BusLogic-2.0.15.tar.gz @@ -557,7 +595,8 @@ Then install "arch/x86/boot/zImage" as your standard kernel, run lilo if appropriate, and reboot. - BUSLOGIC ANNOUNCEMENTS MAILING LIST +BusLogic Announcements Mailing List +=================================== The BusLogic Announcements Mailing List provides a forum for informing Linux users of new driver releases and other announcements regarding Linux support diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index d453fb3f1f7d..6bb2428c1d56 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -15,5 +15,6 @@ Linux SCSI Subsystem aic7xxx bfa bnx2fc + BusLogic scsi_transport_srp/figures diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 3170b295a5da..9b8be4f0da19 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -3652,7 +3652,7 @@ static bool __init blogic_parse(char **str, char *keyword) selected host adapter. The BusLogic Driver Probing Options are described in - . + . */ static int __init blogic_parseopts(char *options) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 18af62594bc0..5ec7330f82b6 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -502,7 +502,7 @@ config SCSI_BUSLOGIC This is support for BusLogic MultiMaster and FlashPoint SCSI Host Adapters. Consult the SCSI-HOWTO, available from , and the files - and + and for more information. Note that support for FlashPoint is only available for 32-bit x86 configurations. From d2ba7ca33840a1e58368594c552fa1fa11b15152 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:45 +0100 Subject: [PATCH 1592/4444] scsi: docs: convert cxgb3i.txt to ReST Link: https://lore.kernel.org/r/0708b62b6ec4f0dddc581e412bb02ba6476f4523.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/{cxgb3i.txt => cxgb3i.rst} | 22 ++++++++++++------- Documentation/scsi/index.rst | 1 + 2 files changed, 15 insertions(+), 8 deletions(-) rename Documentation/scsi/{cxgb3i.txt => cxgb3i.rst} (86%) diff --git a/Documentation/scsi/cxgb3i.txt b/Documentation/scsi/cxgb3i.rst similarity index 86% rename from Documentation/scsi/cxgb3i.txt rename to Documentation/scsi/cxgb3i.rst index 7ac8032ee9b2..e01f18fbfa9f 100644 --- a/Documentation/scsi/cxgb3i.txt +++ b/Documentation/scsi/cxgb3i.rst @@ -1,4 +1,8 @@ +.. SPDX-License-Identifier: GPL-2.0 + +================================= Chelsio S3 iSCSI Driver for Linux +================================= Introduction ============ @@ -49,7 +53,8 @@ The following steps need to be taken to accelerates the open-iscsi initiator: The cxgb3i module registers a new transport class "cxgb3i" with open-iscsi. - * in the case of recompiling the kernel, the cxgb3i selection is located at + * in the case of recompiling the kernel, the cxgb3i selection is located at:: + Device Drivers SCSI device support ---> [*] SCSI low-level drivers ---> @@ -58,25 +63,26 @@ The following steps need to be taken to accelerates the open-iscsi initiator: 2. Create an interface file located under /etc/iscsi/ifaces/ for the new transport class "cxgb3i". - The content of the file should be in the following format: + The content of the file should be in the following format:: + iface.transport_name = cxgb3i iface.net_ifacename = iface.ipaddress = * if iface.ipaddress is specified, needs to be either the - same as the ethX's ip address or an address on the same subnet. Make - sure the ip address is unique in the network. + same as the ethX's ip address or an address on the same subnet. Make + sure the ip address is unique in the network. 3. edit /etc/iscsi/iscsid.conf The default setting for MaxRecvDataSegmentLength (131072) is too big; - replace with a value no bigger than 15360 (for example 8192): + replace with a value no bigger than 15360 (for example 8192):: node.conn[0].iscsi.MaxRecvDataSegmentLength = 8192 * The login would fail for a normal session if MaxRecvDataSegmentLength is - too big. A error message in the format of - "cxgb3i: ERR! MaxRecvSegmentLength too big. Need to be <= ." - would be logged to dmesg. + too big. A error message in the format of + "cxgb3i: ERR! MaxRecvSegmentLength too big. Need to be <= ." + would be logged to dmesg. 4. To direct open-iscsi traffic to go through cxgb3i's accelerated path, "-I " option needs to be specified with most of the diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index 6bb2428c1d56..3809213b83da 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -16,5 +16,6 @@ Linux SCSI Subsystem bfa bnx2fc BusLogic + cxgb3i scsi_transport_srp/figures From 62e3bfa4a1869cf8f221dce8ab90790e836e2b61 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:46 +0100 Subject: [PATCH 1593/4444] scsi: docs: convert dc395x.txt to ReST Link: https://lore.kernel.org/r/3c0876df0045695185f922a0404c497a69de36a9.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/{dc395x.txt => dc395x.rst} | 77 +++++++++++-------- Documentation/scsi/index.rst | 1 + MAINTAINERS | 2 +- drivers/scsi/Kconfig | 2 +- 4 files changed, 49 insertions(+), 33 deletions(-) rename Documentation/scsi/{dc395x.txt => dc395x.rst} (64%) diff --git a/Documentation/scsi/dc395x.txt b/Documentation/scsi/dc395x.rst similarity index 64% rename from Documentation/scsi/dc395x.txt rename to Documentation/scsi/dc395x.rst index 88219f96633d..d779e782b1cb 100644 --- a/Documentation/scsi/dc395x.txt +++ b/Documentation/scsi/dc395x.rst @@ -1,5 +1,8 @@ +.. SPDX-License-Identifier: GPL-2.0 + +====================================== README file for the dc395x SCSI driver -========================================== +====================================== Status ------ @@ -18,14 +21,14 @@ http://lists.twibble.org/mailman/listinfo/dc395x/ Parameters ---------- -The driver uses the settings from the EEPROM set in the SCSI BIOS +The driver uses the settings from the EEPROM set in the SCSI BIOS setup. If there is no EEPROM, the driver uses default values. Both can be overridden by command line parameters (module or kernel parameters). The following parameters are available: - - safe +safe Default: 0, Acceptable values: 0 or 1 If safe is set to 1 then the adapter will use conservative @@ -33,52 +36,63 @@ The following parameters are available: shortcut for dc395x=7,4,9,15,2,10 - - adapter_id +adapter_id Default: 7, Acceptable values: 0 to 15 Sets the host adapter SCSI ID. - - max_speed +max_speed Default: 1, Acceptable value: 0 to 7 - 0 = 20 Mhz - 1 = 12.2 Mhz - 2 = 10 Mhz - 3 = 8 Mhz - 4 = 6.7 Mhz - 5 = 5.8 Hhz - 6 = 5 Mhz - 7 = 4 Mhz - - dev_mode + == ======== + 0 20 Mhz + 1 12.2 Mhz + 2 10 Mhz + 3 8 Mhz + 4 6.7 Mhz + 5 5.8 Hhz + 6 5 Mhz + 7 4 Mhz + == ======== + +dev_mode Bitmap for device configuration DevMode bit definition: - Bit Val(hex) Val(dec) Meaning - *0 0x01 1 Parity check - *1 0x02 2 Synchronous Negotiation - *2 0x04 4 Disconnection - *3 0x08 8 Send Start command on startup. (Not used) - *4 0x10 16 Tagged Command Queueing - *5 0x20 32 Wide Negotiation - - adapter_mode + === ======== ======== ========================================= + Bit Val(hex) Val(dec) Meaning + === ======== ======== ========================================= + 0 0x01 1 Parity check + 1 0x02 2 Synchronous Negotiation + 2 0x04 4 Disconnection + 3 0x08 8 Send Start command on startup. (Not used) + 4 0x10 16 Tagged Command Queueing + 5 0x20 32 Wide Negotiation + === ======== ======== ========================================= + +adapter_mode Bitmap for adapter configuration AdaptMode bit definition + + ===== ======== ======== ==================================================== Bit Val(hex) Val(dec) Meaning - *0 0x01 1 Support more than two drives. (Not used) - *1 0x02 2 Use DOS compatible mapping for HDs greater than 1GB. - *2 0x04 4 Reset SCSI Bus on startup. - *3 0x08 8 Active Negation: Improves SCSI Bus noise immunity. + ===== ======== ======== ==================================================== + 0 0x01 1 Support more than two drives. (Not used) + 1 0x02 2 Use DOS compatible mapping for HDs greater than 1GB. + 2 0x04 4 Reset SCSI Bus on startup. + 3 0x08 8 Active Negation: Improves SCSI Bus noise immunity. 4 0x10 16 Immediate return on BIOS seek command. (Not used) (*)5 0x20 32 Check for LUNs >= 1. + ===== ======== ======== ==================================================== - - tags +tags Default: 3, Acceptable values: 0-5 - + The number of tags is 1<. + Documentation can be found in . To compile this driver as a module, choose M here: the module will be called dc395x. From f22978400e3ea6c35a1050a83a9a11f2c1dc8cb7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:47 +0100 Subject: [PATCH 1594/4444] scsi: docs: convert dpti.txt to ReST Link: https://lore.kernel.org/r/212fd7961c134c5bd73d87cd818bcddc30270804.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/dpti.rst | 92 +++++++++++++++++++++++++++++++++++ Documentation/scsi/dpti.txt | 83 ------------------------------- Documentation/scsi/index.rst | 1 + drivers/scsi/Kconfig | 2 +- drivers/scsi/dpt/dpti_ioctl.h | 2 +- drivers/scsi/dpt_i2o.c | 2 +- drivers/scsi/dpti.h | 2 +- 7 files changed, 97 insertions(+), 87 deletions(-) create mode 100644 Documentation/scsi/dpti.rst delete mode 100644 Documentation/scsi/dpti.txt diff --git a/Documentation/scsi/dpti.rst b/Documentation/scsi/dpti.rst new file mode 100644 index 000000000000..0496919d87d3 --- /dev/null +++ b/Documentation/scsi/dpti.rst @@ -0,0 +1,92 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=================== +Adaptec dpti driver +=================== + +Redistribution and use in source form, with or without modification, are +permitted provided that redistributions of source code must retain the +above copyright notice, this list of conditions and the following disclaimer. + +This software is provided ``as is`` by Adaptec and +any express or implied warranties, including, but not limited to, the +implied warranties of merchantability and fitness for a particular purpose, +are disclaimed. In no event shall Adaptec be +liable for any direct, indirect, incidental, special, exemplary or +consequential damages (including, but not limited to, procurement of +substitute goods or services; loss of use, data, or profits; or business +interruptions) however caused and on any theory of liability, whether in +contract, strict liability, or tort (including negligence or otherwise) +arising in any way out of the use of this driver software, even if advised +of the possibility of such damage. + +This driver supports the Adaptec I2O RAID and DPT SmartRAID V I2O boards. + +Credits +======= + +The original linux driver was ported to Linux by Karen White while at +Dell Computer. It was ported from Bob Pasteur's (of DPT) original +non-Linux driver. Mark Salyzyn and Bob Pasteur consulted on the original +driver. + +2.0 version of the driver by Deanna Bonds and Mark Salyzyn. + +History +======= + +The driver was originally ported to linux version 2.0.34 + +==== ========================================================================== +V2.0 Rewrite of driver. Re-architectured based on i2o subsystem. + This was the first full GPL version since the last version used + i2osig headers which were not GPL. Developer Testing version. +V2.1 Internal testing +V2.2 First released version + +V2.3 Changes: + + - Added Raptor Support + - Fixed bug causing system to hang under extreme load with + - management utilities running (removed GFP_DMA from kmalloc flags) + +V2.4 First version ready to be submitted to be embedded in the kernel + + Changes: + + - Implemented suggestions from Alan Cox + - Added calculation of resid for sg layer + - Better error handling + - Added checking underflow conditions + - Added DATAPROTECT checking + - Changed error return codes + - Fixed pointer bug in bus reset routine + - Enabled hba reset from ioctls (allows a FW flash to reboot and use + the new FW without having to reboot) + - Changed proc output +==== ========================================================================== + +TODO +==== +- Add 64 bit Scatter Gather when compiled on 64 bit architectures +- Add sparse lun scanning +- Add code that checks if a device that had been taken offline is + now online (at the FW level) when test unit ready or inquiry + command from scsi-core +- Add proc read interface +- busrescan command +- rescan command +- Add code to rescan routine that notifies scsi-core about new devices +- Add support for C-PCI (hotplug stuff) +- Add ioctl passthru error recovery + +Notes +===== +The DPT card optimizes the order of processing commands. Consequently, +a command may take up to 6 minutes to complete after it has been sent +to the board. + +The files dpti_ioctl.h dptsig.h osd_defs.h osd_util.h sys_info.h are part of the +interface files for Adaptec's management routines. These define the structures used +in the ioctls. They are written to be portable. They are hard to read, but I need +to use them 'as is' or I can miss changes in the interface. diff --git a/Documentation/scsi/dpti.txt b/Documentation/scsi/dpti.txt deleted file mode 100644 index f36dc0e7c8da..000000000000 --- a/Documentation/scsi/dpti.txt +++ /dev/null @@ -1,83 +0,0 @@ - /* TERMS AND CONDITIONS OF USE - * - * Redistribution and use in source form, with or without modification, are - * permitted provided that redistributions of source code must retain the - * above copyright notice, this list of conditions and the following disclaimer. - * - * This software is provided `as is' by Adaptec and - * any express or implied warranties, including, but not limited to, the - * implied warranties of merchantability and fitness for a particular purpose, - * are disclaimed. In no event shall Adaptec be - * liable for any direct, indirect, incidental, special, exemplary or - * consequential damages (including, but not limited to, procurement of - * substitute goods or services; loss of use, data, or profits; or business - * interruptions) however caused and on any theory of liability, whether in - * contract, strict liability, or tort (including negligence or otherwise) - * arising in any way out of the use of this driver software, even if advised - * of the possibility of such damage. - * - **************************************************************** - * This driver supports the Adaptec I2O RAID and DPT SmartRAID V I2O boards. - * - * CREDITS: - * The original linux driver was ported to Linux by Karen White while at - * Dell Computer. It was ported from Bob Pasteur's (of DPT) original - * non-Linux driver. Mark Salyzyn and Bob Pasteur consulted on the original - * driver. - * - * 2.0 version of the driver by Deanna Bonds and Mark Salyzyn. - * - * HISTORY: - * The driver was originally ported to linux version 2.0.34 - * - * V2.0 Rewrite of driver. Re-architectured based on i2o subsystem. - * This was the first full GPL version since the last version used - * i2osig headers which were not GPL. Developer Testing version. - * V2.1 Internal testing - * V2.2 First released version - * - * V2.3 - * Changes: - * Added Raptor Support - * Fixed bug causing system to hang under extreme load with - * management utilities running (removed GFP_DMA from kmalloc flags) - * - * - * V2.4 First version ready to be submitted to be embedded in the kernel - * Changes: - * Implemented suggestions from Alan Cox - * Added calculation of resid for sg layer - * Better error handling - * Added checking underflow conditions - * Added DATAPROTECT checking - * Changed error return codes - * Fixed pointer bug in bus reset routine - * Enabled hba reset from ioctls (allows a FW flash to reboot and use the new - * FW without having to reboot) - * Changed proc output - * - * TODO: - * Add 64 bit Scatter Gather when compiled on 64 bit architectures - * Add sparse lun scanning - * Add code that checks if a device that had been taken offline is - * now online (at the FW level) when test unit ready or inquiry - * command from scsi-core - * Add proc read interface - * busrescan command - * rescan command - * Add code to rescan routine that notifies scsi-core about new devices - * Add support for C-PCI (hotplug stuff) - * Add ioctl passthru error recovery - * - * NOTES: - * The DPT card optimizes the order of processing commands. Consequently, - * a command may take up to 6 minutes to complete after it has been sent - * to the board. - * - * The files dpti_ioctl.h dptsig.h osd_defs.h osd_util.h sys_info.h are part of the - * interface files for Adaptec's management routines. These define the structures used - * in the ioctls. They are written to be portable. They are hard to read, but I need - * to use them 'as is' or I can miss changes in the interface. - * - */ - diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index 6fe00709cbce..b553dd9904bf 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -18,5 +18,6 @@ Linux SCSI Subsystem BusLogic cxgb3i dc395x + dpti scsi_transport_srp/figures diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 9f5b2ddec6e0..5e834fba7934 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -448,7 +448,7 @@ config SCSI_DPT_I2O help This driver supports all of Adaptec's I2O based RAID controllers as well as the DPT SmartRaid V cards. This is an Adaptec maintained - driver by Deanna Bonds. See . + driver by Deanna Bonds. See . To compile this driver as a module, choose M here: the module will be called dpt_i2o. diff --git a/drivers/scsi/dpt/dpti_ioctl.h b/drivers/scsi/dpt/dpti_ioctl.h index 6bc33f4f020d..25e9251f8c78 100644 --- a/drivers/scsi/dpt/dpti_ioctl.h +++ b/drivers/scsi/dpt/dpti_ioctl.h @@ -5,7 +5,7 @@ begin : Thu Sep 7 2000 copyright : (C) 2001 by Adaptec - See Documentation/scsi/dpti.txt for history, notes, license info + See Documentation/scsi/dpti.rst for history, notes, license info and credits ***************************************************************************/ diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index ac27323ea135..02dff3a684e0 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -8,7 +8,7 @@ July 30, 2001 First version being submitted for inclusion in the kernel. V2.4 - See Documentation/scsi/dpti.txt for history, notes, license info + See Documentation/scsi/dpti.rst for history, notes, license info and credits ***************************************************************************/ diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h index 72293b8450b6..8a079e8d7f65 100644 --- a/drivers/scsi/dpti.h +++ b/drivers/scsi/dpti.h @@ -5,7 +5,7 @@ begin : Thu Sep 7 2000 copyright : (C) 2001 by Adaptec - See Documentation/scsi/dpti.txt for history, notes, license info + See Documentation/scsi/dpti.rst for history, notes, license info and credits ***************************************************************************/ From cc0d9d3ad7e60ee0bc6f78809ef6f58f512a9cae Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:48 +0100 Subject: [PATCH 1595/4444] scsi: docs: convert FlashPoint.txt to ReST Link: https://lore.kernel.org/r/e755b9644047eed6be69fcc77eb797f0801fcb99.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/FlashPoint.rst | 176 ++++++++++++++++++++++++++++++ Documentation/scsi/FlashPoint.txt | 163 --------------------------- Documentation/scsi/index.rst | 1 + drivers/scsi/Kconfig | 2 +- 4 files changed, 178 insertions(+), 164 deletions(-) create mode 100644 Documentation/scsi/FlashPoint.rst delete mode 100644 Documentation/scsi/FlashPoint.txt diff --git a/Documentation/scsi/FlashPoint.rst b/Documentation/scsi/FlashPoint.rst new file mode 100644 index 000000000000..ef3c07e94ad6 --- /dev/null +++ b/Documentation/scsi/FlashPoint.rst @@ -0,0 +1,176 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=================================== +The BusLogic FlashPoint SCSI Driver +=================================== + +The BusLogic FlashPoint SCSI Host Adapters are now fully supported on Linux. +The upgrade program described below has been officially terminated effective +31 March 1997 since it is no longer needed. + +:: + + MYLEX INTRODUCES LINUX OPERATING SYSTEM SUPPORT FOR ITS + BUSLOGIC FLASHPOINT LINE OF SCSI HOST ADAPTERS + + + FREMONT, CA, -- October 8, 1996 -- Mylex Corporation has expanded Linux + operating system support to its BusLogic brand of FlashPoint Ultra SCSI + host adapters. All of BusLogic's other SCSI host adapters, including the + MultiMaster line, currently support the Linux operating system. Linux + drivers and information will be available on October 15th at + http://sourceforge.net/projects/dandelion/. + + "Mylex is committed to supporting the Linux community," says Peter Shambora, + vice president of marketing for Mylex. "We have supported Linux driver + development and provided technical support for our host adapters for several + years, and are pleased to now make our FlashPoint products available to this + user base." + +The Linux Operating System +========================== + +Linux is a freely-distributed implementation of UNIX for Intel x86, Sun +SPARC, SGI MIPS, Motorola 68k, Digital Alpha AXP and Motorola PowerPC +machines. It supports a wide range of software, including the X Window +System, Emacs, and TCP/IP networking. Further information is available at +http://www.linux.org and http://www.ssc.com/. + +FlashPoint Host Adapters +======================== + +The FlashPoint family of Ultra SCSI host adapters, designed for workstation +and file server environments, are available in narrow, wide, dual channel, +and dual channel wide versions. These adapters feature SeqEngine +automation technology, which minimizes SCSI command overhead and reduces +the number of interrupts generated to the CPU. + +About Mylex +=========== + +Mylex Corporation (NASDAQ/NM SYMBOL: MYLX), founded in 1983, is a leading +producer of RAID technology and network management products. The company +produces high performance disk array (RAID) controllers, and complementary +computer products for network servers, mass storage systems, workstations +and system boards. Through its wide range of RAID controllers and its +BusLogic line of Ultra SCSI host adapter products, Mylex provides enabling +intelligent I/O technologies that increase network management control, +enhance CPU utilization, optimize I/O performance, and ensure data security +and availability. Products are sold globally through a network of OEMs, +major distributors, VARs, and system integrators. Mylex Corporation is +headquartered at 34551 Ardenwood Blvd., Fremont, CA. + +Contact: +======== + +:: + + Peter Shambora + Vice President of Marketing + Mylex Corp. + 510/796-6100 + peters@mylex.com + + +:: + + ANNOUNCEMENT + BusLogic FlashPoint LT/BT-948 Upgrade Program + 1 February 1996 + + ADDITIONAL ANNOUNCEMENT + BusLogic FlashPoint LW/BT-958 Upgrade Program + 14 June 1996 + + Ever since its introduction last October, the BusLogic FlashPoint LT has + been problematic for members of the Linux community, in that no Linux + drivers have been available for this new Ultra SCSI product. Despite its + officially being positioned as a desktop workstation product, and not being + particularly well suited for a high performance multitasking operating + system like Linux, the FlashPoint LT has been touted by computer system + vendors as the latest thing, and has been sold even on many of their high + end systems, to the exclusion of the older MultiMaster products. This has + caused grief for many people who inadvertently purchased a system expecting + that all BusLogic SCSI Host Adapters were supported by Linux, only to + discover that the FlashPoint was not supported and would not be for quite + some time, if ever. + + After this problem was identified, BusLogic contacted its major OEM + customers to make sure the BT-946C/956C MultiMaster cards would still be + made available, and that Linux users who mistakenly ordered systems with + the FlashPoint would be able to upgrade to the BT-946C. While this helped + many purchasers of new systems, it was only a partial solution to the + overall problem of FlashPoint support for Linux users. It did nothing to + assist the people who initially purchased a FlashPoint for a supported + operating system and then later decided to run Linux, or those who had + ended up with a FlashPoint LT, believing it was supported, and were unable + to return it. + + In the middle of December, I asked to meet with BusLogic's senior + management to discuss the issues related to Linux and free software support + for the FlashPoint. Rumors of varying accuracy had been circulating + publicly about BusLogic's attitude toward the Linux community, and I felt + it was best that these issues be addressed directly. I sent an email + message after 11pm one evening, and the meeting took place the next + afternoon. Unfortunately, corporate wheels sometimes grind slowly, + especially when a company is being acquired, and so it's taken until now + before the details were completely determined and a public statement could + be made. + + BusLogic is not prepared at this time to release the information necessary + for third parties to write drivers for the FlashPoint. The only existing + FlashPoint drivers have been written directly by BusLogic Engineering, and + there is no FlashPoint documentation sufficiently detailed to allow outside + developers to write a driver without substantial assistance. While there + are people at BusLogic who would rather not release the details of the + FlashPoint architecture at all, that debate has not yet been settled either + way. In any event, even if documentation were available today it would + take quite a while for a usable driver to be written, especially since I'm + not convinced that the effort required would be worthwhile. + + However, BusLogic does remain committed to providing a high performance + SCSI solution for the Linux community, and does not want to see anyone left + unable to run Linux because they have a Flashpoint LT. Therefore, BusLogic + has put in place a direct upgrade program to allow any Linux user worldwide + to trade in their FlashPoint LT for the new BT-948 MultiMaster PCI Ultra + SCSI Host Adapter. The BT-948 is the Ultra SCSI successor to the BT-946C + and has all the best features of both the BT-946C and FlashPoint LT, + including smart termination and a flash PROM for easy firmware updates, and + is of course compatible with the present Linux driver. The price for this + upgrade has been set at US $45 plus shipping and handling, and the upgrade + program will be administered through BusLogic Technical Support, which can + be reached by electronic mail at techsup@buslogic.com, by Voice at +1 408 + 654-0760, or by FAX at +1 408 492-1542. + + As of 14 June 1996, the original BusLogic FlashPoint LT to BT-948 upgrade + program has now been extended to encompass the FlashPoint LW Wide Ultra + SCSI Host Adapter. Any Linux user worldwide may trade in their FlashPoint + LW (BT-950) for a BT-958 MultiMaster PCI Ultra SCSI Host Adapter. The + price for this upgrade has been set at US $65 plus shipping and handling. + + I was a beta test site for the BT-948/958, and versions 1.2.1 and 1.3.1 of + my BusLogic driver already included latent support for the BT-948/958. + Additional cosmetic support for the Ultra SCSI MultiMaster cards was added + subsequent releases. As a result of this cooperative testing process, + several firmware bugs were found and corrected. My heavily loaded Linux + test system provided an ideal environment for testing error recovery + processes that are much more rarely exercised in production systems, but + are crucial to overall system stability. It was especially convenient + being able to work directly with their firmware engineer in demonstrating + the problems under control of the firmware debugging environment; things + sure have come a long way since the last time I worked on firmware for an + embedded system. I am presently working on some performance testing and + expect to have some data to report in the not too distant future. + + BusLogic asked me to send this announcement since a large percentage of the + questions regarding support for the FlashPoint have either been sent to me + directly via email, or have appeared in the Linux newsgroups in which I + participate. To summarize, BusLogic is offering Linux users an upgrade + from the unsupported FlashPoint LT (BT-930) to the supported BT-948 for US + $45 plus shipping and handling, or from the unsupported FlashPoint LW + (BT-950) to the supported BT-958 for $65 plus shipping and handling. + Contact BusLogic Technical Support at techsup@buslogic.com or +1 408 + 654-0760 to take advantage of their offer. + + Leonard N. Zubkoff + lnz@dandelion.com diff --git a/Documentation/scsi/FlashPoint.txt b/Documentation/scsi/FlashPoint.txt deleted file mode 100644 index 5b5f29cb9f8b..000000000000 --- a/Documentation/scsi/FlashPoint.txt +++ /dev/null @@ -1,163 +0,0 @@ -The BusLogic FlashPoint SCSI Host Adapters are now fully supported on Linux. -The upgrade program described below has been officially terminated effective -31 March 1997 since it is no longer needed. - - - - MYLEX INTRODUCES LINUX OPERATING SYSTEM SUPPORT FOR ITS - BUSLOGIC FLASHPOINT LINE OF SCSI HOST ADAPTERS - - -FREMONT, CA, -- October 8, 1996 -- Mylex Corporation has expanded Linux -operating system support to its BusLogic brand of FlashPoint Ultra SCSI -host adapters. All of BusLogic's other SCSI host adapters, including the -MultiMaster line, currently support the Linux operating system. Linux -drivers and information will be available on October 15th at -http://sourceforge.net/projects/dandelion/. - -"Mylex is committed to supporting the Linux community," says Peter Shambora, -vice president of marketing for Mylex. "We have supported Linux driver -development and provided technical support for our host adapters for several -years, and are pleased to now make our FlashPoint products available to this -user base." - -The Linux Operating System - -Linux is a freely-distributed implementation of UNIX for Intel x86, Sun -SPARC, SGI MIPS, Motorola 68k, Digital Alpha AXP and Motorola PowerPC -machines. It supports a wide range of software, including the X Window -System, Emacs, and TCP/IP networking. Further information is available at -http://www.linux.org and http://www.ssc.com/. - -FlashPoint Host Adapters - -The FlashPoint family of Ultra SCSI host adapters, designed for workstation -and file server environments, are available in narrow, wide, dual channel, -and dual channel wide versions. These adapters feature SeqEngine -automation technology, which minimizes SCSI command overhead and reduces -the number of interrupts generated to the CPU. - -About Mylex - -Mylex Corporation (NASDAQ/NM SYMBOL: MYLX), founded in 1983, is a leading -producer of RAID technology and network management products. The company -produces high performance disk array (RAID) controllers, and complementary -computer products for network servers, mass storage systems, workstations -and system boards. Through its wide range of RAID controllers and its -BusLogic line of Ultra SCSI host adapter products, Mylex provides enabling -intelligent I/O technologies that increase network management control, -enhance CPU utilization, optimize I/O performance, and ensure data security -and availability. Products are sold globally through a network of OEMs, -major distributors, VARs, and system integrators. Mylex Corporation is -headquartered at 34551 Ardenwood Blvd., Fremont, CA. - - #### - -Contact: - -Peter Shambora -Vice President of Marketing -Mylex Corp. -510/796-6100 -peters@mylex.com - - ANNOUNCEMENT - BusLogic FlashPoint LT/BT-948 Upgrade Program - 1 February 1996 - - ADDITIONAL ANNOUNCEMENT - BusLogic FlashPoint LW/BT-958 Upgrade Program - 14 June 1996 - -Ever since its introduction last October, the BusLogic FlashPoint LT has -been problematic for members of the Linux community, in that no Linux -drivers have been available for this new Ultra SCSI product. Despite its -officially being positioned as a desktop workstation product, and not being -particularly well suited for a high performance multitasking operating -system like Linux, the FlashPoint LT has been touted by computer system -vendors as the latest thing, and has been sold even on many of their high -end systems, to the exclusion of the older MultiMaster products. This has -caused grief for many people who inadvertently purchased a system expecting -that all BusLogic SCSI Host Adapters were supported by Linux, only to -discover that the FlashPoint was not supported and would not be for quite -some time, if ever. - -After this problem was identified, BusLogic contacted its major OEM -customers to make sure the BT-946C/956C MultiMaster cards would still be -made available, and that Linux users who mistakenly ordered systems with -the FlashPoint would be able to upgrade to the BT-946C. While this helped -many purchasers of new systems, it was only a partial solution to the -overall problem of FlashPoint support for Linux users. It did nothing to -assist the people who initially purchased a FlashPoint for a supported -operating system and then later decided to run Linux, or those who had -ended up with a FlashPoint LT, believing it was supported, and were unable -to return it. - -In the middle of December, I asked to meet with BusLogic's senior -management to discuss the issues related to Linux and free software support -for the FlashPoint. Rumors of varying accuracy had been circulating -publicly about BusLogic's attitude toward the Linux community, and I felt -it was best that these issues be addressed directly. I sent an email -message after 11pm one evening, and the meeting took place the next -afternoon. Unfortunately, corporate wheels sometimes grind slowly, -especially when a company is being acquired, and so it's taken until now -before the details were completely determined and a public statement could -be made. - -BusLogic is not prepared at this time to release the information necessary -for third parties to write drivers for the FlashPoint. The only existing -FlashPoint drivers have been written directly by BusLogic Engineering, and -there is no FlashPoint documentation sufficiently detailed to allow outside -developers to write a driver without substantial assistance. While there -are people at BusLogic who would rather not release the details of the -FlashPoint architecture at all, that debate has not yet been settled either -way. In any event, even if documentation were available today it would -take quite a while for a usable driver to be written, especially since I'm -not convinced that the effort required would be worthwhile. - -However, BusLogic does remain committed to providing a high performance -SCSI solution for the Linux community, and does not want to see anyone left -unable to run Linux because they have a Flashpoint LT. Therefore, BusLogic -has put in place a direct upgrade program to allow any Linux user worldwide -to trade in their FlashPoint LT for the new BT-948 MultiMaster PCI Ultra -SCSI Host Adapter. The BT-948 is the Ultra SCSI successor to the BT-946C -and has all the best features of both the BT-946C and FlashPoint LT, -including smart termination and a flash PROM for easy firmware updates, and -is of course compatible with the present Linux driver. The price for this -upgrade has been set at US $45 plus shipping and handling, and the upgrade -program will be administered through BusLogic Technical Support, which can -be reached by electronic mail at techsup@buslogic.com, by Voice at +1 408 -654-0760, or by FAX at +1 408 492-1542. - -As of 14 June 1996, the original BusLogic FlashPoint LT to BT-948 upgrade -program has now been extended to encompass the FlashPoint LW Wide Ultra -SCSI Host Adapter. Any Linux user worldwide may trade in their FlashPoint -LW (BT-950) for a BT-958 MultiMaster PCI Ultra SCSI Host Adapter. The -price for this upgrade has been set at US $65 plus shipping and handling. - -I was a beta test site for the BT-948/958, and versions 1.2.1 and 1.3.1 of -my BusLogic driver already included latent support for the BT-948/958. -Additional cosmetic support for the Ultra SCSI MultiMaster cards was added -subsequent releases. As a result of this cooperative testing process, -several firmware bugs were found and corrected. My heavily loaded Linux -test system provided an ideal environment for testing error recovery -processes that are much more rarely exercised in production systems, but -are crucial to overall system stability. It was especially convenient -being able to work directly with their firmware engineer in demonstrating -the problems under control of the firmware debugging environment; things -sure have come a long way since the last time I worked on firmware for an -embedded system. I am presently working on some performance testing and -expect to have some data to report in the not too distant future. - -BusLogic asked me to send this announcement since a large percentage of the -questions regarding support for the FlashPoint have either been sent to me -directly via email, or have appeared in the Linux newsgroups in which I -participate. To summarize, BusLogic is offering Linux users an upgrade -from the unsupported FlashPoint LT (BT-930) to the supported BT-948 for US -$45 plus shipping and handling, or from the unsupported FlashPoint LW -(BT-950) to the supported BT-958 for $65 plus shipping and handling. -Contact BusLogic Technical Support at techsup@buslogic.com or +1 408 -654-0760 to take advantage of their offer. - - Leonard N. Zubkoff - lnz@dandelion.com diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index b553dd9904bf..aad8359357e6 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -19,5 +19,6 @@ Linux SCSI Subsystem cxgb3i dc395x dpti + FlashPoint scsi_transport_srp/figures diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 5e834fba7934..e47498f7627e 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -503,7 +503,7 @@ config SCSI_BUSLOGIC Adapters. Consult the SCSI-HOWTO, available from , and the files and - for more information. + for more information. Note that support for FlashPoint is only available for 32-bit x86 configurations. From 3c1e681bcdd86b86c676044330ec945d9abc4533 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:49 +0100 Subject: [PATCH 1596/4444] scsi: docs: convert g_NCR5380.txt to ReST Link: https://lore.kernel.org/r/a66e9ea704be6a7aa81b9864ad66a32b75ab808d.1583136624.git.mchehab+huawei@kernel.org Acked-by: Finn Thain Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/g_NCR5380.rst | 93 ++++++++++++++++++++++++++ Documentation/scsi/g_NCR5380.txt | 68 ------------------- Documentation/scsi/index.rst | 1 + Documentation/scsi/scsi-parameters.txt | 6 +- MAINTAINERS | 2 +- drivers/scsi/g_NCR5380.c | 2 +- 6 files changed, 99 insertions(+), 73 deletions(-) create mode 100644 Documentation/scsi/g_NCR5380.rst delete mode 100644 Documentation/scsi/g_NCR5380.txt diff --git a/Documentation/scsi/g_NCR5380.rst b/Documentation/scsi/g_NCR5380.rst new file mode 100644 index 000000000000..a282059fec43 --- /dev/null +++ b/Documentation/scsi/g_NCR5380.rst @@ -0,0 +1,93 @@ +.. SPDX-License-Identifier: GPL-2.0 +.. include:: + +========================================== +README file for the Linux g_NCR5380 driver +========================================== + +Copyright |copy| 1993 Drew Eckhard + +NCR53c400 extensions Copyright |copy| 1994,1995,1996 Kevin Lentin + +This file documents the NCR53c400 extensions by Kevin Lentin and some +enhancements to the NCR5380 core. + +This driver supports NCR5380 and NCR53c400 and compatible cards in port or +memory mapped modes. + +Use of an interrupt is recommended, if supported by the board, as this will +allow targets to disconnect and thereby improve SCSI bus utilization. + +If the irq parameter is 254 or is omitted entirely, the driver will probe +for the correct IRQ line automatically. If the irq parameter is 0 or 255 +then no IRQ will be used. + +The NCR53c400 does not support DMA but it does have Pseudo-DMA which is +supported by the driver. + +This driver provides some information on what it has detected in +/proc/scsi/g_NCR5380/x where x is the scsi card number as detected at boot +time. More info to come in the future. + +This driver works as a module. +When included as a module, parameters can be passed on the insmod/modprobe +command line: + + ============= =============================================================== + irq=xx[,...] the interrupt(s) + base=xx[,...] the port or base address(es) (for port or memory mapped, resp.) + card=xx[,...] card type(s): + + == ====================================== + 0 NCR5380, + 1 NCR53C400, + 2 NCR53C400A, + 3 Domex Technology Corp 3181E (DTC3181E) + 4 Hewlett Packard C2502 + == ====================================== + ============= =============================================================== + +These old-style parameters can support only one card: + + ============= ================================================= + ncr_irq=xx the interrupt + ncr_addr=xx the port or base address (for port or memory + mapped, resp.) + ncr_5380=1 to set up for a NCR5380 board + ncr_53c400=1 to set up for a NCR53C400 board + ncr_53c400a=1 to set up for a NCR53C400A board + dtc_3181e=1 to set up for a Domex Technology Corp 3181E board + hp_c2502=1 to set up for a Hewlett Packard C2502 board + ============= ================================================= + +E.g. Trantor T130B in its default configuration:: + + modprobe g_NCR5380 irq=5 base=0x350 card=1 + +or alternatively, using the old syntax:: + + modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_53c400=1 + +E.g. a port mapped NCR5380 board, driver to probe for IRQ:: + + modprobe g_NCR5380 base=0x350 card=0 + +or alternatively:: + + modprobe g_NCR5380 ncr_addr=0x350 ncr_5380=1 + +E.g. a memory mapped NCR53C400 board with no IRQ:: + + modprobe g_NCR5380 irq=255 base=0xc8000 card=1 + +or alternatively:: + + modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1 + +E.g. two cards, DTC3181 (in non-PnP mode) at 0x240 with no IRQ +and HP C2502 at 0x300 with IRQ 7:: + + modprobe g_NCR5380 irq=0,7 base=0x240,0x300 card=3,4 + +Kevin Lentin +K.Lentin@cs.monash.edu.au diff --git a/Documentation/scsi/g_NCR5380.txt b/Documentation/scsi/g_NCR5380.txt deleted file mode 100644 index 37b1967a00a9..000000000000 --- a/Documentation/scsi/g_NCR5380.txt +++ /dev/null @@ -1,68 +0,0 @@ -README file for the Linux g_NCR5380 driver. - -(c) 1993 Drew Eckhard -NCR53c400 extensions (c) 1994,1995,1996 Kevin Lentin - -This file documents the NCR53c400 extensions by Kevin Lentin and some -enhancements to the NCR5380 core. - -This driver supports NCR5380 and NCR53c400 and compatible cards in port or -memory mapped modes. - -Use of an interrupt is recommended, if supported by the board, as this will -allow targets to disconnect and thereby improve SCSI bus utilization. - -If the irq parameter is 254 or is omitted entirely, the driver will probe -for the correct IRQ line automatically. If the irq parameter is 0 or 255 -then no IRQ will be used. - -The NCR53c400 does not support DMA but it does have Pseudo-DMA which is -supported by the driver. - -This driver provides some information on what it has detected in -/proc/scsi/g_NCR5380/x where x is the scsi card number as detected at boot -time. More info to come in the future. - -This driver works as a module. -When included as a module, parameters can be passed on the insmod/modprobe -command line: - irq=xx[,...] the interrupt(s) - base=xx[,...] the port or base address(es) (for port or memory mapped, resp.) - card=xx[,...] card type(s): - 0 = NCR5380, - 1 = NCR53C400, - 2 = NCR53C400A, - 3 = Domex Technology Corp 3181E (DTC3181E) - 4 = Hewlett Packard C2502 - -These old-style parameters can support only one card: - ncr_irq=xx the interrupt - ncr_addr=xx the port or base address (for port or memory - mapped, resp.) - ncr_5380=1 to set up for a NCR5380 board - ncr_53c400=1 to set up for a NCR53C400 board - ncr_53c400a=1 to set up for a NCR53C400A board - dtc_3181e=1 to set up for a Domex Technology Corp 3181E board - hp_c2502=1 to set up for a Hewlett Packard C2502 board - -E.g. Trantor T130B in its default configuration: -modprobe g_NCR5380 irq=5 base=0x350 card=1 -or alternatively, using the old syntax, -modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_53c400=1 - -E.g. a port mapped NCR5380 board, driver to probe for IRQ: -modprobe g_NCR5380 base=0x350 card=0 -or alternatively, -modprobe g_NCR5380 ncr_addr=0x350 ncr_5380=1 - -E.g. a memory mapped NCR53C400 board with no IRQ: -modprobe g_NCR5380 irq=255 base=0xc8000 card=1 -or alternatively, -modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1 - -E.g. two cards, DTC3181 (in non-PnP mode) at 0x240 with no IRQ -and HP C2502 at 0x300 with IRQ 7: -modprobe g_NCR5380 irq=0,7 base=0x240,0x300 card=3,4 - -Kevin Lentin -K.Lentin@cs.monash.edu.au diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index aad8359357e6..4b577c9e804e 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -20,5 +20,6 @@ Linux SCSI Subsystem dc395x dpti FlashPoint + g_NCR5380 scsi_transport_srp/figures diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt index 266fd3b2398a..864bbf7f737b 100644 --- a/Documentation/scsi/scsi-parameters.txt +++ b/Documentation/scsi/scsi-parameters.txt @@ -57,13 +57,13 @@ parameters may be changed at runtime by the command See header of drivers/scsi/NCR_D700.c. ncr5380= [HW,SCSI] - See Documentation/scsi/g_NCR5380.txt. + See Documentation/scsi/g_NCR5380.rst. ncr53c400= [HW,SCSI] - See Documentation/scsi/g_NCR5380.txt. + See Documentation/scsi/g_NCR5380.rst. ncr53c400a= [HW,SCSI] - See Documentation/scsi/g_NCR5380.txt. + See Documentation/scsi/g_NCR5380.rst. ncr53c8xx= [HW,SCSI] diff --git a/MAINTAINERS b/MAINTAINERS index 1df63c2d8d68..11a64d2cd938 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11473,7 +11473,7 @@ M: Finn Thain M: Michael Schmitz L: linux-scsi@vger.kernel.org S: Maintained -F: Documentation/scsi/g_NCR5380.txt +F: Documentation/scsi/g_NCR5380.rst F: drivers/scsi/NCR5380.* F: drivers/scsi/arm/cumana_1.c F: drivers/scsi/arm/oak.c diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 2ab774e62e40..2cc676e3df6a 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -20,7 +20,7 @@ * Added ISAPNP support for DTC436 adapters, * Thomas Sailer, sailer@ife.ee.ethz.ch * - * See Documentation/scsi/g_NCR5380.txt for more info. + * See Documentation/scsi/g_NCR5380.rst for more info. */ #include From 1392de9d7a89915bf0269e038b0d2b3a393d253d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:50 +0100 Subject: [PATCH 1597/4444] scsi: docs: convert hpsa.txt to ReST Link: https://lore.kernel.org/r/ea58e04176d43fb7194615b145060aa04c9cf3ad.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/{hpsa.txt => hpsa.rst} | 79 +++++++++++------------ Documentation/scsi/index.rst | 1 + MAINTAINERS | 2 +- 3 files changed, 41 insertions(+), 41 deletions(-) rename Documentation/scsi/{hpsa.txt => hpsa.rst} (77%) diff --git a/Documentation/scsi/hpsa.txt b/Documentation/scsi/hpsa.rst similarity index 77% rename from Documentation/scsi/hpsa.txt rename to Documentation/scsi/hpsa.rst index 891435a72fce..340e10c6e35f 100644 --- a/Documentation/scsi/hpsa.txt +++ b/Documentation/scsi/hpsa.rst @@ -1,6 +1,8 @@ +.. SPDX-License-Identifier: GPL-2.0 +========================================= HPSA - Hewlett Packard Smart Array driver ------------------------------------------ +========================================= This file describes the hpsa SCSI driver for HP Smart Array controllers. The hpsa driver is intended to supplant the cciss driver for newer @@ -11,17 +13,17 @@ driver (for logical drives) AND a SCSI driver (for tape drives). This complexity and eliminating that complexity is one of the reasons for hpsa to exist. -Supported devices: ------------------- +Supported devices +================= -Smart Array P212 -Smart Array P410 -Smart Array P410i -Smart Array P411 -Smart Array P812 -Smart Array P712m -Smart Array P711m -StorageWorks P1210m +- Smart Array P212 +- Smart Array P410 +- Smart Array P410i +- Smart Array P411 +- Smart Array P812 +- Smart Array P712m +- Smart Array P711m +- StorageWorks P1210m Additionally, older Smart Arrays may work with the hpsa driver if the kernel boot parameter "hpsa_allow_any=1" is specified, however these are not tested @@ -35,18 +37,20 @@ mode, each command completion requires an interrupt, while with "performant mode command completions indicated by a single interrupt. HPSA specific entries in /sys ------------------------------ +============================= In addition to the generic SCSI attributes available in /sys, hpsa supports the following attributes: - HPSA specific host attributes: - ------------------------------ +HPSA specific host attributes +============================= - /sys/class/scsi_host/host*/rescan - /sys/class/scsi_host/host*/firmware_revision - /sys/class/scsi_host/host*/resettable - /sys/class/scsi_host/host*/transport_mode + :: + + /sys/class/scsi_host/host*/rescan + /sys/class/scsi_host/host*/firmware_revision + /sys/class/scsi_host/host*/resettable + /sys/class/scsi_host/host*/transport_mode the host "rescan" attribute is a write only attribute. Writing to this attribute will cause the driver to scan for new, changed, or removed devices @@ -58,7 +62,7 @@ HPSA specific entries in /sys tape drives, or entire storage boxes containing pre-configured logical drives. The "firmware_revision" attribute contains the firmware version of the Smart Array. - For example: + For example:: root@host:/sys/class/scsi_host/host4# cat firmware_revision 7.14 @@ -78,16 +82,18 @@ HPSA specific entries in /sys kexec tools to warn the user if they attempt to designate a device which is unable to honor the reset_devices kernel parameter as a dump device. - HPSA specific disk attributes: - ------------------------------ +HPSA specific disk attributes +----------------------------- - /sys/class/scsi_disk/c:b:t:l/device/unique_id - /sys/class/scsi_disk/c:b:t:l/device/raid_level - /sys/class/scsi_disk/c:b:t:l/device/lunid + :: + + /sys/class/scsi_disk/c:b:t:l/device/unique_id + /sys/class/scsi_disk/c:b:t:l/device/raid_level + /sys/class/scsi_disk/c:b:t:l/device/lunid (where c:b:t:l are the controller, bus, target and lun of the device) - For example: + For example:: root@host:/sys/class/scsi_disk/4:0:0:0/device# cat unique_id 600508B1001044395355323037570F77 @@ -96,35 +102,28 @@ HPSA specific entries in /sys root@host:/sys/class/scsi_disk/4:0:0:0/device# cat raid_level RAID 0 -HPSA specific ioctls: ---------------------- +HPSA specific ioctls +==================== For compatibility with applications written for the cciss driver, many, but not all of the ioctls supported by the cciss driver are also supported by the hpsa driver. The data structures used by these are described in include/linux/cciss_ioctl.h - CCISS_DEREGDISK - CCISS_REGNEWDISK - CCISS_REGNEWD - - The above three ioctls all do exactly the same thing, which is to cause the driver - to rescan for new devices. This does exactly the same thing as writing to the - hpsa specific host "rescan" attribute. + CCISS_DEREGDISK, CCISS_REGNEWDISK, CCISS_REGNEWD + The above three ioctls all do exactly the same thing, which is to cause the driver + to rescan for new devices. This does exactly the same thing as writing to the + hpsa specific host "rescan" attribute. CCISS_GETPCIINFO - Returns PCI domain, bus, device and function and "board ID" (PCI subsystem ID). CCISS_GETDRIVVER + Returns driver version in three bytes encoded as:: - Returns driver version in three bytes encoded as: (major_version << 16) | (minor_version << 8) | (subminor_version) - CCISS_PASSTHRU - CCISS_BIG_PASSTHRU - + CCISS_PASSTHRU, CCISS_BIG_PASSTHRU Allows "BMIC" and "CISS" commands to be passed through to the Smart Array. These are used extensively by the HP Array Configuration Utility, SNMP storage agents, etc. See cciss_vol_status at http://cciss.sf.net for some examples. - diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index 4b577c9e804e..b16f348bd31b 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -21,5 +21,6 @@ Linux SCSI Subsystem dpti FlashPoint g_NCR5380 + hpsa scsi_transport_srp/figures diff --git a/MAINTAINERS b/MAINTAINERS index 11a64d2cd938..48cad576dc70 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7416,7 +7416,7 @@ M: Don Brace L: esc.storagedev@microsemi.com L: linux-scsi@vger.kernel.org S: Supported -F: Documentation/scsi/hpsa.txt +F: Documentation/scsi/hpsa.rst F: drivers/scsi/hpsa*.[ch] F: include/linux/cciss*.h F: include/uapi/linux/cciss*.h From ac69461b6058dc8bc84b940665b84828575b0cc6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:51 +0100 Subject: [PATCH 1598/4444] scsi: docs: convert hptiop.txt to ReST Link: https://lore.kernel.org/r/d189a339bb360b7b397914ee3ddeb75d9a7fd788.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/{hptiop.txt => hptiop.rst} | 45 ++++++++++++++++--- Documentation/scsi/index.rst | 1 + MAINTAINERS | 2 +- 3 files changed, 40 insertions(+), 8 deletions(-) rename Documentation/scsi/{hptiop.txt => hptiop.rst} (78%) diff --git a/Documentation/scsi/hptiop.txt b/Documentation/scsi/hptiop.rst similarity index 78% rename from Documentation/scsi/hptiop.txt rename to Documentation/scsi/hptiop.rst index 12ecfd308e55..23ae7ae36971 100644 --- a/Documentation/scsi/hptiop.txt +++ b/Documentation/scsi/hptiop.rst @@ -1,15 +1,25 @@ -HIGHPOINT ROCKETRAID 3xxx/4xxx ADAPTER DRIVER (hptiop) +.. SPDX-License-Identifier: GPL-2.0 +.. include:: + +====================================================== +Highpoint RocketRAID 3xxx/4xxx Adapter Driver (hptiop) +====================================================== Controller Register Map -------------------------- +----------------------- -For RR44xx Intel IOP based adapters, the controller IOP is accessed via PCI BAR0 and BAR2: +For RR44xx Intel IOP based adapters, the controller IOP is accessed via PCI BAR0 and BAR2 + ============== ================================== BAR0 offset Register + ============== ================================== 0x11C5C Link Interface IRQ Set 0x11C60 Link Interface IRQ Clear + ============== ================================== + ============== ================================== BAR2 offset Register + ============== ================================== 0x10 Inbound Message Register 0 0x14 Inbound Message Register 1 0x18 Outbound Message Register 0 @@ -21,10 +31,13 @@ For RR44xx Intel IOP based adapters, the controller IOP is accessed via PCI BAR0 0x34 Outbound Interrupt Mask Register 0x40 Inbound Queue Port 0x44 Outbound Queue Port + ============== ================================== For Intel IOP based adapters, the controller IOP is accessed via PCI BAR0: + ============== ================================== BAR0 offset Register + ============== ================================== 0x10 Inbound Message Register 0 0x14 Inbound Message Register 1 0x18 Outbound Message Register 0 @@ -36,16 +49,22 @@ For Intel IOP based adapters, the controller IOP is accessed via PCI BAR0: 0x34 Outbound Interrupt Mask Register 0x40 Inbound Queue Port 0x44 Outbound Queue Port + ============== ================================== For Marvell not Frey IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1: + ============== ================================== BAR0 offset Register + ============== ================================== 0x20400 Inbound Doorbell Register 0x20404 Inbound Interrupt Mask Register 0x20408 Outbound Doorbell Register 0x2040C Outbound Interrupt Mask Register + ============== ================================== + ============== ================================== BAR1 offset Register + ============== ================================== 0x0 Inbound Queue Head Pointer 0x4 Inbound Queue Tail Pointer 0x8 Outbound Queue Head Pointer @@ -53,14 +72,20 @@ For Marvell not Frey IOP based adapters, the IOP is accessed via PCI BAR0 and BA 0x10 Inbound Message Register 0x14 Outbound Message Register 0x40-0x1040 Inbound Queue - 0x1040-0x2040 Outbound Queue + 0x1040-0x2040 Outbound Queue + ============== ================================== For Marvell Frey IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1: + ============== ================================== BAR0 offset Register + ============== ================================== 0x0 IOP configuration information. + ============== ================================== + ============== =================================================== BAR1 offset Register + ============== =================================================== 0x4000 Inbound List Base Address Low 0x4004 Inbound List Base Address High 0x4018 Inbound List Write Pointer @@ -76,10 +101,11 @@ For Marvell Frey IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1: 0x10420 CPU to PCIe Function 0 Message A 0x10480 CPU to PCIe Function 0 Doorbell 0x10484 CPU to PCIe Function 0 Doorbell Enable + ============== =================================================== I/O Request Workflow of Not Marvell Frey ------------------------------------------- +---------------------------------------- All queued requests are handled via inbound/outbound queue port. A request packet can be allocated in either IOP or host memory. @@ -124,7 +150,7 @@ of an inbound message. I/O Request Workflow of Marvell Frey --------------------------------------- +------------------------------------ All queued requests are handled via inbound/outbound list. @@ -167,13 +193,17 @@ User-level Interface The driver exposes following sysfs attributes: + ================== === ======================== NAME R/W Description + ================== === ======================== driver-version R driver version string firmware-version R firmware version string + ================== === ======================== ----------------------------------------------------------------------------- -Copyright (C) 2006-2012 HighPoint Technologies, Inc. All Rights Reserved. + +Copyright |copy| 2006-2012 HighPoint Technologies, Inc. All Rights Reserved. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -181,4 +211,5 @@ Copyright (C) 2006-2012 HighPoint Technologies, Inc. All Rights Reserved. GNU General Public License for more details. linux@highpoint-tech.com + http://www.highpoint-tech.com diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index b16f348bd31b..b13df9c1810a 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -22,5 +22,6 @@ Linux SCSI Subsystem FlashPoint g_NCR5380 hpsa + hptiop scsi_transport_srp/figures diff --git a/MAINTAINERS b/MAINTAINERS index 48cad576dc70..51cc884037f2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7505,7 +7505,7 @@ HIGHPOINT ROCKETRAID 3xxx RAID DRIVER M: HighPoint Linux Team W: http://www.highpoint-tech.com S: Supported -F: Documentation/scsi/hptiop.txt +F: Documentation/scsi/hptiop.rst F: drivers/scsi/hptiop.c HIPPI From a88dc3ec2ca48d23c7761af02e1ceea731f609e9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:52 +0100 Subject: [PATCH 1599/4444] scsi: docs: convert libsas.txt to ReST Link: https://lore.kernel.org/r/9022cb5551487f774cab16a828fe06b0b6b3add3.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/index.rst | 1 + Documentation/scsi/{libsas.txt => libsas.rst} | 334 +++++++++++------- 2 files changed, 203 insertions(+), 132 deletions(-) rename Documentation/scsi/{libsas.txt => libsas.rst} (57%) diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index b13df9c1810a..e6850c0a1378 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -23,5 +23,6 @@ Linux SCSI Subsystem g_NCR5380 hpsa hptiop + libsas scsi_transport_srp/figures diff --git a/Documentation/scsi/libsas.txt b/Documentation/scsi/libsas.rst similarity index 57% rename from Documentation/scsi/libsas.txt rename to Documentation/scsi/libsas.rst index 8cac6492aade..7216b5d25800 100644 --- a/Documentation/scsi/libsas.txt +++ b/Documentation/scsi/libsas.rst @@ -1,5 +1,8 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========= SAS Layer ---------- +========= The SAS Layer is a management infrastructure which manages SAS LLDDs. It sits between SCSI Core and SAS LLDDs. The @@ -37,16 +40,21 @@ It will then return. Then you enable your phys to actually start OOB (at which point your driver will start calling the notify_* event callbacks). -Structure descriptions: +Structure descriptions +====================== + +``struct sas_phy`` +------------------ -struct sas_phy -------------------- Normally this is statically embedded to your driver's -phy structure: - struct my_phy { - blah; - struct sas_phy sas_phy; - bleh; - }; +phy structure:: + + struct my_phy { + blah; + struct sas_phy sas_phy; + bleh; + }; + And then all the phys are an array of my_phy in your HA struct (shown below). @@ -63,94 +71,122 @@ There is a scheme where the LLDD can RW certain fields, and the SAS layer can only read such ones, and vice versa. The idea is to avoid unnecessary locking. -enabled -- must be set (0/1) -id -- must be set [0,MAX_PHYS) -class, proto, type, role, oob_mode, linkrate -- must be set -oob_mode -- you set this when OOB has finished and then notify -the SAS Layer. +enabled + - must be set (0/1) -sas_addr -- this normally points to an array holding the sas -address of the phy, possibly somewhere in your my_phy -struct. +id + - must be set [0,MAX_PHYS)] -attached_sas_addr -- set this when you (LLDD) receive an -IDENTIFY frame or a FIS frame, _before_ notifying the SAS -layer. The idea is that sometimes the LLDD may want to fake -or provide a different SAS address on that phy/port and this -allows it to do this. At best you should copy the sas -address from the IDENTIFY frame or maybe generate a SAS -address for SATA directly attached devices. The Discover -process may later change this. +class, proto, type, role, oob_mode, linkrate + - must be set -frame_rcvd -- this is where you copy the IDENTIFY/FIS frame -when you get it; you lock, copy, set frame_rcvd_size and -unlock the lock, and then call the event. It is a pointer -since there's no way to know your hw frame size _exactly_, -so you define the actual array in your phy struct and let -this pointer point to it. You copy the frame from your -DMAable memory to that area holding the lock. +oob_mode + - you set this when OOB has finished and then notify + the SAS Layer. -sas_prim -- this is where primitives go when they're -received. See sas.h. Grab the lock, set the primitive, -release the lock, notify. +sas_addr + - this normally points to an array holding the sas + address of the phy, possibly somewhere in your my_phy + struct. -port -- this points to the sas_port if the phy belongs -to a port -- the LLDD only reads this. It points to the -sas_port this phy is part of. Set by the SAS Layer. +attached_sas_addr + - set this when you (LLDD) receive an + IDENTIFY frame or a FIS frame, _before_ notifying the SAS + layer. The idea is that sometimes the LLDD may want to fake + or provide a different SAS address on that phy/port and this + allows it to do this. At best you should copy the sas + address from the IDENTIFY frame or maybe generate a SAS + address for SATA directly attached devices. The Discover + process may later change this. -ha -- may be set; the SAS layer sets it anyway. +frame_rcvd + - this is where you copy the IDENTIFY/FIS frame + when you get it; you lock, copy, set frame_rcvd_size and + unlock the lock, and then call the event. It is a pointer + since there's no way to know your hw frame size _exactly_, + so you define the actual array in your phy struct and let + this pointer point to it. You copy the frame from your + DMAable memory to that area holding the lock. -lldd_phy -- you should set this to point to your phy so you -can find your way around faster when the SAS layer calls one -of your callbacks and passes you a phy. If the sas_phy is -embedded you can also use container_of -- whatever you -prefer. +sas_prim + - this is where primitives go when they're + received. See sas.h. Grab the lock, set the primitive, + release the lock, notify. + +port + - this points to the sas_port if the phy belongs + to a port -- the LLDD only reads this. It points to the + sas_port this phy is part of. Set by the SAS Layer. + +ha + - may be set; the SAS layer sets it anyway. + +lldd_phy + - you should set this to point to your phy so you + can find your way around faster when the SAS layer calls one + of your callbacks and passes you a phy. If the sas_phy is + embedded you can also use container_of -- whatever you + prefer. -struct sas_port -------------------- +``struct sas_port`` +------------------- + The LLDD doesn't set any fields of this struct -- it only reads them. They should be self explanatory. phy_mask is 32 bit, this should be enough for now, as I haven't heard of a HA having more than 8 phys. -lldd_port -- I haven't found use for that -- maybe other -LLDD who wish to have internal port representation can make -use of this. +lldd_port + - I haven't found use for that -- maybe other + LLDD who wish to have internal port representation can make + use of this. +``struct sas_ha_struct`` +------------------------ -struct sas_ha_struct -------------------- It normally is statically declared in your own LLDD -structure describing your adapter: -struct my_sas_ha { - blah; - struct sas_ha_struct sas_ha; - struct my_phy phys[MAX_PHYS]; - struct sas_port sas_ports[MAX_PHYS]; /* (1) */ - bleh; -}; +structure describing your adapter:: -(1) If your LLDD doesn't have its own port representation. + struct my_sas_ha { + blah; + struct sas_ha_struct sas_ha; + struct my_phy phys[MAX_PHYS]; + struct sas_port sas_ports[MAX_PHYS]; /* (1) */ + bleh; + }; + + (1) If your LLDD doesn't have its own port representation. What needs to be initialized (sample function given below). pcidev -sas_addr -- since the SAS layer doesn't want to mess with +^^^^^^ + +sas_addr + - since the SAS layer doesn't want to mess with memory allocation, etc, this points to statically allocated array somewhere (say in your host adapter structure) and holds the SAS address of the host adapter as given by you or the manufacturer, etc. + sas_port -sas_phy -- an array of pointers to structures. (see +^^^^^^^^ + +sas_phy + - an array of pointers to structures. (see note above on sas_addr). These must be set. See more notes below. -num_phys -- the number of phys present in the sas_phy array, + +num_phys + - the number of phys present in the sas_phy array, and the number of ports present in the sas_port array. There can be a maximum num_phys ports (one per port) so we drop the num_ports, and only use num_phys. -The event interface: +The event interface:: /* LLDD calls these to notify the class of an event. */ void (*notify_ha_event)(struct sas_ha_struct *, enum ha_event); @@ -161,7 +197,7 @@ When sas_register_ha() returns, those are set and can be called by the LLDD to notify the SAS layer of such events the SAS layer. -The port notification: +The port notification:: /* The class calls these to notify the LLDD of an event. */ void (*lldd_port_formed)(struct sas_phy *); @@ -171,7 +207,7 @@ If the LLDD wants notification when a port has been formed or deformed it sets those to a function satisfying the type. A SAS LLDD should also implement at least one of the Task -Management Functions (TMFs) described in SAM: +Management Functions (TMFs) described in SAM:: /* Task Management Functions. Must be called from process context. */ int (*lldd_abort_task)(struct sas_task *); @@ -184,7 +220,7 @@ Management Functions (TMFs) described in SAM: For more information please read SAM from T10.org. -Port and Adapter management: +Port and Adapter management:: /* Port and Adapter management */ int (*lldd_clear_nexus_port)(struct sas_port *); @@ -192,75 +228,78 @@ Port and Adapter management: A SAS LLDD should implement at least one of those. -Phy management: +Phy management:: /* Phy management */ int (*lldd_control_phy)(struct sas_phy *, enum phy_func); -lldd_ha -- set this to point to your HA struct. You can also -use container_of if you embedded it as shown above. +lldd_ha + - set this to point to your HA struct. You can also + use container_of if you embedded it as shown above. A sample initialization and registration function can look like this (called last thing from probe()) -*but* before you enable the phys to do OOB: +*but* before you enable the phys to do OOB:: -static int register_sas_ha(struct my_sas_ha *my_ha) -{ - int i; - static struct sas_phy *sas_phys[MAX_PHYS]; - static struct sas_port *sas_ports[MAX_PHYS]; + static int register_sas_ha(struct my_sas_ha *my_ha) + { + int i; + static struct sas_phy *sas_phys[MAX_PHYS]; + static struct sas_port *sas_ports[MAX_PHYS]; - my_ha->sas_ha.sas_addr = &my_ha->sas_addr[0]; + my_ha->sas_ha.sas_addr = &my_ha->sas_addr[0]; - for (i = 0; i < MAX_PHYS; i++) { - sas_phys[i] = &my_ha->phys[i].sas_phy; - sas_ports[i] = &my_ha->sas_ports[i]; - } + for (i = 0; i < MAX_PHYS; i++) { + sas_phys[i] = &my_ha->phys[i].sas_phy; + sas_ports[i] = &my_ha->sas_ports[i]; + } - my_ha->sas_ha.sas_phy = sas_phys; - my_ha->sas_ha.sas_port = sas_ports; - my_ha->sas_ha.num_phys = MAX_PHYS; + my_ha->sas_ha.sas_phy = sas_phys; + my_ha->sas_ha.sas_port = sas_ports; + my_ha->sas_ha.num_phys = MAX_PHYS; - my_ha->sas_ha.lldd_port_formed = my_port_formed; + my_ha->sas_ha.lldd_port_formed = my_port_formed; - my_ha->sas_ha.lldd_dev_found = my_dev_found; - my_ha->sas_ha.lldd_dev_gone = my_dev_gone; + my_ha->sas_ha.lldd_dev_found = my_dev_found; + my_ha->sas_ha.lldd_dev_gone = my_dev_gone; - my_ha->sas_ha.lldd_execute_task = my_execute_task; + my_ha->sas_ha.lldd_execute_task = my_execute_task; - my_ha->sas_ha.lldd_abort_task = my_abort_task; - my_ha->sas_ha.lldd_abort_task_set = my_abort_task_set; - my_ha->sas_ha.lldd_clear_aca = my_clear_aca; - my_ha->sas_ha.lldd_clear_task_set = my_clear_task_set; - my_ha->sas_ha.lldd_I_T_nexus_reset= NULL; (2) - my_ha->sas_ha.lldd_lu_reset = my_lu_reset; - my_ha->sas_ha.lldd_query_task = my_query_task; + my_ha->sas_ha.lldd_abort_task = my_abort_task; + my_ha->sas_ha.lldd_abort_task_set = my_abort_task_set; + my_ha->sas_ha.lldd_clear_aca = my_clear_aca; + my_ha->sas_ha.lldd_clear_task_set = my_clear_task_set; + my_ha->sas_ha.lldd_I_T_nexus_reset= NULL; (2) + my_ha->sas_ha.lldd_lu_reset = my_lu_reset; + my_ha->sas_ha.lldd_query_task = my_query_task; - my_ha->sas_ha.lldd_clear_nexus_port = my_clear_nexus_port; - my_ha->sas_ha.lldd_clear_nexus_ha = my_clear_nexus_ha; + my_ha->sas_ha.lldd_clear_nexus_port = my_clear_nexus_port; + my_ha->sas_ha.lldd_clear_nexus_ha = my_clear_nexus_ha; - my_ha->sas_ha.lldd_control_phy = my_control_phy; + my_ha->sas_ha.lldd_control_phy = my_control_phy; - return sas_register_ha(&my_ha->sas_ha); -} + return sas_register_ha(&my_ha->sas_ha); + } (2) SAS 1.1 does not define I_T Nexus Reset TMF. Events ------- +====== -Events are _the only way_ a SAS LLDD notifies the SAS layer +Events are **the only way** a SAS LLDD notifies the SAS layer of anything. There is no other method or way a LLDD to tell the SAS layer of anything happening internally or in the SAS domain. -Phy events: +Phy events:: + PHYE_LOSS_OF_SIGNAL, (C) PHYE_OOB_DONE, PHYE_OOB_ERROR, (C) PHYE_SPINUP_HOLD. -Port events, passed on a _phy_: +Port events, passed on a _phy_:: + PORTE_BYTES_DMAED, (M) PORTE_BROADCAST_RCVD, (E) PORTE_LINK_RESET_ERR, (C) @@ -271,6 +310,7 @@ Host Adapter event: HAE_RESET A SAS LLDD should be able to generate + - at least one event from group C (choice), - events marked M (mandatory) are mandatory (only one), - events marked E (expander) if it wants the SAS layer @@ -279,26 +319,42 @@ A SAS LLDD should be able to generate Meaning: -HAE_RESET -- when your HA got internal error and was reset. +HAE_RESET + - when your HA got internal error and was reset. -PORTE_BYTES_DMAED -- on receiving an IDENTIFY/FIS frame -PORTE_BROADCAST_RCVD -- on receiving a primitive -PORTE_LINK_RESET_ERR -- timer expired, loss of signal, loss -of DWS, etc. (*) -PORTE_TIMER_EVENT -- DWS reset timeout timer expired (*) -PORTE_HARD_RESET -- Hard Reset primitive received. +PORTE_BYTES_DMAED + - on receiving an IDENTIFY/FIS frame -PHYE_LOSS_OF_SIGNAL -- the device is gone (*) -PHYE_OOB_DONE -- OOB went fine and oob_mode is valid -PHYE_OOB_ERROR -- Error while doing OOB, the device probably -got disconnected. (*) -PHYE_SPINUP_HOLD -- SATA is present, COMWAKE not sent. +PORTE_BROADCAST_RCVD + - on receiving a primitive -(*) should set/clear the appropriate fields in the phy, - or alternatively call the inlined sas_phy_disconnected() - which is just a helper, from their tasklet. +PORTE_LINK_RESET_ERR + - timer expired, loss of signal, loss of DWS, etc. [1]_ -The Execute Command SCSI RPC: +PORTE_TIMER_EVENT + - DWS reset timeout timer expired [1]_ + +PORTE_HARD_RESET + - Hard Reset primitive received. + +PHYE_LOSS_OF_SIGNAL + - the device is gone [1]_ + +PHYE_OOB_DONE + - OOB went fine and oob_mode is valid + +PHYE_OOB_ERROR + - Error while doing OOB, the device probably + got disconnected. [1]_ + +PHYE_SPINUP_HOLD + - SATA is present, COMWAKE not sent. + +.. [1] should set/clear the appropriate fields in the phy, + or alternatively call the inlined sas_phy_disconnected() + which is just a helper, from their tasklet. + +The Execute Command SCSI RPC:: int (*lldd_execute_task)(struct sas_task *, gfp_t gfp_flags); @@ -311,23 +367,28 @@ That is, when lldd_execute_task() is called, the command go out on the transport *immediately*. There is *no* queuing of any sort and at any level in a SAS LLDD. -Returns: -SAS_QUEUE_FULL, -ENOMEM, nothing was queued; - 0, the task(s) were queued. +Returns: -struct sas_task { - dev -- the device this task is destined to - task_proto -- _one_ of enum sas_proto - scatter -- pointer to scatter gather list array - num_scatter -- number of elements in scatter - total_xfer_len -- total number of bytes expected to be transferred - data_dir -- PCI_DMA_... - task_done -- callback when the task has finished execution -}; + * -SAS_QUEUE_FULL, -ENOMEM, nothing was queued; + * 0, the task(s) were queued. -DISCOVERY ---------- +:: + + struct sas_task { + dev -- the device this task is destined to + task_proto -- _one_ of enum sas_proto + scatter -- pointer to scatter gather list array + num_scatter -- number of elements in scatter + total_xfer_len -- total number of bytes expected to be transferred + data_dir -- PCI_DMA_... + task_done -- callback when the task has finished execution + }; + +Discovery +========= The sysfs tree has the following purposes: + a) It shows you the physical layout of the SAS domain at the current time, i.e. how the domain looks in the physical world right now. @@ -336,6 +397,7 @@ The sysfs tree has the following purposes: This is a link to the tree(1) program, very useful in viewing the SAS domain: ftp://mama.indstate.edu/linux/tree/ + I expect user space applications to actually create a graphical interface of this. @@ -359,7 +421,7 @@ contents of the domain_device structure, but it never creates or destroys one. Expander management from User Space ------------------------------------ +=================================== In each expander directory in sysfs, there is a file called "smp_portal". It is a binary sysfs attribute file, which @@ -371,15 +433,23 @@ Functionality is deceptively simple: 1. Build the SMP frame you want to send. The format and layout is described in the SAS spec. Leave the CRC field equal 0. + open(2) + 2. Open the expander's SMP portal sysfs file in RW mode. + write(2) + 3. Write the frame you built in 1. + read(2) + 4. Read the amount of data you expect to receive for the frame you built. If you receive different amount of data you expected to receive, then there was some kind of error. + close(2) + All this process is shown in detail in the function do_smp_func() and its callers, in the file "expander_conf.c". From cbbc70a8cde7edb427b6cf00b3bc0f86181e2b4d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:53 +0100 Subject: [PATCH 1600/4444] scsi: docs: convert link_power_management_policy.txt to ReST Link: https://lore.kernel.org/r/c56177fdf046d80e0dec6031c4139cb4e8c39d31.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/index.rst | 1 + ...t_policy.txt => link_power_management_policy.rst} | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) rename Documentation/scsi/{link_power_management_policy.txt => link_power_management_policy.rst} (65%) diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index e6850c0a1378..c40050ac3b32 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -24,5 +24,6 @@ Linux SCSI Subsystem hpsa hptiop libsas + link_power_management_policy scsi_transport_srp/figures diff --git a/Documentation/scsi/link_power_management_policy.txt b/Documentation/scsi/link_power_management_policy.rst similarity index 65% rename from Documentation/scsi/link_power_management_policy.txt rename to Documentation/scsi/link_power_management_policy.rst index d18993d01884..64288dcf10f6 100644 --- a/Documentation/scsi/link_power_management_policy.txt +++ b/Documentation/scsi/link_power_management_policy.rst @@ -1,8 +1,15 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========================== +Link Power Managent Policy +========================== + This parameter allows the user to set the link (interface) power management. There are 3 possible options: +===================== ===================================================== Value Effect ----------------------------------------------------------------------------- +===================== ===================================================== min_power Tell the controller to try to make the link use the least possible power when possible. This may sacrifice some performance due to increased latency @@ -15,5 +22,4 @@ max_performance Generally, this means no power management. Tell medium_power Tell the controller to enter a lower power state when possible, but do not enter the lowest power state, thus improving latency over min_power setting. - - +===================== ===================================================== From b4adb7578169ea810d2c3d9b2f3ad1aebef96886 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:54 +0100 Subject: [PATCH 1601/4444] scsi: docs: convert lpfc.txt to ReST Link: https://lore.kernel.org/r/48c13184b77ba61ed4fd7c235816fdb8e7530664.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/index.rst | 1 + Documentation/scsi/{lpfc.txt => lpfc.rst} | 16 +++++++--------- 2 files changed, 8 insertions(+), 9 deletions(-) rename Documentation/scsi/{lpfc.txt => lpfc.rst} (93%) diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index c40050ac3b32..22427511e227 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -25,5 +25,6 @@ Linux SCSI Subsystem hptiop libsas link_power_management_policy + lpfc scsi_transport_srp/figures diff --git a/Documentation/scsi/lpfc.txt b/Documentation/scsi/lpfc.rst similarity index 93% rename from Documentation/scsi/lpfc.txt rename to Documentation/scsi/lpfc.rst index 5741ea8aa88a..6e217e82b9b9 100644 --- a/Documentation/scsi/lpfc.txt +++ b/Documentation/scsi/lpfc.rst @@ -1,10 +1,11 @@ +.. SPDX-License-Identifier: GPL-2.0 -LPFC Driver Release Notes: - -============================================================================= +========================= +LPFC Driver Release Notes +========================= - IMPORTANT: +.. important:: Starting in the 8.0.17 release, the driver began to be targeted strictly toward the upstream kernel. As such, we removed #ifdefs for older kernels @@ -22,9 +23,6 @@ LPFC Driver Release Notes: Please heed these dependencies.... - ******************************************************************** - - The following information is provided for additional background on the history of the driver as we push for upstream acceptance. @@ -64,6 +62,7 @@ Cable pull and temporary device Loss: Kernel Support +============== This source package is targeted for the upstream kernel only. (See notes at the top of this file). It relies on interfaces that are slowing @@ -77,7 +76,6 @@ Kernel Support Patches +======= Thankfully, at this time, patches are not needed. - - From a756185de6792278bb5c7d286c9a6fa22722b319 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:55 +0100 Subject: [PATCH 1602/4444] scsi: docs: convert megaraid.txt to ReST Link: https://lore.kernel.org/r/b7ee59230c5a33ff6d60edba0d0bcf3e2aeaa88f.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/index.rst | 1 + .../scsi/{megaraid.txt => megaraid.rst} | 47 +++++++++++-------- MAINTAINERS | 2 +- 3 files changed, 29 insertions(+), 21 deletions(-) rename Documentation/scsi/{megaraid.txt => megaraid.rst} (66%) diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index 22427511e227..37be1fc9d128 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -26,5 +26,6 @@ Linux SCSI Subsystem libsas link_power_management_policy lpfc + megaraid scsi_transport_srp/figures diff --git a/Documentation/scsi/megaraid.txt b/Documentation/scsi/megaraid.rst similarity index 66% rename from Documentation/scsi/megaraid.txt rename to Documentation/scsi/megaraid.rst index 3c7cea51e687..22b75a86ba72 100644 --- a/Documentation/scsi/megaraid.txt +++ b/Documentation/scsi/megaraid.rst @@ -1,7 +1,10 @@ - Notes on Management Module - ~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. SPDX-License-Identifier: GPL-2.0 -Overview: +========================== +Notes on Management Module +========================== + +Overview -------- Different classes of controllers from LSI Logic accept and respond to the @@ -25,28 +28,32 @@ ioctl commands. But this module is envisioned to handle all user space level interactions. So any 'proc', 'sysfs' implementations will be localized in this common module. -Credits: +Credits ------- -"Shared code in a third module, a "library module", is an acceptable -solution. modprobe automatically loads dependent modules, so users -running "modprobe driver1" or "modprobe driver2" would automatically -load the shared library module." +:: - - Jeff Garzik (jgarzik@pobox.com), 02.25.2004 LKML + "Shared code in a third module, a "library module", is an acceptable + solution. modprobe automatically loads dependent modules, so users + running "modprobe driver1" or "modprobe driver2" would automatically + load the shared library module." -"As Jeff hinted, if your userspace<->driver API is consistent between -your new MPT-based RAID controllers and your existing megaraid driver, -then perhaps you need a single small helper module (lsiioctl or some -better name), loaded by both mptraid and megaraid automatically, which -handles registering the /dev/megaraid node dynamically. In this case, -both mptraid and megaraid would register with lsiioctl for each -adapter discovered, and lsiioctl would essentially be a switch, -redirecting userspace tool ioctls to the appropriate driver." +- Jeff Garzik (jgarzik@pobox.com), 02.25.2004 LKML - - Matt Domsch, (Matt_Domsch@dell.com), 02.25.2004 LKML +:: -Design: + "As Jeff hinted, if your userspace<->driver API is consistent between + your new MPT-based RAID controllers and your existing megaraid driver, + then perhaps you need a single small helper module (lsiioctl or some + better name), loaded by both mptraid and megaraid automatically, which + handles registering the /dev/megaraid node dynamically. In this case, + both mptraid and megaraid would register with lsiioctl for each + adapter discovered, and lsiioctl would essentially be a switch, + redirecting userspace tool ioctls to the appropriate driver." + +- Matt Domsch, (Matt_Domsch@dell.com), 02.25.2004 LKML + +Design ------ The Common Management Module is implemented in megaraid_mm.[ch] files. This @@ -61,7 +68,7 @@ uioc_t. The management module converts the older ioctl packets from the older applications into uioc_t. After driver handles the uioc_t, the common module will convert that back into the old format before returning to applications. -As new applications evolve and replace the old ones, the old packet format +As new applications evolve and replace the old ones, the old packet format will be retired. Common module dedicates one uioc_t packet to each controller registered. This diff --git a/MAINTAINERS b/MAINTAINERS index 51cc884037f2..a2e497f95012 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10639,7 +10639,7 @@ L: megaraidlinux.pdl@broadcom.com L: linux-scsi@vger.kernel.org W: http://www.avagotech.com/support/ S: Maintained -F: Documentation/scsi/megaraid.txt +F: Documentation/scsi/megaraid.rst F: drivers/scsi/megaraid.* F: drivers/scsi/megaraid/ From 8dca37d259dff2371d414c51b72b5730e3c1ed01 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2020 09:15:56 +0100 Subject: [PATCH 1603/4444] scsi: docs: convert ncr53c8xx.txt to ReST Link: https://lore.kernel.org/r/cover.1583136624.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- Documentation/scsi/index.rst | 1 + .../scsi/{ncr53c8xx.txt => ncr53c8xx.rst} | 1837 ++++++++++------- drivers/scsi/ncr53c8xx.c | 2 +- 3 files changed, 1093 insertions(+), 747 deletions(-) rename Documentation/scsi/{ncr53c8xx.txt => ncr53c8xx.rst} (55%) diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index 37be1fc9d128..a2545efbb407 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -27,5 +27,6 @@ Linux SCSI Subsystem link_power_management_policy lpfc megaraid + ncr53c8xx scsi_transport_srp/figures diff --git a/Documentation/scsi/ncr53c8xx.txt b/Documentation/scsi/ncr53c8xx.rst similarity index 55% rename from Documentation/scsi/ncr53c8xx.txt rename to Documentation/scsi/ncr53c8xx.rst index 8586efff1e99..c41cec99f07c 100644 --- a/Documentation/scsi/ncr53c8xx.txt +++ b/Documentation/scsi/ncr53c8xx.rst @@ -1,106 +1,114 @@ +.. SPDX-License-Identifier: GPL-2.0 + +================================================= The Linux NCR53C8XX/SYM53C8XX drivers README file +================================================= Written by Gerard Roudier + 21 Rue Carnot + 95170 DEUIL LA BARRE - FRANCE 29 May 1999 -=============================================================================== -1. Introduction -2. Supported chips and SCSI features -3. Advantages of the enhanced 896 driver - 3.1 Optimized SCSI SCRIPTS - 3.2 New features of the SYM53C896 (64 bit PCI dual LVD SCSI controller) -4. Memory mapped I/O versus normal I/O -5. Tagged command queueing -6. Parity checking -7. Profiling information -8. Control commands - 8.1 Set minimum synchronous period - 8.2 Set wide size - 8.3 Set maximum number of concurrent tagged commands - 8.4 Set order type for tagged command - 8.5 Set debug mode - 8.6 Clear profile counters - 8.7 Set flag (no_disc) - 8.8 Set verbose level - 8.9 Reset all logical units of a target - 8.10 Abort all tasks of all logical units of a target -9. Configuration parameters -10. Boot setup commands - 10.1 Syntax - 10.2 Available arguments - 10.2.1 Master parity checking - 10.2.2 Scsi parity checking - 10.2.3 Scsi disconnections - 10.2.4 Special features - 10.2.5 Ultra SCSI support - 10.2.6 Default number of tagged commands - 10.2.7 Default synchronous period factor - 10.2.8 Negotiate synchronous with all devices - 10.2.9 Verbosity level - 10.2.10 Debug mode - 10.2.11 Burst max - 10.2.12 LED support - 10.2.13 Max wide - 10.2.14 Differential mode - 10.2.15 IRQ mode - 10.2.16 Reverse probe - 10.2.17 Fix up PCI configuration space - 10.2.18 Serial NVRAM - 10.2.19 Check SCSI BUS - 10.2.20 Exclude a host from being attached - 10.2.21 Suggest a default SCSI id for hosts - 10.2.22 Enable use of IMMEDIATE ARBITRATION - 10.3 Advised boot setup commands - 10.4 PCI configuration fix-up boot option - 10.5 Serial NVRAM support boot option - 10.6 SCSI BUS checking boot option - 10.7 IMMEDIATE ARBITRATION boot option -11. Some constants and flags of the ncr53c8xx.h header file -12. Installation -13. Architecture dependent features -14. Known problems - 14.1 Tagged commands with Iomega Jaz device - 14.2 Device names change when another controller is added - 14.3 Using only 8 bit devices with a WIDE SCSI controller. - 14.4 Possible data corruption during a Memory Write and Invalidate - 14.5 IRQ sharing problems -15. SCSI problem troubleshooting - 15.1 Problem tracking - 15.2 Understanding hardware error reports -16. Synchronous transfer negotiation tables - 16.1 Synchronous timings for 53C875 and 53C860 Ultra-SCSI controllers - 16.2 Synchronous timings for fast SCSI-2 53C8XX controllers -17. Serial NVRAM support (by Richard Waltham) - 17.1 Features - 17.2 Symbios NVRAM layout - 17.3 Tekram NVRAM layout -18. Support for Big Endian - 18.1 Big Endian CPU - 18.2 NCR chip in Big Endian mode of operations +.. Contents: -=============================================================================== + 1. Introduction + 2. Supported chips and SCSI features + 3. Advantages of the enhanced 896 driver + 3.1 Optimized SCSI SCRIPTS + 3.2 New features of the SYM53C896 (64 bit PCI dual LVD SCSI controller) + 4. Memory mapped I/O versus normal I/O + 5. Tagged command queueing + 6. Parity checking + 7. Profiling information + 8. Control commands + 8.1 Set minimum synchronous period + 8.2 Set wide size + 8.3 Set maximum number of concurrent tagged commands + 8.4 Set order type for tagged command + 8.5 Set debug mode + 8.6 Clear profile counters + 8.7 Set flag (no_disc) + 8.8 Set verbose level + 8.9 Reset all logical units of a target + 8.10 Abort all tasks of all logical units of a target + 9. Configuration parameters + 10. Boot setup commands + 10.1 Syntax + 10.2 Available arguments + 10.2.1 Master parity checking + 10.2.2 Scsi parity checking + 10.2.3 Scsi disconnections + 10.2.4 Special features + 10.2.5 Ultra SCSI support + 10.2.6 Default number of tagged commands + 10.2.7 Default synchronous period factor + 10.2.8 Negotiate synchronous with all devices + 10.2.9 Verbosity level + 10.2.10 Debug mode + 10.2.11 Burst max + 10.2.12 LED support + 10.2.13 Max wide + 10.2.14 Differential mode + 10.2.15 IRQ mode + 10.2.16 Reverse probe + 10.2.17 Fix up PCI configuration space + 10.2.18 Serial NVRAM + 10.2.19 Check SCSI BUS + 10.2.20 Exclude a host from being attached + 10.2.21 Suggest a default SCSI id for hosts + 10.2.22 Enable use of IMMEDIATE ARBITRATION + 10.3 Advised boot setup commands + 10.4 PCI configuration fix-up boot option + 10.5 Serial NVRAM support boot option + 10.6 SCSI BUS checking boot option + 10.7 IMMEDIATE ARBITRATION boot option + 11. Some constants and flags of the ncr53c8xx.h header file + 12. Installation + 13. Architecture dependent features + 14. Known problems + 14.1 Tagged commands with Iomega Jaz device + 14.2 Device names change when another controller is added + 14.3 Using only 8 bit devices with a WIDE SCSI controller. + 14.4 Possible data corruption during a Memory Write and Invalidate + 14.5 IRQ sharing problems + 15. SCSI problem troubleshooting + 15.1 Problem tracking + 15.2 Understanding hardware error reports + 16. Synchronous transfer negotiation tables + 16.1 Synchronous timings for 53C875 and 53C860 Ultra-SCSI controllers + 16.2 Synchronous timings for fast SCSI-2 53C8XX controllers + 17. Serial NVRAM support (by Richard Waltham) + 17.1 Features + 17.2 Symbios NVRAM layout + 17.3 Tekram NVRAM layout + 18. Support for Big Endian + 18.1 Big Endian CPU + 18.2 NCR chip in Big Endian mode of operations 1. Introduction +=============== -The initial Linux ncr53c8xx driver has been a port of the ncr driver from +The initial Linux ncr53c8xx driver has been a port of the ncr driver from FreeBSD that has been achieved in November 1995 by: - Gerard Roudier + + - Gerard Roudier The original driver has been written for 386bsd and FreeBSD by: - Wolfgang Stanglmeier - Stefan Esser + + - Wolfgang Stanglmeier + - Stefan Esser It is now available as a bundle of 2 drivers: -- ncr53c8xx generic driver that supports all the SYM53C8XX family including +- ncr53c8xx generic driver that supports all the SYM53C8XX family including the earliest 810 rev. 1, the latest 896 (2 channel LVD SCSI controller) and the new 895A (1 channel LVD SCSI controller). -- sym53c8xx enhanced driver (a.k.a. 896 drivers) that drops support of oldest - chips in order to gain advantage of new features, as LOAD/STORE instructions - available since the 810A and hardware phase mismatch available with the +- sym53c8xx enhanced driver (a.k.a. 896 drivers) that drops support of oldest + chips in order to gain advantage of new features, as LOAD/STORE instructions + available since the 810A and hardware phase mismatch available with the 896 and the 895A. You can find technical information about the NCR 8xx family in the @@ -109,119 +117,145 @@ Drew Eckhardt. Information about new chips is available at LSILOGIC web server: - http://www.lsilogic.com/ + - http://www.lsilogic.com/ SCSI standard documentations are available at SYMBIOS ftp server: - ftp://ftp.symbios.com/ + - ftp://ftp.symbios.com/ Useful SCSI tools written by Eric Youngdale are available at tsx-11: - ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/scsiinfo-X.Y.tar.gz - ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/scsidev-X.Y.tar.gz + - ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/scsiinfo-X.Y.tar.gz + - ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/scsidev-X.Y.tar.gz These tools are not ALPHA but quite clean and work quite well. It is essential you have the 'scsiinfo' package. This short documentation describes the features of the generic and enhanced -drivers, configuration parameters and control commands available through +drivers, configuration parameters and control commands available through the proc SCSI file system read / write operations. This driver has been tested OK with linux/i386, Linux/Alpha and Linux/PPC. Latest driver version and patches are available at: - ftp://ftp.tux.org/pub/people/gerard-roudier + - ftp://ftp.tux.org/pub/people/gerard-roudier + or - ftp://ftp.symbios.com/mirror/ftp.tux.org/pub/tux/roudier/drivers + + - ftp://ftp.symbios.com/mirror/ftp.tux.org/pub/tux/roudier/drivers I am not a native speaker of English and there are probably lots of mistakes in this README file. Any help will be welcome. 2. Supported chips and SCSI features +==================================== The following features are supported for all chips: - Synchronous negotiation - Disconnection - Tagged command queuing - SCSI parity checking - Master parity checking + - Synchronous negotiation + - Disconnection + - Tagged command queuing + - SCSI parity checking + - Master parity checking "Wide negotiation" is supported for chips that allow it. The -following table shows some characteristics of NCR 8xx family chips +following table shows some characteristics of NCR 8xx family chips and what drivers support them. - Supported by Supported by - On board the generic the enhanced -Chip SDMS BIOS Wide SCSI std. Max. sync driver driver ----- --------- ---- --------- ---------- ------------ ------------- -810 N N FAST10 10 MB/s Y N -810A N N FAST10 10 MB/s Y Y -815 Y N FAST10 10 MB/s Y N -825 Y Y FAST10 20 MB/s Y N -825A Y Y FAST10 20 MB/s Y Y -860 N N FAST20 20 MB/s Y Y -875 Y Y FAST20 40 MB/s Y Y -876 Y Y FAST20 40 MB/s Y Y -895 Y Y FAST40 80 MB/s Y Y -895A Y Y FAST40 80 MB/s Y Y -896 Y Y FAST40 80 MB/s Y Y -897 Y Y FAST40 80 MB/s Y Y -1510D Y Y FAST40 80 MB/s Y Y -1010 Y Y FAST80 160 MB/s N Y -1010_66* Y Y FAST80 160 MB/s N Y ++--------+-----------+-----+-----------+------------+------------+------------+ +| | | | | |Supported by|Supported by| +| |On board | | | |the generic |the enhanced| +|Chip |SDMS BIOS |Wide |SCSI std. | Max. sync |driver |driver | ++--------+-----------+-----+-----------+------------+------------+------------+ +|810 | N | N | FAST10 | 10 MB/s | Y | N | ++--------+-----------+-----+-----------+------------+------------+------------+ +|810A | N | N | FAST10 | 10 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|815 | Y | N | FAST10 | 10 MB/s | Y | N | ++--------+-----------+-----+-----------+------------+------------+------------+ +|825 | Y | Y | FAST10 | 20 MB/s | Y | N | ++--------+-----------+-----+-----------+------------+------------+------------+ +|825A | Y | Y | FAST10 | 20 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|860 | N | N | FAST20 | 20 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|875 | Y | Y | FAST20 | 40 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|876 | Y | Y | FAST20 | 40 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|895 | Y | Y | FAST40 | 80 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|895A | Y | Y | FAST40 | 80 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|896 | Y | Y | FAST40 | 80 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|897 | Y | Y | FAST40 | 80 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|1510D | Y | Y | FAST40 | 80 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|1010 | Y | Y | FAST80 |160 MB/s | N | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|1010_66 | Y | Y | FAST80 |160 MB/s | N | Y | +|[1]_ | | | | | | | ++--------+-----------+-----+-----------+------------+------------+------------+ -* Chip supports 33MHz and 66MHz PCI buses. +.. [1] Chip supports 33MHz and 66MHz PCI buses. Summary of other supported features: -Module: allow to load the driver -Memory mapped I/O: increases performance -Profiling information: read operations from the proc SCSI file system -Control commands: write operations to the proc SCSI file system -Debugging information: written to syslog (expert only) -Scatter / gather -Shared interrupt -Boot setup commands -Serial NVRAM: Symbios and Tekram formats +:Module: allow to load the driver +:Memory mapped I/O: increases performance +:Profiling information: read operations from the proc SCSI file system +:Control commands: write operations to the proc SCSI file system +:Debugging information: written to syslog (expert only) +:Serial NVRAM: Symbios and Tekram formats + +- Scatter / gather +- Shared interrupt +- Boot setup commands 3. Advantages of the enhanced 896 driver +======================================== -3.1 Optimized SCSI SCRIPTS. +3.1 Optimized SCSI SCRIPTS +-------------------------- -The 810A, 825A, 875, 895, 896 and 895A support new SCSI SCRIPTS instructions -named LOAD and STORE that allow to move up to 1 DWORD from/to an IO register -to/from memory much faster that the MOVE MEMORY instruction that is supported +The 810A, 825A, 875, 895, 896 and 895A support new SCSI SCRIPTS instructions +named LOAD and STORE that allow to move up to 1 DWORD from/to an IO register +to/from memory much faster that the MOVE MEMORY instruction that is supported by the 53c7xx and 53c8xx family. -The LOAD/STORE instructions support absolute and DSA relative addressing -modes. The SCSI SCRIPTS had been entirely rewritten using LOAD/STORE instead +The LOAD/STORE instructions support absolute and DSA relative addressing +modes. The SCSI SCRIPTS had been entirely rewritten using LOAD/STORE instead of MOVE MEMORY instructions. 3.2 New features of the SYM53C896 (64 bit PCI dual LVD SCSI controller) +----------------------------------------------------------------------- -The 896 and the 895A allows handling of the phase mismatch context from -SCRIPTS (avoids the phase mismatch interrupt that stops the SCSI processor +The 896 and the 895A allows handling of the phase mismatch context from +SCRIPTS (avoids the phase mismatch interrupt that stops the SCSI processor until the C code has saved the context of the transfer). -Implementing this without using LOAD/STORE instructions would be painful +Implementing this without using LOAD/STORE instructions would be painful and I didn't even want to try it. -The 896 chip supports 64 bit PCI transactions and addressing, while the +The 896 chip supports 64 bit PCI transactions and addressing, while the 895A supports 32 bit PCI transactions and 64 bit addressing. -The SCRIPTS processor of these chips is not true 64 bit, but uses segment -registers for bit 32-63. Another interesting feature is that LOAD/STORE +The SCRIPTS processor of these chips is not true 64 bit, but uses segment +registers for bit 32-63. Another interesting feature is that LOAD/STORE instructions that address the on-chip RAM (8k) remain internal to the chip. -Due to the use of LOAD/STORE SCRIPTS instructions, this driver does not +Due to the use of LOAD/STORE SCRIPTS instructions, this driver does not support the following chips: + - SYM53C810 revision < 0x10 (16) - SYM53C815 all revisions - SYM53C825 revision < 0x10 (16) 4. Memory mapped I/O versus normal I/O +====================================== Memory mapped I/O has less latency than normal I/O. Since linux-1.3.x, memory mapped I/O is used rather than normal I/O. Memory @@ -233,17 +267,18 @@ driver to use normal I/O in all cases. 5. Tagged command queueing +========================== -Queuing more than 1 command at a time to a device allows it to perform -optimizations based on actual head positions and its mechanical +Queuing more than 1 command at a time to a device allows it to perform +optimizations based on actual head positions and its mechanical characteristics. This feature may also reduce average command latency. -In order to really gain advantage of this feature, devices must have -a reasonable cache size (No miracle is to be expected for a low-end +In order to really gain advantage of this feature, devices must have +a reasonable cache size (No miracle is to be expected for a low-end hard disk with 128 KB or less). Some known SCSI devices do not properly support tagged command queuing. -Generally, firmware revisions that fix this kind of problems are available +Generally, firmware revisions that fix this kind of problems are available at respective vendor web/ftp sites. -All I can say is that the hard disks I use on my machines behave well with +All I can say is that the hard disks I use on my machines behave well with this driver with tagged command queuing enabled: - IBM S12 0662 @@ -251,9 +286,9 @@ this driver with tagged command queuing enabled: - Quantum Atlas I - Quantum Atlas II -If your controller has NVRAM, you can configure this feature per target -from the user setup tool. The Tekram Setup program allows to tune the -maximum number of queued commands up to 32. The Symbios Setup only allows +If your controller has NVRAM, you can configure this feature per target +from the user setup tool. The Tekram Setup program allows to tune the +maximum number of queued commands up to 32. The Symbios Setup only allows to enable or disable this feature. The maximum number of simultaneous tagged commands queued to a device @@ -261,16 +296,16 @@ is currently set to 8 by default. This value is suitable for most SCSI disks. With large SCSI disks (>= 2GB, cache >= 512KB, average seek time <= 10 ms), using a larger value may give better performances. -The sym53c8xx driver supports up to 255 commands per device, and the -generic ncr53c8xx driver supports up to 64, but using more than 32 is -generally not worth-while, unless you are using a very large disk or disk -array. It is noticeable that most of recent hard disks seem not to accept -more than 64 simultaneous commands. So, using more than 64 queued commands +The sym53c8xx driver supports up to 255 commands per device, and the +generic ncr53c8xx driver supports up to 64, but using more than 32 is +generally not worth-while, unless you are using a very large disk or disk +array. It is noticeable that most of recent hard disks seem not to accept +more than 64 simultaneous commands. So, using more than 64 queued commands is probably just resource wasting. -If your controller does not have NVRAM or if it is managed by the SDMS -BIOS/SETUP, you can configure tagged queueing feature and device queue -depths from the boot command-line. For example: +If your controller does not have NVRAM or if it is managed by the SDMS +BIOS/SETUP, you can configure tagged queueing feature and device queue +depths from the boot command-line. For example:: ncr53c8xx=tags:4/t2t3q15-t4q7/t1u0q32 @@ -286,80 +321,85 @@ In some special conditions, some SCSI disk firmwares may return a QUEUE FULL status for a SCSI command. This behaviour is managed by the driver using the following heuristic: -- Each time a QUEUE FULL status is returned, tagged queue depth is reduced - to the actual number of disconnected commands. +- Each time a QUEUE FULL status is returned, tagged queue depth is reduced + to the actual number of disconnected commands. - Every 1000 successfully completed SCSI commands, if allowed by the current limit, the maximum number of queueable commands is incremented. -Since QUEUE FULL status reception and handling is resource wasting, the -driver notifies by default this problem to user by indicating the actual -number of commands used and their status, as well as its decision on the +Since QUEUE FULL status reception and handling is resource wasting, the +driver notifies by default this problem to user by indicating the actual +number of commands used and their status, as well as its decision on the device queue depth change. -The heuristic used by the driver in handling QUEUE FULL ensures that the -impact on performances is not too bad. You can get rid of the messages by +The heuristic used by the driver in handling QUEUE FULL ensures that the +impact on performances is not too bad. You can get rid of the messages by setting verbose level to zero, as follow: -1st method: boot your system using 'ncr53c8xx=verb:0' option. -2nd method: apply "setverbose 0" control command to the proc fs entry +1st method: + boot your system using 'ncr53c8xx=verb:0' option. + +2nd method: + apply "setverbose 0" control command to the proc fs entry corresponding to your controller after boot-up. 6. Parity checking +================== The driver supports SCSI parity checking and PCI bus master parity checking. These features must be enabled in order to ensure safe data transfers. However, some flawed devices or mother boards will have -problems with parity. You can disable either PCI parity or SCSI parity +problems with parity. You can disable either PCI parity or SCSI parity checking by entering appropriate options from the boot command line. (See 10: Boot setup commands). 7. Profiling information +======================== Profiling information is available through the proc SCSI file system. -Since gathering profiling information may impact performances, this -feature is disabled by default and requires a compilation configuration +Since gathering profiling information may impact performances, this +feature is disabled by default and requires a compilation configuration option to be set to Y. -The device associated with a host has the following pathname: +The device associated with a host has the following pathname:: /proc/scsi/ncr53c8xx/N (N=0,1,2 ....) -Generally, only 1 board is used on hardware configuration, and that device is: +Generally, only 1 board is used on hardware configuration, and that device is:: + /proc/scsi/ncr53c8xx/0 However, if the driver has been made as module, the number of the hosts is incremented each time the driver is loaded. -In order to display profiling information, just enter: +In order to display profiling information, just enter:: cat /proc/scsi/ncr53c8xx/0 -and you will get something like the following text: +and you will get something like the following text:: -------------------------------------------------------- -General information: - Chip NCR53C810, device id 0x1, revision id 0x2 - IO port address 0x6000, IRQ number 10 - Using memory mapped IO at virtual address 0x282c000 - Synchronous transfer period 25, max commands per lun 4 -Profiling information: - num_trans = 18014 - num_kbytes = 671314 - num_disc = 25763 - num_break = 1673 - num_int = 1685 - num_fly = 18038 - ms_setup = 4940 - ms_data = 369940 - ms_disc = 183090 - ms_post = 1320 -------------------------------------------------------- + General information: + Chip NCR53C810, device id 0x1, revision id 0x2 + IO port address 0x6000, IRQ number 10 + Using memory mapped IO at virtual address 0x282c000 + Synchronous transfer period 25, max commands per lun 4 + Profiling information: + num_trans = 18014 + num_kbytes = 671314 + num_disc = 25763 + num_break = 1673 + num_int = 1685 + num_fly = 18038 + ms_setup = 4940 + ms_data = 369940 + ms_disc = 183090 + ms_post = 1320 General information is easy to understand. The device ID and the revision ID identify the SCSI chip as follows: +======= ============= =========== Chip Device id Revision Id ----- --------- ----------- +======= ============= =========== 810 0x1 < 0x10 810A 0x1 >= 0x10 815 0x4 @@ -368,6 +408,7 @@ Chip Device id Revision Id 825A 0x3 >= 0x10 875 0xf 895 0xc +======= ============= =========== The profiling information is updated upon completion of SCSI commands. A data structure is allocated and zeroed when the host adapter is @@ -425,15 +466,16 @@ Due to the 1/100 second tick of the system clock, "ms_post" time may be wrong. In the example above, we got 18038 interrupts "on the fly" and only -1673 script breaks generally due to disconnections inside a segment +1673 script breaks generally due to disconnections inside a segment of the scatter list. 8. Control commands +=================== Control commands can be sent to the driver with write operations to the proc SCSI file system. The generic command syntax is the -following: +following:: echo " " >/proc/scsi/ncr53c8xx/0 (assumes controller number is 0) @@ -444,66 +486,81 @@ apply to all targets of the SCSI chain (except the controller). Available commands: 8.1 Set minimum synchronous period factor +----------------------------------------- setsync - target: target number - period: minimum synchronous period. + :target: target number + :period: minimum synchronous period. Maximum speed = 1000/(4*period factor) except for special cases below. Specify a period of 255, to force asynchronous transfer mode. - 10 means 25 nano-seconds synchronous period - 11 means 30 nano-seconds synchronous period - 12 means 50 nano-seconds synchronous period + - 10 means 25 nano-seconds synchronous period + - 11 means 30 nano-seconds synchronous period + - 12 means 50 nano-seconds synchronous period 8.2 Set wide size +----------------- setwide - target: target number - size: 0=8 bits, 1=16bits + :target: target number + :size: 0=8 bits, 1=16bits 8.3 Set maximum number of concurrent tagged commands - +---------------------------------------------------- + settags - target: target number - tags: number of concurrent tagged commands + :target: target number + :tags: number of concurrent tagged commands must not be greater than SCSI_NCR_MAX_TAGS (default: 8) 8.4 Set order type for tagged command +------------------------------------- setorder - order: 3 possible values: - simple: use SIMPLE TAG for all operations (read and write) - ordered: use ORDERED TAG for all operations - default: use default tag type, + :order: 3 possible values: + + simple: + use SIMPLE TAG for all operations (read and write) + + ordered: + use ORDERED TAG for all operations + + default: + use default tag type, SIMPLE TAG for read operations ORDERED TAG for write operations 8.5 Set debug mode +------------------ setdebug Available debug flags: - alloc: print info about memory allocations (ccb, lcb) - queue: print info about insertions into the command start queue - result: print sense data on CHECK CONDITION status - scatter: print info about the scatter process - scripts: print info about the script binding process - tiny: print minimal debugging information - timing: print timing information of the NCR chip - nego: print information about SCSI negotiations - phase: print information on script interruptions + + ======== ======================================================== + alloc print info about memory allocations (ccb, lcb) + queue print info about insertions into the command start queue + result print sense data on CHECK CONDITION status + scatter print info about the scatter process + scripts print info about the script binding process + tiny print minimal debugging information + timing print timing information of the NCR chip + nego print information about SCSI negotiations + phase print information on script interruptions + ======== ======================================================== Use "setdebug" with no argument to reset debug flags. 8.6 Clear profile counters +-------------------------- clearprof @@ -513,7 +570,8 @@ Available commands: 8.7 Set flag (no_disc) - +---------------------- + setflag target: target number @@ -523,38 +581,47 @@ Available commands: no_disc: not allow target to disconnect. Do not specify any flag in order to reset the flag. For example: - - setflag 4 + + setflag 4 will reset no_disc flag for target 4, so will allow it disconnections. - - setflag all + + setflag all will allow disconnection for all devices on the SCSI bus. 8.8 Set verbose level +--------------------- setverbose #level - The driver default verbose level is 1. This command allows to change + The driver default verbose level is 1. This command allows to change th driver verbose level after boot-up. 8.9 Reset all logical units of a target +--------------------------------------- resetdev - target: target number + :target: target number + The driver will try to send a BUS DEVICE RESET message to the target. (Only supported by the SYM53C8XX driver and provided for test purpose) 8.10 Abort all tasks of all logical units of a target +----------------------------------------------------- cleardev - target: target number - The driver will try to send a ABORT message to all the logical units + :target: target number + + The driver will try to send a ABORT message to all the logical units of the target. + (Only supported by the SYM53C8XX driver and provided for test purpose) 9. Configuration parameters +=========================== If the firmware of all your devices is perfect enough, all the features supported by the driver can be enabled at start-up. However, @@ -564,6 +631,7 @@ this feature after boot-up only for devices that support it safely. CONFIG_SCSI_NCR53C8XX_IOMAPPED (default answer: n) Answer "y" if you suspect your mother board to not allow memory mapped I/O. + May slow down performance a little. This option is required by Linux/PPC and is used no matter what you select here. Linux/PPC suffers no performance loss with this option since all IO is memory @@ -573,35 +641,37 @@ CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS (default answer: 8) Default tagged command queue depth. CONFIG_SCSI_NCR53C8XX_MAX_TAGS (default answer: 8) - This option allows you to specify the maximum number of tagged commands + This option allows you to specify the maximum number of tagged commands that can be queued to a device. The maximum supported value is 32. CONFIG_SCSI_NCR53C8XX_SYNC (default answer: 5) - This option allows you to specify the frequency in MHz the driver + This option allows you to specify the frequency in MHz the driver will use at boot time for synchronous data transfer negotiations. This frequency can be changed later with the "setsync" control command. 0 means "asynchronous data transfers". CONFIG_SCSI_NCR53C8XX_FORCE_SYNC_NEGO (default answer: n) Force synchronous negotiation for all SCSI-2 devices. - Some SCSI-2 devices do not report this feature in byte 7 of inquiry + + Some SCSI-2 devices do not report this feature in byte 7 of inquiry response but do support it properly (TAMARACK scanners for example). CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT (default and only reasonable answer: n) If you suspect a device of yours does not properly support disconnections, - you can answer "y". Then, all SCSI devices will never disconnect the bus + you can answer "y". Then, all SCSI devices will never disconnect the bus even while performing long SCSI operations. CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT - Genuine SYMBIOS boards use GPIO0 in output for controller LED and GPIO3 + Genuine SYMBIOS boards use GPIO0 in output for controller LED and GPIO3 bit as a flag indicating singled-ended/differential interface. If all the boards of your system are genuine SYMBIOS boards or use BIOS and drivers from SYMBIOS, you would want to enable this option. - This option must NOT be enabled if your system has at least one 53C8XX + + This option must NOT be enabled if your system has at least one 53C8XX based scsi board with a vendor-specific BIOS. - For example, Tekram DC-390/U, DC-390/W and DC-390/F scsi controllers - use a vendor-specific BIOS and are known to not use SYMBIOS compatible - GPIO wiring. So, this option must not be enabled if your system has + For example, Tekram DC-390/U, DC-390/W and DC-390/F scsi controllers + use a vendor-specific BIOS and are known to not use SYMBIOS compatible + GPIO wiring. So, this option must not be enabled if your system has such a board installed. CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT @@ -610,7 +680,7 @@ CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT systems with more than one Symbios compatible controller where at least one has a serial NVRAM, or for a system with a mixture of Symbios and Tekram cards. Enables setting the boot order of host adaptors - to something other than the default order or "reverse probe" order. + to something other than the default order or "reverse probe" order. Also enables Symbios and Tekram cards to be distinguished so CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT may be set in a system with a mixture of Symbios and Tekram cards so the Symbios cards can make use of @@ -618,243 +688,364 @@ CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT causing problems for the Tekram card(s). 10. Boot setup commands +======================= 10.1 Syntax +----------- -Setup commands can be passed to the driver either at boot time or as a +Setup commands can be passed to the driver either at boot time or as a string variable using 'insmod'. -A boot setup command for the ncr53c8xx (sym53c8xx) driver begins with the -driver name "ncr53c8xx="(sym53c8xx). The kernel syntax parser then expects -an optional list of integers separated with comma followed by an optional -list of comma-separated strings. Example of boot setup command under lilo -prompt: +A boot setup command for the ncr53c8xx (sym53c8xx) driver begins with the +driver name "ncr53c8xx="(sym53c8xx). The kernel syntax parser then expects +an optional list of integers separated with comma followed by an optional +list of comma-separated strings. Example of boot setup command under lilo +prompt:: -lilo: linux root=/dev/hda2 ncr53c8xx=tags:4,sync:10,debug:0x200 + lilo: linux root=/dev/hda2 ncr53c8xx=tags:4,sync:10,debug:0x200 - enable tagged commands, up to 4 tagged commands queued. - set synchronous negotiation speed to 10 Mega-transfers / second. - set DEBUG_NEGO flag. -Since comma seems not to be allowed when defining a string variable using -'insmod', the driver also accepts as option separator. -The following command will install driver module with the same options as -above. +Since comma seems not to be allowed when defining a string variable using +'insmod', the driver also accepts as option separator. +The following command will install driver module with the same options as +above:: insmod ncr53c8xx.o ncr53c8xx="tags:4 sync:10 debug:0x200" -For the moment, the integer list of arguments is discarded by the driver. +For the moment, the integer list of arguments is discarded by the driver. It will be used in the future in order to allow a per controller setup. -Each string argument must be specified as "keyword:value". Only lower-case +Each string argument must be specified as "keyword:value". Only lower-case characters and digits are allowed. -In a system that contains multiple 53C8xx adapters insmod will install the +In a system that contains multiple 53C8xx adapters insmod will install the specified driver on each adapter. To exclude a chip use the 'excl' keyword. -The sequence of commands, +The sequence of commands:: insmod sym53c8xx sym53c8xx=excl:0x1400 insmod ncr53c8xx -installs the sym53c8xx driver on all adapters except the one at IO port -address 0x1400 and then installs the ncr53c8xx driver to the adapter at IO +installs the sym53c8xx driver on all adapters except the one at IO port +address 0x1400 and then installs the ncr53c8xx driver to the adapter at IO port address 0x1400. 10.2 Available arguments +------------------------ 10.2.1 Master parity checking +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ====== ======== mpar:y enabled mpar:n disabled + ====== ======== 10.2.2 Scsi parity checking +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ====== ======== spar:y enabled spar:n disabled + ====== ======== 10.2.3 Scsi disconnections +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ====== ======== disc:y enabled disc:n disabled - + ====== ======== + 10.2.4 Special features +^^^^^^^^^^^^^^^^^^^^^^^^ + Only apply to 810A, 825A, 860, 875 and 895 controllers. Have no effect with other ones. + + ======= ================================================= specf:y (or 1) enabled specf:n (or 0) disabled specf:3 enabled except Memory Write And Invalidate - The default driver setup is 'specf:3'. As a consequence, option 'specf:y' - must be specified in the boot setup command to enable Memory Write And + ======= ================================================= + + The default driver setup is 'specf:3'. As a consequence, option 'specf:y' + must be specified in the boot setup command to enable Memory Write And Invalidate. 10.2.5 Ultra SCSI support +^^^^^^^^^^^^^^^^^^^^^^^^^^ + Only apply to 860, 875, 895, 895a, 896, 1010 and 1010_66 controllers. Have no effect with other ones. + + ======= ======================== ultra:n All ultra speeds enabled ultra:2 Ultra2 enabled ultra:1 Ultra enabled ultra:0 Ultra speeds disabled + ======= ======================== 10.2.6 Default number of tagged commands +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ======================= =============================== tags:0 (or tags:1 ) tagged command queuing disabled tags:#tags (#tags > 1) tagged command queuing enabled + ======================= =============================== + #tags will be truncated to the max queued commands configuration parameter. - This option also allows to specify a command queue depth for each device + This option also allows to specify a command queue depth for each device that support tagged command queueing. - Example: + + Example:: + ncr53c8xx=tags:10/t2t3q16-t5q24/t1u2q32 - will set devices queue depth as follow: + + will set devices queue depth as follow: + - controller #0 target #2 and target #3 -> 16 commands, - controller #0 target #5 -> 24 commands, - controller #1 target #1 logical unit #2 -> 32 commands, - all other logical units (all targets, all controllers) -> 10 commands. 10.2.7 Default synchronous period factor - sync:255 disabled (asynchronous transfer mode) - sync:#factor - #factor = 10 Ultra-2 SCSI 40 Mega-transfers / second - #factor = 11 Ultra-2 SCSI 33 Mega-transfers / second - #factor < 25 Ultra SCSI 20 Mega-transfers / second - #factor < 50 Fast SCSI-2 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - In all cases, the driver will use the minimum transfer period supported by +============ ======================================================== +sync:255 disabled (asynchronous transfer mode) +sync:#factor + ============ ======================================= + #factor = 10 Ultra-2 SCSI 40 Mega-transfers / second + #factor = 11 Ultra-2 SCSI 33 Mega-transfers / second + #factor < 25 Ultra SCSI 20 Mega-transfers / second + #factor < 50 Fast SCSI-2 + ============ ======================================= +============ ======================================================== + + In all cases, the driver will use the minimum transfer period supported by controllers according to NCR53C8XX chip type. 10.2.8 Negotiate synchronous with all devices +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (force sync nego) + + ===== ========= fsn:y enabled fsn:n disabled + ===== ========= 10.2.9 Verbosity level +^^^^^^^^^^^^^^^^^^^^^^^ + + ====== ========= verb:0 minimal verb:1 normal verb:2 too much + ====== ========= 10.2.10 Debug mode - debug:0 clear debug flags - debug:#x set debug flags - #x is an integer value combining the following power-of-2 values: - DEBUG_ALLOC 0x1 - DEBUG_PHASE 0x2 - DEBUG_POLL 0x4 - DEBUG_QUEUE 0x8 - DEBUG_RESULT 0x10 - DEBUG_SCATTER 0x20 - DEBUG_SCRIPT 0x40 - DEBUG_TINY 0x80 - DEBUG_TIMING 0x100 - DEBUG_NEGO 0x200 - DEBUG_TAGS 0x400 - DEBUG_FREEZE 0x800 - DEBUG_RESTART 0x1000 +^^^^^^^^^^^^^^^^^^ - You can play safely with DEBUG_NEGO. However, some of these flags may - generate bunches of syslog messages. +======== ================================================================== +debug:0 clear debug flags +debug:#x set debug flags + + #x is an integer value combining the following power-of-2 values: + + ============= ====== + DEBUG_ALLOC 0x1 + DEBUG_PHASE 0x2 + DEBUG_POLL 0x4 + DEBUG_QUEUE 0x8 + DEBUG_RESULT 0x10 + DEBUG_SCATTER 0x20 + DEBUG_SCRIPT 0x40 + DEBUG_TINY 0x80 + DEBUG_TIMING 0x100 + DEBUG_NEGO 0x200 + DEBUG_TAGS 0x400 + DEBUG_FREEZE 0x800 + DEBUG_RESTART 0x1000 + ============= ====== +======== ================================================================== + + You can play safely with DEBUG_NEGO. However, some of these flags may + generate bunches of syslog messages. 10.2.11 Burst max - burst:0 burst disabled - burst:255 get burst length from initial IO register settings. - burst:#x burst enabled (1<<#x burst transfers max) - #x is an integer value which is log base 2 of the burst transfers max. - The NCR53C875 and NCR53C825A support up to 128 burst transfers (#x = 7). - Other chips only support up to 16 (#x = 4). - This is a maximum value. The driver set the burst length according to chip - and revision ids. By default the driver uses the maximum value supported - by the chip. +^^^^^^^^^^^^^^^^^ + +========= ================================================================== +burst:0 burst disabled +burst:255 get burst length from initial IO register settings. +burst:#x burst enabled (1<<#x burst transfers max) + + #x is an integer value which is log base 2 of the burst transfers + max. + + The NCR53C875 and NCR53C825A support up to 128 burst transfers + (#x = 7). + + Other chips only support up to 16 (#x = 4). + + This is a maximum value. The driver set the burst length according + to chip and revision ids. By default the driver uses the maximum + value supported by the chip. +========= ================================================================== 10.2.12 LED support +^^^^^^^^^^^^^^^^^^^ + + ===== =================== led:1 enable LED support led:0 disable LED support + ===== =================== + Donnot enable LED support if your scsi board does not use SDMS BIOS. (See 'Configuration parameters') 10.2.13 Max wide +^^^^^^^^^^^^^^^^ + + ====== =================== wide:1 wide scsi enabled wide:0 wide scsi disabled + ====== =================== + Some scsi boards use a 875 (ultra wide) and only supply narrow connectors. - If you have connected a wide device with a 50 pins to 68 pins cable + If you have connected a wide device with a 50 pins to 68 pins cable converter, any accepted wide negotiation will break further data transfers. - In such a case, using "wide:0" in the bootup command will be helpful. + In such a case, using "wide:0" in the bootup command will be helpful. 10.2.14 Differential mode +^^^^^^^^^^^^^^^^^^^^^^^^^ + + ====== ================================= diff:0 never set up diff mode diff:1 set up diff mode if BIOS set it diff:2 always set up diff mode diff:3 set diff mode if GPIO3 is not set + ====== ================================= 10.2.15 IRQ mode +^^^^^^^^^^^^^^^^ + + ========= ======================================================== irqm:0 always open drain irqm:1 same as initial settings (assumed BIOS settings) irqm:2 always totem pole irqm:0x10 driver will not use IRQF_SHARED flag when requesting irq + ========= ======================================================== (Bits 0x10 and 0x20 can be combined with hardware irq mode option) 10.2.16 Reverse probe +^^^^^^^^^^^^^^^^^^^^^ + + ========= ======================================================== revprob:n probe chip ids from the PCI configuration in this order: 810, 815, 820, 860, 875, 885, 895, 896 revprob:y probe chip ids in the reverse order. + ========= ======================================================== 10.2.17 Fix up PCI configuration space +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pcifix: