* Re: [PATCH 2/5] drivers: gpio: Add support for multiple IPs
From: Linus Walleij @ 2016-11-05 8:23 UTC (permalink / raw)
To: Grygorii Strashko
Cc: Keerthy, Roger Quadros, Alexandre Courbot, Lokesh Vutla,
Rob Herring, linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linux-OMAP
In-Reply-To: <b92f729b-5897-c29a-31ec-97510776d85d-l0cyMroinI0@public.gmane.org>
On Fri, Nov 4, 2016 at 8:59 PM, Grygorii Strashko
<grygorii.strashko-l0cyMroinI0@public.gmane.org> wrote:
> On 11/04/2016 09:28 AM, Linus Walleij wrote:
>> The DT model sort of mandates how the interrupts should be mapped
>> at this point, and as far as I can tell from the binding the example looks
>> like so:
>>
>> gpio: gpio@1e26000 {
>> compatible = "ti,dm6441-gpio";
>> gpio-controller;
>> #gpio-cells = <2>;
>> reg = <0x226000 0x1000>;
>> interrupt-parent = <&intc>;
>> interrupts = <42 IRQ_TYPE_EDGE_BOTH 43 IRQ_TYPE_EDGE_BOTH
>> 44 IRQ_TYPE_EDGE_BOTH 45 IRQ_TYPE_EDGE_BOTH
>> 46 IRQ_TYPE_EDGE_BOTH 47 IRQ_TYPE_EDGE_BOTH
>> 48 IRQ_TYPE_EDGE_BOTH 49 IRQ_TYPE_EDGE_BOTH
>> 50 IRQ_TYPE_EDGE_BOTH>;
>> ti,ngpio = <144>;
>> ti,davinci-gpio-unbanked = <0>;
>> interrupt-controller;
>> #interrupt-cells = <2>;
>> };
>
> Above, DT bindings models Davinci GPIO IP as monolithic GPIO controller
> with N gpio pins, but internally separate GPIO chips are created for each
> banksX&Y register set (32 pins, 2 banked irq -or- 32 direct irqs).
Hm it would be good to get away from that and just have one big gpio
chip.
> Translation from linear GPIO numbering to the proper internal GPIO chip is done
> using chip.of_xlate().
Yeah :/ this could be made simpler with a single chip just spanning all
the banks and the common registers I think.
Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2 1/2] phy: rockchip-inno-usb2: support otg-port for rk3399
From: wlf @ 2016-11-05 2:58 UTC (permalink / raw)
To: Kishon Vijay Abraham I, heiko-4mtYJXux2i+zQB+pC5nmwQ
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
frank.wang-TNX95d0MmH7DzftRWevZcw,
huangtao-TNX95d0MmH7DzftRWevZcw, dianders-hpIqsD4AKlfQT0dZR+AlfA,
briannorris-hpIqsD4AKlfQT0dZR+AlfA, groeck-hpIqsD4AKlfQT0dZR+AlfA
In-Reply-To: <0eeb3dd9-fc1e-f04b-4612-06367929ede6-l0cyMroinI0@public.gmane.org>
Hi Kishon,
在 2016年11月04日 01:17, Kishon Vijay Abraham I 写道:
>
> On Thursday 03 November 2016 07:36 AM, William Wu wrote:
>> The rk3399 SoC USB2 PHY is comprised of one Host port and
>> one OTG port. And OTG port is for USB2.0 part of USB3.0 OTG
>> controller, as a part to construct a fully feature Type-C
>> subsystem.
>>
>> With this patch, we can support OTG port with the following
>> functions:
>> - Support BC1.2 charger detect, and use extcon notifier to
>> send USB charger types to power driver.
>> - Support PHY suspend for power management.
>> - Support OTG Host only mode.
>>
>> Also, correct 480MHz output clock stable time. We found that
>> the system crashed due to 480MHz output clock of USB2 PHY was
>> unstable after clock had been enabled by gpu module.
> Can you split the clock fix into a separate patch?
OK, I will separate the clock patch in next version.
Best regards,
wulf
>
> Thanks
> Kishon
>> Theoretically, 1 millisecond is a critical value for 480 output
>> clock stable time, so we try changing the delay time to 1.2
>> millisecond to avoid this issue.
>>
>> Signed-off-by: William Wu <wulf-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
>> ---
>> Changes in v2:
>> - remove wakelock
>>
>> drivers/phy/phy-rockchip-inno-usb2.c | 593 +++++++++++++++++++++++++++++++++--
>> 1 file changed, 562 insertions(+), 31 deletions(-)
>>
>> diff --git a/drivers/phy/phy-rockchip-inno-usb2.c b/drivers/phy/phy-rockchip-inno-usb2.c
>> index ac20310..8f2d2b6 100644
>> --- a/drivers/phy/phy-rockchip-inno-usb2.c
>> +++ b/drivers/phy/phy-rockchip-inno-usb2.c
>> @@ -17,6 +17,7 @@
>> #include <linux/clk.h>
>> #include <linux/clk-provider.h>
>> #include <linux/delay.h>
>> +#include <linux/extcon.h>
>> #include <linux/interrupt.h>
>> #include <linux/io.h>
>> #include <linux/gpio/consumer.h>
>> @@ -30,11 +31,15 @@
>> #include <linux/of_platform.h>
>> #include <linux/phy/phy.h>
>> #include <linux/platform_device.h>
>> +#include <linux/power_supply.h>
>> #include <linux/regmap.h>
>> #include <linux/mfd/syscon.h>
>> +#include <linux/usb/of.h>
>> +#include <linux/usb/otg.h>
>>
>> #define BIT_WRITEABLE_SHIFT 16
>> -#define SCHEDULE_DELAY (60 * HZ)
>> +#define SCHEDULE_DELAY (60 * HZ)
>> +#define OTG_SCHEDULE_DELAY (2 * HZ)
>>
>> enum rockchip_usb2phy_port_id {
>> USB2PHY_PORT_OTG,
>> @@ -49,6 +54,37 @@ enum rockchip_usb2phy_host_state {
>> PHY_STATE_FS_LS_ONLINE = 4,
>> };
>>
>> +/**
>> + * Different states involved in USB charger detection.
>> + * USB_CHG_STATE_UNDEFINED USB charger is not connected or detection
>> + * process is not yet started.
>> + * USB_CHG_STATE_WAIT_FOR_DCD Waiting for Data pins contact.
>> + * USB_CHG_STATE_DCD_DONE Data pin contact is detected.
>> + * USB_CHG_STATE_PRIMARY_DONE Primary detection is completed (Detects
>> + * between SDP and DCP/CDP).
>> + * USB_CHG_STATE_SECONDARY_DONE Secondary detection is completed (Detects
>> + * between DCP and CDP).
>> + * USB_CHG_STATE_DETECTED USB charger type is determined.
>> + */
>> +enum usb_chg_state {
>> + USB_CHG_STATE_UNDEFINED = 0,
>> + USB_CHG_STATE_WAIT_FOR_DCD,
>> + USB_CHG_STATE_DCD_DONE,
>> + USB_CHG_STATE_PRIMARY_DONE,
>> + USB_CHG_STATE_SECONDARY_DONE,
>> + USB_CHG_STATE_DETECTED,
>> +};
>> +
>> +static const unsigned int rockchip_usb2phy_extcon_cable[] = {
>> + EXTCON_USB,
>> + EXTCON_USB_HOST,
>> + EXTCON_CHG_USB_SDP,
>> + EXTCON_CHG_USB_CDP,
>> + EXTCON_CHG_USB_DCP,
>> + EXTCON_CHG_USB_SLOW,
>> + EXTCON_NONE,
>> +};
>> +
>> struct usb2phy_reg {
>> unsigned int offset;
>> unsigned int bitend;
>> @@ -58,19 +94,55 @@ struct usb2phy_reg {
>> };
>>
>> /**
>> + * struct rockchip_chg_det_reg: usb charger detect registers
>> + * @cp_det: charging port detected successfully.
>> + * @dcp_det: dedicated charging port detected successfully.
>> + * @dp_det: assert data pin connect successfully.
>> + * @idm_sink_en: open dm sink curren.
>> + * @idp_sink_en: open dp sink current.
>> + * @idp_src_en: open dm source current.
>> + * @rdm_pdwn_en: open dm pull down resistor.
>> + * @vdm_src_en: open dm voltage source.
>> + * @vdp_src_en: open dp voltage source.
>> + * @opmode: utmi operational mode.
>> + */
>> +struct rockchip_chg_det_reg {
>> + struct usb2phy_reg cp_det;
>> + struct usb2phy_reg dcp_det;
>> + struct usb2phy_reg dp_det;
>> + struct usb2phy_reg idm_sink_en;
>> + struct usb2phy_reg idp_sink_en;
>> + struct usb2phy_reg idp_src_en;
>> + struct usb2phy_reg rdm_pdwn_en;
>> + struct usb2phy_reg vdm_src_en;
>> + struct usb2phy_reg vdp_src_en;
>> + struct usb2phy_reg opmode;
>> +};
>> +
>> +/**
>> * struct rockchip_usb2phy_port_cfg: usb-phy port configuration.
>> * @phy_sus: phy suspend register.
>> + * @bvalid_det_en: vbus valid rise detection enable register.
>> + * @bvalid_det_st: vbus valid rise detection status register.
>> + * @bvalid_det_clr: vbus valid rise detection clear register.
>> * @ls_det_en: linestate detection enable register.
>> * @ls_det_st: linestate detection state register.
>> * @ls_det_clr: linestate detection clear register.
>> + * @utmi_avalid: utmi vbus avalid status register.
>> + * @utmi_bvalid: utmi vbus bvalid status register.
>> * @utmi_ls: utmi linestate state register.
>> * @utmi_hstdet: utmi host disconnect register.
>> */
>> struct rockchip_usb2phy_port_cfg {
>> struct usb2phy_reg phy_sus;
>> + struct usb2phy_reg bvalid_det_en;
>> + struct usb2phy_reg bvalid_det_st;
>> + struct usb2phy_reg bvalid_det_clr;
>> struct usb2phy_reg ls_det_en;
>> struct usb2phy_reg ls_det_st;
>> struct usb2phy_reg ls_det_clr;
>> + struct usb2phy_reg utmi_avalid;
>> + struct usb2phy_reg utmi_bvalid;
>> struct usb2phy_reg utmi_ls;
>> struct usb2phy_reg utmi_hstdet;
>> };
>> @@ -80,31 +152,51 @@ struct rockchip_usb2phy_port_cfg {
>> * @reg: the address offset of grf for usb-phy config.
>> * @num_ports: specify how many ports that the phy has.
>> * @clkout_ctl: keep on/turn off output clk of phy.
>> + * @chg_det: charger detection registers.
>> */
>> struct rockchip_usb2phy_cfg {
>> unsigned int reg;
>> unsigned int num_ports;
>> struct usb2phy_reg clkout_ctl;
>> const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS];
>> + const struct rockchip_chg_det_reg chg_det;
>> };
>>
>> /**
>> * struct rockchip_usb2phy_port: usb-phy port data.
>> * @port_id: flag for otg port or host port.
>> * @suspended: phy suspended flag.
>> + * @utmi_avalid: utmi avalid status usage flag.
>> + * true - use avalid to get vbus status
>> + * flase - use bvalid to get vbus status
>> + * @vbus_attached: otg device vbus status.
>> + * @bvalid_irq: IRQ number assigned for vbus valid rise detection.
>> * @ls_irq: IRQ number assigned for linestate detection.
>> * @mutex: for register updating in sm_work.
>> - * @sm_work: OTG state machine work.
>> + * @chg_work: charge detect work.
>> + * @otg_sm_work: OTG state machine work.
>> + * @sm_work: HOST state machine work.
>> * @phy_cfg: port register configuration, assigned by driver data.
>> + * @event_nb: hold event notification callback.
>> + * @state: define OTG enumeration states before device reset.
>> + * @mode: the dr_mode of the controller.
>> */
>> struct rockchip_usb2phy_port {
>> struct phy *phy;
>> unsigned int port_id;
>> bool suspended;
>> + bool utmi_avalid;
>> + bool vbus_attached;
>> + int bvalid_irq;
>> int ls_irq;
>> struct mutex mutex;
>> + struct delayed_work chg_work;
>> + struct delayed_work otg_sm_work;
>> struct delayed_work sm_work;
>> const struct rockchip_usb2phy_port_cfg *port_cfg;
>> + struct notifier_block event_nb;
>> + enum usb_otg_state state;
>> + enum usb_dr_mode mode;
>> };
>>
>> /**
>> @@ -113,6 +205,11 @@ struct rockchip_usb2phy_port {
>> * @clk: clock struct of phy input clk.
>> * @clk480m: clock struct of phy output clk.
>> * @clk_hw: clock struct of phy output clk management.
>> + * @chg_state: states involved in USB charger detection.
>> + * @chg_type: USB charger types.
>> + * @dcd_retries: The retry count used to track Data contact
>> + * detection process.
>> + * @edev: extcon device for notification registration
>> * @phy_cfg: phy register configuration, assigned by driver data.
>> * @ports: phy port instance.
>> */
>> @@ -122,6 +219,10 @@ struct rockchip_usb2phy {
>> struct clk *clk;
>> struct clk *clk480m;
>> struct clk_hw clk480m_hw;
>> + enum usb_chg_state chg_state;
>> + enum power_supply_type chg_type;
>> + u8 dcd_retries;
>> + struct extcon_dev *edev;
>> const struct rockchip_usb2phy_cfg *phy_cfg;
>> struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS];
>> };
>> @@ -166,7 +267,7 @@ static int rockchip_usb2phy_clk480m_enable(struct clk_hw *hw)
>> return ret;
>>
>> /* waitting for the clk become stable */
>> - mdelay(1);
>> + udelay(1200);
>> }
>>
>> return 0;
>> @@ -263,33 +364,84 @@ rockchip_usb2phy_clk480m_register(struct rockchip_usb2phy *rphy)
>> return ret;
>> }
>>
>> -static int rockchip_usb2phy_init(struct phy *phy)
>> +static int rockchip_usb2phy_extcon_register(struct rockchip_usb2phy *rphy)
>> {
>> - struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
>> - struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
>> int ret;
>> + struct device_node *node = rphy->dev->of_node;
>> + struct extcon_dev *edev;
>> +
>> + if (of_property_read_bool(node, "extcon")) {
>> + edev = extcon_get_edev_by_phandle(rphy->dev, 0);
>> + if (IS_ERR(edev)) {
>> + if (PTR_ERR(edev) != -EPROBE_DEFER)
>> + dev_err(rphy->dev, "Invalid or missing extcon\n");
>> + return PTR_ERR(edev);
>> + }
>> + } else {
>> + /* Initialize extcon device */
>> + edev = devm_extcon_dev_allocate(rphy->dev,
>> + rockchip_usb2phy_extcon_cable);
>>
>> - if (rport->port_id == USB2PHY_PORT_HOST) {
>> - /* clear linestate and enable linestate detect irq */
>> - mutex_lock(&rport->mutex);
>> + if (IS_ERR(edev))
>> + return -ENOMEM;
>>
>> - ret = property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
>> + ret = devm_extcon_dev_register(rphy->dev, edev);
>> if (ret) {
>> - mutex_unlock(&rport->mutex);
>> + dev_err(rphy->dev, "failed to register extcon device\n");
>> return ret;
>> }
>> + }
>>
>> - ret = property_enable(rphy, &rport->port_cfg->ls_det_en, true);
>> - if (ret) {
>> - mutex_unlock(&rport->mutex);
>> - return ret;
>> + rphy->edev = edev;
>> +
>> + return 0;
>> +}
>> +
>> +static int rockchip_usb2phy_init(struct phy *phy)
>> +{
>> + struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
>> + struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
>> + int ret = 0;
>> +
>> + mutex_lock(&rport->mutex);
>> +
>> + if (rport->port_id == USB2PHY_PORT_OTG) {
>> + if (rport->mode != USB_DR_MODE_HOST) {
>> + /* clear bvalid status and enable bvalid detect irq */
>> + ret = property_enable(rphy,
>> + &rport->port_cfg->bvalid_det_clr,
>> + true);
>> + if (ret)
>> + goto out;
>> +
>> + ret = property_enable(rphy,
>> + &rport->port_cfg->bvalid_det_en,
>> + true);
>> + if (ret)
>> + goto out;
>> +
>> + schedule_delayed_work(&rport->otg_sm_work,
>> + OTG_SCHEDULE_DELAY);
>> + } else {
>> + /* If OTG works in host only mode, do nothing. */
>> + dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode);
>> }
>> + } else if (rport->port_id == USB2PHY_PORT_HOST) {
>> + /* clear linestate and enable linestate detect irq */
>> + ret = property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
>> + if (ret)
>> + goto out;
>> +
>> + ret = property_enable(rphy, &rport->port_cfg->ls_det_en, true);
>> + if (ret)
>> + goto out;
>>
>> - mutex_unlock(&rport->mutex);
>> schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY);
>> }
>>
>> - return 0;
>> +out:
>> + mutex_unlock(&rport->mutex);
>> + return ret;
>> }
>>
>> static int rockchip_usb2phy_power_on(struct phy *phy)
>> @@ -340,7 +492,11 @@ static int rockchip_usb2phy_exit(struct phy *phy)
>> {
>> struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
>>
>> - if (rport->port_id == USB2PHY_PORT_HOST)
>> + if (rport->port_id == USB2PHY_PORT_OTG &&
>> + rport->mode != USB_DR_MODE_HOST) {
>> + cancel_delayed_work_sync(&rport->otg_sm_work);
>> + cancel_delayed_work_sync(&rport->chg_work);
>> + } else if (rport->port_id == USB2PHY_PORT_HOST)
>> cancel_delayed_work_sync(&rport->sm_work);
>>
>> return 0;
>> @@ -354,6 +510,249 @@ static const struct phy_ops rockchip_usb2phy_ops = {
>> .owner = THIS_MODULE,
>> };
>>
>> +static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
>> +{
>> + struct rockchip_usb2phy_port *rport =
>> + container_of(work, struct rockchip_usb2phy_port,
>> + otg_sm_work.work);
>> + struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
>> + static unsigned int cable;
>> + unsigned long delay;
>> + bool vbus_attach, sch_work, notify_charger;
>> +
>> + if (rport->utmi_avalid)
>> + vbus_attach =
>> + property_enabled(rphy, &rport->port_cfg->utmi_avalid);
>> + else
>> + vbus_attach =
>> + property_enabled(rphy, &rport->port_cfg->utmi_bvalid);
>> +
>> + sch_work = false;
>> + notify_charger = false;
>> + delay = OTG_SCHEDULE_DELAY;
>> + dev_dbg(&rport->phy->dev, "%s otg sm work\n",
>> + usb_otg_state_string(rport->state));
>> +
>> + switch (rport->state) {
>> + case OTG_STATE_UNDEFINED:
>> + rport->state = OTG_STATE_B_IDLE;
>> + if (!vbus_attach)
>> + rockchip_usb2phy_power_off(rport->phy);
>> + /* fall through */
>> + case OTG_STATE_B_IDLE:
>> + if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) > 0) {
>> + dev_dbg(&rport->phy->dev, "usb otg host connect\n");
>> + rport->state = OTG_STATE_A_HOST;
>> + rockchip_usb2phy_power_on(rport->phy);
>> + return;
>> + } else if (vbus_attach) {
>> + dev_dbg(&rport->phy->dev, "vbus_attach\n");
>> + switch (rphy->chg_state) {
>> + case USB_CHG_STATE_UNDEFINED:
>> + schedule_delayed_work(&rport->chg_work, 0);
>> + return;
>> + case USB_CHG_STATE_DETECTED:
>> + switch (rphy->chg_type) {
>> + case POWER_SUPPLY_TYPE_USB:
>> + dev_dbg(&rport->phy->dev,
>> + "sdp cable is connecetd\n");
>> + rockchip_usb2phy_power_on(rport->phy);
>> + rport->state = OTG_STATE_B_PERIPHERAL;
>> + notify_charger = true;
>> + sch_work = true;
>> + cable = EXTCON_CHG_USB_SDP;
>> + break;
>> + case POWER_SUPPLY_TYPE_USB_DCP:
>> + dev_dbg(&rport->phy->dev,
>> + "dcp cable is connecetd\n");
>> + rockchip_usb2phy_power_off(rport->phy);
>> + notify_charger = true;
>> + sch_work = true;
>> + cable = EXTCON_CHG_USB_DCP;
>> + break;
>> + case POWER_SUPPLY_TYPE_USB_CDP:
>> + dev_dbg(&rport->phy->dev,
>> + "cdp cable is connecetd\n");
>> + rockchip_usb2phy_power_on(rport->phy);
>> + rport->state = OTG_STATE_B_PERIPHERAL;
>> + notify_charger = true;
>> + sch_work = true;
>> + cable = EXTCON_CHG_USB_CDP;
>> + break;
>> + default:
>> + break;
>> + }
>> + break;
>> + default:
>> + break;
>> + }
>> + } else {
>> + notify_charger = true;
>> + rphy->chg_state = USB_CHG_STATE_UNDEFINED;
>> + rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
>> + }
>> +
>> + if (rport->vbus_attached != vbus_attach) {
>> + rport->vbus_attached = vbus_attach;
>> +
>> + if (notify_charger && rphy->edev)
>> + extcon_set_cable_state_(rphy->edev,
>> + cable, vbus_attach);
>> + }
>> + break;
>> + case OTG_STATE_B_PERIPHERAL:
>> + if (!vbus_attach) {
>> + dev_dbg(&rport->phy->dev, "usb disconnect\n");
>> + rphy->chg_state = USB_CHG_STATE_UNDEFINED;
>> + rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
>> + rport->state = OTG_STATE_B_IDLE;
>> + delay = 0;
>> + rockchip_usb2phy_power_off(rport->phy);
>> + }
>> + sch_work = true;
>> + break;
>> + case OTG_STATE_A_HOST:
>> + if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) == 0) {
>> + dev_dbg(&rport->phy->dev, "usb otg host disconnect\n");
>> + rport->state = OTG_STATE_B_IDLE;
>> + rockchip_usb2phy_power_off(rport->phy);
>> + }
>> + break;
>> + default:
>> + break;
>> + }
>> +
>> + if (sch_work)
>> + schedule_delayed_work(&rport->otg_sm_work, delay);
>> +}
>> +
>> +static const char *chg_to_string(enum power_supply_type chg_type)
>> +{
>> + switch (chg_type) {
>> + case POWER_SUPPLY_TYPE_USB:
>> + return "USB_SDP_CHARGER";
>> + case POWER_SUPPLY_TYPE_USB_DCP:
>> + return "USB_DCP_CHARGER";
>> + case POWER_SUPPLY_TYPE_USB_CDP:
>> + return "USB_CDP_CHARGER";
>> + default:
>> + return "INVALID_CHARGER";
>> + }
>> +}
>> +
>> +static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
>> + bool en)
>> +{
>> + property_enable(rphy, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
>> + property_enable(rphy, &rphy->phy_cfg->chg_det.idp_src_en, en);
>> +}
>> +
>> +static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy,
>> + bool en)
>> +{
>> + property_enable(rphy, &rphy->phy_cfg->chg_det.vdp_src_en, en);
>> + property_enable(rphy, &rphy->phy_cfg->chg_det.idm_sink_en, en);
>> +}
>> +
>> +static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy,
>> + bool en)
>> +{
>> + property_enable(rphy, &rphy->phy_cfg->chg_det.vdm_src_en, en);
>> + property_enable(rphy, &rphy->phy_cfg->chg_det.idp_sink_en, en);
>> +}
>> +
>> +#define CHG_DCD_POLL_TIME (100 * HZ / 1000)
>> +#define CHG_DCD_MAX_RETRIES 6
>> +#define CHG_PRIMARY_DET_TIME (40 * HZ / 1000)
>> +#define CHG_SECONDARY_DET_TIME (40 * HZ / 1000)
>> +static void rockchip_chg_detect_work(struct work_struct *work)
>> +{
>> + struct rockchip_usb2phy_port *rport =
>> + container_of(work, struct rockchip_usb2phy_port, chg_work.work);
>> + struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
>> + bool is_dcd, tmout, vout;
>> + unsigned long delay;
>> +
>> + dev_dbg(&rport->phy->dev, "chg detection work state = %d\n",
>> + rphy->chg_state);
>> + switch (rphy->chg_state) {
>> + case USB_CHG_STATE_UNDEFINED:
>> + if (!rport->suspended)
>> + rockchip_usb2phy_power_off(rport->phy);
>> + /* put the controller in non-driving mode */
>> + property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, false);
>> + /* Start DCD processing stage 1 */
>> + rockchip_chg_enable_dcd(rphy, true);
>> + rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
>> + rphy->dcd_retries = 0;
>> + delay = CHG_DCD_POLL_TIME;
>> + break;
>> + case USB_CHG_STATE_WAIT_FOR_DCD:
>> + /* get data contact detection status */
>> + is_dcd = property_enabled(rphy, &rphy->phy_cfg->chg_det.dp_det);
>> + tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES;
>> + /* stage 2 */
>> + if (is_dcd || tmout) {
>> + /* stage 4 */
>> + /* Turn off DCD circuitry */
>> + rockchip_chg_enable_dcd(rphy, false);
>> + /* Voltage Source on DP, Probe on DM */
>> + rockchip_chg_enable_primary_det(rphy, true);
>> + delay = CHG_PRIMARY_DET_TIME;
>> + rphy->chg_state = USB_CHG_STATE_DCD_DONE;
>> + } else {
>> + /* stage 3 */
>> + delay = CHG_DCD_POLL_TIME;
>> + }
>> + break;
>> + case USB_CHG_STATE_DCD_DONE:
>> + vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.cp_det);
>> + rockchip_chg_enable_primary_det(rphy, false);
>> + if (vout) {
>> + /* Voltage Source on DM, Probe on DP */
>> + rockchip_chg_enable_secondary_det(rphy, true);
>> + delay = CHG_SECONDARY_DET_TIME;
>> + rphy->chg_state = USB_CHG_STATE_PRIMARY_DONE;
>> + } else {
>> + if (tmout) {
>> + /* floating charger found */
>> + rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP;
>> + rphy->chg_state = USB_CHG_STATE_DETECTED;
>> + delay = 0;
>> + } else {
>> + rphy->chg_type = POWER_SUPPLY_TYPE_USB;
>> + rphy->chg_state = USB_CHG_STATE_DETECTED;
>> + delay = 0;
>> + }
>> + }
>> + break;
>> + case USB_CHG_STATE_PRIMARY_DONE:
>> + vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.dcp_det);
>> + /* Turn off voltage source */
>> + rockchip_chg_enable_secondary_det(rphy, false);
>> + if (vout)
>> + rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP;
>> + else
>> + rphy->chg_type = POWER_SUPPLY_TYPE_USB_CDP;
>> + /* fall through */
>> + case USB_CHG_STATE_SECONDARY_DONE:
>> + rphy->chg_state = USB_CHG_STATE_DETECTED;
>> + delay = 0;
>> + /* fall through */
>> + case USB_CHG_STATE_DETECTED:
>> + /* put the controller in normal mode */
>> + property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, true);
>> + rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
>> + dev_info(&rport->phy->dev, "charger = %s\n",
>> + chg_to_string(rphy->chg_type));
>> + return;
>> + default:
>> + return;
>> + }
>> +
>> + schedule_delayed_work(&rport->chg_work, delay);
>> +}
>> +
>> /*
>> * The function manage host-phy port state and suspend/resume phy port
>> * to save power.
>> @@ -485,6 +884,26 @@ static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data)
>> return IRQ_HANDLED;
>> }
>>
>> +static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
>> +{
>> + struct rockchip_usb2phy_port *rport = data;
>> + struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
>> +
>> + if (!property_enabled(rphy, &rport->port_cfg->bvalid_det_st))
>> + return IRQ_NONE;
>> +
>> + mutex_lock(&rport->mutex);
>> +
>> + /* clear bvalid detect irq pending status */
>> + property_enable(rphy, &rport->port_cfg->bvalid_det_clr, true);
>> +
>> + mutex_unlock(&rport->mutex);
>> +
>> + rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
>> +
>> + return IRQ_HANDLED;
>> +}
>> +
>> static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
>> struct rockchip_usb2phy_port *rport,
>> struct device_node *child_np)
>> @@ -509,13 +928,86 @@ static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
>> IRQF_ONESHOT,
>> "rockchip_usb2phy", rport);
>> if (ret) {
>> - dev_err(rphy->dev, "failed to request irq handle\n");
>> + dev_err(rphy->dev, "failed to request linestate irq handle\n");
>> return ret;
>> }
>>
>> return 0;
>> }
>>
>> +static int rockchip_otg_event(struct notifier_block *nb,
>> + unsigned long event, void *ptr)
>> +{
>> + struct rockchip_usb2phy_port *rport =
>> + container_of(nb, struct rockchip_usb2phy_port, event_nb);
>> +
>> + schedule_delayed_work(&rport->otg_sm_work, OTG_SCHEDULE_DELAY);
>> +
>> + return NOTIFY_DONE;
>> +}
>> +
>> +static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
>> + struct rockchip_usb2phy_port *rport,
>> + struct device_node *child_np)
>> +{
>> + int ret;
>> +
>> + rport->port_id = USB2PHY_PORT_OTG;
>> + rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG];
>> + rport->state = OTG_STATE_UNDEFINED;
>> +
>> + /*
>> + * set suspended flag to true, but actually don't
>> + * put phy in suspend mode, it aims to enable usb
>> + * phy and clock in power_on() called by usb controller
>> + * driver during probe.
>> + */
>> + rport->suspended = true;
>> + rport->vbus_attached = false;
>> +
>> + mutex_init(&rport->mutex);
>> +
>> + rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1);
>> + if (rport->mode == USB_DR_MODE_HOST) {
>> + ret = 0;
>> + goto out;
>> + }
>> +
>> + INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work);
>> + INIT_DELAYED_WORK(&rport->otg_sm_work, rockchip_usb2phy_otg_sm_work);
>> +
>> + rport->utmi_avalid =
>> + of_property_read_bool(child_np, "rockchip,utmi-avalid");
>> +
>> + rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid");
>> + if (rport->bvalid_irq < 0) {
>> + dev_err(rphy->dev, "no vbus valid irq provided\n");
>> + ret = rport->bvalid_irq;
>> + goto out;
>> + }
>> +
>> + ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, NULL,
>> + rockchip_usb2phy_bvalid_irq,
>> + IRQF_ONESHOT,
>> + "rockchip_usb2phy_bvalid", rport);
>> + if (ret) {
>> + dev_err(rphy->dev, "failed to request otg-bvalid irq handle\n");
>> + goto out;
>> + }
>> +
>> + if (!IS_ERR(rphy->edev)) {
>> + rport->event_nb.notifier_call = rockchip_otg_event;
>> +
>> + ret = extcon_register_notifier(rphy->edev, EXTCON_USB_HOST,
>> + &rport->event_nb);
>> + if (ret)
>> + dev_err(rphy->dev, "register USB HOST notifier failed\n");
>> + }
>> +
>> +out:
>> + return ret;
>> +}
>> +
>> static int rockchip_usb2phy_probe(struct platform_device *pdev)
>> {
>> struct device *dev = &pdev->dev;
>> @@ -553,8 +1045,14 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
>>
>> rphy->dev = dev;
>> phy_cfgs = match->data;
>> + rphy->chg_state = USB_CHG_STATE_UNDEFINED;
>> + rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
>> platform_set_drvdata(pdev, rphy);
>>
>> + ret = rockchip_usb2phy_extcon_register(rphy);
>> + if (ret)
>> + return ret;
>> +
>> /* find out a proper config which can be matched with dt. */
>> index = 0;
>> while (phy_cfgs[index].reg) {
>> @@ -591,13 +1089,9 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
>> struct rockchip_usb2phy_port *rport = &rphy->ports[index];
>> struct phy *phy;
>>
>> - /*
>> - * This driver aim to support both otg-port and host-port,
>> - * but unfortunately, the otg part is not ready in current,
>> - * so this comments and below codes are interim, which should
>> - * be changed after otg-port is supplied soon.
>> - */
>> - if (of_node_cmp(child_np->name, "host-port"))
>> + /* This driver aims to support both otg-port and host-port */
>> + if (of_node_cmp(child_np->name, "host-port") &&
>> + of_node_cmp(child_np->name, "otg-port"))
>> goto next_child;
>>
>> phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops);
>> @@ -610,9 +1104,18 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
>> rport->phy = phy;
>> phy_set_drvdata(rport->phy, rport);
>>
>> - ret = rockchip_usb2phy_host_port_init(rphy, rport, child_np);
>> - if (ret)
>> - goto put_child;
>> + /* initialize otg/host port separately */
>> + if (!of_node_cmp(child_np->name, "host-port")) {
>> + ret = rockchip_usb2phy_host_port_init(rphy, rport,
>> + child_np);
>> + if (ret)
>> + goto put_child;
>> + } else {
>> + ret = rockchip_usb2phy_otg_port_init(rphy, rport,
>> + child_np);
>> + if (ret)
>> + goto put_child;
>> + }
>>
>> next_child:
>> /* to prevent out of boundary */
>> @@ -654,10 +1157,18 @@ static const struct rockchip_usb2phy_cfg rk3366_phy_cfgs[] = {
>>
>> static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
>> {
>> - .reg = 0xe450,
>> + .reg = 0xe450,
>> .num_ports = 2,
>> .clkout_ctl = { 0xe450, 4, 4, 1, 0 },
>> .port_cfgs = {
>> + [USB2PHY_PORT_OTG] = {
>> + .phy_sus = { 0xe454, 1, 0, 2, 1 },
>> + .bvalid_det_en = { 0xe3c0, 3, 3, 0, 1 },
>> + .bvalid_det_st = { 0xe3e0, 3, 3, 0, 1 },
>> + .bvalid_det_clr = { 0xe3d0, 3, 3, 0, 1 },
>> + .utmi_avalid = { 0xe2ac, 7, 7, 0, 1 },
>> + .utmi_bvalid = { 0xe2ac, 12, 12, 0, 1 },
>> + },
>> [USB2PHY_PORT_HOST] = {
>> .phy_sus = { 0xe458, 1, 0, 0x2, 0x1 },
>> .ls_det_en = { 0xe3c0, 6, 6, 0, 1 },
>> @@ -667,12 +1178,32 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
>> .utmi_hstdet = { 0xe2ac, 23, 23, 0, 1 }
>> }
>> },
>> + .chg_det = {
>> + .opmode = { 0xe454, 3, 0, 5, 1 },
>> + .cp_det = { 0xe2ac, 2, 2, 0, 1 },
>> + .dcp_det = { 0xe2ac, 1, 1, 0, 1 },
>> + .dp_det = { 0xe2ac, 0, 0, 0, 1 },
>> + .idm_sink_en = { 0xe450, 8, 8, 0, 1 },
>> + .idp_sink_en = { 0xe450, 7, 7, 0, 1 },
>> + .idp_src_en = { 0xe450, 9, 9, 0, 1 },
>> + .rdm_pdwn_en = { 0xe450, 10, 10, 0, 1 },
>> + .vdm_src_en = { 0xe450, 12, 12, 0, 1 },
>> + .vdp_src_en = { 0xe450, 11, 11, 0, 1 },
>> + },
>> },
>> {
>> - .reg = 0xe460,
>> + .reg = 0xe460,
>> .num_ports = 2,
>> .clkout_ctl = { 0xe460, 4, 4, 1, 0 },
>> .port_cfgs = {
>> + [USB2PHY_PORT_OTG] = {
>> + .phy_sus = { 0xe464, 1, 0, 2, 1 },
>> + .bvalid_det_en = { 0xe3c0, 8, 8, 0, 1 },
>> + .bvalid_det_st = { 0xe3e0, 8, 8, 0, 1 },
>> + .bvalid_det_clr = { 0xe3d0, 8, 8, 0, 1 },
>> + .utmi_avalid = { 0xe2ac, 10, 10, 0, 1 },
>> + .utmi_bvalid = { 0xe2ac, 16, 16, 0, 1 },
>> + },
>> [USB2PHY_PORT_HOST] = {
>> .phy_sus = { 0xe468, 1, 0, 0x2, 0x1 },
>> .ls_det_en = { 0xe3c0, 11, 11, 0, 1 },
>>
>
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v4 2/2] i2c: aspeed: added documentation for Aspeed I2C driver
From: Brendan Higgins @ 2016-11-05 1:58 UTC (permalink / raw)
To: wsa, robh+dt, mark.rutland
Cc: linux-i2c, devicetree, joel, openbmc, Brendan Higgins
In-Reply-To: <1478311099-6771-1-git-send-email-brendanhiggins@google.com>
Added device tree binding documentation for Aspeed I2C controller and
busses.
Signed-off-by: Brendan Higgins <brendanhiggins@google.com>
---
Changes for v2:
- None
Changes for v3:
- Removed reference to "bus" device tree param
Changes for v4:
- None
---
.../devicetree/bindings/i2c/i2c-aspeed.txt | 61 ++++++++++++++++++++++
1 file changed, 61 insertions(+)
create mode 100644 Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
new file mode 100644
index 0000000..dd11a97
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
@@ -0,0 +1,61 @@
+Device tree configuration for the I2C controller and busses on the AST24XX
+and AST25XX SoCs.
+
+Controller:
+
+ Required Properties:
+ - #address-cells : should be 1
+ - #size-cells : should be 1
+ - #interrupt-cells : should be 1
+ - compatible : should be "aspeed,ast2400-i2c-controller"
+ or "aspeed,ast2500-i2c-controller"
+ - reg : address start and range of controller
+ - ranges : defines address offset and range for busses
+ - interrupts : interrupt number
+ - clocks : root clock of bus, should reference the APB
+ clock
+ - clock-ranges : specifies that child busses can inherit clocks
+ - interrupt-controller : denotes that the controller receives and fires
+ new interrupts for child busses
+
+Bus:
+
+ Required Properties:
+ - #address-cells : should be 1
+ - #size-cells : should be 0
+ - reg : address offset and range of bus
+ - compatible : should be "aspeed,ast2400-i2c-bus"
+ or "aspeed,ast2500-i2c-bus"
+ - interrupts : interrupt number
+
+ Optional Properties:
+ - clock-frequency : frequency of the bus clock in Hz
+ defaults to 100 kHz when not specified
+
+Example:
+
+i2c: i2c@1e78a000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #interrupt-cells = <1>;
+
+ compatible = "aspeed,ast2400-i2c-controller";
+ reg = <0x1e78a000 0x40>;
+ ranges = <0 0x1e78a000 0x1000>;
+ interrupts = <12>;
+ clocks = <&clk_apb>;
+ clock-ranges;
+ interrupt-controller;
+
+ i2c0: i2c-bus@40 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x40 0x40>;
+ compatible = "aspeed,ast2400-i2c-bus";
+ clock-frequency = <100000>;
+ status = "disabled";
+ interrupts = <0>;
+ interrupt-parent = <&i2c>;
+ };
+};
+
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply related
* [PATCH v4 1/2] i2c: aspeed: added driver for Aspeed I2C
From: Brendan Higgins @ 2016-11-05 1:58 UTC (permalink / raw)
To: wsa, robh+dt, mark.rutland
Cc: linux-i2c, devicetree, joel, openbmc, Brendan Higgins
In-Reply-To: <1478311099-6771-1-git-send-email-brendanhiggins@google.com>
Added initial master and slave support for Aspeed I2C controller.
Supports fourteen busses present in ast24xx and ast25xx BMC SoCs by
Aspeed.
Signed-off-by: Brendan Higgins <brendanhiggins@google.com>
---
Changes for v2:
- Added single module_init (multiple was breaking some builds).
Changes for v3:
- Removed "bus" device tree param; now extracted from bus address offset
Changes for v4:
- I2C adapter number is now generated dynamically unless specified in alias.
---
drivers/i2c/busses/Kconfig | 10 +
drivers/i2c/busses/Makefile | 1 +
drivers/i2c/busses/i2c-aspeed.c | 807 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 818 insertions(+)
create mode 100644 drivers/i2c/busses/i2c-aspeed.c
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index d252276..b6caa5d 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -1009,6 +1009,16 @@ config I2C_RCAR
This driver can also be built as a module. If so, the module
will be called i2c-rcar.
+config I2C_ASPEED
+ tristate "Aspeed AST2xxx SoC I2C Controller"
+ depends on ARCH_ASPEED
+ help
+ If you say yes to this option, support will be included for the
+ Aspeed AST2xxx SoC I2C controller.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-aspeed.
+
comment "External I2C/SMBus adapter drivers"
config I2C_DIOLAN_U2C
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 29764cc..826e780 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -99,6 +99,7 @@ obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o
obj-$(CONFIG_I2C_XLR) += i2c-xlr.o
obj-$(CONFIG_I2C_XLP9XX) += i2c-xlp9xx.o
obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o
+obj-$(CONFIG_I2C_ASPEED) += i2c-aspeed.o
# External I2C/SMBus adapter drivers
obj-$(CONFIG_I2C_DIOLAN_U2C) += i2c-diolan-u2c.o
diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
new file mode 100644
index 0000000..88e078a
--- /dev/null
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -0,0 +1,807 @@
+/*
+ * I2C adapter for the ASPEED I2C bus.
+ *
+ * Copyright (C) 2012-2020 ASPEED Technology Inc.
+ * Copyright 2016 IBM Corporation
+ * Copyright 2016 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+/* I2C Register */
+#define ASPEED_I2C_FUN_CTRL_REG 0x00
+#define ASPEED_I2C_AC_TIMING_REG1 0x04
+#define ASPEED_I2C_AC_TIMING_REG2 0x08
+#define ASPEED_I2C_INTR_CTRL_REG 0x0c
+#define ASPEED_I2C_INTR_STS_REG 0x10
+#define ASPEED_I2C_CMD_REG 0x14
+#define ASPEED_I2C_DEV_ADDR_REG 0x18
+#define ASPEED_I2C_BYTE_BUF_REG 0x20
+#define ASPEED_I2C_OFFSET_START 0x40
+#define ASPEED_I2C_OFFSET_INCREMENT 0x40
+
+#define ASPEED_I2C_NUM_BUS 14
+
+/* Global Register Definition */
+/* 0x00 : I2C Interrupt Status Register */
+/* 0x08 : I2C Interrupt Target Assignment */
+
+/* Device Register Definition */
+/* 0x00 : I2CD Function Control Register */
+#define ASPEED_I2CD_MULTI_MASTER_DIS BIT(15)
+#define ASPEED_I2CD_SDA_DRIVE_1T_EN BIT(8)
+#define ASPEED_I2CD_M_SDA_DRIVE_1T_EN BIT(7)
+#define ASPEED_I2CD_M_HIGH_SPEED_EN BIT(6)
+#define ASPEED_I2CD_SLAVE_EN BIT(1)
+#define ASPEED_I2CD_MASTER_EN BIT(0)
+
+/* 0x08 : I2CD Clock and AC Timing Control Register #2 */
+#define ASPEED_NO_TIMEOUT_CTRL 0
+
+
+/* 0x0c : I2CD Interrupt Control Register &
+ * 0x10 : I2CD Interrupt Status Register
+ *
+ * These share bit definitions, so use the same values for the enable &
+ * status bits.
+ */
+#define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT BIT(14)
+#define ASPEED_I2CD_INTR_BUS_RECOVER_DONE BIT(13)
+#define ASPEED_I2CD_INTR_SLAVE_MATCH BIT(7)
+#define ASPEED_I2CD_INTR_SCL_TIMEOUT BIT(6)
+#define ASPEED_I2CD_INTR_ABNORMAL BIT(5)
+#define ASPEED_I2CD_INTR_NORMAL_STOP BIT(4)
+#define ASPEED_I2CD_INTR_ARBIT_LOSS BIT(3)
+#define ASPEED_I2CD_INTR_RX_DONE BIT(2)
+#define ASPEED_I2CD_INTR_TX_NAK BIT(1)
+#define ASPEED_I2CD_INTR_TX_ACK BIT(0)
+
+/* 0x14 : I2CD Command/Status Register */
+#define ASPEED_I2CD_SCL_LINE_STS BIT(18)
+#define ASPEED_I2CD_SDA_LINE_STS BIT(17)
+#define ASPEED_I2CD_BUS_BUSY_STS BIT(16)
+#define ASPEED_I2CD_BUS_RECOVER_CMD BIT(11)
+
+/* Command Bit */
+#define ASPEED_I2CD_M_STOP_CMD BIT(5)
+#define ASPEED_I2CD_M_S_RX_CMD_LAST BIT(4)
+#define ASPEED_I2CD_M_RX_CMD BIT(3)
+#define ASPEED_I2CD_S_TX_CMD BIT(2)
+#define ASPEED_I2CD_M_TX_CMD BIT(1)
+#define ASPEED_I2CD_M_START_CMD BIT(0)
+
+/* 0x18 : I2CD Slave Device Address Register */
+#define ASPEED_I2CD_DEV_ADDR_MASK GENMASK(6, 0)
+
+enum aspeed_i2c_slave_state {
+ ASPEED_I2C_SLAVE_START,
+ ASPEED_I2C_SLAVE_READ_REQUESTED,
+ ASPEED_I2C_SLAVE_READ_PROCESSED,
+ ASPEED_I2C_SLAVE_WRITE_REQUESTED,
+ ASPEED_I2C_SLAVE_WRITE_RECEIVED,
+ ASPEED_I2C_SLAVE_STOP,
+};
+
+struct aspeed_i2c_bus {
+ struct i2c_adapter adap;
+ struct device *dev;
+ void __iomem *base;
+ spinlock_t lock;
+ struct completion cmd_complete;
+ int irq;
+ /* Transaction state. */
+ struct i2c_msg *msg;
+ int msg_pos;
+ u32 cmd_err;
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+ struct i2c_client *slave;
+ enum aspeed_i2c_slave_state slave_state;
+#endif
+};
+
+struct aspeed_i2c_controller {
+ struct device *dev;
+ void __iomem *base;
+ int irq;
+ struct irq_domain *irq_domain;
+};
+
+static inline void aspeed_i2c_write(struct aspeed_i2c_bus *bus, u32 val,
+ u32 reg)
+{
+ writel(val, bus->base + reg);
+}
+
+static inline u32 aspeed_i2c_read(struct aspeed_i2c_bus *bus, u32 reg)
+{
+ return readl(bus->base + reg);
+}
+
+static u8 aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
+{
+ u32 command;
+ unsigned long time_left;
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&bus->lock, flags);
+ command = aspeed_i2c_read(bus, ASPEED_I2C_CMD_REG);
+ /* Bus is idle: no recovery needed. */
+ if ((command & ASPEED_I2CD_SDA_LINE_STS) &&
+ (command & ASPEED_I2CD_SCL_LINE_STS))
+ goto out;
+
+ dev_dbg(bus->dev, "bus hung (state %x), attempting recovery\n",
+ command);
+
+ /* Bus held: put bus in stop state. */
+ if ((command & ASPEED_I2CD_SDA_LINE_STS) &&
+ !(command & ASPEED_I2CD_SCL_LINE_STS)) {
+ aspeed_i2c_write(bus, ASPEED_I2CD_M_STOP_CMD,
+ ASPEED_I2C_CMD_REG);
+ reinit_completion(&bus->cmd_complete);
+ spin_unlock_irqrestore(&bus->lock, flags);
+
+ time_left = wait_for_completion_interruptible_timeout(
+ &bus->cmd_complete, bus->adap.timeout * HZ);
+
+ spin_lock_irqsave(&bus->lock, flags);
+ if (time_left == 0)
+ ret = -ETIMEDOUT;
+ else if (bus->cmd_err)
+ ret = -EIO;
+ /* Bus error. */
+ } else if (!(command & ASPEED_I2CD_SDA_LINE_STS)) {
+ aspeed_i2c_write(bus, ASPEED_I2CD_BUS_RECOVER_CMD,
+ ASPEED_I2C_CMD_REG);
+ reinit_completion(&bus->cmd_complete);
+ spin_unlock_irqrestore(&bus->lock, flags);
+
+ time_left = wait_for_completion_interruptible_timeout(
+ &bus->cmd_complete, bus->adap.timeout * HZ);
+
+ spin_lock_irqsave(&bus->lock, flags);
+ if (time_left == 0)
+ ret = -ETIMEDOUT;
+ else if (bus->cmd_err)
+ ret = -EIO;
+ /* Recovery failed. */
+ else if (!(aspeed_i2c_read(bus, ASPEED_I2C_CMD_REG) &
+ ASPEED_I2CD_SDA_LINE_STS))
+ ret = -EIO;
+ }
+
+out:
+ spin_unlock_irqrestore(&bus->lock, flags);
+ return ret;
+}
+
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+static bool aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus)
+{
+ bool irq_handled = true;
+ u32 command;
+ u32 irq_status;
+ u32 status_ack = 0;
+ u8 value;
+ struct i2c_client *slave = bus->slave;
+
+ spin_lock(&bus->lock);
+ if (!slave) {
+ irq_handled = false;
+ goto out;
+ }
+ command = aspeed_i2c_read(bus, ASPEED_I2C_CMD_REG);
+ irq_status = aspeed_i2c_read(bus, ASPEED_I2C_INTR_STS_REG);
+
+ /* Slave was requested, restart state machine. */
+ if (irq_status & ASPEED_I2CD_INTR_SLAVE_MATCH) {
+ status_ack |= ASPEED_I2CD_INTR_SLAVE_MATCH;
+ bus->slave_state = ASPEED_I2C_SLAVE_START;
+ }
+ /* Slave is not currently active, irq was for someone else. */
+ if (bus->slave_state == ASPEED_I2C_SLAVE_STOP) {
+ irq_handled = false;
+ goto out;
+ }
+
+ dev_dbg(bus->dev, "slave irq status 0x%08x, cmd 0x%08x\n",
+ irq_status, command);
+
+ /* Slave was sent something. */
+ if (irq_status & ASPEED_I2CD_INTR_RX_DONE) {
+ value = aspeed_i2c_read(bus, ASPEED_I2C_BYTE_BUF_REG) >> 8;
+ /* Handle address frame. */
+ if (bus->slave_state == ASPEED_I2C_SLAVE_START) {
+ if (value & 0x1)
+ bus->slave_state =
+ ASPEED_I2C_SLAVE_READ_REQUESTED;
+ else
+ bus->slave_state =
+ ASPEED_I2C_SLAVE_WRITE_REQUESTED;
+ }
+ status_ack |= ASPEED_I2CD_INTR_RX_DONE;
+ }
+
+ /* Slave was asked to stop. */
+ if (irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) {
+ status_ack |= ASPEED_I2CD_INTR_NORMAL_STOP;
+ bus->slave_state = ASPEED_I2C_SLAVE_STOP;
+ }
+ if (irq_status & ASPEED_I2CD_INTR_TX_NAK) {
+ status_ack |= ASPEED_I2CD_INTR_TX_NAK;
+ bus->slave_state = ASPEED_I2C_SLAVE_STOP;
+ }
+
+ if (bus->slave_state == ASPEED_I2C_SLAVE_READ_REQUESTED) {
+ if (irq_status & ASPEED_I2CD_INTR_TX_ACK)
+ dev_err(bus->dev, "Unexpected ACK on read request.\n");
+ bus->slave_state = ASPEED_I2C_SLAVE_READ_PROCESSED;
+
+ i2c_slave_event(slave, I2C_SLAVE_READ_REQUESTED, &value);
+ aspeed_i2c_write(bus, value, ASPEED_I2C_BYTE_BUF_REG);
+ aspeed_i2c_write(bus, ASPEED_I2CD_S_TX_CMD, ASPEED_I2C_CMD_REG);
+ } else if (bus->slave_state == ASPEED_I2C_SLAVE_READ_PROCESSED) {
+ status_ack |= ASPEED_I2CD_INTR_TX_ACK;
+ if (!(irq_status & ASPEED_I2CD_INTR_TX_ACK))
+ dev_err(bus->dev,
+ "Expected ACK after processed read.\n");
+ i2c_slave_event(slave, I2C_SLAVE_READ_PROCESSED, &value);
+ aspeed_i2c_write(bus, value, ASPEED_I2C_BYTE_BUF_REG);
+ aspeed_i2c_write(bus, ASPEED_I2CD_S_TX_CMD, ASPEED_I2C_CMD_REG);
+ } else if (bus->slave_state == ASPEED_I2C_SLAVE_WRITE_REQUESTED) {
+ bus->slave_state = ASPEED_I2C_SLAVE_WRITE_RECEIVED;
+ i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value);
+ } else if (bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED) {
+ i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED, &value);
+ } else if (bus->slave_state == ASPEED_I2C_SLAVE_STOP) {
+ i2c_slave_event(slave, I2C_SLAVE_STOP, &value);
+ }
+
+ if (status_ack != irq_status)
+ dev_err(bus->dev,
+ "irq handled != irq. expected %x, but was %x\n",
+ irq_status, status_ack);
+ aspeed_i2c_write(bus, status_ack, ASPEED_I2C_INTR_STS_REG);
+
+out:
+ spin_unlock(&bus->lock);
+ return irq_handled;
+}
+#endif
+
+static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
+{
+ const u32 errs = ASPEED_I2CD_INTR_ARBIT_LOSS |
+ ASPEED_I2CD_INTR_ABNORMAL |
+ ASPEED_I2CD_INTR_SCL_TIMEOUT |
+ ASPEED_I2CD_INTR_SDA_DL_TIMEOUT |
+ ASPEED_I2CD_INTR_TX_NAK;
+ u32 irq_status;
+
+ spin_lock(&bus->lock);
+ irq_status = aspeed_i2c_read(bus, ASPEED_I2C_INTR_STS_REG);
+ bus->cmd_err = irq_status & errs;
+
+ dev_dbg(bus->dev, "master irq status 0x%08x\n", irq_status);
+
+ /* No message to transfer. */
+ if (bus->cmd_err ||
+ (irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) ||
+ (irq_status & ASPEED_I2CD_INTR_BUS_RECOVER_DONE)) {
+ complete(&bus->cmd_complete);
+ goto out;
+ } else if (!bus->msg || bus->msg_pos >= bus->msg->len)
+ goto out;
+
+ if ((bus->msg->flags & I2C_M_RD) &&
+ (irq_status & ASPEED_I2CD_INTR_RX_DONE)) {
+ bus->msg->buf[bus->msg_pos++] = aspeed_i2c_read(
+ bus, ASPEED_I2C_BYTE_BUF_REG) >> 8;
+ if (bus->msg_pos + 1 < bus->msg->len)
+ aspeed_i2c_write(bus, ASPEED_I2CD_M_RX_CMD,
+ ASPEED_I2C_CMD_REG);
+ else if (bus->msg_pos < bus->msg->len)
+ aspeed_i2c_write(bus, ASPEED_I2CD_M_RX_CMD |
+ ASPEED_I2CD_M_S_RX_CMD_LAST,
+ ASPEED_I2C_CMD_REG);
+ } else if (!(bus->msg->flags & I2C_M_RD) &&
+ (irq_status & ASPEED_I2CD_INTR_TX_ACK)) {
+ aspeed_i2c_write(bus, bus->msg->buf[bus->msg_pos++],
+ ASPEED_I2C_BYTE_BUF_REG);
+ aspeed_i2c_write(bus, ASPEED_I2CD_M_TX_CMD, ASPEED_I2C_CMD_REG);
+ }
+
+ /* Transmission complete: notify caller. */
+ if (bus->msg_pos >= bus->msg->len)
+ complete(&bus->cmd_complete);
+out:
+ aspeed_i2c_write(bus, irq_status, ASPEED_I2C_INTR_STS_REG);
+ spin_unlock(&bus->lock);
+ return true;
+}
+
+static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
+{
+ struct aspeed_i2c_bus *bus = dev_id;
+
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+ if (aspeed_i2c_slave_irq(bus)) {
+ dev_dbg(bus->dev, "irq handled by slave.\n");
+ return IRQ_HANDLED;
+ }
+#endif
+ if (aspeed_i2c_master_irq(bus)) {
+ dev_dbg(bus->dev, "irq handled by master.\n");
+ return IRQ_HANDLED;
+ }
+ dev_err(bus->dev, "irq not handled properly!\n");
+ return IRQ_HANDLED;
+}
+
+static int aspeed_i2c_master_single_xfer(struct i2c_adapter *adap,
+ struct i2c_msg *msg)
+{
+ struct aspeed_i2c_bus *bus = adap->algo_data;
+ unsigned long flags;
+ u8 slave_addr;
+ u32 command = ASPEED_I2CD_M_START_CMD | ASPEED_I2CD_M_TX_CMD;
+ int ret = msg->len;
+ unsigned long time_left;
+
+ spin_lock_irqsave(&bus->lock, flags);
+ bus->msg = msg;
+ bus->msg_pos = 0;
+ slave_addr = msg->addr << 1;
+ if (msg->flags & I2C_M_RD) {
+ slave_addr |= 1;
+ command |= ASPEED_I2CD_M_RX_CMD;
+ if (msg->len == 1)
+ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
+ }
+ aspeed_i2c_write(bus, slave_addr, ASPEED_I2C_BYTE_BUF_REG);
+ aspeed_i2c_write(bus, command, ASPEED_I2C_CMD_REG);
+ reinit_completion(&bus->cmd_complete);
+ spin_unlock_irqrestore(&bus->lock, flags);
+
+ time_left = wait_for_completion_interruptible_timeout(
+ &bus->cmd_complete, bus->adap.timeout * HZ * msg->len);
+ if (time_left == 0)
+ return -ETIMEDOUT;
+
+ spin_lock_irqsave(&bus->lock, flags);
+ if (bus->cmd_err)
+ ret = -EIO;
+ bus->msg = NULL;
+ spin_unlock_irqrestore(&bus->lock, flags);
+
+ return ret;
+}
+
+static int aspeed_i2c_master_xfer(struct i2c_adapter *adap,
+ struct i2c_msg *msgs, int num)
+{
+ struct aspeed_i2c_bus *bus = adap->algo_data;
+ int ret;
+ int i;
+ unsigned long flags;
+ unsigned long time_left;
+
+ /* If bus is busy, attempt recovery. We assume a single master
+ * environment.
+ */
+ if (aspeed_i2c_read(bus, ASPEED_I2C_CMD_REG) &
+ ASPEED_I2CD_BUS_BUSY_STS) {
+ ret = aspeed_i2c_recover_bus(bus);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < num; i++) {
+ ret = aspeed_i2c_master_single_xfer(adap, &msgs[i]);
+ if (ret < 0)
+ break;
+ /* TODO: Support other forms of I2C protocol mangling. */
+ if (msgs[i].flags & I2C_M_STOP) {
+ spin_lock_irqsave(&bus->lock, flags);
+ aspeed_i2c_write(bus, ASPEED_I2CD_M_STOP_CMD,
+ ASPEED_I2C_CMD_REG);
+ reinit_completion(&bus->cmd_complete);
+ spin_unlock_irqrestore(&bus->lock, flags);
+
+ time_left = wait_for_completion_interruptible_timeout(
+ &bus->cmd_complete,
+ bus->adap.timeout * HZ);
+ if (time_left == 0)
+ return -ETIMEDOUT;
+ }
+ }
+
+ spin_lock_irqsave(&bus->lock, flags);
+ aspeed_i2c_write(bus, ASPEED_I2CD_M_STOP_CMD, ASPEED_I2C_CMD_REG);
+ reinit_completion(&bus->cmd_complete);
+ spin_unlock_irqrestore(&bus->lock, flags);
+
+ time_left = wait_for_completion_interruptible_timeout(
+ &bus->cmd_complete, bus->adap.timeout * HZ);
+ if (time_left == 0)
+ return -ETIMEDOUT;
+
+ /* If nothing went wrong, return number of messages transferred. */
+ if (ret < 0)
+ return ret;
+ else
+ return i;
+}
+
+static u32 aspeed_i2c_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA;
+}
+
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+static int aspeed_i2c_reg_slave(struct i2c_client *client)
+{
+ struct aspeed_i2c_bus *bus;
+ unsigned long flags;
+ u32 addr_reg_val;
+ u32 func_ctrl_reg_val;
+
+ bus = client->adapter->algo_data;
+ spin_lock_irqsave(&bus->lock, flags);
+ if (bus->slave) {
+ spin_unlock_irqrestore(&bus->lock, flags);
+ return -EINVAL;
+ }
+
+ /* Set slave addr. */
+ addr_reg_val = aspeed_i2c_read(bus, ASPEED_I2C_DEV_ADDR_REG);
+ addr_reg_val &= ~ASPEED_I2CD_DEV_ADDR_MASK;
+ addr_reg_val |= client->addr & ASPEED_I2CD_DEV_ADDR_MASK;
+ aspeed_i2c_write(bus, addr_reg_val, ASPEED_I2C_DEV_ADDR_REG);
+
+ /* Switch from master mode to slave mode. */
+ func_ctrl_reg_val = aspeed_i2c_read(bus, ASPEED_I2C_FUN_CTRL_REG);
+ func_ctrl_reg_val &= ~ASPEED_I2CD_MASTER_EN;
+ func_ctrl_reg_val |= ASPEED_I2CD_SLAVE_EN;
+ aspeed_i2c_write(bus, func_ctrl_reg_val, ASPEED_I2C_FUN_CTRL_REG);
+
+ bus->slave = client;
+ bus->slave_state = ASPEED_I2C_SLAVE_STOP;
+ spin_unlock_irqrestore(&bus->lock, flags);
+ return 0;
+}
+
+static int aspeed_i2c_unreg_slave(struct i2c_client *client)
+{
+ struct aspeed_i2c_bus *bus = client->adapter->algo_data;
+ unsigned long flags;
+ u32 func_ctrl_reg_val;
+
+ spin_lock_irqsave(&bus->lock, flags);
+ if (!bus->slave) {
+ spin_unlock_irqrestore(&bus->lock, flags);
+ return -EINVAL;
+ }
+
+ /* Switch from slave mode to master mode. */
+ func_ctrl_reg_val = aspeed_i2c_read(bus, ASPEED_I2C_FUN_CTRL_REG);
+ func_ctrl_reg_val &= ~ASPEED_I2CD_SLAVE_EN;
+ func_ctrl_reg_val |= ASPEED_I2CD_MASTER_EN;
+ aspeed_i2c_write(bus, func_ctrl_reg_val, ASPEED_I2C_FUN_CTRL_REG);
+
+ bus->slave = NULL;
+ spin_unlock_irqrestore(&bus->lock, flags);
+ return 0;
+}
+#endif
+
+static const struct i2c_algorithm aspeed_i2c_algo = {
+ .master_xfer = aspeed_i2c_master_xfer,
+ .functionality = aspeed_i2c_functionality,
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+ .reg_slave = aspeed_i2c_reg_slave,
+ .unreg_slave = aspeed_i2c_unreg_slave,
+#endif
+};
+
+static u32 aspeed_i2c_get_clk_reg_val(u32 divider_ratio)
+{
+ unsigned int inc = 0, div;
+ u32 scl_low, scl_high, data;
+
+ for (div = 0; divider_ratio >= 16; div++) {
+ inc |= (divider_ratio & 1);
+ divider_ratio >>= 1;
+ }
+ divider_ratio += inc;
+ scl_low = (divider_ratio >> 1) - 1;
+ scl_high = divider_ratio - scl_low - 2;
+ data = 0x77700300 | (scl_high << 16) | (scl_low << 12) | div;
+ return data;
+}
+
+static int aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus,
+ struct platform_device *pdev)
+{
+ struct clk *pclk;
+ u32 clk_freq;
+ u32 divider_ratio;
+ int ret;
+
+ pclk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(pclk)) {
+ dev_err(&pdev->dev, "clk_get failed\n");
+ return PTR_ERR(pclk);
+ }
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "clock-frequency", &clk_freq);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "Could not read clock-frequency property\n");
+ clk_freq = 100000;
+ }
+ divider_ratio = clk_get_rate(pclk) / clk_freq;
+ /* We just need the clock rate, we don't actually use the clk object. */
+ devm_clk_put(&pdev->dev, pclk);
+
+ /* Set AC Timing */
+ if (clk_freq / 1000 > 400) {
+ aspeed_i2c_write(bus, aspeed_i2c_read(bus,
+ ASPEED_I2C_FUN_CTRL_REG) |
+ ASPEED_I2CD_M_HIGH_SPEED_EN |
+ ASPEED_I2CD_M_SDA_DRIVE_1T_EN |
+ ASPEED_I2CD_SDA_DRIVE_1T_EN,
+ ASPEED_I2C_FUN_CTRL_REG);
+
+ aspeed_i2c_write(bus, 0x3, ASPEED_I2C_AC_TIMING_REG2);
+ aspeed_i2c_write(bus, aspeed_i2c_get_clk_reg_val(divider_ratio),
+ ASPEED_I2C_AC_TIMING_REG1);
+ } else {
+ aspeed_i2c_write(bus, aspeed_i2c_get_clk_reg_val(divider_ratio),
+ ASPEED_I2C_AC_TIMING_REG1);
+ aspeed_i2c_write(bus, ASPEED_NO_TIMEOUT_CTRL,
+ ASPEED_I2C_AC_TIMING_REG2);
+ }
+
+ return 0;
+}
+
+static void noop(struct irq_data *data) { }
+
+static struct irq_chip aspeed_i2c_irqchip = {
+ .name = "ast-i2c",
+ .irq_unmask = noop,
+ .irq_mask = noop,
+};
+
+static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+{
+ struct aspeed_i2c_bus *bus;
+ struct aspeed_i2c_controller *controller =
+ dev_get_drvdata(pdev->dev.parent);
+ struct resource *res;
+ int ret, irq;
+ u32 hwirq;
+
+ bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
+ if (!bus)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ bus->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(bus->base))
+ return PTR_ERR(bus->base);
+
+ bus->irq = platform_get_irq(pdev, 0);
+ if (bus->irq < 0)
+ return -ENXIO;
+ ret = of_property_read_u32(pdev->dev.of_node, "interrupts", &hwirq);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "no I2C 'interrupts' property\n");
+ return -ENXIO;
+ }
+ irq = irq_create_mapping(controller->irq_domain, hwirq);
+ irq_set_chip_data(irq, controller);
+ irq_set_chip_and_handler(irq, &aspeed_i2c_irqchip, handle_simple_irq);
+ ret = devm_request_irq(&pdev->dev, bus->irq, aspeed_i2c_bus_irq,
+ 0, dev_name(&pdev->dev), bus);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request interrupt\n");
+ return -ENXIO;
+ }
+
+ /* Initialize the I2C adapter */
+ spin_lock_init(&bus->lock);
+ init_completion(&bus->cmd_complete);
+ bus->adap.owner = THIS_MODULE;
+ bus->adap.retries = 0;
+ bus->adap.timeout = 5;
+ bus->adap.algo = &aspeed_i2c_algo;
+ bus->adap.algo_data = bus;
+ bus->adap.dev.parent = &pdev->dev;
+ bus->adap.dev.of_node = pdev->dev.of_node;
+ snprintf(bus->adap.name, sizeof(bus->adap.name), "Aspeed i2c");
+
+ bus->dev = &pdev->dev;
+
+ /* reset device: disable master & slave functions */
+ aspeed_i2c_write(bus, 0, ASPEED_I2C_FUN_CTRL_REG);
+
+ ret = aspeed_i2c_init_clk(bus, pdev);
+ if (ret < 0)
+ return ret;
+
+ /* Enable Master Mode */
+ aspeed_i2c_write(bus, aspeed_i2c_read(bus, ASPEED_I2C_FUN_CTRL_REG) |
+ ASPEED_I2CD_MASTER_EN |
+ ASPEED_I2CD_MULTI_MASTER_DIS, ASPEED_I2C_FUN_CTRL_REG);
+
+ /* Set interrupt generation of I2C controller */
+ aspeed_i2c_write(bus, ASPEED_I2CD_INTR_SDA_DL_TIMEOUT |
+ ASPEED_I2CD_INTR_BUS_RECOVER_DONE |
+ ASPEED_I2CD_INTR_SCL_TIMEOUT |
+ ASPEED_I2CD_INTR_ABNORMAL |
+ ASPEED_I2CD_INTR_NORMAL_STOP |
+ ASPEED_I2CD_INTR_ARBIT_LOSS |
+ ASPEED_I2CD_INTR_RX_DONE |
+ ASPEED_I2CD_INTR_TX_NAK |
+ ASPEED_I2CD_INTR_TX_ACK,
+ ASPEED_I2C_INTR_CTRL_REG);
+
+ ret = i2c_add_adapter(&bus->adap);
+ if (ret < 0)
+ return -ENXIO;
+
+ platform_set_drvdata(pdev, bus);
+
+ dev_info(bus->dev, "i2c bus %d registered, irq %d\n",
+ bus->adap.nr, bus->irq);
+
+ return 0;
+}
+
+static int aspeed_i2c_remove_bus(struct platform_device *pdev)
+{
+ struct aspeed_i2c_bus *bus = platform_get_drvdata(pdev);
+
+ i2c_del_adapter(&bus->adap);
+ return 0;
+}
+
+static const struct of_device_id aspeed_i2c_bus_of_table[] = {
+ { .compatible = "aspeed,ast2400-i2c-bus", },
+ { .compatible = "aspeed,ast2500-i2c-bus", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, aspeed_i2c_bus_of_table);
+
+static struct platform_driver aspeed_i2c_bus_driver = {
+ .probe = aspeed_i2c_probe_bus,
+ .remove = aspeed_i2c_remove_bus,
+ .driver = {
+ .name = "ast-i2c-bus",
+ .of_match_table = aspeed_i2c_bus_of_table,
+ },
+};
+
+static void aspeed_i2c_controller_irq(struct irq_desc *desc)
+{
+ struct aspeed_i2c_controller *c = irq_desc_get_handler_data(desc);
+ unsigned long p, status;
+ unsigned int bus_irq;
+
+ status = readl(c->base);
+ for_each_set_bit(p, &status, ASPEED_I2C_NUM_BUS) {
+ bus_irq = irq_find_mapping(c->irq_domain, p);
+ generic_handle_irq(bus_irq);
+ }
+}
+
+static int aspeed_i2c_probe_controller(struct platform_device *pdev)
+{
+ struct aspeed_i2c_controller *controller;
+ struct device_node *np;
+ struct resource *res;
+
+ controller = kzalloc(sizeof(*controller), GFP_KERNEL);
+ if (!controller)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ controller->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(controller->base))
+ return PTR_ERR(controller->base);
+
+ controller->irq = platform_get_irq(pdev, 0);
+ if (controller->irq < 0)
+ return -ENXIO;
+
+ controller->irq_domain = irq_domain_add_linear(pdev->dev.of_node,
+ ASPEED_I2C_NUM_BUS, &irq_domain_simple_ops, NULL);
+ if (!controller->irq_domain)
+ return -ENXIO;
+ controller->irq_domain->name = "ast-i2c-domain";
+
+ irq_set_chained_handler_and_data(controller->irq,
+ aspeed_i2c_controller_irq, controller);
+
+ controller->dev = &pdev->dev;
+
+ platform_set_drvdata(pdev, controller);
+
+ dev_info(controller->dev, "i2c controller registered, irq %d\n",
+ controller->irq);
+
+ for_each_child_of_node(pdev->dev.of_node, np) {
+ of_platform_device_create(np, NULL, &pdev->dev);
+ of_node_put(np);
+ }
+
+ return 0;
+}
+
+static int aspeed_i2c_remove_controller(struct platform_device *pdev)
+{
+ struct aspeed_i2c_controller *controller = platform_get_drvdata(pdev);
+
+ irq_domain_remove(controller->irq_domain);
+ return 0;
+}
+
+static const struct of_device_id aspeed_i2c_controller_of_table[] = {
+ { .compatible = "aspeed,ast2400-i2c-controller", },
+ { .compatible = "aspeed,ast2500-i2c-controller", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, aspeed_i2c_controller_of_table);
+
+static struct platform_driver aspeed_i2c_controller_driver = {
+ .probe = aspeed_i2c_probe_controller,
+ .remove = aspeed_i2c_remove_controller,
+ .driver = {
+ .name = "ast-i2c-controller",
+ .of_match_table = aspeed_i2c_controller_of_table,
+ },
+};
+
+static int __init aspeed_i2c_driver_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&aspeed_i2c_controller_driver);
+ if (ret < 0)
+ return ret;
+ return platform_driver_register(&aspeed_i2c_bus_driver);
+}
+module_init(aspeed_i2c_driver_init);
+
+static void __exit aspeed_i2c_driver_exit(void)
+{
+ platform_driver_unregister(&aspeed_i2c_bus_driver);
+ platform_driver_unregister(&aspeed_i2c_controller_driver);
+}
+module_exit(aspeed_i2c_driver_exit);
+
+MODULE_AUTHOR("Brendan Higgins <brendanhiggins@google.com>");
+MODULE_DESCRIPTION("Aspeed I2C Bus Driver");
+MODULE_LICENSE("GPL");
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply related
* [PATCH v4 0/2] i2c: aspeed: added driver for Aspeed I2C
From: Brendan Higgins @ 2016-11-05 1:58 UTC (permalink / raw)
To: wsa-z923LK4zBo2bacvFa/9K2g, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8
Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, joel-U3u1mxZcP9KHXe+LvDLADg,
openbmc-uLR06cmDAlY/bJ5BZ2RsiQ
Sorry, been a while since I was able to send an update for this.
As a refresher, I added a master mode and slave mode I2C driver for the Aspeed
24XX/25XX SoC as well as device binding documentation.
Changes since first update:
- I have removed the bus device tree param as requested here:
http://www.spinics.net/lists/devicetree/msg143850.html
- I2C adapter number is now generated dynamically unless an alias is provided
- I changed the Kconfig for the driver to depend only on ARCH_ASPEED
- Replaced the two module_platform_driver registrations with single
module_init
Changes have been tested on the Aspeed evaluation board.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2 1/3] remoteproc: qcom: Encapsulate pvt data structure for q6v56 hexagon.
From: kbuild test robot @ 2016-11-04 23:51 UTC (permalink / raw)
Cc: kbuild-all-JC7UmRfGjtg, bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A,
Avaneesh Kumar Dwivedi, Ohad Ben-Cohen, Rob Herring, Mark Rutland,
open list:REMOTE PROCESSOR (REMOTEPROC) SUBSYSTEM,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list
In-Reply-To: <1478268057-11847-2-git-send-email-akdwived-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 7190 bytes --]
Hi Avaneesh,
[auto build test ERROR on robh/for-next]
[also build test ERROR on v4.9-rc3 next-20161028]
[cannot apply to remoteproc/for-next]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
[Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on]
[Check https://git-scm.com/docs/git-format-patch for more information]
url: https://github.com/0day-ci/linux/commits/Avaneesh-Kumar-Dwivedi/remoteproc-qcom-Encapsulate-pvt-data-structure-for-q6v56-hexagon/20161104-220712
base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
config: arm64-allyesconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm64
Note: the linux-review/Avaneesh-Kumar-Dwivedi/remoteproc-qcom-Encapsulate-pvt-data-structure-for-q6v56-hexagon/20161104-220712 HEAD 1b4c0b8bb3bb8cd30a996282b7a6aa9f352836a2 builds fine.
It only hurts bisectibility.
All errors (new ones prefixed by >>):
drivers/remoteproc/qcom_q6v5_pil.c: In function 'q6_probe':
drivers/remoteproc/qcom_q6v5_pil.c:848:7: warning: assignment discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
desc = of_device_get_match_data(&pdev->dev);
^
drivers/remoteproc/qcom_q6v5_pil.c: At top level:
>> drivers/remoteproc/qcom_q6v5_pil.c:986:19: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
.q6_reset_init = q6v5_init_reset,
^~~~~~~~~~~~~~~
drivers/remoteproc/qcom_q6v5_pil.c:986:19: note: (near initialization for 'msm_8916_res.q6_reset_init')
cc1: some warnings being treated as errors
vim +986 drivers/remoteproc/qcom_q6v5_pil.c
842 {
843 struct q6v5 *qproc;
844 struct rproc *rproc;
845 struct q6_rproc_res *desc;
846 int ret;
847
> 848 desc = of_device_get_match_data(&pdev->dev);
849 if (!desc)
850 return -EINVAL;
851
852 rproc = rproc_alloc(&pdev->dev, pdev->name, &q6_ops,
853 desc->q6_mba_image, sizeof(*qproc));
854 if (!rproc) {
855 dev_err(&pdev->dev, "failed to allocate rproc\n");
856 return -ENOMEM;
857 }
858
859 rproc->fw_ops = &q6_fw_ops;
860
861 qproc = (struct q6v5 *)rproc->priv;
862 qproc->dev = &pdev->dev;
863 qproc->rproc = rproc;
864 platform_set_drvdata(pdev, qproc);
865
866 init_completion(&qproc->start_done);
867 init_completion(&qproc->stop_done);
868
869 qproc->q6_rproc_res = desc;
870 ret = q6v5_init_mem(qproc, pdev);
871 if (ret)
872 goto free_rproc;
873
874 ret = q6v5_alloc_memory_region(qproc);
875 if (ret)
876 goto free_rproc;
877
878 ret = q6v5_init_clocks(qproc);
879 if (ret)
880 goto free_rproc;
881
882 ret = q6v5_regulator_init(qproc);
883 if (ret)
884 goto free_rproc;
885
886 ret = qproc->q6_rproc_res->q6_reset_init(qproc, pdev);
887 if (ret)
888 goto free_rproc;
889
890 ret = q6v5_request_irq(qproc, pdev, "wdog", q6v5_wdog_interrupt);
891 if (ret < 0)
892 goto free_rproc;
893
894 ret = q6v5_request_irq(qproc, pdev, "fatal", q6v5_fatal_interrupt);
895 if (ret < 0)
896 goto free_rproc;
897
898 ret = q6v5_request_irq(qproc, pdev, "handover", q6v5_handover_interrupt);
899 if (ret < 0)
900 goto free_rproc;
901
902 ret = q6v5_request_irq(qproc, pdev, "stop-ack", q6v5_stop_ack_interrupt);
903 if (ret < 0)
904 goto free_rproc;
905
906 qproc->state = qcom_smem_state_get(&pdev->dev, "stop", &qproc->stop_bit);
907 if (IS_ERR(qproc->state))
908 goto free_rproc;
909
910 ret = rproc_add(rproc);
911 if (ret)
912 goto free_rproc;
913
914 return 0;
915
916 free_rproc:
917 rproc_put(rproc);
918
919 return ret;
920 }
921
922 static int q6_remove(struct platform_device *pdev)
923 {
924 struct q6v5 *qproc = platform_get_drvdata(pdev);
925
926 rproc_del(qproc->rproc);
927 rproc_put(qproc->rproc);
928
929 return 0;
930 }
931
932 char *proxy_8x96_reg_str[] = {"mx", "cx", "vdd_pll"};
933 int proxy_8x96_reg_action[3][2] = { {0, 1}, {1, 1}, {1, 0} };
934 int proxy_8x96_reg_load[] = {0, 100000, 100000};
935 int proxy_8x96_reg_min_voltage[] = {1050000, 1250000, 0};
936 char *proxy_8x96_clk_str[] = {"xo", "pnoc", "qdss"};
937 char *active_8x96_clk_str[] = {"iface", "bus", "mem", "gpll0_mss_clk",
938 "snoc_axi_clk", "mnoc_axi_clk"};
939
940 static struct q6_rproc_res msm_8996_res = {
941 .proxy_clks = proxy_8x96_clk_str,
942 .proxy_clk_cnt = 3,
943 .active_clks = active_8x96_clk_str,
944 .active_clk_cnt = 6,
945 .proxy_regs = proxy_8x96_reg_str,
946 .active_regs = NULL,
947 .proxy_reg_action = (int **)proxy_8x96_reg_action,
948 .proxy_reg_load = (int *)proxy_8x96_reg_load,
949 .active_reg_action = NULL,
950 .active_reg_load = NULL,
951 .proxy_reg_voltage = (int *)proxy_8x96_reg_min_voltage,
952 .active_reg_voltage = NULL,
953 .proxy_reg_cnt = 3,
954 .active_reg_cnt = 0,
955 .q6_reset_init = q6v56_init_reset,
956 .q6_version = "v56",
957 .q6_mba_image = "mba.mbn",
958 };
959
960 char *proxy_8x16_reg_str[] = {"mx", "cx", "pll"};
961 char *active_8x16_reg_str[] = {"mss"};
962 int proxy_8x16_reg_action[4][2] = { {0, 1}, {1, 0}, {1, 0} };
963 int active_8x16_reg_action[1][2] = { {1, 1} };
964 int proxy_8x16_reg_load[] = {100000, 0, 100000, 100000};
965 int active_8x16_reg_load[] = {100000};
966 int proxy_8x16_reg_min_voltage[] = {1050000, 0, 0};
967 int active_8x16_reg_min_voltage[] = {1000000};
968 char *proxy_8x16_clk_str[] = {"xo"};
969 char *active_8x16_clk_str[] = {"iface", "bus", "mem"};
970
971 static struct q6_rproc_res msm_8916_res = {
972 .proxy_clks = proxy_8x16_clk_str,
973 .proxy_clk_cnt = 1,
974 .active_clks = active_8x16_clk_str,
975 .active_clk_cnt = 3,
976 .proxy_regs = proxy_8x16_reg_str,
977 .active_regs = active_8x16_reg_str,
978 .proxy_reg_action = (int **)proxy_8x16_reg_action,
979 .proxy_reg_load = (int *)proxy_8x16_reg_load,
980 .active_reg_action = (int **)active_8x16_reg_action,
981 .active_reg_load = (int *)active_8x16_reg_load,
982 .proxy_reg_voltage = (int *)proxy_8x16_reg_min_voltage,
983 .active_reg_voltage = active_8x16_reg_min_voltage,
984 .proxy_reg_cnt = 3,
985 .active_reg_cnt = 1,
> 986 .q6_reset_init = q6v5_init_reset,
987 .q6_version = "v5",
988 .q6_mba_image = "mba.b00",
989 };
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 51385 bytes --]
^ permalink raw reply
* Re: [v17 2/2] drm/bridge: Add I2C based driver for ps8640 bridge
From: Daniel Kurtz @ 2016-11-04 23:21 UTC (permalink / raw)
To: Matthias Brugger
Cc: Enric Balletbo Serra, Jitao Shi, David Airlie, Thierry Reding,
Mark Rutland, stonea168, dri-devel, Andy Yan, Ajay Kumar,
Vincent Palatin, cawa cheng,
Bibby Hsieh (謝濟遠),
CK Hu (胡俊光), Russell King,
devicetree@vger.kernel.org, Sascha Hauer, Pawel Moll,
Ian Campbell
In-Reply-To: <e00519e2-990c-b9b2-71d4-a4c8d36f5e65@gmail.com>
On Tue, Oct 25, 2016 at 6:23 AM, Matthias Brugger
<matthias.bgg@gmail.com> wrote:
>
> On 10/18/2016 04:37 PM, Enric Balletbo Serra wrote:
> [...]
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/bridge/parade-ps8640.c
> [...]
>>>
>>> +
>>> +/* Firmware */
>>> +#define PS_FW_NAME "ps864x_fw.bin"
>>> +
>>
>> From where I can download this firmware image?
>
> I suppose this FW bits have to be added to linux-firmware repository first, before this patch can be accepted.
All PS8640 devices should already ship with working firmware.
The firmware update procedure is only used in the unlikely event where
one wants to update the bridge to a different firmware provided by
Parade.
Why must the lack of firmware really block landing this driver?
If this is really so, can we just land the functional part of the
driver first, and add the firmware update in a follow-up patch.
>
> Regards,
> Matthias
^ permalink raw reply
* Re: [PATCH] Documentation: bindings: fix twl-rtc documentation
From: Alexandre Belloni @ 2016-11-04 23:09 UTC (permalink / raw)
To: Nicolae Rosia
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
linux-omap-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Mark Rutland,
Alessandro Zummo
In-Reply-To: <1477993356-9195-1-git-send-email-Nicolae_Rosia-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
On 01/11/2016 at 11:42:36 +0200, Nicolae Rosia wrote :
> Add interrupts documentation
> Fix example and formatting
>
> Signed-off-by: Nicolae Rosia <Nicolae_Rosia-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
> ---
> Documentation/devicetree/bindings/rtc/twl-rtc.txt | 19 +++++++++----------
> 1 file changed, 9 insertions(+), 10 deletions(-)
>
Applied, thanks.
--
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v3 1/7] rtc: rtc-jz4740: Add support for the RTC in the jz4780 SoC
From: Alexandre Belloni @ 2016-11-04 23:08 UTC (permalink / raw)
To: Paul Cercueil
Cc: rtc-linux-/JYPxA39Uh5TLH3MbocFFw, Alessandro Zummo, Rob Herring,
Mark Rutland, Ralf Baechle, Maarten ter Huurne,
Lars-Peter Clausen, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-mips-6z/3iImG2C8G8FEW9MqTrA
In-Reply-To: <20161031203951.5444-1-paul-icTtO2rgO2OTuSrc4Mpeew@public.gmane.org>
On 31/10/2016 at 21:39:45 +0100, Paul Cercueil wrote :
> The RTC unit present in the JZ4780 works mostly the same as the one in
> the JZ4740. The major difference is that register writes need to be
> explicitly enabled, by writing a magic code (0xA55A) to a "write
> enable" register before each access.
>
> Signed-off-by: Paul Cercueil <paul-icTtO2rgO2OTuSrc4Mpeew@public.gmane.org>
> Acked-by: Maarten ter Huurne <maarten-Ph2Y2OKCxY1M656bX5wj8A@public.gmane.org>
> ---
> drivers/rtc/Kconfig | 6 +++---
> drivers/rtc/rtc-jz4740.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 51 insertions(+), 5 deletions(-)
>
> v2: No change
> v3: No change
>
All applied, thanks
--
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply
* Re: [PATCH V5] pinctrl: qcom: Add msm8994 pinctrl driver
From: Linus Walleij @ 2016-11-04 22:58 UTC (permalink / raw)
To: Michael Scott
Cc: linux-gpio@vger.kernel.org, linux-arm-msm@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
Rob Herring, Mark Rutland, Andy Gross, David Brown,
Bjorn Andersson, Joonwoo Park, Jeremy McNicoll, Stephen Boyd
In-Reply-To: <20161103211526.6095-1-michael.scott@linaro.org>
On Thu, Nov 3, 2016 at 10:15 PM, Michael Scott <michael.scott@linaro.org> wrote:
> Initial pinctrl driver for QCOM msm8994 platforms.
>
> In order to continue the initial board support for QCOM msm8994/msm8992
> presented in patches from Jeremy McNicoll <jeremymc@redhat.com>, let's put
> a proper pinctrl driver in place.
>
> Currently, the DT for these platforms uses the msm8x74 pinctrl driver to
> enable basic UART. Beyond the first few pins the rest are different enough
> to justify it's own driver.
>
> Note: This driver is also used by QCOM's msm8992 platform as it's TLM block
> is the same.
>
> - Initial formatting and style was taken from the msm8x74 pinctrl driver
> added by Björn Andersson <bjorn.andersson@linaro.org>
> - Data was then adjusted per QCOM MSM8994v2 documentation for Top Level
> Multiplexing
> - Bindings documentation was based on qcom,msm8996-pinctrl.txt by
> Joonwoo Park <joonwoop@codeaurora.org> and then modified for msm8994
> content
>
> Signed-off-by: Michael Scott <michael.scott@linaro.org>
> Tested-by: Jeremy McNicoll <jeremymc@redhat.com>
> Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> Acked-by: Rob Herring <robh@kernel.org>
> ---
> V5:
This v5 version applied.
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH 1/2] pinctrl: tegra: Add DT binding for io pads control
From: Linus Walleij @ 2016-11-04 22:29 UTC (permalink / raw)
To: Laxman Dewangan
Cc: thierry.reding@gmail.com, Stephen Warren, Rob Herring,
Mark Rutland, Jon Hunter, Masahiro Yamada,
linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,
linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <1478077742-25437-2-git-send-email-ldewangan@nvidia.com>
On Wed, Nov 2, 2016 at 10:09 AM, Laxman Dewangan <ldewangan@nvidia.com> wrote:
> NVIDIA Tegra124 and later SoCs support the multi-voltage level and
> low power state of some of its IO pads. The IO pads can work in
> the voltage of the 1.8V and 3.3V of IO power rail sources. When IO
> interface are not used then IO pads can be configure in low power
> state to reduce the power from that IO pads.
>
> On Tegra124, the IO power rail source is auto detected by SoC and hence
> it is only require to configure in low power mode if IO pads are not
> used.
>
> On T210 onwards, the auto-detection is removed from SoC and hence SW
> must configure the PMC register explicitly to set proper voltage in
> IO pads based on IO rail power source voltage.
>
> Add DT binding document for detailing the DT properties for
> configuring IO pads voltage levels and its power state.
>
> Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
(...)
> +-nvidia,power-source-voltage: Integer. The voltage level of IO pads. The
> + valid values are 1.8V and 3.3V. Macros are
> + defined for these voltage levels in
> + <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h>
> + Use TEGRA_IO_PAD_POWER_SOURCE_1800000UV for 1.8V
> + Use TEGRA_IO_PAD_POWER_SOURCE_3300000UV for 3.3V
> +
> + All IO pads do not support the 1.8V/3.3V
> + configurations. Valid values for "pins" are
> + audio-hv, dmic, gpio, sdmmc1, sdmmc3, spi-hv.
As mentioned in another patch, what is wrong with the standard
power-source binding?
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH 2/2] pinctrl: tegra: Add driver to configure voltage and power of io pads
From: Linus Walleij @ 2016-11-04 22:24 UTC (permalink / raw)
To: Laxman Dewangan
Cc: thierry.reding@gmail.com, Stephen Warren, Rob Herring,
Mark Rutland, Jon Hunter, Masahiro Yamada,
linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,
linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <1478077742-25437-3-git-send-email-ldewangan@nvidia.com>
On Wed, Nov 2, 2016 at 10:09 AM, Laxman Dewangan <ldewangan@nvidia.com> wrote:
> NVIDIA Tegra124 and later SoCs support the multi-voltage level and
> low power state of some of its IO pads. The IO pads can work in
> the voltage of the 1.8V and 3.3V of IO power rail sources. When IO
> interface are not used then IO pads can be configure in low power
> state to reduce the power from that IO pads.
>
> On Tegra124, the IO power rail source is auto detected by SoC and hence
> it is only require to configure in low power mode if IO pads are not
> used.
>
> On T210 onwards, the auto-detection is removed from SoC and hence SW
> must configure the PMC register explicitly to set proper voltage in
> IO pads based on IO rail power source voltage.
>
> This driver adds the IO pad driver to configure the power state and
> IO pad voltage based on the usage and power tree via pincontrol
> framework. The configuration can be static and dynamic.
>
> Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Looking for an ACK from Stephen &| Thierry.
> ---
> On top of the branch from Thierry's T186 work
> https://github.com/thierryreding/linux/tree/tegra186
But it's an orthogonal patch right?
The build robot seems to have problems with it so pls fix these.
> +static const struct pinconf_generic_params tegra_io_pads_cfg_params[] = {
> + {
> + .property = "nvidia,power-source-voltage",
> + .param = TEGRA_IO_PAD_POWER_SOURCE_VOLTAGE,
> + },
> +};
Why can you not use the standard power-source binding
from Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
instead of inventing this nvidia,* variant?
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v2 2/3] irqchip: mtk-cirq: Add mediatek mtk-cirq implement
From: Marc Zyngier @ 2016-11-04 22:21 UTC (permalink / raw)
To: Youlin Pei
Cc: Rob Herring, Matthias Brugger, Thomas Gleixner, Jason Cooper,
Mark Rutland, Russell King, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
hongkun.cao-NuS5LvNUpcJWk0Htik3J/w,
yong.wu-NuS5LvNUpcJWk0Htik3J/w, erin.lo-NuS5LvNUpcJWk0Htik3J/w,
chieh-jay.liu-NuS5LvNUpcJWk0Htik3J/w
In-Reply-To: <1478234577.7975.29.camel@mtksdaap41>
On Fri, Nov 04 2016 at 04:42:57 AM, Youlin Pei <youlin.pei-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org> wrote:
> On Tue, 2016-11-01 at 20:49 +0000, Marc Zyngier wrote:
>> On Tue, Nov 01 2016 at 11:52:01 AM, Youlin Pei <youlin.pei-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org> wrote:
>> > In Mediatek SOCs, the CIRQ is a low power interrupt controller
>> > designed to works outside MCUSYS which comprises with Cortex-Ax
>> > cores,CCI and GIC.
>> >
>> > The CIRQ controller is integrated in between MCUSYS( include
>> > Cortex-Ax, CCI and GIC ) and interrupt sources as the second
>> > level interrupt controller. The external interrupts which outside
>> > MCUSYS will feed through CIRQ then bypass to GIC. CIRQ can monitors
>> > all edge trigger interupts. When an edge interrupt is triggered,
>> > CIRQ can record the status and generate a pulse signal to GIC when
>> > flush command executed.
>> >
>> > When system enters sleep mode, MCUSYS will be turned off to improve
>> > power consumption, also GIC is power down. The edge trigger interrupts
>> > will be lost in this scenario without CIRQ.
>> >
>> > This commit provides the CIRQ irqchip implement.
>> >
>> > Signed-off-by: Youlin Pei <youlin.pei-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
>> > ---
>> > drivers/irqchip/Makefile | 2 +-
>> > drivers/irqchip/irq-mtk-cirq.c | 262 ++++++++++++++++++++++++++++++++++++++++
>> > 2 files changed, 263 insertions(+), 1 deletion(-)
>> > create mode 100644 drivers/irqchip/irq-mtk-cirq.c
>> >
>> > diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
>> > index e4dbfc8..8f33580 100644
>> > --- a/drivers/irqchip/Makefile
>> > +++ b/drivers/irqchip/Makefile
>> > @@ -60,7 +60,7 @@ obj-$(CONFIG_BCM7120_L2_IRQ) += irq-bcm7120-l2.o
>> > obj-$(CONFIG_BRCMSTB_L2_IRQ) += irq-brcmstb-l2.o
>> > obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o
>> > obj-$(CONFIG_MIPS_GIC) += irq-mips-gic.o
>> > -obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o
>> > +obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o irq-mtk-cirq.o
>> > obj-$(CONFIG_ARCH_DIGICOLOR) += irq-digicolor.o
>> > obj-$(CONFIG_RENESAS_H8300H_INTC) += irq-renesas-h8300h.o
>> > obj-$(CONFIG_RENESAS_H8S_INTC) += irq-renesas-h8s.o
>> > diff --git a/drivers/irqchip/irq-mtk-cirq.c b/drivers/irqchip/irq-mtk-cirq.c
>> > new file mode 100644
>> > index 0000000..fc43ef3
>> > --- /dev/null
>> > +++ b/drivers/irqchip/irq-mtk-cirq.c
>> > @@ -0,0 +1,262 @@
>> > +/*
>> > + * Copyright (c) 2016 MediaTek Inc.
>> > + * Author: Youlin.Pei <youlin.pei-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
>> > + *
>> > + * This program is free software; you can redistribute it and/or modify
>> > + * it under the terms of the GNU General Public License version 2 as
>> > + * published by the Free Software Foundation.
>> > + *
>> > + * This program 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.
>> > + */
>> > +
>> > +#include <linux/irq.h>
>> > +#include <linux/irqchip.h>
>> > +#include <linux/irqdomain.h>
>> > +#include <linux/of.h>
>> > +#include <linux/of_irq.h>
>> > +#include <linux/of_address.h>
>> > +#include <linux/io.h>
>> > +#include <linux/slab.h>
>> > +#include <linux/syscore_ops.h>
>> > +
>> > +#define CIRQ_ACK 0x40
>> > +#define CIRQ_MASK_SET 0xc0
>> > +#define CIRQ_MASK_CLR 0x100
>> > +#define CIRQ_SENS_SET 0x180
>> > +#define CIRQ_SENS_CLR 0x1c0
>> > +#define CIRQ_POL_SET 0x240
>> > +#define CIRQ_POL_CLR 0x280
>> > +#define CIRQ_CONTROL 0x300
>> > +
>> > +#define CIRQ_EN 0x1
>> > +#define CIRQ_EDGE 0x2
>> > +#define CIRQ_FLUSH 0x4
>> > +
>> > +#define CIRQ_IRQ_NUM 0x200
>> > +
>> > +struct mtk_cirq_chip_data {
>> > + void __iomem *base;
>> > + unsigned int ext_irq_start;
>> > +};
>> > +
>> > +static struct mtk_cirq_chip_data *cirq_data;
>>
>> Are you guaranteed that you'll only ever have a single CIRQ in any
>> system?
>
> In Mediatek's SOC, only hace a single CIRQ.
>
>>
>> > +
>> > +static void mtk_cirq_write_mask(struct irq_data *data, unsigned int offset)
>> > +{
>> > + struct mtk_cirq_chip_data *chip_data = data->chip_data;
>> > + unsigned int cirq_num = data->hwirq;
>> > + u32 mask = 1 << (cirq_num % 32);
>> > +
>> > + writel(mask, chip_data->base + offset + (cirq_num / 32) * 4);
>>
>> Why can't you use the relaxed accessors?
>
> It seems that i use wrong function, i will change the writel to
> writel_relaxed in next version.
>
>>
>> > +}
>> > +
>> > +static void mtk_cirq_mask(struct irq_data *data)
>> > +{
>> > + mtk_cirq_write_mask(data, CIRQ_MASK_SET);
>> > + irq_chip_mask_parent(data);
>> > +}
>> > +
>> > +static void mtk_cirq_unmask(struct irq_data *data)
>> > +{
>> > + mtk_cirq_write_mask(data, CIRQ_MASK_CLR);
>> > + irq_chip_unmask_parent(data);
>> > +}
>> > +
>> > +static void mtk_cirq_eoi(struct irq_data *data)
>> > +{
>> > + mtk_cirq_write_mask(data, CIRQ_ACK);
>>
>> EOI and ACK have very different semantics. What is this write actually
>> doing? Also, you're now doing an additional MMIO write on each interrupt
>> EOI, doubling its cost. Do you really need to do actually signal the HW
>> that we've EOIed an interrupt? I would have hoped that you'd be able to
>> put it in "bypass" mode as long as you're not suspending...
>>
>
> When external interrupt happened, CIRQ status register record the status
> even CIRQ is not enabled. when execute the flush command, CIRQ will
> resend the signals according to the status. So if don't clear the
> status, CIRQ will resend the wrong signals. the ACK write operation will
> clear the status.
But at this time, we haven't suspended yet, and there is nothing to
replay. Also, you only enable the edge capture when suspending. So what
are you ACKing here? Can't you simply clear everything right when
suspending and not do it at all on the fast path?
Thanks,
M.
--
Jazz is not dead. It just smells funny.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] pinctrl: meson: Add GXL pinctrl definitions
From: Linus Walleij @ 2016-11-04 22:07 UTC (permalink / raw)
To: Neil Armstrong
Cc: Kevin Hilman, Carlo Caione, linux-gpio@vger.kernel.org,
open list:ARM/Amlogic Meson...,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, devicetree@vger.kernel.org
In-Reply-To: <1477931531-27120-1-git-send-email-narmstrong@baylibre.com>
On Mon, Oct 31, 2016 at 5:32 PM, Neil Armstrong <narmstrong@baylibre.com> wrote:
> Add support for the Amlogic Meson GXL SoC, this is a partially complete
> definition only based on the Amlogic Vendor tree.
>
> This definition differs a lot from the GXBB and needs a separate entry.
>
> Acked-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Patch applied with Kevin's ACK.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH v2 11/11] ARM: dts: sk-rzg1e: add Ether support
From: Sergei Shtylyov @ 2016-11-04 22:05 UTC (permalink / raw)
To: horms, linux-renesas-soc, robh+dt, mark.rutland, devicetree
Cc: magnus.damm, linux, linux-arm-kernel
In-Reply-To: <2368353.xfo5beGC5E@wasted.cogentembedded.com>
Define the SK-RZG1E board dependent part of the Ether device node.
Enable DHCP and NFS root for the kernel booting.
Based on the original (and large) patch by Dmitry Shifrin
<dmitry.shifrin@cogentembedded.com>.
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Changes in version 2:
- added Geert's tag.
arch/arm/boot/dts/r8a7745-sk-rzg1e.dts | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
Index: renesas/arch/arm/boot/dts/r8a7745-sk-rzg1e.dts
===================================================================
--- renesas.orig/arch/arm/boot/dts/r8a7745-sk-rzg1e.dts
+++ renesas/arch/arm/boot/dts/r8a7745-sk-rzg1e.dts
@@ -20,7 +20,7 @@
};
chosen {
- bootargs = "ignore_loglevel";
+ bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp";
stdout-path = "serial0:115200n8";
};
@@ -37,3 +37,16 @@
&scif2 {
status = "okay";
};
+
+ðer {
+ phy-handle = <&phy1>;
+ renesas,ether-link-active-low;
+ status = "okay";
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ interrupt-parent = <&irqc>;
+ interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+ micrel,led-mode = <1>;
+ };
+};
^ permalink raw reply
* [PATCH v2 10/11] ARM: dts: sk-rzg1e: initial device tree
From: Sergei Shtylyov @ 2016-11-04 22:04 UTC (permalink / raw)
To: horms, linux-renesas-soc, robh+dt, mark.rutland, devicetree
Cc: magnus.damm, linux, linux-arm-kernel
In-Reply-To: <2368353.xfo5beGC5E@wasted.cogentembedded.com>
Add the initial device tree for the R8A7745 SoC based SK-RZG1E board.
The board has 1 debug serial port (SCIF2); include support for it,
so that the serial console can work.
Based on the original (and large) patch by Dmitry Shifrin
<dmitry.shifrin@cogentembedded.com>.
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Changes in version 2:
- added Geert's tag.
arch/arm/boot/dts/Makefile | 1
arch/arm/boot/dts/r8a7745-sk-rzg1e.dts | 39 +++++++++++++++++++++++++++++++++
2 files changed, 40 insertions(+)
Index: renesas/arch/arm/boot/dts/Makefile
===================================================================
--- renesas.orig/arch/arm/boot/dts/Makefile
+++ renesas/arch/arm/boot/dts/Makefile
@@ -678,6 +678,7 @@ dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += \
r8a73a4-ape6evm.dtb \
r8a7740-armadillo800eva.dtb \
r8a7743-sk-rzg1m.dtb \
+ r8a7745-sk-rzg1e.dtb \
r8a7778-bockw.dtb \
r8a7779-marzen.dtb \
r8a7790-lager.dtb \
Index: renesas/arch/arm/boot/dts/r8a7745-sk-rzg1e.dts
===================================================================
--- /dev/null
+++ renesas/arch/arm/boot/dts/r8a7745-sk-rzg1e.dts
@@ -0,0 +1,39 @@
+/*
+ * Device Tree Source for the SK-RZG1E board
+ *
+ * Copyright (C) 2016 Cogent Embedded, Inc.
+ *
+ * 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.
+ */
+
+/dts-v1/;
+#include "r8a7745.dtsi"
+
+/ {
+ model = "SK-RZG1E";
+ compatible = "renesas,sk-rzg1e", "renesas,r8a7745";
+
+ aliases {
+ serial0 = &scif2;
+ };
+
+ chosen {
+ bootargs = "ignore_loglevel";
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0 0x40000000 0 0x40000000>;
+ };
+};
+
+&extal_clk {
+ clock-frequency = <20000000>;
+};
+
+&scif2 {
+ status = "okay";
+};
^ permalink raw reply
* [PATCH v2 09/11] ARM: shmobile: document SK-RZG1E board
From: Sergei Shtylyov @ 2016-11-04 22:02 UTC (permalink / raw)
To: horms, linux-renesas-soc, robh+dt, mark.rutland, devicetree
In-Reply-To: <2368353.xfo5beGC5E@wasted.cogentembedded.com>
Document the SK-RZG1E device tree bindings, listing it as a supported board.
This allows to use checkpatch.pl to validate .dts files referring to the
SK-RZG1E board.
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Changes in version 2:
- fixed the subject;
- added Geert's tag.
Documentation/devicetree/bindings/arm/shmobile.txt | 2 ++
1 file changed, 2 insertions(+)
Index: renesas/Documentation/devicetree/bindings/arm/shmobile.txt
===================================================================
--- renesas.orig/Documentation/devicetree/bindings/arm/shmobile.txt
+++ renesas/Documentation/devicetree/bindings/arm/shmobile.txt
@@ -77,6 +77,8 @@ Boards:
compatible = "renesas,salvator-x", "renesas,r8a7796";
- SILK (RTP0RC7794LCB00011S)
compatible = "renesas,silk", "renesas,r8a7794"
+ - SK-RZG1E (YR8A77450S000BE)
+ compatible = "renesas,sk-rzg1e", "renesas,r8a7745"
- SK-RZG1M (YR8A77430S000BE)
compatible = "renesas,sk-rzg1m", "renesas,r8a7743"
- Wheat
^ permalink raw reply
* [PATCH v2 08/11] ARM: dts: r8a7745: add IRQC support
From: Sergei Shtylyov @ 2016-11-04 21:59 UTC (permalink / raw)
To: horms-/R6kz+dDXgpPR4JQBCEnsQ,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: magnus.damm-Re5JQEeQqe8AvxtiuMwx3w, linux-lFZ/pmaqli7XmaaqVzeoHQ,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <2368353.xfo5beGC5E-gHKXc3Y1Z8zGSmamagVegGFoWSdPRAKMAL8bYrjMMd8@public.gmane.org>
Describe the IRQC interrupt controller in the R8A7745 device tree.
Based on the original (and large) patch by Dmitry Shifrin
<dmitry.shifrin-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org>.
Signed-off-by: Sergei Shtylyov <sergei.shtylyov-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org>
Reviewed-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
---
Changes in version 2:
- added Geert's tag;
- refreshed the patch.
arch/arm/boot/dts/r8a7745.dtsi | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
Index: renesas/arch/arm/boot/dts/r8a7745.dtsi
===================================================================
--- renesas.orig/arch/arm/boot/dts/r8a7745.dtsi
+++ renesas/arch/arm/boot/dts/r8a7745.dtsi
@@ -62,6 +62,25 @@
IRQ_TYPE_LEVEL_HIGH)>;
};
+ irqc: interrupt-controller@e61c0000 {
+ compatible = "renesas,irqc-r8a7745", "renesas,irqc";
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ reg = <0 0xe61c0000 0 0x200>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 407>;
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ };
+
timer {
compatible = "arm,armv7-timer";
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) |
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v2 07/11] ARM: dts: r8a7745: add Ether support
From: Sergei Shtylyov @ 2016-11-04 21:57 UTC (permalink / raw)
To: horms, linux-renesas-soc, robh+dt, mark.rutland, devicetree
Cc: magnus.damm, linux, linux-arm-kernel
In-Reply-To: <2368353.xfo5beGC5E@wasted.cogentembedded.com>
Define the generic R8A7745 part of the Ether device node.
Based on the original (and large) patch by Dmitry Shifrin
<dmitry.shifrin@cogentembedded.com>.
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Changes in version 2:
- added Geert's tag.
arch/arm/boot/dts/r8a7745.dtsi | 12 ++++++++++++
1 file changed, 12 insertions(+)
Index: renesas/arch/arm/boot/dts/r8a7745.dtsi
===================================================================
--- renesas.orig/arch/arm/boot/dts/r8a7745.dtsi
+++ renesas/arch/arm/boot/dts/r8a7745.dtsi
@@ -418,6 +418,18 @@
power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
status = "disabled";
};
+
+ ether: ethernet@ee700000 {
+ compatible = "renesas,ether-r8a7745";
+ reg = <0 0xee700000 0 0x400>;
+ interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 813>;
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ phy-mode = "rmii";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
};
/* External root clock */
^ permalink raw reply
* [PATCH v2 06/11] ARM: dts: r8a7745: add [H]SCIF{|A|B} support
From: Sergei Shtylyov @ 2016-11-04 21:55 UTC (permalink / raw)
To: horms, linux-renesas-soc, robh+dt, mark.rutland, devicetree
Cc: magnus.damm, linux, linux-arm-kernel
In-Reply-To: <2368353.xfo5beGC5E@wasted.cogentembedded.com>
Describe [H]SCIF{|A|B} ports in the R8A7745 device tree.
Based on the original (and large) patch by Dmitry Shifrin
<dmitry.shifrin@cogentembedded.com>.
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Changes in version 2:
- used the R-Car gen2 bindings instead of the RZ/G family ones;
- added Geert's tag.
arch/arm/boot/dts/r8a7745.dtsi | 261 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 261 insertions(+)
Index: renesas/arch/arm/boot/dts/r8a7745.dtsi
===================================================================
--- renesas.orig/arch/arm/boot/dts/r8a7745.dtsi
+++ renesas/arch/arm/boot/dts/r8a7745.dtsi
@@ -157,6 +157,267 @@
#dma-cells = <1>;
dma-channels = <15>;
};
+
+ scifa0: serial@e6c40000 {
+ compatible = "renesas,scifa-r8a7745",
+ "renesas,rcar-gen2-scifa", "renesas,scifa";
+ reg = <0 0xe6c40000 0 0x40>;
+ interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 204>;
+ clock-names = "fck";
+ dmas = <&dmac0 0x21>, <&dmac0 0x22>,
+ <&dmac1 0x21>, <&dmac1 0x22>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ scifa1: serial@e6c50000 {
+ compatible = "renesas,scifa-r8a7745",
+ "renesas,rcar-gen2-scifa", "renesas,scifa";
+ reg = <0 0xe6c50000 0 0x40>;
+ interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 203>;
+ clock-names = "fck";
+ dmas = <&dmac0 0x25>, <&dmac0 0x26>,
+ <&dmac1 0x25>, <&dmac1 0x26>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ scifa2: serial@e6c60000 {
+ compatible = "renesas,scifa-r8a7745",
+ "renesas,rcar-gen2-scifa", "renesas,scifa";
+ reg = <0 0xe6c60000 0 0x40>;
+ interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 202>;
+ clock-names = "fck";
+ dmas = <&dmac0 0x27>, <&dmac0 0x28>,
+ <&dmac1 0x27>, <&dmac1 0x28>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ scifa3: serial@e6c70000 {
+ compatible = "renesas,scifa-r8a7745",
+ "renesas,rcar-gen2-scifa", "renesas,scifa";
+ reg = <0 0xe6c70000 0 0x40>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 1106>;
+ clock-names = "fck";
+ dmas = <&dmac0 0x1b>, <&dmac0 0x1c>,
+ <&dmac1 0x1b>, <&dmac1 0x1c>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ scifa4: serial@e6c78000 {
+ compatible = "renesas,scifa-r8a7745",
+ "renesas,rcar-gen2-scifa", "renesas,scifa";
+ reg = <0 0xe6c78000 0 0x40>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 1107>;
+ clock-names = "fck";
+ dmas = <&dmac0 0x1f>, <&dmac0 0x20>,
+ <&dmac1 0x1f>, <&dmac1 0x20>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ scifa5: serial@e6c80000 {
+ compatible = "renesas,scifa-r8a7745",
+ "renesas,rcar-gen2-scifa", "renesas,scifa";
+ reg = <0 0xe6c80000 0 0x40>;
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 1108>;
+ clock-names = "fck";
+ dmas = <&dmac0 0x23>, <&dmac0 0x24>,
+ <&dmac1 0x23>, <&dmac1 0x24>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ scifb0: serial@e6c20000 {
+ compatible = "renesas,scifb-r8a7745",
+ "renesas,rcar-gen2-scifb", "renesas,scifb";
+ reg = <0 0xe6c20000 0 0x100>;
+ interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 206>;
+ clock-names = "fck";
+ dmas = <&dmac0 0x3d>, <&dmac0 0x3e>,
+ <&dmac1 0x3d>, <&dmac1 0x3e>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ scifb1: serial@e6c30000 {
+ compatible = "renesas,scifb-r8a7745",
+ "renesas,rcar-gen2-scifb", "renesas,scifb";
+ reg = <0 0xe6c30000 0 0x100>;
+ interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 207>;
+ clock-names = "fck";
+ dmas = <&dmac0 0x19>, <&dmac0 0x1a>,
+ <&dmac1 0x19>, <&dmac1 0x1a>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ scifb2: serial@e6ce0000 {
+ compatible = "renesas,scifb-r8a7745",
+ "renesas,rcar-gen2-scifb", "renesas,scifb";
+ reg = <0 0xe6ce0000 0 0x100>;
+ interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 216>;
+ clock-names = "fck";
+ dmas = <&dmac0 0x1d>, <&dmac0 0x1e>,
+ <&dmac1 0x1d>, <&dmac1 0x1e>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ scif0: serial@e6e60000 {
+ compatible = "renesas,scif-r8a7745",
+ "renesas,rcar-gen2-scif", "renesas,scif";
+ reg = <0 0xe6e60000 0 0x40>;
+ interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 721>,
+ <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x29>, <&dmac0 0x2a>,
+ <&dmac1 0x29>, <&dmac1 0x2a>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ scif1: serial@e6e68000 {
+ compatible = "renesas,scif-r8a7745",
+ "renesas,rcar-gen2-scif", "renesas,scif";
+ reg = <0 0xe6e68000 0 0x40>;
+ interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 720>,
+ <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x2d>, <&dmac0 0x2e>,
+ <&dmac1 0x2d>, <&dmac1 0x2e>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ scif2: serial@e6e58000 {
+ compatible = "renesas,scif-r8a7745",
+ "renesas,rcar-gen2-scif", "renesas,scif";
+ reg = <0 0xe6e58000 0 0x40>;
+ interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 719>,
+ <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x2b>, <&dmac0 0x2c>,
+ <&dmac1 0x2b>, <&dmac1 0x2c>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ scif3: serial@e6ea8000 {
+ compatible = "renesas,scif-r8a7745",
+ "renesas,rcar-gen2-scif", "renesas,scif";
+ reg = <0 0xe6ea8000 0 0x40>;
+ interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 718>,
+ <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x2f>, <&dmac0 0x30>,
+ <&dmac1 0x2f>, <&dmac1 0x30>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ scif4: serial@e6ee0000 {
+ compatible = "renesas,scif-r8a7745",
+ "renesas,rcar-gen2-scif", "renesas,scif";
+ reg = <0 0xe6ee0000 0 0x40>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 715>,
+ <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0xfb>, <&dmac0 0xfc>,
+ <&dmac1 0xfb>, <&dmac1 0xfc>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ scif5: serial@e6ee8000 {
+ compatible = "renesas,scif-r8a7745",
+ "renesas,rcar-gen2-scif", "renesas,scif";
+ reg = <0 0xe6ee8000 0 0x40>;
+ interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 714>,
+ <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0xfd>, <&dmac0 0xfe>,
+ <&dmac1 0xfd>, <&dmac1 0xfe>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ hscif0: serial@e62c0000 {
+ compatible = "renesas,hscif-r8a7745",
+ "renesas,rcar-gen2-hscif", "renesas,hscif";
+ reg = <0 0xe62c0000 0 0x60>;
+ interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 717>,
+ <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x39>, <&dmac0 0x3a>,
+ <&dmac1 0x39>, <&dmac1 0x3a>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ hscif1: serial@e62c8000 {
+ compatible = "renesas,hscif-r8a7745",
+ "renesas,rcar-gen2-hscif", "renesas,hscif";
+ reg = <0 0xe62c8000 0 0x60>;
+ interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 716>,
+ <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x4d>, <&dmac0 0x4e>,
+ <&dmac1 0x4d>, <&dmac1 0x4e>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ hscif2: serial@e62d0000 {
+ compatible = "renesas,hscif-r8a7745",
+ "renesas,rcar-gen2-hscif", "renesas,hscif";
+ reg = <0 0xe62d0000 0 0x60>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 713>,
+ <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x3b>, <&dmac0 0x3c>,
+ <&dmac1 0x3b>, <&dmac1 0x3c>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
};
/* External root clock */
^ permalink raw reply
* Re: [PATCH 4/4] ARM: dts: Add #pinctrl-cells for pinctrl-single instances
From: Linus Walleij @ 2016-11-04 21:55 UTC (permalink / raw)
To: Tony Lindgren
Cc: Jon Hunter, Mark Rutland, Rob Herring, Grygorii Strashko,
Nishanth Menon,
linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linux-OMAP
In-Reply-To: <20161103163550.27330-5-tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
On Thu, Nov 3, 2016 at 5:35 PM, Tony Lindgren <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org> wrote:
> Drivers using pinctrl-single,pins have #pinctrl-cells = <1>, while
> pinctrl-single,bits need #pinctrl-cells = <2>.
>
> Note that this patch can be optionally applied separately from the
> driver changes as the driver supports also the legacy binding without
> #pinctrl-cells.
>
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Signed-off-by: Tony Lindgren <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
Reviewed-by: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Please take this through the OMAP tree to avoid hazzle.
Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v2 05/11] ARM: dts: r8a7745: add SYS-DMAC support
From: Sergei Shtylyov @ 2016-11-04 21:54 UTC (permalink / raw)
To: horms, linux-renesas-soc, robh+dt, mark.rutland, devicetree
Cc: magnus.damm, linux, linux-arm-kernel
In-Reply-To: <2368353.xfo5beGC5E@wasted.cogentembedded.com>
Describe SYS-DMAC0/1 in the R8A7745 device tree.
Based on the original (and large) patch by Dmitry Shifrin
<dmitry.shifrin@cogentembedded.com>.
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Changes in version 2:
- added Geert's tag;
- refreshed the patch.
arch/arm/boot/dts/r8a7745.dtsi | 64 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
Index: renesas/arch/arm/boot/dts/r8a7745.dtsi
===================================================================
--- renesas.orig/arch/arm/boot/dts/r8a7745.dtsi
+++ renesas/arch/arm/boot/dts/r8a7745.dtsi
@@ -93,6 +93,70 @@
compatible = "renesas,r8a7745-rst";
reg = <0 0xe6160000 0 0x0200>;
};
+
+ dmac0: dma-controller@e6700000 {
+ compatible = "renesas,dmac-r8a7745",
+ "renesas,rcar-dmac";
+ reg = <0 0xe6700000 0 0x20000>;
+ interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14";
+ clocks = <&cpg CPG_MOD 219>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ #dma-cells = <1>;
+ dma-channels = <15>;
+ };
+
+ dmac1: dma-controller@e6720000 {
+ compatible = "renesas,dmac-r8a7745",
+ "renesas,rcar-dmac";
+ reg = <0 0xe6720000 0 0x20000>;
+ interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14";
+ clocks = <&cpg CPG_MOD 218>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ #dma-cells = <1>;
+ dma-channels = <15>;
+ };
};
/* External root clock */
^ permalink raw reply
* Re: [PATCH 3/4] pinctrl: single: Use generic parser and #pinctrl-cells for pinctrl-single,bits
From: Linus Walleij @ 2016-11-04 21:54 UTC (permalink / raw)
To: Tony Lindgren
Cc: Jon Hunter, Mark Rutland, Rob Herring, Grygorii Strashko,
Nishanth Menon,
linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linux-OMAP
In-Reply-To: <20161103163550.27330-4-tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
On Thu, Nov 3, 2016 at 5:35 PM, Tony Lindgren <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org> wrote:
> We can now use generic parser and keep things compatible with the
> old binding.
>
> Signed-off-by: Tony Lindgren <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
V2 Patch applied.
Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v2 04/11] ARM: dts: r8a7745: initial SoC device tree
From: Sergei Shtylyov @ 2016-11-04 21:53 UTC (permalink / raw)
To: horms, linux-renesas-soc, robh+dt, mark.rutland, devicetree
Cc: magnus.damm, linux, linux-arm-kernel
In-Reply-To: <2368353.xfo5beGC5E@wasted.cogentembedded.com>
The initial R8A7745 SoC device tree including CPU0, GIC, timer, SYSC, RST,
CPG, and the required clock descriptions.
Based on the original (and large) patch by Dmitry Shifrin
<dmitry.shifrin@cogentembedded.com>.
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Changes in version 2:
- reformatted the "interrupts" props of the GIC/timer device nodes;
- added Geert's tag.
arch/arm/boot/dts/r8a7745.dtsi | 120 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 120 insertions(+)
Index: renesas/arch/arm/boot/dts/r8a7745.dtsi
===================================================================
--- /dev/null
+++ renesas/arch/arm/boot/dts/r8a7745.dtsi
@@ -0,0 +1,120 @@
+/*
+ * Device Tree Source for the r8a7745 SoC
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * 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.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/r8a7745-cpg-mssr.h>
+#include <dt-bindings/power/r8a7745-sysc.h>
+
+/ {
+ compatible = "renesas,r8a7745";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0>;
+ clock-frequency = <1000000000>;
+ clocks = <&cpg CPG_CORE R8A7745_CLK_Z2>;
+ power-domains = <&sysc R8A7745_PD_CA7_CPU0>;
+ next-level-cache = <&L2_CA7>;
+ };
+
+ L2_CA7: cache-controller@0 {
+ compatible = "cache";
+ reg = <0>;
+ cache-unified;
+ cache-level = <2>;
+ power-domains = <&sysc R8A7745_PD_CA7_SCU>;
+ };
+ };
+
+ soc {
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ gic: interrupt-controller@f1001000 {
+ compatible = "arm,gic-400";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0 0xf1001000 0 0x1000>,
+ <0 0xf1002000 0 0x1000>,
+ <0 0xf1004000 0 0x2000>,
+ <0 0xf1006000 0 0x2000>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) |
+ IRQ_TYPE_LEVEL_HIGH)>;
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) |
+ IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) |
+ IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) |
+ IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) |
+ IRQ_TYPE_LEVEL_LOW)>;
+ };
+
+ cpg: clock-controller@e6150000 {
+ compatible = "renesas,r8a7745-cpg-mssr";
+ reg = <0 0xe6150000 0 0x1000>;
+ clocks = <&extal_clk>, <&usb_extal_clk>;
+ clock-names = "extal", "usb_extal";
+ #clock-cells = <2>;
+ #power-domain-cells = <0>;
+ };
+
+ sysc: system-controller@e6180000 {
+ compatible = "renesas,r8a7745-sysc";
+ reg = <0 0xe6180000 0 0x200>;
+ #power-domain-cells = <1>;
+ };
+
+ rst: reset-controller@e6160000 {
+ compatible = "renesas,r8a7745-rst";
+ reg = <0 0xe6160000 0 0x100>;
+ };
+ };
+
+ /* External root clock */
+ extal_clk: extal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board. */
+ clock-frequency = <0>;
+ };
+
+ /* External USB clock - can be overridden by the board */
+ usb_extal_clk: usb_extal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <48000000>;
+ };
+
+ /* External SCIF clock */
+ scif_clk: scif {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board. */
+ clock-frequency = <0>;
+ };
+};
^ permalink raw reply
* Re: [PATCH 2/4] pinctrl: single: Use generic parser and #pinctrl-cells for pinctrl-single,pins
From: Linus Walleij @ 2016-11-04 21:52 UTC (permalink / raw)
To: Tony Lindgren
Cc: Jon Hunter, Mark Rutland, Rob Herring, Grygorii Strashko,
Nishanth Menon, linux-gpio@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
Linux-OMAP
In-Reply-To: <20161103163550.27330-3-tony@atomide.com>
On Thu, Nov 3, 2016 at 5:35 PM, Tony Lindgren <tony@atomide.com> wrote:
> We can now use generic parser. To support the legacy binding without
> #pinctrl-cells, add pcs_quirk_missing_pinctrl_cells() and warn about
> missing #pinctrl-cells.
>
> Let's also update the documentation for struct pcs_soc_data while at it
> as that seems to be out of date.
>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
This v2 patch applied.
Yours,
Linus Walleij
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox