Re: [RFC PATCH 0/6] DRIVERS: IRQCHIP: Add support for crossbar IP

2013-10-01 Thread Sricharan R
Hi,

On Monday 30 September 2013 08:39 PM, Rob Herring wrote:
> On 09/30/2013 08:59 AM, Sricharan R wrote:
>> Some socs have a large number of interrupts requests to service
>> the needs of its many peripherals and subsystems. All of the interrupt
>> requests lines from the subsystems are not needed at the same
>> time, so they have to be muxed to the controllers appropriately.
>> In such places a interrupt controllers are preceded by an
>> IRQ CROSSBAR that provides flexibility in muxing the device interrupt
>> requests to the controller inputs.
>>
>> This series models the peripheral interrupts that can be routed through
>> the crossbar to the GIC as 'routable-irqs'. The routable irqs are added
>> in a separate linear domain inside the GIC. The registered routable domain's
>> callback are invoked as a part of the GIC's callback, which in turn should
>> allocate a free irq line and configure the IP accordingly. So every 
>> peripheral
>> in the dts files mentions the fixed crossbar number as its interrupt. A free
>> gic line for that gets allocated and configured when the peripheral's 
>> interrupt
>> is mapped.
>>
>> The minimal crossbar driver to track and allocate free GIC lines and 
>> configure the
>> crossbar is added here, along with the DT bindings.
> Seems like interrupt-map property is what you need here.
>
> http://devicetree.org/Device_Tree_Usage#Advanced_Interrupt_Mapping
>
> Versatile Express also has an example.
   OK, but the idea was not to tie up the crossbar<->interrupt numbers at the
   DTS level, but to assign it dynamically during runtime. This was one of the
  comments that came up with first crossbar support patches, which was 
assigning a
  interrupt line to crossbar number in the DTS and setting it up in crossbar 
probe.

https://lkml.org/lkml/2013/7/18/416

   Since this approach of assigning in DTS was opposed, we moved to IRQCHIP and
   that did not go as well. Finally was asked to handle this as a part of GIC 
driver with
   a separate domain.
   
  http://www.spinics.net/lists/linux-omap/msg97085.html
  
Regards,
 Sricharan

 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 1/4] DRIVERS: IRQCHIP: Add crossbar irqchip driver

2013-09-18 Thread Sricharan R
Hi Thomas,

On Tuesday 17 September 2013 05:56 PM, Linus Walleij wrote:
> On Fri, Sep 13, 2013 at 4:24 PM, Thomas Gleixner  wrote:
>
>> So why can't you make use of irq domains and have the whole routing
>> business implemented sanely?
>>
>> What's needed is in gic_init_bases():
>> irq
>>if (of_property_read(node, "routable_irqs", &nr_routable_irqs) {
>>   irq_domain_add_legacy(nr_gic_irqs);
>>} else {
>>   irq_domain_add_legacy(nr_per_cpu_irqs);
>>   irq_domain_add_linear(nr_routable_irqs);
>>}
>>
>> Now that separate domain has an xlate function which grabs a free GIC
>> irq from a bitmap and returns the hardware irq number in the gic
>> space. The map/unmap callbacks take care of setting up / tearing down
>> the route in the crossbar.
> This is obviously the right approach, it's exactly what .map should do
> the only special thing here being that we have hardware to perform
> the mapping ... bah why didn't I realize this :-(
>
> Yours,
> Linus Walleij
Thanks for the suggestion.

So as i understand this, this implies using the GIC domain itself and
 add the support for dynamically routable irqs (like crossbar) with in the
GIC driver itself right ?

Regards,
 Sricharan
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 1/4] DRIVERS: IRQCHIP: Add crossbar irqchip driver

2013-09-18 Thread Sricharan R
On Wednesday 18 September 2013 07:22 PM, Sricharan R wrote:
> Hi Thomas,
>
> On Tuesday 17 September 2013 05:56 PM, Linus Walleij wrote:
>> On Fri, Sep 13, 2013 at 4:24 PM, Thomas Gleixner  wrote:
>>
>>> So why can't you make use of irq domains and have the whole routing
>>> business implemented sanely?
>>>
>>> What's needed is in gic_init_bases():
>>> irq
>>>if (of_property_read(node, "routable_irqs", &nr_routable_irqs) {
>>>   irq_domain_add_legacy(nr_gic_irqs);
>>>} else {
>>>   irq_domain_add_legacy(nr_per_cpu_irqs);
>>>   irq_domain_add_linear(nr_routable_irqs);
>>>}
>>>
>>> Now that separate domain has an xlate function which grabs a free GIC
>>> irq from a bitmap and returns the hardware irq number in the gic
>>> space. The map/unmap callbacks take care of setting up / tearing down
>>> the route in the crossbar.
>> This is obviously the right approach, it's exactly what .map should do
>> the only special thing here being that we have hardware to perform
>> the mapping ... bah why didn't I realize this :-(
>>
>> Yours,
>> Linus Walleij
> Thanks for the suggestion.
>
> So as i understand this, this implies using the GIC domain itself and
>  add the support for dynamically routable irqs (like crossbar) with in the
> GIC driver itself right ?
  Please ignore this. So the question was more of how to implement the
  call outs in the case of routable irqs from map/ unmap callbacks.
 I will look more here and come back.

Regards,
 Sricharan
 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 1/4] DRIVERS: IRQCHIP: Add crossbar irqchip driver

2013-09-20 Thread Sricharan R
Hi Mark,

On Friday 20 September 2013 02:28 PM, Mark Rutland wrote:
> Hi,
>
> I have a few comments, mostly on the DT binding and parsing.
>
 Thanks for the review. The idea of seeing the crossbar as a new IRQCHIP
 itself did not go and the latest direction on this was to handle it inside the 
GIC.

  http://www.spinics.net/lists/linux-omap/msg97085.html
  I am working on that now.

  I would have agreed with most of the comments below, otherwise.

>> diff --git a/Documentation/devicetree/bindings/arm/omap/irq-crossbar.txt 
>> b/Documentation/devicetree/bindings/arm/omap/irq-crossbar.txt
>> new file mode 100644
>> index 000..5d465cf
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/omap/irq-crossbar.txt
>> @@ -0,0 +1,39 @@
>> +* IRQ CROSSBAR
>> +
>> +Some socs have a large number of interrupts requests to service
>> +the needs of its many peripherals and subsystems. All of the
>> +interrupt lines from the subsystems are not needed at the same
>> +time, so they have to be muxed to the irq-controller appropriately.
>> +In such places a interrupt controllers are preceded by an CROSSBAR
>> +that provides flexibility in muxing the device requests to the controller
>> +inputs.
>> +
>> +Required properties:
>> +- compatible : Should be "irq-crossbar"
> Missing vendor prefix, this should be something like "ti,irq-crossbar".
> Does this have a more specific name than CROSSBAR that can be used to
> qualify it?
 yes, ti,irq-crossbar. Not sure if it can be called as anything
 generically apart from crossbar .
>> +- interrupt-parent: phandle to crossbar's interrupt parent.
>> +- interrupt-controller: Identifies the node as an interrupt controller.
>> +- interrupt-cells: Should be the same value as the interrupt parent.
> That doesn't make sense. The crossbar driver is necessarily interpreting
> these cells in a way the parent won't (as it supports more interrupts).
> What are the meaning of these cells?
 These properties were added so that the DT code identifies this as a
 interrupt controller and map the children's irq in to this domain and
 to map the free irqs allocated in this driver to its parent.
>> +- reg: Base address and the size of the crossbar registers.
>> +- max-crossbar-lines: Total number of input lines of the crossbar.
>> +- max-irqs: Total number of irqs available at the interrupt controller.
> Is this the maximum number of interrupts targeting the parent interrupt
> controller? Starting at what number, ending at what number? Can this
> have gaps?
>
> Is this a shortcut so in the GIC case you don't have to describe up to
> 160 interrupts? I can see why you don't want to, but there's a big loss
> of generality here...
>
 Yes, this was the maximum irqs available at the parent.
 The gaps was not considered here because it was mentioned
 used the below property irqs-reserved.
>> +- reg-size: size of the crossbar registers.
> As in the size of all the registers (the size component of reg)?
>
> Or is this the size of each individual register? Does that apply to all
> registers or only a subset of them?
>
> What units are these in, bytes?
>
> What are valid sizes?
>
> Is this really that configurable?
 This was meant to describe the size a individual register and applied to
 all. This was used to choose the API's to write. But yes some more
 description could be made here.
>> +- irqs-reserved: List of the reserved irq lines that are not muxed using
>> +crossbar. These interrupt lines are reserved in the soc,
>> +so crossbar bar driver should not consider them as free
>> +lines.
> Are these reserved inputs lines, or outputs to the parent interrupt
> controller?
>
> What is the format of each entry in this list?
>
> The example seems to be a different format to the parent interrupt
> controller (which per your binding also defined the crossbar's interrupt
> format). While <0 1 2> is a valid interrupt per the GIC binding (SPI 0
> edge-triggered both ways), <3 5 6>, <131 132 139>, and <140 . .> are
> not.
 These were parent's input lines that were not muxed from crossbar
 but directly connected from peripherals, so the driver should not
consider it as a free line while allocating a irq. This property was meant to
 interpreted only in this driver.
>> +
>> +Examples:
>> +   crossbar_mpu: @4a02 {
>> +   compatible = "irq-crossbar";
>> +   interrupt-parent = <&gic>;
>> +   interrupt-controller;
>> +   #interrupt-cells = <3>;
>> +   reg = <0x4a002a48 0x130>;
>> +   max-crossbar-lines = <512>;
>> +   max-irqs = <160>;
>> +   reg-size = <2>;
>> +   irqs-reserved = <0 1 2 3 5 6 131 132 139 140>;
>> +   #address-cells = <1>;
>> +   #size-cells = <1>;
> Why are there #address-cells and #size cells? This has no children, and
> 

[RFC PATCH 0/4] DRIVERS: IRQCHIP: Add crossbar irqchip driver

2013-09-12 Thread Sricharan R
Some socs have a large number of interrupts requests to service
the needs of its many peripherals and subsystems. All of the interrupt
requests lines from the subsystems are not needed at the same
time, so they have to be muxed to the controllers appropriately.
In such places a interrupt controllers are preceded by an
IRQ CROSSBAR that provides flexibility in muxing the device interrupt
requests to the controller inputs.

This series models the crossbar IP as a cascaded irqchip controller.
The peripheral crossbar inputs are mapped on to the crossbar irq-domain.
The driver then allocates a 'free' irq line and maps that to the
actual interrupt controller's domain. So every external peripheral interrupt
is routed through the crossbar handler.

This series adds a crossbar driver and the DT bindings for the
same. Also the DT nodes for DRA7xx SOC which has a IRQ
crossbar has been added here.

Sricharan R (4):
  DRIVERS: IRQCHIP: Add crossbar irqchip driver
  ARM: DTS: DRA: Add crossbar device binding
  ARM: DTS: DRA: Replace peripheral interrupt numbers with crossbar
inputs.
  ARM: DRA: Kconfig: Enable crossbar irqchip driver for DRA7xx

 .../devicetree/bindings/arm/omap/irq-crossbar.txt  |   39 ++
 arch/arm/boot/dts/dra7.dtsi|  104 ++---
 arch/arm/mach-omap2/Kconfig|1 +
 drivers/irqchip/Kconfig|9 +
 drivers/irqchip/Makefile   |1 +
 drivers/irqchip/irq-crossbar.c |  407 
 6 files changed, 517 insertions(+), 44 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/omap/irq-crossbar.txt
 create mode 100644 drivers/irqchip/irq-crossbar.c

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC PATCH 2/4] ARM: DTS: DRA: Add crossbar device binding

2013-09-12 Thread Sricharan R
This adds the irq crossbar device node.

There is a IRQ crossbar device in the soc, which
maps the irq requests from the peripherals to the
mpu interrupt controller's inputs. The Peripheral irq
requests are connected to only one crossbar
input and the output of the crossbar is connected to only one
controller's input line. This models the crossbar as an interrupt
controller. This a cascaded irqchip where the peripheral interrupt
lines are connected to the crossbar and the crossbar's outputs
are in turn connected to the GIC.

Signed-off-by: Sricharan R 
---
 arch/arm/boot/dts/dra7.dtsi |   16 
 1 file changed, 16 insertions(+)

diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index a5d9350..da977e1 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -84,6 +84,7 @@
#size-cells = <1>;
ranges;
ti,hwmods = "l3_main_1", "l3_main_2";
+   interrupt-parent = <&crossbar_mpu>;
 
counter32k: counter@4ae04000 {
compatible = "ti,omap-counter32k";
@@ -491,5 +492,20 @@
dmas = <&sdma 70>, <&sdma 71>;
dma-names = "tx0", "rx0";
};
+
+   crossbar_mpu: @4a02 {
+   compatible = "crossbar-irqchip";
+   interrupt-parent = <&gic>;
+   interrupt-controller;
+   #interrupt-cells = <3>;
+   reg = <0x4a002a48 0x130>;
+   max-crossbar-lines = <512>;
+   max-irqs = <160>;
+   reg-size = <2>;
+   irqs-reserved = <0 1 2 3 5 6 131 132 139 140>;
+   #address-cells = <1>;
+   #size-cells = <1>;
+   };
+
};
 };
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC PATCH 1/4] DRIVERS: IRQCHIP: Add crossbar irqchip driver

2013-09-12 Thread Sricharan R
Some socs have a large number of interrupts requests to service
the needs of its many peripherals and subsystems. All of the
interrupt lines from the subsystems are not needed at the same
time, so they have to be muxed to the irq-controller appropriately.
In such places a interrupt controllers are preceded by an CROSSBAR
that provides flexibility in muxing the device requests to the controller
inputs.

This models the crossbar IP as a cascaded irqchip controller.
The peripheral crossbar inputs are mapped on to the crossbar irq-domain.
The driver then allocates a 'free' irq line and maps that to the
actual interrupt controller's domain. So every external peripheral interrupt
is routed through the crossbar handler.

 GIC  <- CROSSBAR <- PERIPHERAL INTERRUPT LINES

 peripheral's irq_of_parse_and_map()
  |
  |
crossbar_xlate()
  |
  |
 saves the interrupt properties passed

 peripheral's request_irq(crossbar_number)
  |
  |
crossbar_request_irq
  |
  |
allocates free irq and maps it to parent domain
  |
  |
request_irq(mapped interrupt number)

 gic_interrupt_hanadler
|
|
 crossbar_irq(interrupt number)
|
|
 get crossbar number from interrupt number
|
|
 handle_irq(crossbar_domain(crossbar number))

The irqchip callback hooks added here are just a redirection to the
parent irqchip.

This adds a extra translation in the fast path. The maximum increase in
the average interrupt latency due to the same was measured as around 1.63us
on a cpu running at 1GHZ.

cat /proc/interrupts looks like this, with both crossbar and interrupt number

   CPU0   CPU1
 45:267  0   GIC  OMAP UART0
205:267  0  CROSSBAR  OMAP UART0

Cc: Thomas Gleixner 
Cc: Linus Walleij 
Cc: Santosh Shilimkar 
Cc: Russell King 
Cc: Tony Lindgren 
Cc: Rajendra Nayak 
Signed-off-by: Sricharan R 
---
There is lockdep warning during the boot. This is because we try to
do one request_irq with in another and that results in kmalloc being
called from an atomic context, which generates the warning.
Any suggestions to overcome this will help.

  WARNING: at kernel/lockdep.c:2740 lockdep_trace_alloc+0xe8/0x108()
  DEBUG_LOCKS_WARN_ON(irqs_disabled_flags(flags))

 .../devicetree/bindings/arm/omap/irq-crossbar.txt  |   39 ++
 drivers/irqchip/Kconfig|9 +
 drivers/irqchip/Makefile   |1 +
 drivers/irqchip/irq-crossbar.c |  407 
 4 files changed, 456 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/omap/irq-crossbar.txt
 create mode 100644 drivers/irqchip/irq-crossbar.c

diff --git a/Documentation/devicetree/bindings/arm/omap/irq-crossbar.txt 
b/Documentation/devicetree/bindings/arm/omap/irq-crossbar.txt
new file mode 100644
index 000..5d465cf
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/irq-crossbar.txt
@@ -0,0 +1,39 @@
+* IRQ CROSSBAR
+
+Some socs have a large number of interrupts requests to service
+the needs of its many peripherals and subsystems. All of the
+interrupt lines from the subsystems are not needed at the same
+time, so they have to be muxed to the irq-controller appropriately.
+In such places a interrupt controllers are preceded by an CROSSBAR
+that provides flexibility in muxing the device requests to the controller
+inputs.
+
+Required properties:
+- compatible : Should be "irq-crossbar"
+- interrupt-parent: phandle to crossbar's interrupt parent.
+- interrupt-controller: Identifies the node as an interrupt controller.
+- interrupt-cells: Should be the same value as the interrupt parent.
+- reg: Base address and the size of the crossbar registers.
+- max-crossbar-lines: Total number of input lines of the crossbar.
+- max-irqs: Total number of irqs available at the interrupt controller.
+- reg-size: size of the crossbar registers.
+- irqs-reserved: List of the reserved irq lines that are not muxed using
+crossbar. These interrupt lines are reserved in the soc,
+so crossbar bar driver should not consider them as free
+lines.
+
+Examples:
+   crossbar_mpu: @4a02 {
+   compatible = "irq-crossbar";
+   interrupt-parent = <&gic>;
+   interrupt-controller;
+   #interrupt-cells = <3>;
+   reg = <0x4a002a48 0x130>;
+   max-crossbar-lines = <512>;
+   max-irqs = <160>;
+   reg-size = <2>;
+   irqs-reserved = <0 1 2 3 5 6 131 132 139 140>;
+   #address-cells = <1>;
+ 

[RFC PATCH 4/4] ARM: DRA: Kconfig: Enable crossbar irqchip driver for DRA7xx

2013-09-12 Thread Sricharan R
Enable the crossbar irqchip driver for DRA7xx soc.

Signed-off-by: Sricharan R 
---
 arch/arm/mach-omap2/Kconfig |1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 8413252..b602168 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -120,6 +120,7 @@ config SOC_DRA7XX
select ARM_GIC
select HAVE_SMP
select COMMON_CLK
+   select IRQCHIP_CROSSBAR
 
 comment "OMAP Core Type"
depends on ARCH_OMAP2
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC PATCH 3/4] ARM: DTS: DRA: Replace peripheral interrupt numbers with crossbar inputs.

2013-09-12 Thread Sricharan R
Now with the crossbar IP in picture, the peripherals do not have the
fixed interrupt lines. Instead they rely on the crossbar irqchip to
allocate and map a free interrupt line to its crossbar input. So replacing
all the peripheral interrupt numbers with its fixed crossbar input lines.

Signed-off-by: Sricharan R 
---
 arch/arm/boot/dts/dra7.dtsi |   88 +--
 1 file changed, 44 insertions(+), 44 deletions(-)

diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index da977e1..2c541af 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -104,10 +104,10 @@
sdma: dma-controller@4a056000 {
compatible = "ti,omap4430-sdma";
reg = <0x4a056000 0x1000>;
-   interrupts = <0 12 0x4>,
-<0 13 0x4>,
-<0 14 0x4>,
-<0 15 0x4>;
+   interrupts = <0 7 0x4>,
+<0 8 0x4>,
+<0 9 0x4>,
+<0 10 0x4>;
#dma-cells = <1>;
#dma-channels = <32>;
#dma-requests = <127>;
@@ -116,7 +116,7 @@
gpio1: gpio@4ae1 {
compatible = "ti,omap4-gpio";
reg = <0x4ae1 0x200>;
-   interrupts = <0 29 0x4>;
+   interrupts = <0 24 0x4>;
ti,hwmods = "gpio1";
gpio-controller;
#gpio-cells = <2>;
@@ -127,7 +127,7 @@
gpio2: gpio@48055000 {
compatible = "ti,omap4-gpio";
reg = <0x48055000 0x200>;
-   interrupts = <0 30 0x4>;
+   interrupts = <0 25 0x4>;
ti,hwmods = "gpio2";
gpio-controller;
#gpio-cells = <2>;
@@ -138,7 +138,7 @@
gpio3: gpio@48057000 {
compatible = "ti,omap4-gpio";
reg = <0x48057000 0x200>;
-   interrupts = <0 31 0x4>;
+   interrupts = <0 26 0x4>;
ti,hwmods = "gpio3";
gpio-controller;
#gpio-cells = <2>;
@@ -149,7 +149,7 @@
gpio4: gpio@48059000 {
compatible = "ti,omap4-gpio";
reg = <0x48059000 0x200>;
-   interrupts = <0 32 0x4>;
+   interrupts = <0 27 0x4>;
ti,hwmods = "gpio4";
gpio-controller;
#gpio-cells = <2>;
@@ -160,7 +160,7 @@
gpio5: gpio@4805b000 {
compatible = "ti,omap4-gpio";
reg = <0x4805b000 0x200>;
-   interrupts = <0 33 0x4>;
+   interrupts = <0 28 0x4>;
ti,hwmods = "gpio5";
gpio-controller;
#gpio-cells = <2>;
@@ -171,7 +171,7 @@
gpio6: gpio@4805d000 {
compatible = "ti,omap4-gpio";
reg = <0x4805d000 0x200>;
-   interrupts = <0 34 0x4>;
+   interrupts = <0 29 0x4>;
ti,hwmods = "gpio6";
gpio-controller;
#gpio-cells = <2>;
@@ -182,7 +182,7 @@
gpio7: gpio@48051000 {
compatible = "ti,omap4-gpio";
reg = <0x48051000 0x200>;
-   interrupts = <0 35 0x4>;
+   interrupts = <0 30 0x4>;
ti,hwmods = "gpio7";
gpio-controller;
#gpio-cells = <2>;
@@ -193,7 +193,7 @@
gpio8: gpio@48053000 {
compatible = "ti,omap4-gpio";
reg = <0x48053000 0x200>;
-   interrupts = <0 121 0x4>;
+   interrupts = <0 116 0x4>;
ti,hwmods = "gpio8";
gpio-controller;
#gpio-cells = <2>;
@@ -204,7 +204,7 @@
uart1: serial@4806a000 {
compatible = "ti,om

Re: [RFC PATCH 1/4] DRIVERS: IRQCHIP: Add crossbar irqchip driver

2013-09-13 Thread Sricharan R
On Friday 13 September 2013 07:12 AM, Santosh Shilimkar wrote:
> On Thursday 12 September 2013 08:26 PM, Thomas Gleixner wrote:
>> On Thu, 12 Sep 2013, Santosh Shilimkar wrote:
>>> On Thursday 12 September 2013 06:22 PM, Thomas Gleixner wrote:
 Now the real question is, how that expansion mechanism is supposed to
 work. There are two possible scenarios:

 1) Expand the number of handled interrupts beyond the GIC capacity:

That requires a mechanism in CROSSBAR to map several CROSSBAR
interrupts to a particular GIC interrupt and provide a demux
mechanism to invoke the shared handlers.

>>> This is not possible in hardware and not supported. Hardware has
>>> no notion of muxing multiple IRQ's to generate 1 IRQ or ack etc
>>> functionality. Its a simple MUX to tie knots between input and output
>>> wires.
>> It's not a MUX. It's a ROUTING mechanism. That's similar to the
>> mechanisms which are used by MSI[X]. We assign arbitrary interrupt
>> numbers to a device and route them to some underlying limited hardware
>> interrupt controller.
>>
 2) Provide a mapping mechanism between possibly 250 interrupt numbers
and a limitation of a total 160 active interrupts by the underlying
GIC.

>>> This is the need and problem we are trying to solve.
>> Let me summarize:
>>
>>- GIC supports up to 160 interrupts
>>
>>- CROSSBAR supports up to 250 interrupts 
>>
>>- CROSSBAR routes up to 160 out of 250 interrupts to the GIC ones
>>
>>- Drivers request a CROSSBAR interrupt number which must be mapped
>>  to some arbitrary available GIC irq number
>>
> Correct.
>
>> So basically the CROSSBAR mechanism is pretty much the same as MSI[X]
>> just in a different flavour and with a different set of semantics and
>> limitations, i.e. poor mans MSI[X] with a new level of bogosity.
>>
>> So if CROSSBAR is going to be the new fangled SoC MSI[X] long term
>> equivalent then you better provide some infrastructure for that and
>> make the drivers ready to use it. Maybe check with the PCI/MSI folks
>> to share some of the interfaces.
>>
>> If that whole thing is another onetime HW designers wet dream, then
>> please go back to the limited but completely functional (Who is going
>> to use more than 160 peripheral interrupts) device tree model. I
>> really have no interest to support hardware designer brain farts.
>>
> Thanks for clear NAK for irqchip approach. I should have looped you
> in the discussion where I was also suggesting against the irqchip
> approach. We will try to look at MSI stuff but if its get too
> complicated am going to fall-back to the initial probe based
> approach to achieve the functionality.
>
> Thanks again for clear direction and useful discussion.
 Thanks for the feedback. I will look in to the MSI driver and
 see if how that would work.

Regards,
 Sricharan
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC PATCH 0/6] DRIVERS: IRQCHIP: Add support for crossbar IP

2013-09-30 Thread Sricharan R
Some socs have a large number of interrupts requests to service
the needs of its many peripherals and subsystems. All of the interrupt
requests lines from the subsystems are not needed at the same
time, so they have to be muxed to the controllers appropriately.
In such places a interrupt controllers are preceded by an
IRQ CROSSBAR that provides flexibility in muxing the device interrupt
requests to the controller inputs.

This series models the peripheral interrupts that can be routed through
the crossbar to the GIC as 'routable-irqs'. The routable irqs are added
in a separate linear domain inside the GIC. The registered routable domain's
callback are invoked as a part of the GIC's callback, which in turn should
allocate a free irq line and configure the IP accordingly. So every peripheral
in the dts files mentions the fixed crossbar number as its interrupt. A free
gic line for that gets allocated and configured when the peripheral's interrupt
is mapped.

The minimal crossbar driver to track and allocate free GIC lines and configure 
the
crossbar is added here, along with the DT bindings.

Sricharan R (6):
  DRIVERS: IRQCHIP: IRQ-GIC: Add support for routable irqs
  DRIVERS: IRQCHIP: CROSSBAR: Add support for Crossbar IP
  ARM: DTS: DRA: Add crossbar device binding
  ARM: DTS: DRA: Replace peripheral interrupt numbers with crossbar
inputs.
  ARM: OMAP4+: Correct Wakeup-gen code to use physical irq number
  ARM: DRA: Enable Crossbar IP support for DRA7XX

 Documentation/devicetree/bindings/arm/gic.txt  |5 +
 .../devicetree/bindings/arm/omap/crossbar.txt  |   27 +++
 arch/arm/boot/dts/dra7.dtsi|   98 +-
 arch/arm/mach-omap2/Kconfig|1 +
 arch/arm/mach-omap2/omap-wakeupgen.c   |4 +-
 arch/arm/mach-omap2/omap4-common.c |4 +
 drivers/irqchip/Kconfig|8 +
 drivers/irqchip/Makefile   |1 +
 drivers/irqchip/irq-crossbar.c |  195 
 drivers/irqchip/irq-gic.c  |   57 +-
 include/linux/irqchip/arm-gic.h|8 +-
 include/linux/irqchip/irq-crossbar.h   |   11 ++
 12 files changed, 363 insertions(+), 56 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/omap/crossbar.txt
 create mode 100644 drivers/irqchip/irq-crossbar.c
 create mode 100644 include/linux/irqchip/irq-crossbar.h

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC PATCH 5/6] ARM: OMAP4+: Correct Wakeup-gen code to use physical irq number

2013-09-30 Thread Sricharan R
The wakeup gen mask/unmask callback uses the irq element of the
irq_data to setup. The irq is the linux virtual irq number and
is same as the hardware irq number only when the parent irqchip
is setup as a legacy domain. When it is used as a linear domain,
the virtual irqs are allocated dynamically and wakeup gen code
cannot rely on these numbers to access the irq registers. Instead
use the hwirq element of the irq_data which represent the physical
irq number.

Cc: Santosh Shilimkar 
Cc: Rajendra Nayak 
Cc: Tony Lindgren 
Signed-off-by: Sricharan R 
---
 arch/arm/mach-omap2/omap-wakeupgen.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c 
b/arch/arm/mach-omap2/omap-wakeupgen.c
index 4dc16c2c..244839c 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -134,7 +134,7 @@ static void wakeupgen_mask(struct irq_data *d)
unsigned long flags;
 
raw_spin_lock_irqsave(&wakeupgen_lock, flags);
-   _wakeupgen_clear(d->irq, irq_target_cpu[d->irq]);
+   _wakeupgen_clear(d->hwirq, irq_target_cpu[d->hwirq]);
raw_spin_unlock_irqrestore(&wakeupgen_lock, flags);
 }
 
@@ -146,7 +146,7 @@ static void wakeupgen_unmask(struct irq_data *d)
unsigned long flags;
 
raw_spin_lock_irqsave(&wakeupgen_lock, flags);
-   _wakeupgen_set(d->irq, irq_target_cpu[d->irq]);
+   _wakeupgen_set(d->hwirq, irq_target_cpu[d->hwirq]);
raw_spin_unlock_irqrestore(&wakeupgen_lock, flags);
 }
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC PATCH 4/6] ARM: DTS: DRA: Replace peripheral interrupt numbers with crossbar inputs.

2013-09-30 Thread Sricharan R
Now with the crossbar IP in picture, the peripherals do not have the
fixed interrupt lines. Instead they rely on the crossbar irqchip to
allocate and map a free interrupt line to its crossbar input. So replacing
all the peripheral interrupt numbers with its fixed crossbar input lines.

Cc: Benoit Cousson 
Cc: Santosh Shilimkar 
Cc: Rajendra Nayak 
Cc: Tony Lindgren 
Signed-off-by: Sricharan R 
---
 arch/arm/boot/dts/dra7.dtsi |   88 +--
 1 file changed, 44 insertions(+), 44 deletions(-)

diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index 799b7be..bef1c99 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -104,10 +104,10 @@
sdma: dma-controller@4a056000 {
compatible = "ti,omap4430-sdma";
reg = <0x4a056000 0x1000>;
-   interrupts = <0 12 0x4>,
-<0 13 0x4>,
-<0 14 0x4>,
-<0 15 0x4>;
+   interrupts = <0 7 0x4>,
+<0 8 0x4>,
+<0 9 0x4>,
+<0 10 0x4>;
#dma-cells = <1>;
#dma-channels = <32>;
#dma-requests = <127>;
@@ -116,7 +116,7 @@
gpio1: gpio@4ae1 {
compatible = "ti,omap4-gpio";
reg = <0x4ae1 0x200>;
-   interrupts = <0 29 0x4>;
+   interrupts = <0 24 0x4>;
ti,hwmods = "gpio1";
gpio-controller;
#gpio-cells = <2>;
@@ -127,7 +127,7 @@
gpio2: gpio@48055000 {
compatible = "ti,omap4-gpio";
reg = <0x48055000 0x200>;
-   interrupts = <0 30 0x4>;
+   interrupts = <0 25 0x4>;
ti,hwmods = "gpio2";
gpio-controller;
#gpio-cells = <2>;
@@ -138,7 +138,7 @@
gpio3: gpio@48057000 {
compatible = "ti,omap4-gpio";
reg = <0x48057000 0x200>;
-   interrupts = <0 31 0x4>;
+   interrupts = <0 26 0x4>;
ti,hwmods = "gpio3";
gpio-controller;
#gpio-cells = <2>;
@@ -149,7 +149,7 @@
gpio4: gpio@48059000 {
compatible = "ti,omap4-gpio";
reg = <0x48059000 0x200>;
-   interrupts = <0 32 0x4>;
+   interrupts = <0 27 0x4>;
ti,hwmods = "gpio4";
gpio-controller;
#gpio-cells = <2>;
@@ -160,7 +160,7 @@
gpio5: gpio@4805b000 {
compatible = "ti,omap4-gpio";
reg = <0x4805b000 0x200>;
-   interrupts = <0 33 0x4>;
+   interrupts = <0 28 0x4>;
ti,hwmods = "gpio5";
gpio-controller;
#gpio-cells = <2>;
@@ -171,7 +171,7 @@
gpio6: gpio@4805d000 {
compatible = "ti,omap4-gpio";
reg = <0x4805d000 0x200>;
-   interrupts = <0 34 0x4>;
+   interrupts = <0 29 0x4>;
ti,hwmods = "gpio6";
gpio-controller;
#gpio-cells = <2>;
@@ -182,7 +182,7 @@
gpio7: gpio@48051000 {
compatible = "ti,omap4-gpio";
reg = <0x48051000 0x200>;
-   interrupts = <0 35 0x4>;
+   interrupts = <0 30 0x4>;
ti,hwmods = "gpio7";
gpio-controller;
#gpio-cells = <2>;
@@ -193,7 +193,7 @@
gpio8: gpio@48053000 {
compatible = "ti,omap4-gpio";
reg = <0x48053000 0x200>;
-   interrupts = <0 121 0x4>;
+   interrupts = <0 116 0x4>;
ti,hwmods = "gpio8";
gpio-controller;
#gpio-cells = <2>;
@@ -2

[RFC PATCH 3/6] ARM: DTS: DRA: Add crossbar device binding

2013-09-30 Thread Sricharan R
This adds the irq crossbar device node.

There is a IRQ crossbar device in the soc, which
maps the irq requests from the peripherals to the
mpu interrupt controller's inputs. The Peripheral irq
requests are connected to only one crossbar
input and the output of the crossbar is connected to only one
controller's input line. The crossbar device is used to map
a peripheral input to a free mpu's interrupt controller line.

Cc: Benoit Cousson 
Cc: Santosh Shilimkar 
Cc: Rajendra Nayak 
Cc: Tony Lindgren 
Signed-off-by: Sricharan R 
---
 arch/arm/boot/dts/dra7.dtsi |9 +
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index b35cb12..799b7be 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -492,5 +492,14 @@
dmas = <&sdma 70>, <&sdma 71>;
dma-names = "tx0", "rx0";
};
+
+   crossbar_mpu: @4a02 {
+   compatible = "ti,irq-crossbar";
+   reg = <0x4a002a48 0x130>;
+   max-irqs = <160>;
+   reg-size = <2>;
+   irqs-reserved = <0 1 2 3 5 6 131 132 139 140>;
+   };
+
};
 };
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC PATCH 6/6] ARM: DRA: Enable Crossbar IP support for DRA7XX

2013-09-30 Thread Sricharan R
Enable the crossbar IP support for DRA7xx soc.

Cc: Santosh Shilimkar 
Cc: Rajendra Nayak 
Cc: Tony Lindgren 
Signed-off-by: Sricharan R 
---
 arch/arm/mach-omap2/Kconfig|1 +
 arch/arm/mach-omap2/omap4-common.c |4 
 2 files changed, 5 insertions(+)

diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 8413252..10ec40c 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -120,6 +120,7 @@ config SOC_DRA7XX
select ARM_GIC
select HAVE_SMP
select COMMON_CLK
+   select IRQ_CROSSBAR
 
 comment "OMAP Core Type"
depends on ARCH_OMAP2
diff --git a/arch/arm/mach-omap2/omap4-common.c 
b/arch/arm/mach-omap2/omap4-common.c
index adbe86b..4692f1c 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -287,9 +288,12 @@ void __init omap_gic_of_init(void)
 
 skip_errata_init:
omap_wakeupgen_init();
+   if (soc_is_dra7xx())
+   crossbar_init();
irqchip_init();
 }
 
+
 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 static int omap4_twl6030_hsmmc_late_init(struct device *dev)
 {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC PATCH 2/6] DRIVERS: IRQCHIP: CROSSBAR: Add support for Crossbar IP

2013-09-30 Thread Sricharan R
Some socs have a large number of interrupts requests to service
the needs of its many peripherals and subsystems. All of the
interrupt lines from the subsystems are not needed at the same
time, so they have to be muxed to the irq-controller appropriately.
In such places a interrupt controllers are preceded by an CROSSBAR
that provides flexibility in muxing the device requests to the controller
inputs.

This driver takes care a allocating a free irq and then configuring the
crossbar IP as a part of the mpu's irqchip callbacks. crossbar_init should
be called right before the irqchip_init, so that it is setup to handle the
irqchip callbacks.

Cc: Thomas Gleixner 
Cc: Linus Walleij 
Cc: Santosh Shilimkar 
Cc: Russell King 
Cc: Tony Lindgren 
Cc: Rajendra Nayak 
Cc: Marc Zyngier 
Cc: Grant Likely 
Cc: Rob Herring 
Signed-off-by: Sricharan R 
---
 .../devicetree/bindings/arm/omap/crossbar.txt  |   27 +++
 drivers/irqchip/Kconfig|8 +
 drivers/irqchip/Makefile   |1 +
 drivers/irqchip/irq-crossbar.c |  195 
 include/linux/irqchip/irq-crossbar.h   |   11 ++
 5 files changed, 242 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/omap/crossbar.txt
 create mode 100644 drivers/irqchip/irq-crossbar.c
 create mode 100644 include/linux/irqchip/irq-crossbar.h

diff --git a/Documentation/devicetree/bindings/arm/omap/crossbar.txt 
b/Documentation/devicetree/bindings/arm/omap/crossbar.txt
new file mode 100644
index 000..cdec2cd
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/crossbar.txt
@@ -0,0 +1,27 @@
+Some socs have a large number of interrupts requests to service
+the needs of its many peripherals and subsystems. All of the
+interrupt lines from the subsystems are not needed at the same
+time, so they have to be muxed to the irq-controller appropriately.
+In such places a interrupt controllers are preceded by an CROSSBAR
+that provides flexibility in muxing the device requests to the controller
+inputs.
+
+Required properties:
+- compatible : Should be "ti,irq-crossbar"
+- reg: Base address and the size of the crossbar registers.
+- max-irqs: Total number of irqs available at the interrupt controller.
+- reg-size: Size of a individual register in bytes. Every individual
+   register is assumed to be of same size. Valid sizes are 1, 2, 4.
+- irqs-reserved: List of the reserved irq lines that are not muxed using
+crossbar. These interrupt lines are reserved in the soc,
+so crossbar bar driver should not consider them as free
+lines.
+
+Examples:
+   crossbar_mpu: @4a02 {
+   compatible = "ti,irq-crossbar";
+   reg = <0x4a002a48 0x130>;
+   max-irqs = <160>;
+   reg-size = <2>;
+   irqs-reserved = <0 1 2 3 5 6 131 132 139 140>;
+   };
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 4a33351..ed6ced28 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -41,3 +41,11 @@ config VERSATILE_FPGA_IRQ_NR
int
default 4
depends on VERSATILE_FPGA_IRQ
+
+config IRQ_CROSSBAR
+   bool
+   help
+ Support for a CROSSBAR ip that preceeds the main interrupt controller.
+ The primary irqchip invokes the crossbar's callback which inturn 
allocates
+ a free irq and configures the IP. Thus the peripheral interrupts are
+ routed to one of the free irqchip interrupt lines.
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index cda4cb5..7f690b7 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_RENESAS_INTC_IRQPIN) += 
irq-renesas-intc-irqpin.o
 obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)   += irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_VT8500)  += irq-vt8500.o
+obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c
new file mode 100644
index 000..3e1b488
--- /dev/null
+++ b/drivers/irqchip/irq-crossbar.c
@@ -0,0 +1,195 @@
+/*
+ *  drivers/irqchip/irq-crossbar.c
+ *
+ *  Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define IRQ_FREE   -1
+#define GIC_IRQ_START  32
+
+/*
+ * @int_max: maximum number of supported interrupts
+ * @irq_map: array of interrupts to crossbar number mapping
+ * @crossbar_base: crossbar base address
+ * @register_offsets: of

[RFC PATCH 1/6] DRIVERS: IRQCHIP: IRQ-GIC: Add support for routable irqs

2013-09-30 Thread Sricharan R
In some socs the gic can be preceded by a crossbar IP which
routes the peripheral interrupts to the gic inputs. The peripheral
interrupts are associated with a fixed crossbar input line and the
crossbar routes that to one of the free gic input line.

The DT entries for peripherals provides the fixed crossbar input line
as its interrupt number and the mapping code should associate this with
a free gic input line. This patch adds the support inside the gic irqchip
to handle such routable irqs. The routable irqs are registered in a linear
domain. The registered routable domain's callback should be implemented
to get a free irq and to configure the IP to route it.

Cc: Thomas Gleixner 
Cc: Linus Walleij 
Cc: Santosh Shilimkar 
Cc: Russell King 
Cc: Tony Lindgren 
Cc: Rajendra Nayak 
Cc: Marc Zyngier 
Cc: Grant Likely 
Cc: Rob Herring 
Signed-off-by: Sricharan R 
---
 Documentation/devicetree/bindings/arm/gic.txt |5 +++
 arch/arm/boot/dts/dra7.dtsi   |1 +
 drivers/irqchip/irq-gic.c |   57 +
 include/linux/irqchip/arm-gic.h   |8 +++-
 4 files changed, 61 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/gic.txt 
b/Documentation/devicetree/bindings/arm/gic.txt
index 3dfb0c0..2d8c680 100644
--- a/Documentation/devicetree/bindings/arm/gic.txt
+++ b/Documentation/devicetree/bindings/arm/gic.txt
@@ -49,6 +49,11 @@ Optional
   regions, used when the GIC doesn't have banked registers. The offset is
   cpu-offset * cpu-nr.
 
+- routable-irqs: Total number of gic irq inputs which are not directly
+ connected from the peripherals, but are routed dynamically
+ by a crossbar/multiplexer preceding the GIC. The GIC irq
+ input line is assigned dynamically when the corresponding
+ peripheral's crossbar line is mapped.
 Example:
 
intc: interrupt-controller@fff11000 {
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index a5d9350..b35cb12 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -55,6 +55,7 @@
compatible = "arm,cortex-a15-gic";
interrupt-controller;
#interrupt-cells = <3>;
+   routable_irqs = <160>;
reg = <0x48211000 0x1000>,
  <0x48212000 0x1000>;
};
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 1760ceb..c5778ab 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -72,6 +72,8 @@ struct gic_chip_data {
 
 static DEFINE_RAW_SPINLOCK(irq_controller_lock);
 
+const struct irq_domain_ops *gic_routable_irq_domain_ops;
+
 /*
  * The GIC mapping of CPU interfaces does not necessarily match
  * the logical CPU numbering.  Let's use a mapping as returned
@@ -675,11 +677,26 @@ static int gic_irq_domain_map(struct irq_domain *d, 
unsigned int irq,
irq_set_chip_and_handler(irq, &gic_chip,
 handle_fasteoi_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+
+   if (gic_routable_irq_domain_ops &&
+   gic_routable_irq_domain_ops->map)
+   gic_routable_irq_domain_ops->map(d, irq, hw);
}
irq_set_chip_data(irq, d->host_data);
return 0;
 }
 
+static void gic_irq_domain_unmap(struct irq_domain *d, unsigned int irq)
+{
+   irq_hw_number_t hw = irq_get_irq_data(irq)->hwirq;
+
+   if (hw > 32) {
+   if (gic_routable_irq_domain_ops &&
+   gic_routable_irq_domain_ops->unmap)
+   gic_routable_irq_domain_ops->unmap(d, irq);
+   }
+}
+
 static int gic_irq_domain_xlate(struct irq_domain *d,
struct device_node *controller,
const u32 *intspec, unsigned int intsize,
@@ -694,8 +711,15 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
*out_hwirq = intspec[1] + 16;
 
/* For SPIs, we need to add 16 more to get the GIC irq ID number */
-   if (!intspec[0])
-   *out_hwirq += 16;
+   if (!intspec[0]) {
+   if (gic_routable_irq_domain_ops &&
+   gic_routable_irq_domain_ops->xlate)
+   *out_hwirq = gic_routable_irq_domain_ops->xlate(d,
+   controller, intspec, intsize,
+   out_hwirq, out_type);
+   else
+   *out_hwirq += 16;
+   }
 
*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
return 0;
@@ -722,6 +746,7 @@ static struct notifier_block __cpuinitdata gic_cpu_notifier 
= {
 
 const struct irq_domain_ops gic_irq_domain_ops = {
.map = gic_irq_domain_map,
+ 

Re: [RFC PATCH 1/6] DRIVERS: IRQCHIP: IRQ-GIC: Add support for routable irqs

2013-09-30 Thread Sricharan R
On Monday 30 September 2013 07:52 PM, Santosh Shilimkar wrote:
> On Monday 30 September 2013 10:16 AM, Marc Zyngier wrote:
>> On 30/09/13 14:59, Sricharan R wrote:
>>> In some socs the gic can be preceded by a crossbar IP which
>>> routes the peripheral interrupts to the gic inputs. The peripheral
>>> interrupts are associated with a fixed crossbar input line and the
>>> crossbar routes that to one of the free gic input line.
>>>
>>> The DT entries for peripherals provides the fixed crossbar input line
>>> as its interrupt number and the mapping code should associate this with
>>> a free gic input line. This patch adds the support inside the gic irqchip
>>> to handle such routable irqs. The routable irqs are registered in a linear
>>> domain. The registered routable domain's callback should be implemented
>>> to get a free irq and to configure the IP to route it.
>> Isn't this just another chained interrupt controller? How is it GIC
>> specific?
>>
> No it isn't a irq controller rather a event router. Patch is missing
> reference to the previous discussion. Previous discussion is here [1]
>
> Regards,
> Santosh
>
> [1] https://lkml.org/lkml/2013/9/13/413
>
Sorry, missed adding that and thanks for pointing it.

Regards,
 Sricharan

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] gpio/omap: auto-setup a GPIO when used as an IRQ

2013-09-24 Thread Sricharan R
Hi,
On Monday 23 September 2013 10:37 PM, Tony Lindgren wrote:
> * Javier Martinez Canillas  [130923 10:09]:
>> On 09/23/2013 06:45 PM, Tony Lindgren wrote:
>>> Hmm does this still work for legacy platform data based
>>> drivers that are doing gpio_request() first?
>>>
>> Yes it still work when booting using board files. I tested on my OMAP3 board 
>> and
>> it worked in both DT and legacy booting mode.
> OK great.
>  
>>> And what's the path for clearing things for PM when free_irq()
>>> gets called? It seems that this would leave the GPIO bank
>>> enabled causing a PM regression?
>>>
>> Indeed, I did set bank->mod_usage |= 1 << offset so the bank is enabled if 
>> the
>> device goes to suspended and then resumed but I completely forget about the
>> clearing path when the IRQ is freed.
>>
>> Which makes me think that we should probably maintain two usage variables, 
>> one
>> for GPIO and another one for IRQ and check both of them on the 
>> suspend/resume pm
>> functions.
> Yes that it seems that they should be treated separately.
 To understand, why cant the flag be cleared in gpio_irq_shutdown ?

Regards,
 Sricharan
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] gpio/omap: auto-setup a GPIO when used as an IRQ

2013-09-24 Thread Sricharan R
On Tuesday 24 September 2013 01:24 PM, Javier Martinez Canillas wrote:
> On 09/24/2013 09:39 AM, Sricharan R wrote:
>> Hi,
>> On Monday 23 September 2013 10:37 PM, Tony Lindgren wrote:
>>> * Javier Martinez Canillas  [130923 10:09]:
>>>> On 09/23/2013 06:45 PM, Tony Lindgren wrote:
>>>>> Hmm does this still work for legacy platform data based
>>>>> drivers that are doing gpio_request() first?
>>>>>
>>>> Yes it still work when booting using board files. I tested on my OMAP3 
>>>> board and
>>>> it worked in both DT and legacy booting mode.
>>> OK great.
>>>  
>>>>> And what's the path for clearing things for PM when free_irq()
>>>>> gets called? It seems that this would leave the GPIO bank
>>>>> enabled causing a PM regression?
>>>>>
>>>> Indeed, I did set bank->mod_usage |= 1 << offset so the bank is enabled if 
>>>> the
>>>> device goes to suspended and then resumed but I completely forget about the
>>>> clearing path when the IRQ is freed.
>>>>
>>>> Which makes me think that we should probably maintain two usage variables, 
>>>> one
>>>> for GPIO and another one for IRQ and check both of them on the 
>>>> suspend/resume pm
>>>> functions.
>>> Yes that it seems that they should be treated separately.
>>  To understand, why cant the flag be cleared in gpio_irq_shutdown ?
> Hi Sricharan,
>
> Without this patch today drivers do this:
>
> gpio_request(gpio, "foo IRQ"); // bank->mod_usage |= 1 << offset
> gpio_direction_input(gpio);
>
> and then request a IRQ with:
>
> irq = gpio_to_irq(gpio);
> request_irq(irq, ...);
>
> later on its cleanup path:
>
> free_irq(irq, dev);
> gpio_free(gpio) // bank->mod_usage &= ~(1 << offset);
>
> So if you clear the flag on gpio_irq_shutdown then bank module won't be 
> enabled
> after a suspend making drivers using the GPIO after freeing the IRQ to fail.
>
> So the idea is to have something like this:
>
> a) Drivers that request both the GPIO and IRQ
>
> gpio_request(gpio, "foo IRQ"); // bank->mod_usage |= 1 << offset
> gpio_direction_input(gpio);
>
> irq = gpio_to_irq(gpio);
> request_irq(irq, ...); // bank->irq_usage |= 1 << offset
>
> free_irq(irq, dev); // bank->irq_usage &= ~(1 << offset);
> gpio_free(gpio) // bank->mod_usage &= ~(1 << offset);
>
> b) Drivers that just request the IRQ:
>
> irq = gpio_to_irq(gpio);
> request_irq(irq, ...); // bank->irq_usage |= 1 << offset
> free_irq(irq, dev); // bank->irq_usage &= ~(1 << offset);
>
> So irq_usage or mod_usage is set means that the bank has to be enabled and if
> both are not set means that the bank module can be disabled.
>
 Ok get it. Thanks.

Regards,
 Sricharan
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] misc: Add crossbar driver

2013-08-22 Thread Sricharan R
Hi Linus,

On Thursday 22 August 2013 02:40 AM, Linus Walleij wrote:
> On Thu, Aug 15, 2013 at 11:14 PM, Santosh Shilimkar
>  wrote:
>> On Thursday 15 August 2013 04:51 PM, Linus Walleij wrote:
> (...)
>>> Sorry I don't understand what thread that is... can you point me there?
>>> My previous statement on this issue what this:
>>> http://marc.info/?l=linux-kernel&m=137442541628641&w=2
> (...)
 I don't see how you can make this happen with an irqchip
 infrastructure.
>>> I think my post above describes this.
>>>
>> Sorry for being dumb but I don't think cascaded irqchip examples
>> like GPIO and cross-bars are same. If you take an example of
>> GPIO irqchip, it always have a physical connection even if it
>> is 1 IRQ line for (32 logical/sparse IRQs). That goes with
>> other MFD examples too.
>>
>> So may be I am still missing something in your proposal.
> Why does it matter if it is a GPIO or MFD or whatever?
> The point is that the IRQ line passes thru something else,
> and this we model as an irqdomain.
>
> Anyway here is a silicon cascaded IRQ chip:
> arch/arm/mach-versatile/core.c
> See versatile_init_irq():
>
> __vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0, np);
> (...)
> fpga_irq_init(VA_SIC_BASE, "SIC", IRQ_SIC_START,
> IRQ_VICSOURCE31, PIC_VALID, np);
>
> The VIC in the versatile has the SIC cascaded from one of
> its IRQ lines. Both the VIC and SIC (fpga IRQ) are
> using irqdomains so the SIC spawns a child irqdomain
> from IRQ 31 (last IRQ) of the VIC.
 Ok, this is a typical example of irqchip cascaded.
> The difference with a crossbar is that it can software-config
> which IRQ goes where, and does not have a callback
> to clear interrupts or anything like that, it just passes them
> thru. But it is best modeled as an irqdomain IMO.
We can model crossbar as irqchip and gic as its interrupt parent
and peripherals to have crossbar as interrupt-parent.
   
 peripherals will do request_irq(crossbar_number)
  |
  |
 crossbar_unmask()
  |
  |
 maps crossbar number<->  to interrupt number and
 calls request_irq(int_no, crossbar_handler,..)

 
 crossbar_handler(interrupt number)
|
|
 get crossbar number from interrupt number
|
|
 handle_irq(crossbar_domain(crossbar number))
 

So this means a extra dummy handler.
Also the concern is by modelling it as irqchip, we will have
to find a different solution for DMA crossbar.

Regards,
 Sricharan


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] misc: Add crossbar driver

2013-08-22 Thread Sricharan R
Hi,
On Friday 23 August 2013 10:17 AM, Rajendra Nayak wrote:
> On Thursday 22 August 2013 05:03 PM, Sricharan R wrote:
>>  maps crossbar number<->  to interrupt number and
>>  calls request_irq(int_no, crossbar_handler,..)
> So will this mapping happen based on some data passed from DT or
> just based on whats available when the device does a request_irq()?
>
> If its based on whats available then I see an issue when you need
> to remap something thats already mapped by default (and not used)
> since you run out of all free ones.
Yes, when done based on what is available then there is a
problem when we run out of free ones because we do not
know which one to replace. I was thinking of something like
this,
1) DT would give a list of all free ones, and also if some are
mapped as default and not used, mark those also as free.

 2) While mapping see if it has a default mapping and use it.
  otherwise, pick from free list.   

  This should be ok right ?

Regards,
 Sricharan

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] misc: Add crossbar driver

2013-08-22 Thread Sricharan R
On Friday 23 August 2013 12:06 PM, Sekhar Nori wrote:
> On Friday 23 August 2013 11:41 AM, Sricharan R wrote:
>> Hi,
>> On Friday 23 August 2013 10:17 AM, Rajendra Nayak wrote:
>>> On Thursday 22 August 2013 05:03 PM, Sricharan R wrote:
>>>>  maps crossbar number<->  to interrupt number and
>>>>  calls request_irq(int_no, crossbar_handler,..)
>>> So will this mapping happen based on some data passed from DT or
>>> just based on whats available when the device does a request_irq()?
>>>
>>> If its based on whats available then I see an issue when you need
>>> to remap something thats already mapped by default (and not used)
>>> since you run out of all free ones.
>> Yes, when done based on what is available then there is a
>> problem when we run out of free ones because we do not
>> know which one to replace. I was thinking of something like
>> this,
>> 1) DT would give a list of all free ones, and also if some are
>> mapped as default and not used, mark those also as free.
>>
>>  2) While mapping see if it has a default mapping and use it.
>>   otherwise, pick from free list.   
> Since the entire DT is available to you at boot time, you should be able
> to find each node where interrupt-parent = <&crossbar> and then allocate
> one of 0-160 GIC interrupt numbers for that node, no? Where would there
> be a need for default mapping and remapping? From one the mails in the
> thread the crossbar is completely flexible - any of the 320 crossbar
> interrupts can be mapped to any of the 160 GIC interrupts.
>
> Any GIC interrupts left after this boot-time scan can be added to an
> unused list for use with runtime DT fragments (when that support comes).
>  
> Sorry if I misunderstood, but above proposal sounds like maintaining a
> separate free interrupt lines list in DT. That will quickly go out of sync.
 Say, peripheral x uses crossbar 1 and specifies this in DT.
 During boot crossbar 1 gets mapped int 10. So if by default
some other crossbar has its interrupt mapped to 10,
then it should be removed.  Instead clear all crossbar registers
once and mark all as free, then  allocate only during request.
Correct ?. In this the free no need to maintain any list.

Regards,
 Sricharan
 

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/3] Add crossbar driver

2013-07-18 Thread Sricharan R
Some socs have a large number of interrupts/dma requests to service
the needs of its many peripherals and subsystems. All of the
requests lines from the subsystems are not needed at the same
time, so they have to be muxed to the controllers appropriately.
In such places a interrupt/dma controllers are preceded by an
IRQ/DMA CROSSBAR that provides flexibility in muxing the device
requests to the controller inputs.

This series adds a crossbar driver and the DT bindings for the
same. Also the DT nodes for DRA7xx SOC which has a IRQ/DMA
crossbar has been added here.

This series is on top of the basic DRA support from Rajendra [1][2]

[1] http://comments.gmane.org/gmane.linux.ports.arm.omap/100763
[2] http://comments.gmane.org/gmane.linux.ports.arm.omap/100773

Sricharan R (3):
  misc: Add crossbar driver
  ARM: dts: DRA: Add crossbar device binding
  ARM: DRA: Enable crossbar driver for dra soc

 .../devicetree/bindings/arm/omap/crossbar.txt  |   24 ++
 arch/arm/boot/dts/dra7.dtsi|   19 ++
 arch/arm/mach-omap2/Kconfig|1 +
 drivers/misc/Kconfig   |8 +
 drivers/misc/Makefile  |1 +
 drivers/misc/crossbar.c|  258 
 include/linux/crossbar.h   |   71 ++
 7 files changed, 382 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/omap/crossbar.txt
 create mode 100644 drivers/misc/crossbar.c
 create mode 100644 include/linux/crossbar.h

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/3] misc: Add crossbar driver

2013-07-18 Thread Sricharan R
Some socs have a large number of interrupts/dma requests to service
the needs of its many peripherals and subsystems. All of the
requests lines from the subsystems are not needed at the same
time, so they have to be muxed to the controllers appropriately.
In such places a interrupt/dma controllers are preceded by an
IRQ/DMA CROSSBAR that provides flexibility in muxing the device
requests to the controller inputs.

The Peripheral irq/dma requests are connected to one crossbar's input
and the output of the crossbar is connected to controller's input
line. On POR, there are some mappings which are done by default.
Those peripherals which do not have a mapping on POR, should be configured
to route its requests using the crossbar.

The drivers identifies every controller's crossbar as individual devices.
The mappings can be specified from the DT crossbar nodes and those gets mapped
during the crossbar device's probe. The mappings can also be specified by adding
the crossbar lines to the peripheral device nodes and map it with
crossbar_map/unmap apis.

Signed-off-by: Sricharan R 
---
 .../devicetree/bindings/arm/omap/crossbar.txt  |   24 ++
 drivers/misc/Kconfig   |8 +
 drivers/misc/Makefile  |1 +
 drivers/misc/crossbar.c|  258 
 include/linux/crossbar.h   |   71 ++
 5 files changed, 362 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/omap/crossbar.txt
 create mode 100644 drivers/misc/crossbar.c
 create mode 100644 include/linux/crossbar.h

diff --git a/Documentation/devicetree/bindings/arm/omap/crossbar.txt 
b/Documentation/devicetree/bindings/arm/omap/crossbar.txt
new file mode 100644
index 000..02a8a28
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/crossbar.txt
@@ -0,0 +1,24 @@
+* TI - IRQ/DMA Crossbar
+
+This version is an implementation of the Crossbar IRQ/DMA IP
+
+Required properties:
+- compatible : Should be "ti,dra-crossbar"
+- crossbar-name: Name of the controller to which crossbar output is routed
+- reg: Contains crossbar register address range
+- reg-width: Represents the width of the individual registers
+- crossbar-lines:  Default mappings.Should contain the crossbar-name
+  device name, int/dma request number, crossbar number,
+  register offset in the same order.
+
+Examples:
+   crossbar_mpu: mpuirq@4a002a48 {
+   compatible = "crossbar";
+   crossbar-name = "mpu-irq";
+   reg = <0x4a002a48 0x0130>;
+   reg-width = <16>;
+   crossbar-lines = "mpu-irq", "rtc-ss-alarm", <0x9f 0xd9 
0x12c>,
+"mpu-irq", "mcasp3-arevt", <0x9e 0x96 
0x12a>,
+"mpu-irq", "mcasp3-axevt", <0x9d 0x97 
0x128>;
+   };
+
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index c002d86..de89bff 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -527,6 +527,14 @@ config SRAM
  the genalloc API. It is supposed to be used for small on-chip SRAM
  areas found on many SoCs.
 
+config CROSSBAR
+   bool "on-chip crossbar driver"
+   select REGMAP_MMIO
+   help
+ This driver is for IRQ/DMA crossbar devices which is responsible for
+ muxing the irq/dma requests from external peripherals to the 
corresponding
+ controller's inputs.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index c235d5b..37ce1b8 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_INTEL_MEI)   += mei/
 obj-$(CONFIG_VMWARE_VMCI)  += vmw_vmci/
 obj-$(CONFIG_LATTICE_ECP3_CONFIG)  += lattice-ecp3-config.o
 obj-$(CONFIG_SRAM) += sram.o
+obj-$(CONFIG_CROSSBAR) += crossbar.o
diff --git a/drivers/misc/crossbar.c b/drivers/misc/crossbar.c
new file mode 100644
index 000..c0a7e83
--- /dev/null
+++ b/drivers/misc/crossbar.c
@@ -0,0 +1,258 @@
+/*
+ * IRQ/DMA CROSSBAR DRIVER
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * Sricharan R 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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 

[PATCH 2/3] ARM: dts: DRA: Add crossbar device binding

2013-07-18 Thread Sricharan R
This adds the irq/dma crossbar device nodes.

There is a IRQ and DMA crossbar device in the soc, which
maps the irq/dma requests from the peripherals to the
mpu/dsp/ipu/eve interrupt and sdma/edma controller's inputs.
The Peripheral irq/dma requests are connected to only one crossbar
input and the output of the crossbar is connected to only one
controller's input line. On POR, there are some mappings which
are done by default. Those peripherals which do not have a
mapping on POR, should be configured to route its requests
using the crossbar control registers.

The irq/dma mapping for some peripherals are
added with the crossbar nodes here.

Signed-off-by: Sricharan R 
---
 arch/arm/boot/dts/dra7.dtsi |   19 +++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index a5d9350..e6208b4 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -85,6 +85,25 @@
ranges;
ti,hwmods = "l3_main_1", "l3_main_2";
 
+   crossbar_mpu: mpuirq@4a002a48 {
+   compatible = "crossbar";
+   crossbar-name = "mpu-irq";
+   reg = <0x4a002a48 0x0130>;
+   reg-width = <16>;
+   crossbar-lines = "mpu-irq", "rtc-ss-alarm", <0x9f 0xd9 
0x12c>,
+"mpu-irq", "mcasp3-arevt", <0x9e 0x96 
0x12a>,
+"mpu-irq", "mcasp3-axevt", <0x9d 0x97 
0x128>;
+   };
+
+   crossbar_dma: dmareq@4a002b78 {
+   compatible = "crossbar";
+   crossbar-name = "dma-req";
+   reg = <0x4a002b78 0x0100>;
+   reg-width = <16>;
+   crossbar-lines = "dma-req", "mcasp3-rx", <0x7e 0x84 
0xfc>,
+"dma-req", "mcasp3-tx", <0x7d 0x85 
0xfa>;
+   };
+
counter32k: counter@4ae04000 {
compatible = "ti,omap-counter32k";
reg = <0x4ae04000 0x40>;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/3] ARM: DRA7xx: Enable crossbar driver for the soc

2013-07-18 Thread Sricharan R
Enable the crossbar driver to handle the irq/dma
crossbar devices in the soc.

Signed-off-by: Sricharan R 
---
 arch/arm/mach-omap2/Kconfig |1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 80aaadc..3def350 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -120,6 +120,7 @@ config SOC_DRA7XX
select ARM_GIC
select HAVE_SMP
select COMMON_CLK
+   select CROSSBAR
 
 comment "OMAP Core Type"
depends on ARCH_OMAP2
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] misc: Add crossbar driver

2013-07-19 Thread Sricharan R
Hi,

On Friday 19 July 2013 05:43 AM, Nishanth Menon wrote:
> On Thu, Jul 18, 2013 at 6:39 PM, Santosh Shilimkar
>  wrote:
>> On Thursday 18 July 2013 02:56 PM, Nishanth Menon wrote:
>>> On 07/18/2013 11:43 AM, Sricharan R wrote:
>>>> Some socs have a large number of interrupts/dma requests to service
>>>> the needs of its many peripherals and subsystems. All of the
>>>> requests lines from the subsystems are not needed at the same
>>>> time, so they have to be muxed to the controllers appropriately.
>>>> In such places a interrupt/dma controllers are preceded by an
>>>> IRQ/DMA CROSSBAR that provides flexibility in muxing the device
>>>> requests to the controller inputs.
>>>>
>>>> The Peripheral irq/dma requests are connected to one crossbar's input
>>>> and the output of the crossbar is connected to controller's input
>>>> line. On POR, there are some mappings which are done by default.
>>>> Those peripherals which do not have a mapping on POR, should be configured
>>>> to route its requests using the crossbar.
>>>>
>>>> The drivers identifies every controller's crossbar as individual devices.
>>>> The mappings can be specified from the DT crossbar nodes and those gets 
>>>> mapped
>>>> during the crossbar device's probe. The mappings can also be specified by 
>>>> adding
>>>> the crossbar lines to the peripheral device nodes and map it with
>>>> crossbar_map/unmap apis.
>>>>
>>>> Signed-off-by: Sricharan R 
>>>> ---
>>>>   .../devicetree/bindings/arm/omap/crossbar.txt  |   24 ++
>>>>   drivers/misc/Kconfig   |8 +
>>>>   drivers/misc/Makefile  |1 +
>>>>   drivers/misc/crossbar.c|  258 
>>>> 
>>>>   include/linux/crossbar.h   |   71 ++
>>>>   5 files changed, 362 insertions(+)
>>>>   create mode 100644 
>>>> Documentation/devicetree/bindings/arm/omap/crossbar.txt
>>>>   create mode 100644 drivers/misc/crossbar.c
>>>>   create mode 100644 include/linux/crossbar.h
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/arm/omap/crossbar.txt 
>>>> b/Documentation/devicetree/bindings/arm/omap/crossbar.txt
>>>> new file mode 100644
>>>> index 000..02a8a28
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/arm/omap/crossbar.txt
>>>> @@ -0,0 +1,24 @@
>>>> +* TI - IRQ/DMA Crossbar
>>>> +
>>>> +This version is an implementation of the Crossbar IRQ/DMA IP
>>>> +
>>>> +Required properties:
>>>> +- compatible : Should be "ti,dra-crossbar"
>>>> +- crossbar-name: Name of the controller to which crossbar output is routed
>>>> +- reg:Contains crossbar register address range
>>>> +- reg-width: Represents the width of the individual registers
>>>> +- crossbar-lines:  Default mappings.Should contain the crossbar-name
>>>> +   device name, int/dma request number, crossbar number,
>>>> +   register offset in the same order.
>>>> +
>>>> +Examples:
>>>> +crossbar_mpu: mpuirq@4a002a48 {
>>>> +compatible = "crossbar";
>>>> +crossbar-name = "mpu-irq";
>>>> +reg = <0x4a002a48 0x0130>;
>>>> +reg-width = <16>;
>>>> +crossbar-lines = "mpu-irq", "rtc-ss-alarm", <0x9f 0xd9 0x12c>,
>>>> + "mpu-irq", "mcasp3-arevt", <0x9e 0x96 0x12a>,
>>>> + "mpu-irq", "mcasp3-axevt", <0x9d 0x97 0x128>;
>>>> +};
>>> I carry forward my TI internal objection to this approach:
>>>
>>> NAK.
>>>
>>> DRA7 uses a cross bar to map a line to GIC interrupt. Flow of interrupt is 
>>> as follows:
>>> hardware IP block -interrupt line-> IRQ Cross bar -> GIC IRQ line --> MPU 
>>> IRQ.
>>>
>>>
>>> What we have done today for DRA is to provide IRQ numbers as direct maps 
>>> from hardware IP block to GIC based on default IRQ cross bar mapping.
>>>
>>> Lets see what happens as a result of this:
>>>

Re: [PATCH 1/3] misc: Add crossbar driver

2013-07-19 Thread Sricharan R
On Friday 19 July 2013 12:47 PM, Tony Lindgren wrote:
>> On Thursday 18 July 2013 02:56 PM, Nishanth Menon wrote:
>>
>> Since the cross-bar is not limited t0 IRQ lines and applicable for
>> DMA request lines as well, making it IRQ chip doesn't make sense. Its
>> not typical pin control functionality either but at least that framework
>> is much closer to consider as an option.
>>
>> Actually its more of setting up the IRQ and DMA pins maps once
>> at boot for a given SOC based on chosen configuration by the
>> board. So I am leaning towards pinctrl as well. Just haven't
>> thought enough about whether thats the best approach.
>>
>> CC'ing Linus W and Tony L whether we can use pinctrl framework
>> for such an IP and if yes how ;-).
> If it really muxes signals then using pinctrl seems logical.
> Especially if the registers are in the SCM block.
>
> It might be already possible to handle it already with
> pinctrl-single,bits for the muxing part.
 I also thought of using the pinctrl itself.
 But then i wanted  to have the error handling as well,
 hence did this.

Regards,
 Sricharan
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] misc: Add crossbar driver

2013-07-22 Thread Sricharan R
Hi Linus,
On Sunday 21 July 2013 10:19 PM, Linus Walleij wrote:
> On Thu, Jul 18, 2013 at 8:56 PM, Nishanth Menon  wrote:
>
>> I carry forward my TI internal objection to this approach:
> It is actually a very good sign of FOSS-maturity that you as a company
> take unresolved architectural issues to the community. Kudos!
>
>> Lets see what happens as a result of this:
>>
>> https://patchwork.kernel.org/patch/2825148/ (introducing DTS for DRA7)
>> uart1 to uart6 is defined. while in fact 10 uarts exist on IP block.
>> uart1: serial@4806a000 {
>> 
>> +   interrupts = <0 72 0x4>;
>> Assumes that GIC interrupt by default mapping used.
> So introducing this inbetween the GIC lines and its actual device IRQ
> lines inevitably means that the GIC three-cell concept is completely
> ill-devised to handle this.
>
> For routing IRQs, I think the proper solution would be to use a
> cascaded struct irqchip, which in turn contains an irqdomain
> translation to remux the signal onto the GIC inputs.
>
> I.e. the interrupt-controller given to that serial would be the
> crossbar irqchip, and that in turn will hog and allocate apropriate
> lines from the gic to it would probably itself list *all* the IRQs
> of the GIC as "its" IRQs.
>
> We already have plenty of cascading irqchips such as GPIO
> controller providing IRQs, just that they only multiplex on a
> single GIC line instead of the whole lot.
>
> Mock example:
>
> intc: interrupt-controller@0 {
> compatible = "arm,cortex-a9-gic";
> #interrupt-cells = <3>;
> #address-cells = <1>;
> interrupt-controller;
> reg = ...;
> };
>
> crossbar: crossbar@0 {
> compatible = "...";
> interrupt-controller;
> #interrupt-cells = <1>;
> interrupt-parent = <&intc>;
> interrupts = <0 0 IRQ_TYPE_LEVEL_HIGH>,
>   <0 1 IRQ_TYPE_LEVEL_HIGH>,
>   <0 2 IRQ_TYPE_LEVEL_HIGH>,
>   
>   <0 n IRQ_TYPE_LEVEL_HIGH>;
> };
>
> uart0: serial@0 {
> compatible = "...";
> interrupt-parent = <&crossbar>;
> interrupts = <1234>;
>  };
>
> Maybe the interrupts provided from crossbar cannot even be
> specified by a number, maybe a line name need to be used
> or so. I don't know the particulars.
>
> Whether this as a whole is a good idea, I don't know,
> but you would have to go about it something like this.
>
> What happens if there is no line to mux in a certain IRQ?
 Thanks for this.
 Was thinking of a similar kind of approach with irqchip.
 But then, there was a GAP since crossbar does not have an irq unlike
 other irqchips. But as you said  this can be done by setting the crossbar
 to map and receive the GIC interrupts and then direct to devices.
 Only thing is, this is fine for IRQs, and something different has to be done
 for DMA crossbars  again. Also when we allocate dynamically here,
 finding out a irq line when there is no free line is a question.

  With the other approach of using/extending  the pinctrl framework that you
 gave, it is good to handle both irqs/dma.  I looked at the other example in
 drivers/dma/amba-pl08x.c and i see that data is getting populated and passed
 from the platform. I initially started with something similar, where the data
 was passed statically from DT and a driver to use that.  So now it looks good
 to extend the pinctrl fw. I will try a approach for that first and see how it 
looks.

Regards,
 Sricharan


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] misc: Add crossbar driver

2013-07-24 Thread Sricharan R
On Wednesday 24 July 2013 10:17 PM, Nishanth Menon wrote:
> On 07/24/2013 11:38 AM, Santosh Shilimkar wrote:
>> On Wednesday 24 July 2013 12:08 PM, Nishanth Menon wrote: 
>>> That said, maybe a intermediate pinctrl approach might be more pragmatic 
>>> and less theoretically flexible.
>>> an option might be to "statically allocate" default number of interrupts to 
>>> a domain - example:
>>> * GIC IRQ 72->78 allotted to UARTs
>>> * pinctrl mapping provided for those but only 6 can be used (rest are 
>>> marked status="disabled" as default) at any given time (choice of pinctrl 
>>> option determines GIC interrupt line to use)
>>> * All modules will have a pinctrl definition to have a mapping - to avoid 
>>> bootloader overriding default cross bar setting in ways un-expected by 
>>> kernel.
>>>
>>> Does that sound fair trade off?
>> This sounds better. That way we can get all the devices in the DT at least.
>
> Fair enough - if Linus and Tony are still ok with this approach to the 
> problem, seeing a patch series with the effect would be beneficial.
>
 Ok, i will use this idea of certain number interrupts to groups.
Yes on DRA7XX, we have about 160 gic lines and 320 irq crossbar device inputs 
contending for it.
1:2 and fully arbitrary.  But will we be really exhausting them ?

Regards,
 Sricharan
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] misc: Add crossbar driver

2013-08-13 Thread Sricharan R
Hi Tony,

On Tuesday 13 August 2013 01:40 PM, Tony Lindgren wrote:
> * Santosh Shilimkar  [130724 12:06]:
>> On Wednesday 24 July 2013 02:51 PM, Nishanth Menon wrote:
>>> On 07/24/2013 01:43 PM, Sricharan R wrote:
>>>> On Wednesday 24 July 2013 10:17 PM, Nishanth Menon wrote:
>>>>> On 07/24/2013 11:38 AM, Santosh Shilimkar wrote:
>>>>>> On Wednesday 24 July 2013 12:08 PM, Nishanth Menon wrote:
>>>>>>> That said, maybe a intermediate pinctrl approach might be more 
>>>>>>> pragmatic and less theoretically flexible.
>>>>>>> an option might be to "statically allocate" default number of 
>>>>>>> interrupts to a domain - example:
>>>>>>> * GIC IRQ 72->78 allotted to UARTs
>>>>>>> * pinctrl mapping provided for those but only 6 can be used (rest are 
>>>>>>> marked status="disabled" as default) at any given time (choice of 
>>>>>>> pinctrl option determines GIC interrupt line to use)
>>>>>>> * All modules will have a pinctrl definition to have a mapping - to 
>>>>>>> avoid bootloader overriding default cross bar setting in ways 
>>>>>>> un-expected by kernel.
>>>>>>>
>>>>>>> Does that sound fair trade off?
>>>>>> This sounds better. That way we can get all the devices in the DT at 
>>>>>> least.
>>>>> Fair enough - if Linus and Tony are still ok with this approach to the 
>>>>> problem, seeing a patch series with the effect would be beneficial.
>>>>>
>>>>   Ok, i will use this idea of certain number interrupts to groups.
>>>> Yes on DRA7XX, we have about 160 gic lines and 320 irq crossbar device 
>>>> inputs contending for it.
>>>> 1:2 and fully arbitrary.  But will we be really exhausting them ?
>>>>
>>> Depends on how we allocate :). The default arbitary allocation can be made 
>>> more logical in your series ofcourse :).
>>>
>> I would just most logical peripherals rather than providing every single
>> IP connected to cross bar. Otherwise we will end up wth hwmod like
>> scenario where now started removing the unused stuff because of
>> maintenance and loc issues ;-)
> Sorry for the delay on this, I think the best way to set this up
> is as a separate drivers/irqchip controller. Then just map the
> configured interrupts for the board with interrupt-map and
> interrupt-map-mask binding. No need to stuff all the SoC specific
> maps to the .dts, just the ones used for the board.
>
> Regards,
>
> Tony
>  
 Initially irqchip was discussed, but we also have a DMA crossbar
 to map the dma-requests. Since both irq/dma crossbars should be handled,
 pinctrl was suggested as the appropriate place to handle this.

Regards,
 Sricharan
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] ARM: map_init_section flushes incorrect pmd

2013-05-28 Thread Sricharan R
On Tuesday 28 May 2013 06:35 PM, Will Deacon wrote:
> On Tue, May 28, 2013 at 11:48:20AM +0100, Po-Yu Chuang wrote:
>> This bug was introduced in commit e651eab0.
>> Some v4/v5 platforms failed to boot due to this.
>>
>> Signed-off-by: Po-Yu Chuang 
>> ---
>>  arch/arm/mm/mmu.c |4 +++-
>>  1 file changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
>> index e0d8565..19a43f8 100644
>> --- a/arch/arm/mm/mmu.c
>> +++ b/arch/arm/mm/mmu.c
>> @@ -620,6 +620,8 @@ static void __init map_init_section(pmd_t *pmd, unsigned 
>> long addr,
>>  unsigned long end, phys_addr_t phys,
>>  const struct mem_type *type)
>>  {
>> +pmd_t *p = pmd;
>> +
>>  #ifndef CONFIG_ARM_LPAE
>>  /*
>>   * In classic MMU format, puds and pmds are folded in to
>> @@ -638,7 +640,7 @@ static void __init map_init_section(pmd_t *pmd, unsigned 
>> long addr,
>>  phys += SECTION_SIZE;
>>  } while (pmd++, addr += SECTION_SIZE, addr != end);
>>  
>> -flush_pmd_entry(pmd);
>> +flush_pmd_entry(p);
> Wait, shouldn't this flush be *inside* the loop anyway? Otherwise we just
> flush the cacheline containing the first pmd. The flushing code could also
> flush to PoU instead of PoC for UP ARMv7, but that's an unrelated 
> optimisation.
   I think in LPAE this loop iterates once and non LPAE twice.
   So both the entries should be contained in same cache line right ?

Regards,
 Sricharan
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] ARM: map_init_section flushes incorrect pmd

2013-05-28 Thread Sricharan R
On Tuesday 28 May 2013 07:37 PM, Will Deacon wrote:
> On Tue, May 28, 2013 at 03:03:36PM +0100, Sricharan R wrote:
>> On Tuesday 28 May 2013 06:35 PM, Will Deacon wrote:
>>> On Tue, May 28, 2013 at 11:48:20AM +0100, Po-Yu Chuang wrote:
>>>> This bug was introduced in commit e651eab0.
>>>> Some v4/v5 platforms failed to boot due to this.
>>>>
>>>> Signed-off-by: Po-Yu Chuang 
>>>> ---
>>>>  arch/arm/mm/mmu.c |4 +++-
>>>>  1 file changed, 3 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
>>>> index e0d8565..19a43f8 100644
>>>> --- a/arch/arm/mm/mmu.c
>>>> +++ b/arch/arm/mm/mmu.c
>>>> @@ -620,6 +620,8 @@ static void __init map_init_section(pmd_t *pmd, 
>>>> unsigned long addr,
>>>>unsigned long end, phys_addr_t phys,
>>>>const struct mem_type *type)
>>>>  {
>>>> +  pmd_t *p = pmd;
>>>> +
>>>>  #ifndef CONFIG_ARM_LPAE
>>>>/*
>>>> * In classic MMU format, puds and pmds are folded in to
>>>> @@ -638,7 +640,7 @@ static void __init map_init_section(pmd_t *pmd, 
>>>> unsigned long addr,
>>>>phys += SECTION_SIZE;
>>>>} while (pmd++, addr += SECTION_SIZE, addr != end);
>>>>  
>>>> -  flush_pmd_entry(pmd);
>>>> +  flush_pmd_entry(p);
>>> Wait, shouldn't this flush be *inside* the loop anyway? Otherwise we just
>>> flush the cacheline containing the first pmd. The flushing code could also
>>> flush to PoU instead of PoC for UP ARMv7, but that's an unrelated 
>>> optimisation.
>>I think in LPAE this loop iterates once and non LPAE twice.
>>So both the entries should be contained in same cache line right ?
> Dunno, are there any guarantees about alignment of the starting pmd? Even
> so, the function takes the range as parameters, so I don't think we
> should tailor it to the caller. It may explain why this hasn't come up
> sooner though.
>
> Will
 
 This function is not exposed outside. And the ranges passed to this is going
to not more than 2 entries in any case. If we put the flush inside the loop,
then we will end up doing an extra flush for the same line. Regarding the
alignment, I think if the pgd base is aligned, then rest should be fine.
Will have to check this.

Regards,
 Sricharan


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 00/18] rpmsg: glink: Add glink smem based transport

2017-08-16 Thread Sricharan R
The glink protocol works uses a shared-memory(transport) for
communication between the local and remote processors. The
existing glink-rpm driver implements the basic features
of the protocol and uses msgram as the transport.

The same is extended to support smem based transport as well.
The first few patches consolidates the code, so that the
core protocol code is made common for both the types of
transport.

The next set of patches add the additional features of the
protocol required by clients using smem based transport,
particularly support for intents.

 * What is intents ?
Intents are nothing but pre-allocated buffers that
both the local and the remote clients allocate and
share the details (about the buffer size and an id)
before intending to receive data. The transmitter then
searches for an suitable 'intent-id' based on size from
the list that it was notified previously and sends the data
targeting that intent buffer, which is then copied by the
receiver in to the same intent-buffer. So this avoids memory
allocation stalls on copy based transports.

Bjorn Andersson (7):
  rpmsg: glink: Rename glink_rpm_xx functions to qcom_glink_xx
  rpmsg: glink: Associate indirections for pipe fifo accessor's
  rpmsg: glink: Split rpm_probe to reuse the common code
  rpmsg: glink: Move the common glink protocol implementation to
glink_native.c
  rpmsg: glink: Allow unaligned data access
  rpmsg: glink: Introduce glink smem based transport
  rpmsg: glink: Make RX FIFO peak accessor to take an offset

Sricharan R (11):
  rpmsg: glink: Fix default case while handling received commands
  rpmsg: glink: Add support for transport version negotiation
  rpmsg: glink: Fix idr_lock from mutex to spinlock
  rpmsg: glink: Add support for TX intents
  rpmsg: glink: Use the local intents when receiving data
  rpmsg: glink: Add rx done command
  rpmsg: glink: Add announce_create ops and preallocate intents
  rpmsg: glink: Receive and store the remote intent buffers
  rpmsg: glink: Use the intents passed by remote
  rpmsg: glink: Request for intents when unavailable
  rpmsg: glink: Handle remote rx done command

 drivers/rpmsg/Kconfig |   16 +-
 drivers/rpmsg/Makefile|2 +
 drivers/rpmsg/qcom_glink_native.c | 1593 +
 drivers/rpmsg/qcom_glink_native.h |   44 +
 drivers/rpmsg/qcom_glink_rpm.c| 1026 ++--
 drivers/rpmsg/qcom_glink_smem.c   |  309 +++
 include/linux/rpmsg/qcom_glink.h  |   27 +
 7 files changed, 2066 insertions(+), 951 deletions(-)
 create mode 100644 drivers/rpmsg/qcom_glink_native.c
 create mode 100644 drivers/rpmsg/qcom_glink_native.h
 create mode 100644 drivers/rpmsg/qcom_glink_smem.c
 create mode 100644 include/linux/rpmsg/qcom_glink.h

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 01/18] rpmsg: glink: Rename glink_rpm_xx functions to qcom_glink_xx

2017-08-16 Thread Sricharan R
From: Bjorn Andersson 

Renaming the glink_rpm_xx functions and structs to qcom_glink_xx
equivalents helps to reuse the core glink protocol while adding
support for smem based glink transport in the later patches.

Signed-off-by: Bjorn Andersson 
Signed-off-by: Sricharan R 
---
 drivers/rpmsg/qcom_glink_rpm.c | 248 +
 1 file changed, 128 insertions(+), 120 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c
index 3559a3e..56a0a66 100644
--- a/drivers/rpmsg/qcom_glink_rpm.c
+++ b/drivers/rpmsg/qcom_glink_rpm.c
@@ -101,7 +101,7 @@ struct glink_defer_cmd {
  * @lcids: idr of all channels with a known local channel id
  * @rcids: idr of all channels with a known remote channel id
  */
-struct glink_rpm {
+struct qcom_glink {
struct device *dev;
 
struct mbox_client mbox_client;
@@ -134,7 +134,7 @@ enum {
  * struct glink_channel - internal representation of a channel
  * @rpdev: rpdev reference, only used for primary endpoints
  * @ept:   rpmsg endpoint this channel is associated with
- * @glink: glink_rpm context handle
+ * @glink: qcom_glink context handle
  * @refcount:  refcount for the channel object
  * @recv_lock: guard for @ept.cb
  * @name:  unique channel name/identifier
@@ -150,7 +150,7 @@ struct glink_channel {
struct rpmsg_endpoint ept;
 
struct rpmsg_device *rpdev;
-   struct glink_rpm *glink;
+   struct qcom_glink *glink;
 
struct kref refcount;
 
@@ -184,8 +184,8 @@ struct glink_channel {
 
 #define GLINK_FEATURE_INTENTLESS   BIT(1)
 
-static struct glink_channel *glink_rpm_alloc_channel(struct glink_rpm *glink,
-const char *name)
+static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
+ const char *name)
 {
struct glink_channel *channel;
 
@@ -206,7 +206,7 @@ static struct glink_channel *glink_rpm_alloc_channel(struct 
glink_rpm *glink,
return channel;
 }
 
-static void glink_rpm_channel_release(struct kref *ref)
+static void qcom_glink_channel_release(struct kref *ref)
 {
struct glink_channel *channel = container_of(ref, struct glink_channel,
 refcount);
@@ -215,7 +215,7 @@ static void glink_rpm_channel_release(struct kref *ref)
kfree(channel);
 }
 
-static size_t glink_rpm_rx_avail(struct glink_rpm *glink)
+static size_t qcom_glink_rx_avail(struct qcom_glink *glink)
 {
struct glink_rpm_pipe *pipe = &glink->rx_pipe;
unsigned int head;
@@ -230,8 +230,8 @@ static size_t glink_rpm_rx_avail(struct glink_rpm *glink)
return head - tail;
 }
 
-static void glink_rpm_rx_peak(struct glink_rpm *glink,
- void *data, size_t count)
+static void qcom_glink_rx_peak(struct qcom_glink *glink,
+  void *data, size_t count)
 {
struct glink_rpm_pipe *pipe = &glink->rx_pipe;
unsigned int tail;
@@ -251,8 +251,8 @@ static void glink_rpm_rx_peak(struct glink_rpm *glink,
}
 }
 
-static void glink_rpm_rx_advance(struct glink_rpm *glink,
-size_t count)
+static void qcom_glink_rx_advance(struct qcom_glink *glink,
+ size_t count)
 {
struct glink_rpm_pipe *pipe = &glink->rx_pipe;
unsigned int tail;
@@ -266,7 +266,7 @@ static void glink_rpm_rx_advance(struct glink_rpm *glink,
writel(tail, pipe->tail);
 }
 
-static size_t glink_rpm_tx_avail(struct glink_rpm *glink)
+static size_t qcom_glink_tx_avail(struct qcom_glink *glink)
 {
struct glink_rpm_pipe *pipe = &glink->tx_pipe;
unsigned int head;
@@ -281,9 +281,9 @@ static size_t glink_rpm_tx_avail(struct glink_rpm *glink)
return tail - head;
 }
 
-static unsigned int glink_rpm_tx_write(struct glink_rpm *glink,
-  unsigned int head,
-  const void *data, size_t count)
+static unsigned int qcom_glink_tx_write(struct qcom_glink *glink,
+   unsigned int head,
+   const void *data, size_t count)
 {
struct glink_rpm_pipe *pipe = &glink->tx_pipe;
size_t len;
@@ -306,8 +306,8 @@ static unsigned int glink_rpm_tx_write(struct glink_rpm 
*glink,
return head;
 }
 
-static int glink_rpm_tx(struct glink_rpm *glink,
-   const void *hdr, size_t hlen,
+static int qcom_glink_tx(struct qcom_glink *glink,
+const void *hdr, size_t hlen,
const void *data, size_t dlen, bool wait)
 {
struct glink_rpm_pipe *pipe = &glink->tx_pipe;
@@ -326,7 +326,7 @@ static int glink_rpm_tx(struct glink_rpm *glink,
if (ret

[PATCH 00/18] rpmsg: glink: Add glink smem based transport

2017-08-16 Thread Sricharan R
The glink protocol works uses a shared-memory(transport) for
communication between the local and remote processors. The
existing glink-rpm driver implements the basic features
of the protocol and uses msgram as the transport.

The same is extended to support smem based transport as well.
The first few patches consolidates the code, so that the
core protocol code is made common for both the types of
transport.

The next set of patches add the additional features of the
protocol required by clients using smem based transport,
particularly support for intents.

 * What is intents ?
Intents are nothing but pre-allocated buffers that
both the local and the remote clients allocate and
share the details (about the buffer size and an id)
before intending to receive data. The transmitter then
searches for an suitable 'intent-id' based on size from
the list that it was notified previously and sends the data
targeting that intent buffer, which is then copied by the
receiver in to the same intent-buffer. So this avoids memory
allocation stalls on copy based transports.

Bjorn Andersson (7):
  rpmsg: glink: Rename glink_rpm_xx functions to qcom_glink_xx
  rpmsg: glink: Associate indirections for pipe fifo accessor's
  rpmsg: glink: Split rpm_probe to reuse the common code
  rpmsg: glink: Move the common glink protocol implementation to
glink_native.c
  rpmsg: glink: Allow unaligned data access
  rpmsg: glink: Introduce glink smem based transport
  rpmsg: glink: Make RX FIFO peak accessor to take an offset

Sricharan R (11):
  rpmsg: glink: Fix default case while handling received commands
  rpmsg: glink: Add support for transport version negotiation
  rpmsg: glink: Fix idr_lock from mutex to spinlock
  rpmsg: glink: Add support for TX intents
  rpmsg: glink: Use the local intents when receiving data
  rpmsg: glink: Add rx done command
  rpmsg: glink: Add announce_create ops and preallocate intents
  rpmsg: glink: Receive and store the remote intent buffers
  rpmsg: glink: Use the intents passed by remote
  rpmsg: glink: Request for intents when unavailable
  rpmsg: glink: Handle remote rx done command

 drivers/rpmsg/Kconfig |   16 +-
 drivers/rpmsg/Makefile|2 +
 drivers/rpmsg/qcom_glink_native.c | 1593 +
 drivers/rpmsg/qcom_glink_native.h |   44 +
 drivers/rpmsg/qcom_glink_rpm.c| 1026 ++--
 drivers/rpmsg/qcom_glink_smem.c   |  309 +++
 include/linux/rpmsg/qcom_glink.h  |   27 +
 7 files changed, 2066 insertions(+), 951 deletions(-)
 create mode 100644 drivers/rpmsg/qcom_glink_native.c
 create mode 100644 drivers/rpmsg/qcom_glink_native.h
 create mode 100644 drivers/rpmsg/qcom_glink_smem.c
 create mode 100644 include/linux/rpmsg/qcom_glink.h

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 04/18] rpmsg: glink: Move the common glink protocol implementation to glink_native.c

2017-08-16 Thread Sricharan R
From: Bjorn Andersson 

Move the common part of glink core protocol implementation to
glink_native.c that can be shared with the smem based glink
transport in the later patches.

Signed-off-by: Bjorn Andersson 
Signed-off-by: Sricharan R 
---
 drivers/rpmsg/Kconfig |6 +-
 drivers/rpmsg/Makefile|1 +
 drivers/rpmsg/qcom_glink_native.c | 1014 +
 drivers/rpmsg/qcom_glink_native.h |   38 ++
 drivers/rpmsg/qcom_glink_rpm.c|  995 +---
 5 files changed, 1061 insertions(+), 993 deletions(-)
 create mode 100644 drivers/rpmsg/qcom_glink_native.c
 create mode 100644 drivers/rpmsg/qcom_glink_native.h

diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index 2a5d2b4..ac33688 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -13,9 +13,13 @@ config RPMSG_CHAR
  in /dev. They make it possible for user-space programs to send and
  receive rpmsg packets.
 
+config RPMSG_QCOM_GLINK_NATIVE
+   tristate
+   select RPMSG
+
 config RPMSG_QCOM_GLINK_RPM
tristate "Qualcomm RPM Glink driver"
-   select RPMSG
+select RPMSG_QCOM_GLINK_NATIVE
depends on HAS_IOMEM
depends on MAILBOX
help
diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
index 28cc190..09a756c 100644
--- a/drivers/rpmsg/Makefile
+++ b/drivers/rpmsg/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_RPMSG)+= rpmsg_core.o
 obj-$(CONFIG_RPMSG_CHAR)   += rpmsg_char.o
 obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o
+obj-$(CONFIG_RPMSG_QCOM_GLINK_NATIVE) += qcom_glink_native.o
 obj-$(CONFIG_RPMSG_QCOM_SMD)   += qcom_smd.o
 obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o
diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
new file mode 100644
index 000..04afbb2
--- /dev/null
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -0,0 +1,1014 @@
+/*
+ * Copyright (c) 2016-2017, Linaro Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "rpmsg_internal.h"
+#include "qcom_glink_native.h"
+
+#define GLINK_NAME_SIZE32
+
+#define RPM_GLINK_CID_MIN  1
+#define RPM_GLINK_CID_MAX  65536
+
+struct glink_msg {
+   __le16 cmd;
+   __le16 param1;
+   __le32 param2;
+   u8 data[];
+} __packed;
+
+/**
+ * struct glink_defer_cmd - deferred incoming control message
+ * @node:  list node
+ * @msg:   message header
+ * data:   payload of the message
+ *
+ * Copy of a received control message, to be added to @rx_queue and processed
+ * by @rx_work of @glink_rpm.
+ */
+struct glink_defer_cmd {
+   struct list_head node;
+
+   struct glink_msg msg;
+   u8 data[];
+};
+
+/**
+ * struct glink_rpm - driver context, relates to one remote subsystem
+ * @dev:   reference to the associated struct device
+ * @doorbell:  "rpm_hlos" ipc doorbell
+ * @rx_pipe:   pipe object for receive FIFO
+ * @tx_pipe:   pipe object for transmit FIFO
+ * @irq:   IRQ for signaling incoming events
+ * @rx_work:   worker for handling received control messages
+ * @rx_lock:   protects the @rx_queue
+ * @rx_queue:  queue of received control messages to be processed in @rx_work
+ * @tx_lock:   synchronizes operations on the tx fifo
+ * @idr_lock:  synchronizes @lcids and @rcids modifications
+ * @lcids: idr of all channels with a known local channel id
+ * @rcids: idr of all channels with a known remote channel id
+ */
+struct qcom_glink {
+   struct device *dev;
+
+   struct mbox_client mbox_client;
+   struct mbox_chan *mbox_chan;
+
+   struct qcom_glink_pipe *rx_pipe;
+   struct qcom_glink_pipe *tx_pipe;
+
+   int irq;
+
+   struct work_struct rx_work;
+   spinlock_t rx_lock;
+   struct list_head rx_queue;
+
+   struct mutex tx_lock;
+
+   struct mutex idr_lock;
+   struct idr lcids;
+   struct idr rcids;
+};
+
+enum {
+   GLINK_STATE_CLOSED,
+   GLINK_STATE_OPENING,
+   GLINK_STATE_OPEN,
+   GLINK_STATE_CLOSING,
+};
+
+/**
+ * struct glink_channel - internal representation of a channel
+ * @rpdev: rpdev reference, only used for primary endpoints
+ * @ept:   rpmsg endpoint this channel is associated with
+ * @glink: qcom_glink context handle
+ * @refcount:  refcount for the channel object
+ *

[PATCH 07/18] rpmsg: glink: Fix default case while handling received commands

2017-08-16 Thread Sricharan R
Currently if we receive a command that we still do not
support, then its simply discarded. While doing so, the
RX FIFO pointer also needs to be incremented. Fixing this.

Signed-off-by: Sricharan R 
---
 drivers/rpmsg/qcom_glink_native.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 1aa92daf..dd22a23 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -540,6 +540,7 @@ static irqreturn_t qcom_glink_native_intr(int irq, void 
*data)
ret = 0;
break;
default:
+   qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
dev_err(glink->dev, "unhandled rx cmd: %d\n", cmd);
ret = -EINVAL;
break;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 13/18] rpmsg: glink: Add rx done command

2017-08-16 Thread Sricharan R
Send RX data receive ack to remote and also inform
that local intent buffer is used and freed. This
informs the remote to request for next set of
intent buffers before doing a send operation.

Signed-off-by: Sricharan R 
Signed-off-by: Bjorn Andersson 
---
 drivers/rpmsg/qcom_glink_native.c | 83 +++
 1 file changed, 83 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index b2a583a..b8db74a 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -76,6 +76,8 @@ struct glink_core_rx_intent {
bool reuse;
bool in_use;
u32 offset;
+
+   struct list_head node;
 };
 
 /**
@@ -137,6 +139,8 @@ enum {
  * @rcid:  channel id, in remote space
  * @intent_lock: lock for protection of @liids
  * @liids: idr of all local intents
+ * @intent_work: worker responsible for transmitting rx_done packets
+ * @done_intents: list of intents that needs to be announced rx_done
  * @buf:   receive buffer, for gathering fragments
  * @buf_offset:write offset in @buf
  * @buf_size:  size of current @buf
@@ -159,6 +163,8 @@ struct glink_channel {
 
spinlock_t intent_lock;
struct idr liids;
+   struct work_struct intent_work;
+   struct list_head done_intents;
 
struct glink_core_rx_intent *buf;
int buf_offset;
@@ -178,15 +184,19 @@ struct glink_channel {
 #define RPM_CMD_CLOSE  3
 #define RPM_CMD_OPEN_ACK   4
 #define RPM_CMD_INTENT 5
+#define RPM_CMD_RX_DONE6
 #define RPM_CMD_RX_INTENT_REQ  7
 #define RPM_CMD_RX_INTENT_REQ_ACK  8
 #define RPM_CMD_TX_DATA9
 #define RPM_CMD_CLOSE_ACK  11
 #define RPM_CMD_TX_DATA_CONT   12
 #define RPM_CMD_READ_NOTIF 13
+#define RPM_CMD_RX_DONE_W_REUSE14
 
 #define GLINK_FEATURE_INTENTLESS   BIT(1)
 
+static void qcom_glink_rx_done_work(struct work_struct *work);
+
 static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
  const char *name)
 {
@@ -198,12 +208,16 @@ static struct glink_channel 
*qcom_glink_alloc_channel(struct qcom_glink *glink,
 
/* Setup glink internal glink_channel data */
spin_lock_init(&channel->recv_lock);
+
channel->glink = glink;
channel->name = kstrdup(name, GFP_KERNEL);
 
init_completion(&channel->open_req);
init_completion(&channel->open_ack);
 
+   INIT_LIST_HEAD(&channel->done_intents);
+   INIT_WORK(&channel->intent_work, qcom_glink_rx_done_work);
+
idr_init(&channel->liids);
kref_init(&channel->refcount);
 
@@ -395,6 +409,70 @@ static void qcom_glink_send_close_ack(struct qcom_glink 
*glink,
qcom_glink_tx(glink, &req, sizeof(req), NULL, 0, true);
 }
 
+static void qcom_glink_rx_done_work(struct work_struct *work)
+{
+   struct glink_channel *channel = container_of(work, struct glink_channel,
+intent_work);
+   struct qcom_glink *glink = channel->glink;
+   struct glink_core_rx_intent *intent, *tmp;
+   struct {
+   u16 id;
+   u16 lcid;
+   u32 liid;
+   } __packed cmd;
+
+   unsigned int cid = channel->lcid;
+   unsigned int iid;
+   bool reuse;
+   unsigned long flags;
+
+   spin_lock_irqsave(&channel->intent_lock, flags);
+   list_for_each_entry_safe(intent, tmp, &channel->done_intents, node) {
+   list_del(&intent->node);
+   spin_unlock_irqrestore(&channel->intent_lock, flags);
+   iid = intent->id;
+   reuse = intent->reuse;
+
+   cmd.id = reuse ? RPM_CMD_RX_DONE_W_REUSE : RPM_CMD_RX_DONE;
+   cmd.lcid = cid;
+   cmd.liid = iid;
+
+   qcom_glink_tx(glink, &cmd, sizeof(cmd), NULL, 0, true);
+   if (!reuse) {
+   kfree(intent->data);
+   kfree(intent);
+   }
+   spin_lock_irqsave(&channel->intent_lock, flags);
+   }
+   spin_unlock_irqrestore(&channel->intent_lock, flags);
+}
+
+static void qcom_glink_rx_done(struct qcom_glink *glink,
+  struct glink_channel *channel,
+  struct glink_core_rx_intent *intent)
+{
+   /* We don't send RX_DONE to intentless systems */
+   if (glink->intentless) {
+   kfree(intent->data);
+   kfree(intent);
+   return;
+   }
+
+   /* Take it off the tree of receive intents */
+   if (!intent->reuse) {
+   spin_lock(&channel->intent_lock);
+   idr_remo

[PATCH 15/18] rpmsg: glink: Receive and store the remote intent buffers

2017-08-16 Thread Sricharan R
Just like we allocating and sending intent ids to remote,
remote side allocates and sends us the intents as well.
So save the intent ids and use it later while sending
data targeting the appropriate intents based on the size.

Signed-off-by: Sricharan R 
Signed-off-by: Bjorn Andersson 
---
 drivers/rpmsg/qcom_glink_native.c | 69 +++
 1 file changed, 69 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index c111046..738303e 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -139,6 +139,7 @@ enum {
  * @rcid:  channel id, in remote space
  * @intent_lock: lock for protection of @liids
  * @liids: idr of all local intents
+ * @riids: idr of all remote intents
  * @intent_work: worker responsible for transmitting rx_done packets
  * @done_intents: list of intents that needs to be announced rx_done
  * @buf:   receive buffer, for gathering fragments
@@ -163,6 +164,7 @@ struct glink_channel {
 
spinlock_t intent_lock;
struct idr liids;
+   struct idr riids;
struct work_struct intent_work;
struct list_head done_intents;
 
@@ -219,6 +221,7 @@ static struct glink_channel 
*qcom_glink_alloc_channel(struct qcom_glink *glink,
INIT_WORK(&channel->intent_work, qcom_glink_rx_done_work);
 
idr_init(&channel->liids);
+   idr_init(&channel->riids);
kref_init(&channel->refcount);
 
return channel;
@@ -230,6 +233,7 @@ static void qcom_glink_channel_release(struct kref *ref)
 refcount);
 
idr_destroy(&channel->liids);
+   idr_destroy(&channel->riids);
kfree(channel->name);
kfree(channel);
 }
@@ -799,6 +803,68 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, 
size_t avail)
return ret;
 }
 
+static void qcom_glink_handle_intent(struct qcom_glink *glink,
+unsigned int cid,
+unsigned int count,
+size_t avail)
+{
+   struct glink_core_rx_intent *intent;
+   struct glink_channel *channel;
+   struct intent_pair {
+   __le32 size;
+   __le32 iid;
+   };
+
+   struct {
+   struct glink_msg msg;
+   struct intent_pair intents[];
+   } __packed *msg;
+
+   const size_t msglen = sizeof(*msg) + sizeof(struct intent_pair) * count;
+   int ret;
+   int i;
+   unsigned long flags;
+
+   if (avail < msglen) {
+   dev_dbg(glink->dev, "Not enough data in fifo\n");
+   return;
+   }
+
+   spin_lock_irqsave(&glink->idr_lock, flags);
+   channel = idr_find(&glink->rcids, cid);
+   spin_unlock_irqrestore(&glink->idr_lock, flags);
+   if (!channel) {
+   dev_err(glink->dev, "intents for non-existing channel\n");
+   return;
+   }
+
+   msg = kmalloc(msglen, GFP_ATOMIC);
+   if (!msg)
+   return;
+
+   qcom_glink_rx_peak(glink, msg, 0, msglen);
+
+   for (i = 0; i < count; ++i) {
+   intent = kzalloc(sizeof(*intent), GFP_ATOMIC);
+   if (!intent)
+   break;
+
+   intent->id = le32_to_cpu(msg->intents[i].iid);
+   intent->size = le32_to_cpu(msg->intents[i].size);
+
+   spin_lock_irqsave(&channel->intent_lock, flags);
+   ret = idr_alloc(&channel->riids, intent,
+   intent->id, intent->id + 1, GFP_ATOMIC);
+   spin_unlock_irqrestore(&channel->intent_lock, flags);
+
+   if (ret < 0)
+   dev_err(glink->dev, "failed to store remote intent\n");
+   }
+
+   kfree(msg);
+   qcom_glink_rx_advance(glink, ALIGN(msglen, 8));
+}
+
 static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid)
 {
struct glink_channel *channel;
@@ -864,6 +930,9 @@ static irqreturn_t qcom_glink_native_intr(int irq, void 
*data)
 
ret = 0;
break;
+   case RPM_CMD_INTENT:
+   qcom_glink_handle_intent(glink, param1, param2, avail);
+   break;
default:
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
dev_err(glink->dev, "unhandled rx cmd: %d\n", cmd);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 18/18] rpmsg: glink: Handle remote rx done command

2017-08-16 Thread Sricharan R
Once the remote side sends a rx done ack, check
for the intent reuse information from it and
suitably discard or reuse the remote passed
intent buffers.

Signed-off-by: Sricharan R 
Signed-off-by: Bjorn Andersson 
---
 drivers/rpmsg/qcom_glink_native.c | 42 +++
 1 file changed, 42 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index cfacf4d..870bff6 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -647,6 +647,40 @@ static int qcom_glink_advertise_intent(struct qcom_glink 
*glink,
return intent;
 }
 
+static void qcom_glink_handle_rx_done(struct qcom_glink *glink,
+ u32 cid, uint32_t iid,
+ bool reuse)
+{
+   struct glink_core_rx_intent *intent;
+   struct glink_channel *channel;
+   unsigned long flags;
+
+   spin_lock_irqsave(&glink->idr_lock, flags);
+   channel = idr_find(&glink->rcids, cid);
+   spin_unlock_irqrestore(&glink->idr_lock, flags);
+   if (!channel) {
+   dev_err(glink->dev, "invalid channel id received\n");
+   return;
+   }
+
+   spin_lock_irqsave(&channel->intent_lock, flags);
+   intent = idr_find(&channel->riids, iid);
+
+   if (!intent) {
+   spin_unlock_irqrestore(&channel->intent_lock, flags);
+   dev_err(glink->dev, "invalid intent id received\n");
+   return;
+   }
+
+   intent->in_use = false;
+
+   if (!reuse) {
+   idr_remove(&channel->riids, intent->id);
+   kfree(intent);
+   }
+   spin_unlock_irqrestore(&channel->intent_lock, flags);
+}
+
 /**
  * glink_core_rx_cmd_remote_rx_intent_req() - Receive a request for rx_intent
  * from remote side
@@ -955,6 +989,14 @@ static irqreturn_t qcom_glink_native_intr(int irq, void 
*data)
case RPM_CMD_INTENT:
qcom_glink_handle_intent(glink, param1, param2, avail);
break;
+   case RPM_CMD_RX_DONE:
+   qcom_glink_handle_rx_done(glink, param1, param2, false);
+   qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
+   break;
+   case RPM_CMD_RX_DONE_W_REUSE:
+   qcom_glink_handle_rx_done(glink, param1, param2, true);
+   qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
+   break;
case RPM_CMD_RX_INTENT_REQ_ACK:
qcom_glink_handle_intent_req_ack(glink, param1, param2);
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 10/18] rpmsg: glink: Add support for TX intents

2017-08-16 Thread Sricharan R
Intents are nothing but pre-allocated buffers of
appropriate size that are allocated on the local
side and communicated to the remote side and the
remote stores the list of intent ids that it is
informed.

Later when remote side is intenting to send data,
it picks up a right intent (based on the size) and
sends the data buffer and the intent id. Local side
receives the data and copies it to the local intent
buffer.

The whole idea is to avoid stalls on the transport
for allocating memory, used for copy based transports.

When the remote request to allocate buffers using
CMD_RX_INTENT_REQ, we allocate buffers of requested
size, store the buffer id locally and also communicate
the intent id to the remote.

Signed-off-by: Sricharan R 
Signed-off-by: Bjorn Andersson 
---
 drivers/rpmsg/qcom_glink_native.c | 161 +-
 drivers/rpmsg/qcom_glink_native.h |   3 +-
 drivers/rpmsg/qcom_glink_rpm.c|   3 +-
 drivers/rpmsg/qcom_glink_smem.c   |   5 +-
 4 files changed, 167 insertions(+), 5 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index acf5558..cbc9f9e 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -60,6 +60,25 @@ struct glink_defer_cmd {
 };
 
 /**
+ * RX intent
+ *
+ * data: pointer to the data (may be NULL for zero-copy)
+ * id: remote or local intent ID
+ * size: size of the original intent (do not modify)
+ * reuse: To mark if the intent can be reused after first use
+ * in_use: To mark if intent is already in use for the channel
+ * offset: next write offset (initially 0)
+ */
+struct glink_core_rx_intent {
+   void *data;
+   u32 id;
+   size_t size;
+   bool reuse;
+   bool in_use;
+   u32 offset;
+};
+
+/**
  * struct glink_rpm - driver context, relates to one remote subsystem
  * @dev:   reference to the associated struct device
  * @doorbell:  "rpm_hlos" ipc doorbell
@@ -116,6 +135,8 @@ enum {
  * @name:  unique channel name/identifier
  * @lcid:  channel id, in local space
  * @rcid:  channel id, in remote space
+ * @intent_lock: lock for protection of @liids
+ * @liids: idr of all local intents
  * @buf:   receive buffer, for gathering fragments
  * @buf_offset:write offset in @buf
  * @buf_size:  size of current @buf
@@ -136,6 +157,9 @@ struct glink_channel {
unsigned int lcid;
unsigned int rcid;
 
+   spinlock_t intent_lock;
+   struct idr liids;
+
void *buf;
int buf_offset;
int buf_size;
@@ -153,6 +177,9 @@ struct glink_channel {
 #define RPM_CMD_OPEN   2
 #define RPM_CMD_CLOSE  3
 #define RPM_CMD_OPEN_ACK   4
+#define RPM_CMD_INTENT 5
+#define RPM_CMD_RX_INTENT_REQ  7
+#define RPM_CMD_RX_INTENT_REQ_ACK  8
 #define RPM_CMD_TX_DATA9
 #define RPM_CMD_CLOSE_ACK  11
 #define RPM_CMD_TX_DATA_CONT   12
@@ -177,6 +204,7 @@ static struct glink_channel 
*qcom_glink_alloc_channel(struct qcom_glink *glink,
init_completion(&channel->open_req);
init_completion(&channel->open_ack);
 
+   idr_init(&channel->liids);
kref_init(&channel->refcount);
 
return channel;
@@ -187,6 +215,7 @@ static void qcom_glink_channel_release(struct kref *ref)
struct glink_channel *channel = container_of(ref, struct glink_channel,
 refcount);
 
+   idr_destroy(&channel->liids);
kfree(channel->name);
kfree(channel);
 }
@@ -423,6 +452,130 @@ static void qcom_glink_receive_version_ack(struct 
qcom_glink *glink,
}
 }
 
+/**
+ * qcom_glink_send_intent_req_ack() - convert an rx intent request ack cmd to
+ wire format and transmit
+ * @glink: The transport to transmit on.
+ * @channel:   The glink channel
+ * @granted:   The request response to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int qcom_glink_send_intent_req_ack(struct qcom_glink *glink,
+ struct glink_channel *channel,
+ bool granted)
+{
+   struct glink_msg msg;
+
+   msg.cmd = cpu_to_le16(RPM_CMD_RX_INTENT_REQ_ACK);
+   msg.param1 = cpu_to_le16(channel->lcid);
+   msg.param2 = cpu_to_le32(granted);
+
+   qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true);
+
+   return 0;
+}
+
+/**
+ * tx_cmd_local_rx_intent() - convert an rx intent cmd to wire format and
+ *transmit
+ * @glink: The transport to transmit on.
+ * @channel:   The local channel
+ * @size:  The intent to pass on to remote.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int qcom_glink_advertise_intent(struct qcom_glink *glink,
+

[PATCH 11/18] rpmsg: glink: Use the local intents when receiving data

2017-08-16 Thread Sricharan R
So previously on request from remote side, we allocated local
intent buffers and passed the ids to the remote. Now when
we receive data buffers from remote directed to that intent
id, copy the data to the corresponding preallocated intent
buffer.

Signed-off-by: Sricharan R 
Signed-off-by: Bjorn Andersson 
---
 drivers/rpmsg/qcom_glink_native.c | 75 ++-
 1 file changed, 50 insertions(+), 25 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index cbc9f9e..d6aa589 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -160,7 +160,7 @@ struct glink_channel {
spinlock_t intent_lock;
struct idr liids;
 
-   void *buf;
+   struct glink_core_rx_intent *buf;
int buf_offset;
int buf_size;
 
@@ -607,6 +607,7 @@ static int qcom_glink_rx_defer(struct qcom_glink *glink, 
size_t extra)
 
 static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail)
 {
+   struct glink_core_rx_intent *intent;
struct glink_channel *channel;
struct {
struct glink_msg msg;
@@ -616,6 +617,8 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, 
size_t avail)
unsigned int chunk_size;
unsigned int left_size;
unsigned int rcid;
+   unsigned int liid;
+   int ret = 0;
unsigned long flags;
 
if (avail < sizeof(hdr)) {
@@ -643,56 +646,78 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, 
size_t avail)
dev_dbg(glink->dev, "Data on non-existing channel\n");
 
/* Drop the message */
-   qcom_glink_rx_advance(glink,
- ALIGN(sizeof(hdr) + chunk_size, 8));
-   return 0;
+   goto advance_rx;
}
 
-   /* Might have an ongoing, fragmented, message to append */
-   if (!channel->buf) {
-   channel->buf = kmalloc(chunk_size + left_size, GFP_ATOMIC);
-   if (!channel->buf)
-   return -ENOMEM;
+   if (glink->intentless) {
+   /* Might have an ongoing, fragmented, message to append */
+   if (!channel->buf) {
+   intent = kzalloc(sizeof(*intent), GFP_ATOMIC);
+   if (!intent)
+   return -ENOMEM;
+
+   intent->data = kmalloc(chunk_size + left_size,
+  GFP_ATOMIC);
+   if (!intent->data) {
+   kfree(intent);
+   return -ENOMEM;
+   }
+
+   intent->id = 0xbabababa;
+   intent->size = chunk_size + left_size;
+   intent->offset = 0;
+
+   channel->buf = intent;
+   } else {
+   intent = channel->buf;
+   }
+   } else {
+   liid = le32_to_cpu(hdr.msg.param2);
 
-   channel->buf_size = chunk_size + left_size;
-   channel->buf_offset = 0;
-   }
+   spin_lock_irqsave(&channel->intent_lock, flags);
+   intent = idr_find(&channel->liids, liid);
+   spin_unlock_irqrestore(&channel->intent_lock, flags);
 
-   qcom_glink_rx_advance(glink, sizeof(hdr));
+   if (!intent) {
+   dev_err(glink->dev,
+   "no intent found for channel %s intent %d",
+   channel->name, liid);
+   goto advance_rx;
+   }
+   }
 
-   if (channel->buf_size - channel->buf_offset < chunk_size) {
-   dev_err(glink->dev, "Insufficient space in input buffer\n");
+   if (intent->size - intent->offset < chunk_size) {
+   dev_err(glink->dev, "Insufficient space in intent\n");
 
/* The packet header lied, drop payload */
-   qcom_glink_rx_advance(glink, chunk_size);
-   return -ENOMEM;
+   goto advance_rx;
}
 
-   qcom_glink_rx_peak(glink, channel->buf + channel->buf_offset,
+   qcom_glink_rx_advance(glink, ALIGN(sizeof(hdr), 8));
+   qcom_glink_rx_peak(glink, intent->data + intent->offset,
   chunk_size);
-   channel->buf_offset += chunk_size;
+   intent->offset += chunk_size;
 
/* Handle message when no fragments remain to be received */
if (!left_size) {
spin_lock(&channel->recv_lock);
if (channel->ept.cb) {
channel->ept.cb(channel->ept.rpdev,
-   channel-&g

[PATCH 17/18] rpmsg: glink: Request for intents when unavailable

2017-08-16 Thread Sricharan R
While sending data, we search for suitable sized
intent to map and simply fail if a intent is not
found. Instead request for a intent of required
size and wait till one is alloted.

Signed-off-by: Sricharan R 
Signed-off-by: Bjorn Andersson 
---
 drivers/rpmsg/qcom_glink_native.c | 73 +--
 1 file changed, 71 insertions(+), 2 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 7b43adc..cfacf4d 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -174,6 +174,10 @@ struct glink_channel {
 
struct completion open_ack;
struct completion open_req;
+
+   struct mutex intent_req_lock;
+   bool intent_req_result;
+   struct completion intent_req_comp;
 };
 
 #define to_glink_channel(_ept) container_of(_ept, struct glink_channel, ept)
@@ -335,6 +339,24 @@ static void qcom_glink_send_open_ack(struct qcom_glink 
*glink,
qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true);
 }
 
+static void qcom_glink_handle_intent_req_ack(struct qcom_glink *glink,
+unsigned int cid, bool granted)
+{
+   struct glink_channel *channel;
+   unsigned long flags;
+
+   spin_lock_irqsave(&glink->idr_lock, flags);
+   channel = idr_find(&glink->rcids, cid);
+   spin_unlock_irqrestore(&glink->idr_lock, flags);
+   if (!channel) {
+   dev_err(glink->dev, "unable to find channel\n");
+   return;
+   }
+
+   channel->intent_req_result = granted;
+   complete(&channel->intent_req_comp);
+}
+
 /**
  * qcom_glink_send_open_req() - send a RPM_CMD_OPEN request to the remote
  * @glink:
@@ -933,6 +955,10 @@ static irqreturn_t qcom_glink_native_intr(int irq, void 
*data)
case RPM_CMD_INTENT:
qcom_glink_handle_intent(glink, param1, param2, avail);
break;
+   case RPM_CMD_RX_INTENT_REQ_ACK:
+   qcom_glink_handle_intent_req_ack(glink, param1, param2);
+   qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
+   break;
default:
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
dev_err(glink->dev, "unhandled rx cmd: %d\n", cmd);
@@ -1099,6 +1125,42 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint 
*ept)
qcom_glink_send_close_req(glink, channel);
 }
 
+static int qcom_glink_request_intent(struct qcom_glink *glink,
+struct glink_channel *channel,
+size_t size)
+{
+   struct {
+   u16 id;
+   u16 cid;
+   u32 size;
+   } __packed cmd;
+
+   int ret;
+
+   mutex_lock(&channel->intent_req_lock);
+
+   reinit_completion(&channel->intent_req_comp);
+
+   cmd.id = RPM_CMD_RX_INTENT_REQ;
+   cmd.cid = channel->lcid;
+   cmd.size = size;
+
+   ret = qcom_glink_tx(glink, &cmd, sizeof(cmd), NULL, 0, true);
+   if (ret)
+   return ret;
+
+   ret = wait_for_completion_timeout(&channel->intent_req_comp, 10 * HZ);
+   if (!ret) {
+   dev_err(glink->dev, "intent request timed out\n");
+   ret = -ETIMEDOUT;
+   } else {
+   ret = channel->intent_req_result ? 0 : -ECANCELED;
+   }
+
+   mutex_unlock(&channel->intent_req_lock);
+   return ret;
+}
+
 static int __qcom_glink_send(struct glink_channel *channel,
 void *data, int len, bool wait)
 {
@@ -1115,7 +1177,7 @@ static int __qcom_glink_send(struct glink_channel 
*channel,
unsigned long flags;
 
if (!glink->intentless) {
-   if (!intent) {
+   while (!intent) {
spin_lock_irqsave(&channel->intent_lock, flags);
idr_for_each_entry(&channel->riids, tmp, iid) {
if (tmp->size >= len && !tmp->in_use) {
@@ -1127,8 +1189,15 @@ static int __qcom_glink_send(struct glink_channel 
*channel,
spin_unlock_irqrestore(&channel->intent_lock, flags);
 
/* We found an available intent */
-   if (!intent)
+   if (intent)
+   break;
+
+   if (!wait)
return -EBUSY;
+
+   ret = qcom_glink_request_intent(glink, channel, len);
+   if (ret < 0)
+   return ret;
}
 
iid = intent->id;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 16/18] rpmsg: glink: Use the intents passed by remote

2017-08-16 Thread Sricharan R
While sending data, use the remote intent id buffer
of suitable size that was passed by remote previously.

Signed-off-by: Sricharan R 
Signed-off-by: Bjorn Andersson 
---
 drivers/rpmsg/qcom_glink_native.c | 35 +--
 1 file changed, 33 insertions(+), 2 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 738303e..7b43adc 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1103,19 +1103,50 @@ static int __qcom_glink_send(struct glink_channel 
*channel,
 void *data, int len, bool wait)
 {
struct qcom_glink *glink = channel->glink;
+   struct glink_core_rx_intent *intent = NULL;
+   struct glink_core_rx_intent *tmp;
+   int iid = 0;
struct {
struct glink_msg msg;
__le32 chunk_size;
__le32 left_size;
} __packed req;
+   int ret;
+   unsigned long flags;
+
+   if (!glink->intentless) {
+   if (!intent) {
+   spin_lock_irqsave(&channel->intent_lock, flags);
+   idr_for_each_entry(&channel->riids, tmp, iid) {
+   if (tmp->size >= len && !tmp->in_use) {
+   tmp->in_use = true;
+   intent = tmp;
+   break;
+   }
+   }
+   spin_unlock_irqrestore(&channel->intent_lock, flags);
+
+   /* We found an available intent */
+   if (!intent)
+   return -EBUSY;
+   }
+
+   iid = intent->id;
+   }
 
req.msg.cmd = cpu_to_le16(RPM_CMD_TX_DATA);
req.msg.param1 = cpu_to_le16(channel->lcid);
-   req.msg.param2 = cpu_to_le32(channel->rcid);
+   req.msg.param2 = cpu_to_le32(iid);
req.chunk_size = cpu_to_le32(len);
req.left_size = cpu_to_le32(0);
 
-   return qcom_glink_tx(glink, &req, sizeof(req), data, len, wait);
+   ret = qcom_glink_tx(glink, &req, sizeof(req), data, len, wait);
+
+   /* Mark intent available if we failed */
+   if (ret)
+   intent->in_use = false;
+
+   return ret;
 }
 
 static int qcom_glink_send(struct rpmsg_endpoint *ept, void *data, int len)
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 12/18] rpmsg: glink: Make RX FIFO peak accessor to take an offset

2017-08-16 Thread Sricharan R
From: Bjorn Andersson 

To fully read the received rx data from FIFO both the
command and data has to be read. Currently we read
command, data separately and process them. By adding
an offset parameter to RX FIFO peak accessor, command
and data can be read together, simplifying things.
So introduce this.

Signed-off-by: Bjorn Andersson 
Signed-off-by: Sricharan R 
---
 drivers/rpmsg/qcom_glink_native.c | 15 +++
 drivers/rpmsg/qcom_glink_native.h |  2 +-
 drivers/rpmsg/qcom_glink_rpm.c|  5 -
 drivers/rpmsg/qcom_glink_smem.c   |  5 -
 4 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index d6aa589..b2a583a 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -226,9 +226,9 @@ static size_t qcom_glink_rx_avail(struct qcom_glink *glink)
 }
 
 static void qcom_glink_rx_peak(struct qcom_glink *glink,
-  void *data, size_t count)
+  void *data, unsigned int offset, size_t count)
 {
-   glink->rx_pipe->peak(glink->rx_pipe, data, count);
+   glink->rx_pipe->peak(glink->rx_pipe, data, offset, count);
 }
 
 static void qcom_glink_rx_advance(struct qcom_glink *glink, size_t count)
@@ -593,7 +593,7 @@ static int qcom_glink_rx_defer(struct qcom_glink *glink, 
size_t extra)
 
INIT_LIST_HEAD(&dcmd->node);
 
-   qcom_glink_rx_peak(glink, &dcmd->msg, sizeof(dcmd->msg) + extra);
+   qcom_glink_rx_peak(glink, &dcmd->msg, 0, sizeof(dcmd->msg) + extra);
 
spin_lock(&glink->rx_lock);
list_add_tail(&dcmd->node, &glink->rx_queue);
@@ -626,7 +626,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, 
size_t avail)
return -EAGAIN;
}
 
-   qcom_glink_rx_peak(glink, &hdr, sizeof(hdr));
+   qcom_glink_rx_peak(glink, &hdr, 0, sizeof(hdr));
chunk_size = le32_to_cpu(hdr.chunk_size);
left_size = le32_to_cpu(hdr.left_size);
 
@@ -693,9 +693,8 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, 
size_t avail)
goto advance_rx;
}
 
-   qcom_glink_rx_advance(glink, ALIGN(sizeof(hdr), 8));
qcom_glink_rx_peak(glink, intent->data + intent->offset,
-  chunk_size);
+  sizeof(hdr), chunk_size);
intent->offset += chunk_size;
 
/* Handle message when no fragments remain to be received */
@@ -715,7 +714,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, 
size_t avail)
}
 
 advance_rx:
-   qcom_glink_rx_advance(glink, ALIGN(chunk_size, 8));
+   qcom_glink_rx_advance(glink, ALIGN(sizeof(hdr) + chunk_size, 8));
 
return ret;
 }
@@ -752,7 +751,7 @@ static irqreturn_t qcom_glink_native_intr(int irq, void 
*data)
if (avail < sizeof(msg))
break;
 
-   qcom_glink_rx_peak(glink, &msg, sizeof(msg));
+   qcom_glink_rx_peak(glink, &msg, 0, sizeof(msg));
 
cmd = le16_to_cpu(msg.cmd);
param1 = le16_to_cpu(msg.param1);
diff --git a/drivers/rpmsg/qcom_glink_native.h 
b/drivers/rpmsg/qcom_glink_native.h
index d7538c3..0e1e420 100644
--- a/drivers/rpmsg/qcom_glink_native.h
+++ b/drivers/rpmsg/qcom_glink_native.h
@@ -24,7 +24,7 @@ struct qcom_glink_pipe {
size_t (*avail)(struct qcom_glink_pipe *glink_pipe);
 
void (*peak)(struct qcom_glink_pipe *glink_pipe, void *data,
-size_t count);
+unsigned int offset, size_t count);
void (*advance)(struct qcom_glink_pipe *glink_pipe, size_t count);
 
void (*write)(struct qcom_glink_pipe *glink_pipe,
diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c
index 5a86e08..69b25d1 100644
--- a/drivers/rpmsg/qcom_glink_rpm.c
+++ b/drivers/rpmsg/qcom_glink_rpm.c
@@ -77,13 +77,16 @@ static size_t glink_rpm_rx_avail(struct qcom_glink_pipe 
*glink_pipe)
 }
 
 static void glink_rpm_rx_peak(struct qcom_glink_pipe *glink_pipe,
- void *data, size_t count)
+ void *data, unsigned int offset, size_t count)
 {
struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe);
unsigned int tail;
size_t len;
 
tail = readl(pipe->tail);
+   tail += offset;
+   if (tail >= pipe->native.length)
+   tail -= pipe->native.length;
 
len = min_t(size_t, count, pipe->native.length - tail);
if (len) {
diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c
index e792895..6d8f41f 100644
--- a/drivers/rpmsg/qcom_glink_smem.c
+++ b/drivers/rpmsg/qcom_glink_smem.c
@@ -87,13 +87,16 @@ static size_t glink_smem_rx_avail(struct qcom_glink_pipe 
*np)
 }
 
 static void glink_smem_rx_peak(struct qcom_glink_pipe *np,

[PATCH 09/18] rpmsg: glink: Fix idr_lock from mutex to spinlock

2017-08-16 Thread Sricharan R
The channel members lcids, rcids synchronised using
the idr_lock is accessed in both atomic/non-atomic
contexts. The readers are not currently synchronised.
That no correct, so add the readers as well under the
lock and use a spinlock.

Signed-off-by: Sricharan R 
Signed-off-by: Bjorn Andersson 
---
 drivers/rpmsg/qcom_glink_native.c | 58 +++
 1 file changed, 40 insertions(+), 18 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 4d24561..acf5558 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -91,7 +91,7 @@ struct qcom_glink {
 
struct mutex tx_lock;
 
-   struct mutex idr_lock;
+   spinlock_t idr_lock;
struct idr lcids;
struct idr rcids;
unsigned long features;
@@ -308,14 +308,15 @@ static int qcom_glink_send_open_req(struct qcom_glink 
*glink,
int name_len = strlen(channel->name) + 1;
int req_len = ALIGN(sizeof(req.msg) + name_len, 8);
int ret;
+   unsigned long flags;
 
kref_get(&channel->refcount);
 
-   mutex_lock(&glink->idr_lock);
+   spin_lock_irqsave(&glink->idr_lock, flags);
ret = idr_alloc_cyclic(&glink->lcids, channel,
   RPM_GLINK_CID_MIN, RPM_GLINK_CID_MAX,
   GFP_KERNEL);
-   mutex_unlock(&glink->idr_lock);
+   spin_unlock_irqrestore(&glink->idr_lock, flags);
if (ret < 0)
return ret;
 
@@ -333,10 +334,10 @@ static int qcom_glink_send_open_req(struct qcom_glink 
*glink,
return 0;
 
 remove_idr:
-   mutex_lock(&glink->idr_lock);
+   spin_lock_irqsave(&glink->idr_lock, flags);
idr_remove(&glink->lcids, channel->lcid);
channel->lcid = 0;
-   mutex_unlock(&glink->idr_lock);
+   spin_unlock_irqrestore(&glink->idr_lock, flags);
 
return ret;
 }
@@ -462,6 +463,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, 
size_t avail)
unsigned int chunk_size;
unsigned int left_size;
unsigned int rcid;
+   unsigned long flags;
 
if (avail < sizeof(hdr)) {
dev_dbg(glink->dev, "Not enough data in fifo\n");
@@ -481,7 +483,9 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, 
size_t avail)
return -EINVAL;
 
rcid = le16_to_cpu(hdr.msg.param1);
+   spin_lock_irqsave(&glink->idr_lock, flags);
channel = idr_find(&glink->rcids, rcid);
+   spin_unlock_irqrestore(&glink->idr_lock, flags);
if (!channel) {
dev_dbg(glink->dev, "Data on non-existing channel\n");
 
@@ -542,11 +546,13 @@ static int qcom_glink_rx_open_ack(struct qcom_glink 
*glink, unsigned int lcid)
 {
struct glink_channel *channel;
 
+   spin_lock(&glink->idr_lock);
channel = idr_find(&glink->lcids, lcid);
if (!channel) {
dev_err(glink->dev, "Invalid open ack packet\n");
return -EINVAL;
}
+   spin_unlock(&glink->idr_lock);
 
complete(&channel->open_ack);
 
@@ -620,6 +626,7 @@ static struct glink_channel *qcom_glink_create_local(struct 
qcom_glink *glink,
 {
struct glink_channel *channel;
int ret;
+   unsigned long flags;
 
channel = qcom_glink_alloc_channel(glink, name);
if (IS_ERR(channel))
@@ -643,9 +650,9 @@ static struct glink_channel *qcom_glink_create_local(struct 
qcom_glink *glink,
 
 err_timeout:
/* qcom_glink_send_open_req() did register the channel in lcids*/
-   mutex_lock(&glink->idr_lock);
+   spin_lock_irqsave(&glink->idr_lock, flags);
idr_remove(&glink->lcids, channel->lcid);
-   mutex_unlock(&glink->idr_lock);
+   spin_unlock_irqrestore(&glink->idr_lock, flags);
 
 release_channel:
/* Release qcom_glink_send_open_req() reference */
@@ -702,11 +709,14 @@ static struct rpmsg_endpoint 
*qcom_glink_create_ept(struct rpmsg_device *rpdev,
const char *name = chinfo.name;
int cid;
int ret;
+   unsigned long flags;
 
+   spin_lock_irqsave(&glink->idr_lock, flags);
idr_for_each_entry(&glink->rcids, channel, cid) {
if (!strcmp(channel->name, name))
break;
}
+   spin_unlock_irqrestore(&glink->idr_lock, flags);
 
if (!channel) {
channel = qcom_glink_create_local(glink, name);
@@ -828,11 +838,14 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, 
unsigned int rcid,
struct device_node *node;
int lcid;
int ret;
+   unsigned long flags;
 
+   spin_lock_irqsave(&glink->idr_lock, flags);
idr_for_each_entry(&gl

[PATCH 14/18] rpmsg: glink: Add announce_create ops and preallocate intents

2017-08-16 Thread Sricharan R
Preallocate local intent buffers and pass the intent ids
to the remote. This way there are some default intents
available  for the remote to start sending data without
having to wait by sending intent requests. Do this by
adding the rpmsg announce_create ops, which gets called
right after the rpmsg device gets probed.

Signed-off-by: Sricharan R 
Signed-off-by: Bjorn Andersson 
---
 drivers/rpmsg/qcom_glink_native.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index b8db74a..c111046 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -995,6 +995,25 @@ static struct rpmsg_endpoint *qcom_glink_create_ept(struct 
rpmsg_device *rpdev,
return ept;
 }
 
+static int qcom_glink_announce_create(struct rpmsg_device *rpdev)
+{
+   struct glink_channel *channel = to_glink_channel(rpdev->ept);
+   struct glink_core_rx_intent *intent;
+   struct qcom_glink *glink = channel->glink;
+   int num_intents = glink->intentless ? 0 : 5;
+
+   /* Channel is now open, advertise base set of intents */
+   while (num_intents--) {
+   intent = qcom_glink_alloc_intent(glink, channel, SZ_1K, true);
+   if (!intent)
+   break;
+
+   qcom_glink_advertise_intent(glink, channel, intent);
+   }
+
+   return 0;
+}
+
 static void qcom_glink_destroy_ept(struct rpmsg_endpoint *ept)
 {
struct glink_channel *channel = to_glink_channel(ept);
@@ -1070,6 +1089,7 @@ static struct device_node 
*qcom_glink_match_channel(struct device_node *node,
 
 static const struct rpmsg_device_ops glink_device_ops = {
.create_ept = qcom_glink_create_ept,
+   .announce_create = qcom_glink_announce_create,
 };
 
 static const struct rpmsg_endpoint_ops glink_endpoint_ops = {
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 05/18] rpmsg: glink: Allow unaligned data access

2017-08-16 Thread Sricharan R
From: Bjorn Andersson 

Glink protocol requires that each message is aligned
on a 8 byte offset. This is purely a restriction
from glink, so in order to support clients which
do not adher to this, allow data packets of any size,
but align the head index accordingly, effectively
removing the alignment restriction.

Signed-off-by: Bjorn Andersson 
Signed-off-by: Sricharan R 
---
 drivers/rpmsg/qcom_glink_native.c |  6 --
 drivers/rpmsg/qcom_glink_rpm.c| 22 +-
 2 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 04afbb2..1aa92daf 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -226,9 +226,6 @@ static int qcom_glink_tx(struct qcom_glink *glink,
if (tlen >= glink->tx_pipe->length)
return -EINVAL;
 
-   if (WARN(tlen % 8, "Unaligned TX request"))
-   return -EINVAL;
-
ret = mutex_lock_interruptible(&glink->tx_lock);
if (ret)
return ret;
@@ -694,9 +691,6 @@ static int __qcom_glink_send(struct glink_channel *channel,
__le32 left_size;
} __packed req;
 
-   if (WARN(len % 8, "RPM GLINK expects 8 byte aligned messages\n"))
-   return -EINVAL;
-
req.msg.cmd = cpu_to_le16(RPM_CMD_TX_DATA);
req.msg.param1 = cpu_to_le16(channel->lcid);
req.msg.param2 = cpu_to_le32(channel->rcid);
diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c
index 33daa32..cc73af0 100644
--- a/drivers/rpmsg/qcom_glink_rpm.c
+++ b/drivers/rpmsg/qcom_glink_rpm.c
@@ -156,11 +156,31 @@ static void glink_rpm_tx_write(struct qcom_glink_pipe 
*glink_pipe,
   const void *data, size_t dlen)
 {
struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe);
+   size_t tlen = hlen + dlen;
+   size_t aligned_dlen;
unsigned int head;
+   char padding[8] = {0};
+   size_t pad;
+
+   /* Header length comes from glink native and is always 4 byte aligned */
+   if (WARN(hlen % 4, "Glink Header length must be 4 bytes aligned\n"))
+   return;
+
+   /*
+* Move the unaligned tail of the message to the padding chunk, to
+* ensure word aligned accesses
+*/
+   aligned_dlen = ALIGN_DOWN(dlen, 4);
+   if (aligned_dlen != dlen)
+   memcpy(padding, data + aligned_dlen, dlen - aligned_dlen);
 
head = readl(pipe->head);
head = glink_rpm_tx_write_one(pipe, head, hdr, hlen);
-   head = glink_rpm_tx_write_one(pipe, head, data, dlen);
+   head = glink_rpm_tx_write_one(pipe, head, data, aligned_dlen);
+
+   pad = ALIGN(tlen, 8) - ALIGN_DOWN(tlen, 4);
+   if (pad)
+   head = glink_rpm_tx_write_one(pipe, head, padding, pad);
writel(head, pipe->head);
 }
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 06/18] rpmsg: glink: Introduce glink smem based transport

2017-08-16 Thread Sricharan R
From: Bjorn Andersson 

The glink protocol supports different types of
transports (shared memory). With the core protocol
remaining the same, the way the transport's memory is
probed and accessed is different. So add support for
glink's smem based transports.

Adding a new smem transport register function and the
fifo accessors for the same.

Signed-off-by: Bjorn Andersson 
Signed-off-by: Sricharan R 
---
 drivers/rpmsg/Kconfig|  10 ++
 drivers/rpmsg/Makefile   |   1 +
 drivers/rpmsg/qcom_glink_smem.c  | 304 +++
 include/linux/rpmsg/qcom_glink.h |  27 
 4 files changed, 342 insertions(+)
 create mode 100644 drivers/rpmsg/qcom_glink_smem.c
 create mode 100644 include/linux/rpmsg/qcom_glink.h

diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index ac33688..4bd9ba3 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -27,6 +27,16 @@ config RPMSG_QCOM_GLINK_RPM
  which serves as a channel for communication with the RPM in GLINK
  enabled systems.
 
+config RPMSG_QCOM_GLINK_SMEM
+   tristate "Qualcomm SMEM Glink driver"
+   select RPMSG_QCOM_GLINK_NATIVE
+   depends on HAS_IOMEM
+   depends on MAILBOX
+   help
+ Say y here to enable support for the GLINK SMEM communication driver,
+ which provides support for using the GLINK communication protocol
+ over SMEM.
+
 config RPMSG_QCOM_SMD
tristate "Qualcomm Shared Memory Driver (SMD)"
depends on QCOM_SMEM
diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
index 09a756c..c71f4ab 100644
--- a/drivers/rpmsg/Makefile
+++ b/drivers/rpmsg/Makefile
@@ -2,5 +2,6 @@ obj-$(CONFIG_RPMSG) += rpmsg_core.o
 obj-$(CONFIG_RPMSG_CHAR)   += rpmsg_char.o
 obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o
 obj-$(CONFIG_RPMSG_QCOM_GLINK_NATIVE) += qcom_glink_native.o
+obj-$(CONFIG_RPMSG_QCOM_GLINK_SMEM) += qcom_glink_smem.o
 obj-$(CONFIG_RPMSG_QCOM_SMD)   += qcom_smd.o
 obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o
diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c
new file mode 100644
index 000..defa10b
--- /dev/null
+++ b/drivers/rpmsg/qcom_glink_smem.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2016, Linaro Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "qcom_glink_native.h"
+
+#define FIFO_FULL_RESERVE 8
+#define FIFO_ALIGNMENT 8
+#define TX_BLOCKED_CMD_RESERVE 8 /* size of struct read_notif_request */
+
+#define SMEM_GLINK_NATIVE_XPRT_DESCRIPTOR  478
+#define SMEM_GLINK_NATIVE_XPRT_FIFO_0  479
+#define SMEM_GLINK_NATIVE_XPRT_FIFO_1  480
+
+struct glink_smem_pipe {
+   struct qcom_glink_pipe native;
+
+   __le32 *tail;
+   __le32 *head;
+
+   void *fifo;
+
+   int remote_pid;
+};
+
+#define to_smem_pipe(p) container_of(p, struct glink_smem_pipe, native)
+
+static size_t glink_smem_rx_avail(struct qcom_glink_pipe *np)
+{
+   struct glink_smem_pipe *pipe = to_smem_pipe(np);
+   size_t len;
+   void *fifo;
+   u32 head;
+   u32 tail;
+
+   if (!pipe->fifo) {
+   fifo = qcom_smem_get(pipe->remote_pid,
+SMEM_GLINK_NATIVE_XPRT_FIFO_1, &len);
+   if (IS_ERR(fifo)) {
+   pr_err("failed to acquire RX fifo handle: %ld\n",
+  PTR_ERR(fifo));
+   return 0;
+   }
+
+   pipe->fifo = fifo;
+   pipe->native.length = len;
+   }
+
+   head = le32_to_cpu(*pipe->head);
+   tail = le32_to_cpu(*pipe->tail);
+
+   if (head < tail)
+   return pipe->native.length - tail + head;
+   else
+   return head - tail;
+}
+
+static void glink_smem_rx_peak(struct qcom_glink_pipe *np,
+  void *data, size_t count)
+{
+   struct glink_smem_pipe *pipe = to_smem_pipe(np);
+   size_t len;
+   u32 tail;
+
+   tail = le32_to_cpu(*pipe->tail);
+
+   len = min_t(size_t, count, pipe->native.length - tail);
+   if (len) {
+   __ioread32_copy(data, pipe->fifo + tail,
+   len / sizeof(u32));
+  

[PATCH 08/18] rpmsg: glink: Add support for transport version negotiation

2017-08-16 Thread Sricharan R
G-link supports a version number and feature flags for each transport.
A combination of the version number and feature flags enable/disable:

 (*) G-Link software updates for each edge
 (*) Individual features for each edge

Endpoints negotiate both the version and the supported flags when
the transport is opened and they cannot be changed after negotiation has
been completed.

Each full implementation of G-Link must support a minimum of the current
version, the previous version, and the base negotiation version called v0.

Signed-off-by: Sricharan R 
Signed-off-by: Bjorn Andersson 
---
 drivers/rpmsg/qcom_glink_native.c | 75 ---
 drivers/rpmsg/qcom_glink_native.h |  5 +++
 drivers/rpmsg/qcom_glink_rpm.c|  4 ++-
 drivers/rpmsg/qcom_glink_smem.c   |  1 +
 4 files changed, 79 insertions(+), 6 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index dd22a23..4d24561 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -31,6 +31,7 @@
 #include "qcom_glink_native.h"
 
 #define GLINK_NAME_SIZE32
+#define GLINK_VERSION_11
 
 #define RPM_GLINK_CID_MIN  1
 #define RPM_GLINK_CID_MAX  65536
@@ -93,6 +94,9 @@ struct qcom_glink {
struct mutex idr_lock;
struct idr lcids;
struct idr rcids;
+   unsigned long features;
+
+   bool intentless;
 };
 
 enum {
@@ -255,8 +259,8 @@ static int qcom_glink_send_version(struct qcom_glink *glink)
struct glink_msg msg;
 
msg.cmd = cpu_to_le16(RPM_CMD_VERSION);
-   msg.param1 = cpu_to_le16(1);
-   msg.param2 = cpu_to_le32(GLINK_FEATURE_INTENTLESS);
+   msg.param1 = cpu_to_le16(GLINK_VERSION_1);
+   msg.param2 = cpu_to_le32(glink->features);
 
return qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true);
 }
@@ -266,8 +270,8 @@ static void qcom_glink_send_version_ack(struct qcom_glink 
*glink)
struct glink_msg msg;
 
msg.cmd = cpu_to_le16(RPM_CMD_VERSION_ACK);
-   msg.param1 = cpu_to_le16(1);
-   msg.param2 = cpu_to_le32(0);
+   msg.param1 = cpu_to_le16(GLINK_VERSION_1);
+   msg.param2 = cpu_to_le32(glink->features);
 
qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true);
 }
@@ -361,6 +365,63 @@ static void qcom_glink_send_close_ack(struct qcom_glink 
*glink,
qcom_glink_tx(glink, &req, sizeof(req), NULL, 0, true);
 }
 
+/**
+ * qcom_glink_receive_version() - receive version/features from remote system
+ *
+ * @glink: pointer to transport interface
+ * @r_version: remote version
+ * @r_features:remote features
+ *
+ * This function is called in response to a remote-initiated version/feature
+ * negotiation sequence.
+ */
+static void qcom_glink_receive_version(struct qcom_glink *glink,
+  u32 version,
+  u32 features)
+{
+   switch (version) {
+   case 0:
+   break;
+   case GLINK_VERSION_1:
+   glink->features &= features;
+   /* FALLTHROUGH */
+   default:
+   qcom_glink_send_version_ack(glink);
+   break;
+   }
+}
+
+/**
+ * qcom_glink_receive_version_ack() - receive negotiation ack from remote 
system
+ *
+ * @glink: pointer to transport interface
+ * @r_version: remote version response
+ * @r_features:remote features response
+ *
+ * This function is called in response to a local-initiated version/feature
+ * negotiation sequence and is the counter-offer from the remote side based
+ * upon the initial version and feature set requested.
+ */
+static void qcom_glink_receive_version_ack(struct qcom_glink *glink,
+  u32 version,
+  u32 features)
+{
+   switch (version) {
+   case 0:
+   /* Version negotiation failed */
+   break;
+   case GLINK_VERSION_1:
+   if (features == glink->features)
+   break;
+
+   glink->features &= features;
+   /* FALLTHROUGH */
+   default:
+   qcom_glink_send_version(glink);
+   break;
+   }
+}
+
 static int qcom_glink_rx_defer(struct qcom_glink *glink, size_t extra)
 {
struct glink_defer_cmd *dcmd;
@@ -908,9 +969,10 @@ static void qcom_glink_work(struct work_struct *work)
 
switch (cmd) {
case RPM_CMD_VERSION:
-   qcom_glink_send_version_ack(glink);
+   qcom_glink_receive_version(glink, param1, param2);
break;
case RPM_CMD_VERSION_ACK:
+   qcom_glink_receive_version_ack(glink, param1, param2);
break;
case RPM_CMD_OPEN:
qcom_glink_rx_open(glink, param1

[PATCH 02/18] rpmsg: glink: Associate indirections for pipe fifo accessor's

2017-08-16 Thread Sricharan R
From: Bjorn Andersson 

With the intention of reusing the glink core protocol commands
and code across both rpm and smem based transports, the only thing
different is way of accessing the shared-memory of the transport
(FIFO). So put the fifo accessor's of the transport's pipe (rx/tx)
behind indirections, so that the rest of the code can be shared.

For this, have a qcom_glink_pipe that can be used in the common code
containing the indirections and wrap it with glink_rpm_pipe that contains
the transport specific members.

Signed-off-by: Bjorn Andersson 
Signed-off-by: Sricharan R 
---
 drivers/rpmsg/qcom_glink_rpm.c | 144 ++---
 1 file changed, 106 insertions(+), 38 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c
index 56a0a66..870ce32 100644
--- a/drivers/rpmsg/qcom_glink_rpm.c
+++ b/drivers/rpmsg/qcom_glink_rpm.c
@@ -41,12 +41,28 @@
 #define RPM_GLINK_CID_MIN  1
 #define RPM_GLINK_CID_MAX  65536
 
+#define to_rpm_pipe(p) container_of(p, struct glink_rpm_pipe, native)
+
 struct rpm_toc_entry {
__le32 id;
__le32 offset;
__le32 size;
 } __packed;
 
+struct qcom_glink;
+
+struct qcom_glink_pipe {
+   size_t length;
+
+   size_t (*avail)(struct qcom_glink_pipe *glink_pipe);
+   void (*peak)(struct qcom_glink_pipe *glink_pipe, void *data,
+size_t count);
+   void (*advance)(struct qcom_glink_pipe *glink_pipe, size_t count);
+   void (*write)(struct qcom_glink_pipe *glink_pipe,
+ const void *hdr, size_t hlen,
+ const void *data, size_t dlen);
+};
+
 struct rpm_toc {
__le32 magic;
__le32 count;
@@ -62,12 +78,12 @@ struct glink_msg {
 } __packed;
 
 struct glink_rpm_pipe {
+   struct qcom_glink_pipe native;
+
void __iomem *tail;
void __iomem *head;
 
void __iomem *fifo;
-
-   size_t length;
 };
 
 /**
@@ -107,8 +123,8 @@ struct qcom_glink {
struct mbox_client mbox_client;
struct mbox_chan *mbox_chan;
 
-   struct glink_rpm_pipe rx_pipe;
-   struct glink_rpm_pipe tx_pipe;
+   struct qcom_glink_pipe *rx_pipe;
+   struct qcom_glink_pipe *tx_pipe;
 
int irq;
 
@@ -215,9 +231,9 @@ static void qcom_glink_channel_release(struct kref *ref)
kfree(channel);
 }
 
-static size_t qcom_glink_rx_avail(struct qcom_glink *glink)
+static size_t glink_rpm_rx_avail(struct qcom_glink_pipe *glink_pipe)
 {
-   struct glink_rpm_pipe *pipe = &glink->rx_pipe;
+   struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe);
unsigned int head;
unsigned int tail;
 
@@ -225,21 +241,26 @@ static size_t qcom_glink_rx_avail(struct qcom_glink 
*glink)
tail = readl(pipe->tail);
 
if (head < tail)
-   return pipe->length - tail + head;
+   return pipe->native.length - tail + head;
else
return head - tail;
 }
 
-static void qcom_glink_rx_peak(struct qcom_glink *glink,
-  void *data, size_t count)
+static size_t qcom_glink_rx_avail(struct qcom_glink *glink)
+{
+   return glink->rx_pipe->avail(glink->rx_pipe);
+}
+
+static void glink_rpm_rx_peak(struct qcom_glink_pipe *glink_pipe,
+ void *data, size_t count)
 {
-   struct glink_rpm_pipe *pipe = &glink->rx_pipe;
+   struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe);
unsigned int tail;
size_t len;
 
tail = readl(pipe->tail);
 
-   len = min_t(size_t, count, pipe->length - tail);
+   len = min_t(size_t, count, pipe->native.length - tail);
if (len) {
__ioread32_copy(data, pipe->fifo + tail,
len / sizeof(u32));
@@ -251,24 +272,35 @@ static void qcom_glink_rx_peak(struct qcom_glink *glink,
}
 }
 
-static void qcom_glink_rx_advance(struct qcom_glink *glink,
- size_t count)
+static void qcom_glink_rx_peak(struct qcom_glink *glink,
+  void *data, size_t count)
 {
-   struct glink_rpm_pipe *pipe = &glink->rx_pipe;
+   glink->rx_pipe->peak(glink->rx_pipe, data, count);
+}
+
+static void glink_rpm_rx_advance(struct qcom_glink_pipe *glink_pipe,
+size_t count)
+{
+   struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe);
unsigned int tail;
 
tail = readl(pipe->tail);
 
tail += count;
-   if (tail >= pipe->length)
-   tail -= pipe->length;
+   if (tail >= pipe->native.length)
+   tail -= pipe->native.length;
 
writel(tail, pipe->tail);
 }
 
-static size_t qcom_glink_tx_avail(struct qcom_glink *glink)
+static void qcom_glink_rx_advance(struct qcom_glink *glink, size_t count)
+{
+   glink->rx_pipe->advance(glink->rx_

[PATCH 03/18] rpmsg: glink: Split rpm_probe to reuse the common code

2017-08-16 Thread Sricharan R
From: Bjorn Andersson 

There is quite some code common in glink_rpm_probe that
can reused for glink-smem based transport as well. So
split the function and move the code to glink_native_probe
that can be used later when we add the support for
glink-smem based transport. Also reuse driver's remove as well.

Signed-off-by: Bjorn Andersson 
Signed-off-by: Sricharan R 
---
 drivers/rpmsg/qcom_glink_rpm.c | 85 --
 1 file changed, 49 insertions(+), 36 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c
index 870ce32..5f0fa0d 100644
--- a/drivers/rpmsg/qcom_glink_rpm.c
+++ b/drivers/rpmsg/qcom_glink_rpm.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1155,29 +1156,21 @@ static int glink_rpm_parse_toc(struct device *dev,
return -EINVAL;
 }
 
-static int glink_rpm_probe(struct platform_device *pdev)
+struct qcom_glink *qcom_glink_native_probe(struct device *dev,
+  struct qcom_glink_pipe *rx,
+  struct qcom_glink_pipe *tx)
 {
-   struct qcom_glink *glink;
-   struct glink_rpm_pipe *rx_pipe;
-   struct glink_rpm_pipe *tx_pipe;
-   struct device_node *np;
-   void __iomem *msg_ram;
-   size_t msg_ram_size;
-   struct device *dev = &pdev->dev;
-   struct resource r;
int irq;
int ret;
+   struct qcom_glink *glink;
 
glink = devm_kzalloc(dev, sizeof(*glink), GFP_KERNEL);
if (!glink)
-   return -ENOMEM;
+   return ERR_PTR(-ENOMEM);
 
glink->dev = dev;
-
-   rx_pipe = devm_kzalloc(&pdev->dev, sizeof(*rx_pipe), GFP_KERNEL);
-   tx_pipe = devm_kzalloc(&pdev->dev, sizeof(*tx_pipe), GFP_KERNEL);
-   if (!rx_pipe || !tx_pipe)
-   return -ENOMEM;
+   glink->tx_pipe = tx;
+   glink->rx_pipe = rx;
 
mutex_init(&glink->tx_lock);
spin_lock_init(&glink->rx_lock);
@@ -1188,14 +1181,48 @@ static int glink_rpm_probe(struct platform_device *pdev)
idr_init(&glink->lcids);
idr_init(&glink->rcids);
 
-   glink->mbox_client.dev = &pdev->dev;
+   glink->mbox_client.dev = dev;
glink->mbox_chan = mbox_request_channel(&glink->mbox_client, 0);
if (IS_ERR(glink->mbox_chan)) {
if (PTR_ERR(glink->mbox_chan) != -EPROBE_DEFER)
-   dev_err(&pdev->dev, "failed to acquire IPC channel\n");
-   return PTR_ERR(glink->mbox_chan);
+   dev_err(dev, "failed to acquire IPC channel\n");
+   return ERR_CAST(glink->mbox_chan);
+   }
+
+   irq = of_irq_get(dev->of_node, 0);
+   ret = devm_request_irq(dev, irq,
+  qcom_glink_intr,
+  IRQF_NO_SUSPEND | IRQF_SHARED,
+  "glink-native", glink);
+   if (ret) {
+   dev_err(dev, "failed to request IRQ\n");
+   return ERR_PTR(ret);
}
 
+   ret = qcom_glink_send_version(glink);
+   if (ret)
+   return ERR_PTR(ret);
+
+   return glink;
+}
+
+static int glink_rpm_probe(struct platform_device *pdev)
+{
+   struct qcom_glink *glink;
+   struct glink_rpm_pipe *rx_pipe;
+   struct glink_rpm_pipe *tx_pipe;
+   struct device_node *np;
+   void __iomem *msg_ram;
+   size_t msg_ram_size;
+   struct device *dev = &pdev->dev;
+   struct resource r;
+   int ret;
+
+   rx_pipe = devm_kzalloc(&pdev->dev, sizeof(*rx_pipe), GFP_KERNEL);
+   tx_pipe = devm_kzalloc(&pdev->dev, sizeof(*tx_pipe), GFP_KERNEL);
+   if (!rx_pipe || !tx_pipe)
+   return -ENOMEM;
+
np = of_parse_phandle(dev->of_node, "qcom,rpm-msg-ram", 0);
ret = of_address_to_resource(np, 0, &r);
of_node_put(np);
@@ -1219,27 +1246,13 @@ static int glink_rpm_probe(struct platform_device *pdev)
tx_pipe->native.avail = glink_rpm_tx_avail;
tx_pipe->native.write = glink_rpm_tx_write;
 
-   glink->tx_pipe = &tx_pipe->native;
-   glink->rx_pipe = &rx_pipe->native;
-
writel(0, tx_pipe->head);
writel(0, rx_pipe->tail);
 
-   irq = platform_get_irq(pdev, 0);
-   ret = devm_request_irq(dev, irq,
-  qcom_glink_intr,
-  IRQF_NO_SUSPEND | IRQF_SHARED,
-  "glink-rpm", glink);
-   if (ret) {
-   dev_err(dev, "Failed to request IRQ\n");
-   return ret;
-   }
-
-   glink->irq = irq;
-
-   ret = qcom_glink_send_version(glink);
-   if (ret)
-   return r

Re: [RESEND: PATCH v4 2/4] remoteproc: qcom: refactor mss fw image loading sequence

2017-05-25 Thread Sricharan R
Hi Bjorn,

On 5/26/2017 12:33 AM, Bjorn Andersson wrote:
> On Mon 22 May 06:26 PDT 2017, Dwivedi, Avaneesh Kumar (avani) wrote:
>> On 5/22/2017 4:07 PM, Sricharan R wrote:
>>> Hi,
>>>
>>> On 5/22/2017 3:03 PM, Dwivedi, Avaneesh Kumar (avani) wrote:
>>>>
>>>> On 5/20/2017 8:25 AM, Sricharan R wrote:
>>>>> Hi Bjorn/Avaneesh,
>>>>>
>>>>> On 5/16/2017 11:32 PM, Avaneesh Kumar Dwivedi wrote:
> [..]
>>>>>> -
>>>>>> -size = readl(qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG);
>>>>>> -if (!size) {
>>>>>> -boot_addr = relocate ? qproc->mpss_phys : min_addr;
>>>>>> -writel(boot_addr, qproc->rmb_base + RMB_PMI_CODE_START_REG);
>>>>>> -writel(RMB_CMD_LOAD_READY, qproc->rmb_base + 
>>>>>> RMB_MBA_COMMAND_REG);
>>>>>> -}
>>>>>> -
>>>>>>size += phdr->p_memsz;
>>>>>> -writel(size, qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG);
>>>>>>}
>>>>> So while moving this down, can we use qcom_mdt_load instead for
>>>>> the mpss image loading part above ?
>>>> qcom_mdt_load() can not be used to load segments for mpss, as MPSS
>>>> blobs are self authenticated.  while qcom_mdt_load() is used in
>>>> cases where authentication of loaded blobs is done by trustzone.
>>>> for that qcom_mdt_load() does extra steps to send pas_id to
>>>> trustzone and mem_setup() etc.
>>> Right, so my intention of asking this was if the code which does the
>>> calculation and loads the segments in qcom_mdt_load can somehow be
>>> abstracted out, so that future self authenticating rproc (even mpss
>>> in this case) can use them to load mdt ?
>> As i understand, you want to replace the piece of code which does
>> parse mdt and load individual firmware blobs in a separate routine.
>> So that it can be called by any one without again doing parsing and
>> loading for self authentication.?  Till now only MPSS does rely on
>> self authentication, all other subsystems use qcom_mdt_load().  I
>> think this is reason why the qcom_mdt_load() equivalent routine has
>> not been used.  Bjorn may further add in this.
> 
> I have not been able to come up with a clean way to provide a useful
> mdt-loader abstraction that works for the SCM PILs, the
> self-authenticated PILs and the non-PIL SCM users.
> 
> Further more with the upcoming ramdump support we will need to extract
> segment information from the mdt header, so we will have to revisit this
> topic.
> 
> 
> Regardless, I would prefer that we follow up with such refactoring after
> getting this series sorted out.
> 

ok, agree.  While trying to add Q6 support for ipq8074, which is again
a self-authenticating PIL with mdt, i can try this.

>>>
>>>>>> +/* Transfer ownership of modem region with modem fw */
>>>>>> +boot_addr = relocate ? qproc->mpss_phys : min_addr;
>>>>>> +writel(boot_addr, qproc->rmb_base + RMB_PMI_CODE_START_REG);
>>>>>> +writel(RMB_CMD_LOAD_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG);
>>>>>> +writel(size, qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG);
>>>>> For ipq8074 [1], wcnss core has an Q6V5 version of the ip for
>>>>> which the initialization/boot sequence is pretty much the same
>>>>> as that has been added for msm8996 in this series. So wanted to
>>>>> understand if its better to use this remoteproc itself by
>>>>> keeping the Q6 and mpss parts separately (or) add a new
>>>>> remoteproc ?
>>>> Bjorn can better answer this query, but i believe this remoteproc
>>>> can be extended to load mpss part by adding private initialization
>>>> for the IP.
>>> ya, the mpss part can be separated out, so that this can be a Q6 +
>>> MPSS (or) Q6 + WCNSS remoteproc. Was asking this to get the right
>>> way for adding the Q6 + WCNSS remoteproc, as the Q6 part is same
>>> what you have added for msm8996.
>> Again, i believe yes but leave Bjorn to make final comment.
> 
> It definitely sounds like there's room for reuse here, how much of the
> initialization and authentication sequences are common between the two?

The initialization sequence is exactly the same as what was done for
msm8996(Q6) one added in this series. So for reusing this driver for Q6,
the Q6 + MPSS has to be decoupled and driver has to look common for
Q6 + any, (ie) Q6 + mpss (or) Q6 + wcnss. Incase if that's not neat,
atleast the Q6 initialization sequence can be reused.

Regards,
 Sricharan

> 
> Regards,
> Bjorn
> 

-- 
"QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation


[PATCH v2] arm: dma-mapping: Reset the device's dma_ops

2017-05-26 Thread Sricharan R
arch_teardown_dma_ops() being the inverse of arch_setup_dma_ops()
,dma_ops should be cleared in the teardown path. Currently, only the
device's iommu mapping structures are cleared in arch_teardown_dma_ops,
but not the dma_ops. So on the next reprobe, dma_ops left in place is
stale from the first IOMMU setup, but iommu mappings has been disposed
of. This is a problem when the probe of the device is deferred and
recalled with the IOMMU probe deferral.

So for fixing this, slightly refactor by moving the code from
__arm_iommu_detach_device to arm_iommu_detach_device and cleanup
the former. This takes care of resetting the dma_ops in the teardown
path.

Signed-off-by: Sricharan R 
Fixes: 09515ef5ddad ("of/acpi: Configure dma operations at probe time for 
platform/amba/pci bus devices")
---
 arch/arm/mm/dma-mapping.c | 25 ++---
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index c742dfd..6e82e87 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -2311,7 +2311,14 @@ int arm_iommu_attach_device(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(arm_iommu_attach_device);
 
-static void __arm_iommu_detach_device(struct device *dev)
+/**
+ * arm_iommu_detach_device
+ * @dev: valid struct device pointer
+ *
+ * Detaches the provided device from a previously attached map.
+ * This voids the dma operations (dma_map_ops pointer)
+ */
+void arm_iommu_detach_device(struct device *dev)
 {
struct dma_iommu_mapping *mapping;
 
@@ -2324,22 +2331,10 @@ static void __arm_iommu_detach_device(struct device 
*dev)
iommu_detach_device(mapping->domain, dev);
kref_put(&mapping->kref, release_iommu_mapping);
to_dma_iommu_mapping(dev) = NULL;
+   set_dma_ops(dev, NULL);
 
pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev));
 }
-
-/**
- * arm_iommu_detach_device
- * @dev: valid struct device pointer
- *
- * Detaches the provided device from a previously attached map.
- * This voids the dma operations (dma_map_ops pointer)
- */
-void arm_iommu_detach_device(struct device *dev)
-{
-   __arm_iommu_detach_device(dev);
-   set_dma_ops(dev, NULL);
-}
 EXPORT_SYMBOL_GPL(arm_iommu_detach_device);
 
 static const struct dma_map_ops *arm_get_iommu_dma_map_ops(bool coherent)
@@ -2379,7 +2374,7 @@ static void arm_teardown_iommu_dma_ops(struct device *dev)
if (!mapping)
return;
 
-   __arm_iommu_detach_device(dev);
+   arm_iommu_detach_device(dev);
arm_iommu_release_mapping(mapping);
 }
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



Re: [PATCH v2] arm: dma-mapping: Reset the device's dma_ops

2017-05-26 Thread Sricharan R
Hi Laurent,

On 5/26/2017 7:44 PM, Laurent Pinchart wrote:
> Hi Sricharan,
> 
> Thank you for the patch.
> 
> On Friday 26 May 2017 16:13:37 Sricharan R wrote:
>> arch_teardown_dma_ops() being the inverse of arch_setup_dma_ops()
>> ,dma_ops should be cleared in the teardown path. Currently, only the
>> device's iommu mapping structures are cleared in arch_teardown_dma_ops,
>> but not the dma_ops. So on the next reprobe, dma_ops left in place is
>> stale from the first IOMMU setup, but iommu mappings has been disposed
>> of. This is a problem when the probe of the device is deferred and
>> recalled with the IOMMU probe deferral.
>>
>> So for fixing this, slightly refactor by moving the code from
>> __arm_iommu_detach_device to arm_iommu_detach_device and cleanup
>> the former. This takes care of resetting the dma_ops in the teardown
>> path.
>>
>> Signed-off-by: Sricharan R 
>> Fixes: 09515ef5ddad ("of/acpi: Configure dma operations at probe time for
>> platform/amba/pci bus devices")
> 
> Reviewed-by: Laurent Pinchart 
> 
> Could you please push this upstream along with "[PATCH] ARM: dma-mapping: 
> Don't tear third-party mappings" ?
> 
> (And feel free to s/tear/tear down/ in the subject of that patch, I've only 
> noticed now that I forgot one word)

ok, will change the above and post it with the other patches.

Regards,
 Sricharan

> 
>> ---
>>  arch/arm/mm/dma-mapping.c | 25 ++---
>>  1 file changed, 10 insertions(+), 15 deletions(-)
>>
>> diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
>> index c742dfd..6e82e87 100644
>> --- a/arch/arm/mm/dma-mapping.c
>> +++ b/arch/arm/mm/dma-mapping.c
>> @@ -2311,7 +2311,14 @@ int arm_iommu_attach_device(struct device *dev,
>>  }
>>  EXPORT_SYMBOL_GPL(arm_iommu_attach_device);
>>
>> -static void __arm_iommu_detach_device(struct device *dev)
>> +/**
>> + * arm_iommu_detach_device
>> + * @dev: valid struct device pointer
>> + *
>> + * Detaches the provided device from a previously attached map.
>> + * This voids the dma operations (dma_map_ops pointer)
>> + */
>> +void arm_iommu_detach_device(struct device *dev)
>>  {
>>  struct dma_iommu_mapping *mapping;
>>
>> @@ -2324,22 +2331,10 @@ static void __arm_iommu_detach_device(struct device
>> *dev) iommu_detach_device(mapping->domain, dev);
>>  kref_put(&mapping->kref, release_iommu_mapping);
>>  to_dma_iommu_mapping(dev) = NULL;
>> +set_dma_ops(dev, NULL);
>>
>>  pr_debug("Detached IOMMU controller from %s device.\n", 
> dev_name(dev));
>>  }
>> -
>> -/**
>> - * arm_iommu_detach_device
>> - * @dev: valid struct device pointer
>> - *
>> - * Detaches the provided device from a previously attached map.
>> - * This voids the dma operations (dma_map_ops pointer)
>> - */
>> -void arm_iommu_detach_device(struct device *dev)
>> -{
>> -__arm_iommu_detach_device(dev);
>> -set_dma_ops(dev, NULL);
>> -}
>>  EXPORT_SYMBOL_GPL(arm_iommu_detach_device);
>>
>>  static const struct dma_map_ops *arm_get_iommu_dma_map_ops(bool coherent)
>> @@ -2379,7 +2374,7 @@ static void arm_teardown_iommu_dma_ops(struct device
>> *dev) if (!mapping)
>>  return;
>>
>> -__arm_iommu_detach_device(dev);
>> +arm_iommu_detach_device(dev);
>>  arm_iommu_release_mapping(mapping);
>>  }
> 

-- 
"QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation


[PATCH v6 1/6] iommu: of: Fix check for returning EPROBE_DEFER

2017-05-27 Thread Sricharan R
Now with IOMMU probe deferral, we return -EPROBE_DEFER
for masters that are connected to an IOMMU which is not
probed yet, but going to get probed, so that we can attach
the correct dma_ops. So while trying to defer the probe of
the master, check if the of_iommu node that it is connected
to is marked in DT as 'status=disabled', then the IOMMU is never
is going to get probed. So simply return NULL and let the master
work without an IOMMU.

Fixes: 7b07cbefb68d ("iommu: of: Handle IOMMU lookup failure with deferred 
probing or error")
Reported-by: Geert Uytterhoeven 
Reviewed-by: Laurent Pinchart 
Tested-by: Will Deacon 
Tested-by: Magnus Damn 
Acked-by: Will Deacon 
Signed-off-by: Sricharan R 
---
 drivers/iommu/of_iommu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 9f44ee8..e6e9bec 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -118,6 +118,7 @@ static bool of_iommu_driver_present(struct device_node *np)
 
ops = iommu_ops_from_fwnode(fwnode);
if ((ops && !ops->of_xlate) ||
+   !of_device_is_available(iommu_spec->np) ||
(!ops && !of_iommu_driver_present(iommu_spec->np)))
return NULL;
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH v6 3/6] ACPI/IORT: Ignore all errors except EPROBE_DEFER

2017-05-27 Thread Sricharan R
While deferring the probe of IOMMU masters, xlate and
add_device callbacks called from iort_iommu_configure
can pass back error values like -ENODEV, which means
the IOMMU cannot be connected with that master for real
reasons. Before the IOMMU probe deferral, all such errors
were ignored. Now all those errors are propagated back,
killing the master's probe for such errors. Instead ignore
all the errors except EPROBE_DEFER, which is the only one
of concern and let the master work without IOMMU, thus
restoring the old behavior. Also make explicit that
acpi_dma_configure handles only -EPROBE_DEFER from
iort_iommu_configure.

Fixes: 5a1bb638d567 ("drivers: acpi: Handle IOMMU lookup failure with deferred 
probing or error")
Signed-off-by: Sricharan R 
---
 drivers/acpi/arm64/iort.c | 6 ++
 drivers/acpi/scan.c   | 4 ++--
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index c5fecf9..16e101f 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -782,6 +782,12 @@ const struct iommu_ops *iort_iommu_configure(struct device 
*dev)
if (err)
ops = ERR_PTR(err);
 
+   /* Ignore all other errors apart from EPROBE_DEFER */
+   if (IS_ERR(ops) && (PTR_ERR(ops) != -EPROBE_DEFER)) {
+   dev_dbg(dev, "Adding to IOMMU failed: %ld\n", PTR_ERR(ops));
+   ops = NULL;
+   }
+
return ops;
 }
 
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index e39ec7b..3a10d757 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1371,8 +1371,8 @@ int acpi_dma_configure(struct device *dev, enum 
dev_dma_attr attr)
iort_set_dma_mask(dev);
 
iommu = iort_iommu_configure(dev);
-   if (IS_ERR(iommu))
-   return PTR_ERR(iommu);
+   if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
+   return -EPROBE_DEFER;
 
size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
/*
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH v6 4/6] ARM: dma-mapping: Don't tear down third-party mappings

2017-05-27 Thread Sricharan R
From: Laurent Pinchart 

arch_setup_dma_ops() is used in device probe code paths to create an
IOMMU mapping and attach it to the device. The function assumes that the
device is attached to a device-specific IOMMU instance (or at least a
device-specific TLB in a shared IOMMU instance) and thus creates a
separate mapping for every device.

On several systems (Renesas R-Car Gen2 being one of them), that
assumption is not true, and IOMMU mappings must be shared between
multiple devices. In those cases the IOMMU driver knows better than the
generic ARM dma-mapping layer and attaches mapping to devices manually
with arm_iommu_attach_device(), which sets the DMA ops for the device.

The arch_setup_dma_ops() function takes this into account and bails out
immediately if the device already has DMA ops assigned. However, the
corresponding arch_teardown_dma_ops() function, called from driver
unbind code paths (including probe deferral), will tear the mapping down
regardless of who created it. When the device is reprobed
arch_setup_dma_ops() will be called again but won't perform any
operation as the DMA ops will still be set.

We need to reset the DMA ops in arch_teardown_dma_ops() to fix this.
However, we can't do so unconditionally, as then a new mapping would be
created by arch_setup_dma_ops() when the device is reprobed, regardless
of whether the device needs to share a mapping or not. We must thus keep
track of whether arch_setup_dma_ops() created the mapping, and only in
that case tear it down in arch_teardown_dma_ops().

Keep track of that information in the dev_archdata structure. As the
structure is embedded in all instances of struct device let's not grow
it, but turn the existing dma_coherent bool field into a bitfield that
can be used for other purposes.

Fixes: 09515ef5ddad ("of/acpi: Configure dma operations at probe time for 
platform/amba/pci bus devices")
Reviewed-by: Robin Murphy 
Signed-off-by: Laurent Pinchart 
---
 arch/arm/include/asm/device.h | 3 ++-
 arch/arm/mm/dma-mapping.c | 4 
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/device.h b/arch/arm/include/asm/device.h
index 36ec9c8..3234fe9 100644
--- a/arch/arm/include/asm/device.h
+++ b/arch/arm/include/asm/device.h
@@ -19,7 +19,8 @@ struct dev_archdata {
 #ifdef CONFIG_XEN
const struct dma_map_ops *dev_dma_ops;
 #endif
-   bool dma_coherent;
+   unsigned int dma_coherent:1;
+   unsigned int dma_ops_setup:1;
 };
 
 struct omap_device;
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index c742dfd..b48998f 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -2430,9 +2430,13 @@ void arch_setup_dma_ops(struct device *dev, u64 
dma_base, u64 size,
dev->dma_ops = xen_dma_ops;
}
 #endif
+   dev->archdata.dma_ops_setup = true;
 }
 
 void arch_teardown_dma_ops(struct device *dev)
 {
+   if (!dev->archdata.dma_ops_setup)
+   return;
+
arm_teardown_iommu_dma_ops(dev);
 }
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH v6 6/6] arm: dma-mapping: Reset the device's dma_ops

2017-05-27 Thread Sricharan R
arch_teardown_dma_ops() being the inverse of arch_setup_dma_ops()
,dma_ops should be cleared in the teardown path. Currently, only the
device's iommu mapping structures are cleared in arch_teardown_dma_ops,
but not the dma_ops. So on the next reprobe, dma_ops left in place is
stale from the first IOMMU setup, but iommu mappings has been disposed
of. This is a problem when the probe of the device is deferred and
recalled with the IOMMU probe deferral.

So for fixing this, slightly refactor by moving the code from
__arm_iommu_detach_device to arm_iommu_detach_device and cleanup
the former. This takes care of resetting the dma_ops in the teardown
path.

Fixes: 09515ef5ddad ("of/acpi: Configure dma operations at probe time for 
platform/amba/pci bus devices")
Reviewed-by: Laurent Pinchart 
Signed-off-by: Sricharan R 
---
 arch/arm/mm/dma-mapping.c | 25 ++---
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index b48998f..bd83c53 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -2311,7 +2311,14 @@ int arm_iommu_attach_device(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(arm_iommu_attach_device);
 
-static void __arm_iommu_detach_device(struct device *dev)
+/**
+ * arm_iommu_detach_device
+ * @dev: valid struct device pointer
+ *
+ * Detaches the provided device from a previously attached map.
+ * This voids the dma operations (dma_map_ops pointer)
+ */
+void arm_iommu_detach_device(struct device *dev)
 {
struct dma_iommu_mapping *mapping;
 
@@ -2324,22 +2331,10 @@ static void __arm_iommu_detach_device(struct device 
*dev)
iommu_detach_device(mapping->domain, dev);
kref_put(&mapping->kref, release_iommu_mapping);
to_dma_iommu_mapping(dev) = NULL;
+   set_dma_ops(dev, NULL);
 
pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev));
 }
-
-/**
- * arm_iommu_detach_device
- * @dev: valid struct device pointer
- *
- * Detaches the provided device from a previously attached map.
- * This voids the dma operations (dma_map_ops pointer)
- */
-void arm_iommu_detach_device(struct device *dev)
-{
-   __arm_iommu_detach_device(dev);
-   set_dma_ops(dev, NULL);
-}
 EXPORT_SYMBOL_GPL(arm_iommu_detach_device);
 
 static const struct dma_map_ops *arm_get_iommu_dma_map_ops(bool coherent)
@@ -2379,7 +2374,7 @@ static void arm_teardown_iommu_dma_ops(struct device *dev)
if (!mapping)
return;
 
-   __arm_iommu_detach_device(dev);
+   arm_iommu_detach_device(dev);
arm_iommu_release_mapping(mapping);
 }
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH v6 5/6] ACPI/IORT: Move the check to get iommu_ops from translated fwspec

2017-05-27 Thread Sricharan R
From: Lorenzo Pieralisi 

With IOMMU probe deferral, iort_iommu_configure can be called
multiple times for the same device. Hence we have a check
to see if the device's fwspec is already translated and return
the iommu_ops from that directly. But the check is wrongly
placed in iort_iommu_xlate, which breaks devices with multiple
sids. Move the check to iort_iommu_configure.

Fixes: 5a1bb638d567 ("drivers: acpi: Handle IOMMU lookup failure with deferred 
probing or error")
Tested-by: Nate Watterson 
Signed-off-by: Lorenzo Pieralisi 
---
 drivers/acpi/arm64/iort.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 16e101f..797b28d 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -666,14 +666,6 @@ static const struct iommu_ops *iort_iommu_xlate(struct 
device *dev,
int ret = -ENODEV;
struct fwnode_handle *iort_fwnode;
 
-   /*
-* If we already translated the fwspec there
-* is nothing left to do, return the iommu_ops.
-*/
-   ops = iort_fwspec_iommu_ops(dev->iommu_fwspec);
-   if (ops)
-   return ops;
-
if (node) {
iort_fwnode = iort_get_fwnode(node);
if (!iort_fwnode)
@@ -735,6 +727,14 @@ const struct iommu_ops *iort_iommu_configure(struct device 
*dev)
u32 streamid = 0;
int err;
 
+   /*
+* If we already translated the fwspec there
+* is nothing left to do, return the iommu_ops.
+*/
+   ops = iort_fwspec_iommu_ops(dev->iommu_fwspec);
+   if (ops)
+   return ops;
+
if (dev_is_pci(dev)) {
struct pci_bus *bus = to_pci_dev(dev)->bus;
u32 rid;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH v6 2/6] iommu: of: Ignore all errors except EPROBE_DEFER

2017-05-27 Thread Sricharan R
While deferring the probe of IOMMU masters, xlate and
add_device callbacks called from of_iommu_configure
can pass back error values like -ENODEV, which means
the IOMMU cannot be connected with that master for real
reasons. Before the IOMMU probe deferral, all such errors
were ignored. Now all those errors are propagated back,
killing the master's probe for such errors. Instead ignore
all the errors except EPROBE_DEFER, which is the only one
of concern and let the master work without IOMMU, thus
restoring the old behavior. Also make explicit that
of_dma_configure handles only -EPROBE_DEFER from
of_iommu_configure.

Fixes: 7b07cbefb68d ("iommu: of: Handle IOMMU lookup failure with deferred 
probing or error")
Reported-by: Geert Uytterhoeven 
Tested-by: Magnus Damn 
Signed-off-by: Sricharan R 
---
 drivers/iommu/of_iommu.c | 6 ++
 drivers/of/device.c  | 4 ++--
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index e6e9bec..19779b8 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -237,6 +237,12 @@ const struct iommu_ops *of_iommu_configure(struct device 
*dev,
ops = ERR_PTR(err);
}
 
+   /* Ignore all other errors apart from EPROBE_DEFER */
+   if (IS_ERR(ops) && (PTR_ERR(ops) != -EPROBE_DEFER)) {
+   dev_dbg(dev, "Adding to IOMMU failed: %ld\n", PTR_ERR(ops));
+   ops = NULL;
+   }
+
return ops;
 }
 
diff --git a/drivers/of/device.c b/drivers/of/device.c
index 9416d05..28c38c7 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -144,8 +144,8 @@ int of_dma_configure(struct device *dev, struct device_node 
*np)
coherent ? " " : " not ");
 
iommu = of_iommu_configure(dev, np);
-   if (IS_ERR(iommu))
-   return PTR_ERR(iommu);
+   if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
+   return -EPROBE_DEFER;
 
dev_dbg(dev, "device is%sbehind an iommu\n",
iommu ? " " : " not ");
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



Re: [PATCH v6 3/6] ACPI/IORT: Ignore all errors except EPROBE_DEFER

2017-05-28 Thread Sricharan R
Hi Rafael,

On 5/28/2017 12:48 AM, Rafael J. Wysocki wrote:
> On Saturday, May 27, 2017 07:17:42 PM Sricharan R wrote:
>> While deferring the probe of IOMMU masters, xlate and
>> add_device callbacks called from iort_iommu_configure
>> can pass back error values like -ENODEV, which means
>> the IOMMU cannot be connected with that master for real
>> reasons. Before the IOMMU probe deferral, all such errors
>> were ignored. Now all those errors are propagated back,
>> killing the master's probe for such errors. Instead ignore
>> all the errors except EPROBE_DEFER, which is the only one
>> of concern and let the master work without IOMMU, thus
>> restoring the old behavior. Also make explicit that
>> acpi_dma_configure handles only -EPROBE_DEFER from
>> iort_iommu_configure.
>>
>> Fixes: 5a1bb638d567 ("drivers: acpi: Handle IOMMU lookup failure with 
>> deferred probing or error")
>> Signed-off-by: Sricharan R 
>> ---
>>  drivers/acpi/arm64/iort.c | 6 ++
>>  drivers/acpi/scan.c   | 4 ++--
>>  2 files changed, 8 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
>> index c5fecf9..16e101f 100644
>> --- a/drivers/acpi/arm64/iort.c
>> +++ b/drivers/acpi/arm64/iort.c
>> @@ -782,6 +782,12 @@ const struct iommu_ops *iort_iommu_configure(struct 
>> device *dev)
>>  if (err)
>>  ops = ERR_PTR(err);
>>  
>> +/* Ignore all other errors apart from EPROBE_DEFER */
>> +if (IS_ERR(ops) && (PTR_ERR(ops) != -EPROBE_DEFER)) {
>> +dev_dbg(dev, "Adding to IOMMU failed: %ld\n", PTR_ERR(ops));
>> +ops = NULL;
>> +}
>> +
>>  return ops;
>>  }
>>  
>> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
>> index e39ec7b..3a10d757 100644
>> --- a/drivers/acpi/scan.c
>> +++ b/drivers/acpi/scan.c
>> @@ -1371,8 +1371,8 @@ int acpi_dma_configure(struct device *dev, enum 
>> dev_dma_attr attr)
>>  iort_set_dma_mask(dev);
>>  
>>  iommu = iort_iommu_configure(dev);
>> -if (IS_ERR(iommu))
>> -return PTR_ERR(iommu);
>> +if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
>> +return -EPROBE_DEFER;
>>  
>>  size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
>>  /*
>>
> 
> ACK for the scan.c change and I'm assuming this to go in via ARM64.
> 

Thanks for the ACK, should go through the IOMMU tree, since this fixes the 
IOMMU probe deferral
that got merged through it.

Regards,
 Sricharan

> Thanks,
> Rafael
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

-- 
"QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation


Re: [PATCH v4 5/6] remoteproc: qcom: Add support for q6v5-wcss pil

2017-11-14 Thread Sricharan R
Hi Rob,

On 11/11/2017 2:38 AM, Rob Herring wrote:
> On Thu, Nov 09, 2017 at 08:16:14PM +0530, Sricharan R wrote:
>> IPQ8074 has an integrated Hexagon dsp core q6v5 and a wireless lan
>> (Lithium) IP. An mdt type single image format is used for the
>> firmware. So the mdt_load function can be directly used to load
>> the firmware. Also add the relevant resets required for this core.
>>
>> Signed-off-by: Sricharan R 
>> ---
>>  .../devicetree/bindings/remoteproc/qcom,q6v5.txt   |  7 ++-
> 
> Please add acks when posting new versions.

oops.Really sorry, missed it. will update.

Regards,
 Sricharan

-- 
"QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation

---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus



[PATCH v5 0/6] Add support for Hexagon q6v5-wcss integrated core

2017-11-14 Thread Sricharan R
IPQ8074 has an integrated Hexagon dsp core Q6v5 and a wireless lan
(Lithium) IP. This series adds the remoteproc driver to reset, load
and boot Q6 firmware.

The first patch is to make the mdt_loader authenticate
the firmware only if required, so that the code can be reused for
self-authenticating firmware like the Q6v5 core in IPQ8074. The second
patch exports the elf header's get_boot_addr helper to reuse it.
The next couple of patches arranges the code in the original q6v5-mpss
rproc to add q6v5-wcss later. The last couple of patches add the relevant
bits for the q6v5-wcss core.

This is done on top of Avaneesh's msm8996 rproc support [1]

[1] https://lkml.org/lkml/2017/10/24/771

v5:
No change. Just updated tags in PATCH #5

V4:
Fixed Bjorn's comment in PATCH#1 and added his acked-by
Rebased on top of Avinash's latest rproc for msm8996 q6 support.

V3:
Rebased on top of latest remoteproc next

V2:
Last time introduced this a new rproc driver, but there is lot
of code that can be shared if it is added to the q6v5-mpss pil
    driver.

Sricharan R (6):
  remoteproc: qcom: mdt_loader: Make the firmware authentication
optional
  remoteproc: Export rproc_elf_get_boot_addr
  remoteproc: qcom: Push reset ops, fw ops, rproc ops in to of_match
data
  remoteproc: qcom: Split the head and tail of the q6v5-pil rproc start
function
  remoteproc: qcom: Add support for q6v5-wcss pil
  remoteproc: qcom: Add q6v5-wcss rproc ops

 .../devicetree/bindings/remoteproc/qcom,q6v5.txt   |   7 +-
 drivers/remoteproc/Kconfig |   1 +
 drivers/remoteproc/qcom_q6v5_pil.c | 469 +
 drivers/remoteproc/remoteproc_elf_loader.c |   2 +-
 drivers/remoteproc/remoteproc_internal.h   |   3 +
 drivers/soc/qcom/mdt_loader.c  |  82 +++-
 include/linux/soc/qcom/mdt_loader.h|   3 +
 7 files changed, 453 insertions(+), 114 deletions(-)

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH v5 1/6] remoteproc: qcom: mdt_loader: Make the firmware authentication optional

2017-11-14 Thread Sricharan R
qcom_mdt_load function loads the mdt type firmware and
initialises the secure memory as well. Make the initialisation only
when requested by the caller, so that the function can be used
by self-authenticating remoteproc as well.

Acked-by: Bjorn Andersson 
Signed-off-by: Sricharan R 
---
 drivers/soc/qcom/mdt_loader.c   | 82 ++---
 include/linux/soc/qcom/mdt_loader.h |  3 ++
 2 files changed, 62 insertions(+), 23 deletions(-)

diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index 08bd854..65ab833 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -74,21 +74,9 @@ ssize_t qcom_mdt_get_size(const struct firmware *fw)
 }
 EXPORT_SYMBOL_GPL(qcom_mdt_get_size);
 
-/**
- * qcom_mdt_load() - load the firmware which header is loaded as fw
- * @dev:   device handle to associate resources with
- * @fw:firmware object for the mdt file
- * @firmware:  name of the firmware, for construction of segment file names
- * @pas_id:PAS identifier
- * @mem_region:allocated memory region to load firmware into
- * @mem_phys:  physical address of allocated memory region
- * @mem_size:  size of the allocated memory region
- *
- * Returns 0 on success, negative errno otherwise.
- */
-int qcom_mdt_load(struct device *dev, const struct firmware *fw,
- const char *firmware, int pas_id, void *mem_region,
- phys_addr_t mem_phys, size_t mem_size)
+static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
+  const char *firmware, int pas_id, void *mem_region,
+  phys_addr_t mem_phys, size_t mem_size, bool pas_init)
 {
const struct elf32_phdr *phdrs;
const struct elf32_phdr *phdr;
@@ -119,10 +107,12 @@ int qcom_mdt_load(struct device *dev, const struct 
firmware *fw,
if (!fw_name)
return -ENOMEM;
 
-   ret = qcom_scm_pas_init_image(pas_id, fw->data, fw->size);
-   if (ret) {
-   dev_err(dev, "invalid firmware metadata\n");
-   goto out;
+   if (pas_init) {
+   ret = qcom_scm_pas_init_image(pas_id, fw->data, fw->size);
+   if (ret) {
+   dev_err(dev, "invalid firmware metadata\n");
+   goto out;
+   }
}
 
for (i = 0; i < ehdr->e_phnum; i++) {
@@ -142,10 +132,13 @@ int qcom_mdt_load(struct device *dev, const struct 
firmware *fw,
}
 
if (relocate) {
-   ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - 
min_addr);
-   if (ret) {
-   dev_err(dev, "unable to setup relocation\n");
-   goto out;
+   if (pas_init) {
+   ret = qcom_scm_pas_mem_setup(pas_id, mem_phys,
+max_addr - min_addr);
+   if (ret) {
+   dev_err(dev, "unable to setup relocation\n");
+   goto out;
+   }
}
 
/*
@@ -197,7 +190,50 @@ int qcom_mdt_load(struct device *dev, const struct 
firmware *fw,
 
return ret;
 }
+
+/**
+ * qcom_mdt_load() - sets up the secure memory for the firmware and
+loads the firmware
+ * @dev:   device handle to associate resources with
+ * @fw:firmware object for the mdt file
+ * @firmware:  name of the firmware, for construction of segment file names
+ * @pas_id:PAS identifier
+ * @mem_region:allocated memory region to load firmware into
+ * @mem_phys:  physical address of allocated memory region
+ * @mem_size:  size of the allocated memory region
+ *
+ * Returns 0 on success, negative errno otherwise.
+ */
+int qcom_mdt_load(struct device *dev, const struct firmware *fw,
+ const char *firmware, int pas_id, void *mem_region,
+ phys_addr_t mem_phys, size_t mem_size)
+{
+   return __qcom_mdt_load(dev, fw, firmware, pas_id, mem_region, mem_phys,
+  mem_size, true);
+}
 EXPORT_SYMBOL_GPL(qcom_mdt_load);
 
+/**
+ * qcom_mdt_load_no_init() - load the firmware which header is loaded as fw
+ * @dev:   device handle to associate resources with
+ * @fw:firmware object for the mdt file
+ * @firmware:  name of the firmware, for construction of segment file names
+ * @pas_id:PAS identifier
+ * @mem_region:allocated memory region to load firmware into
+ * @mem_phys:  physical address of allocated memory region
+ * @mem_size:  size of the allocated memory region
+ *
+ * Returns 0 on success, negative errno otherwise.
+ */
+int qcom_mdt_load_no_init(struct device *dev, const struct firmware *fw,
+ const char *firmware, int pas_id,
+ 

[PATCH v5 2/6] remoteproc: Export rproc_elf_get_boot_addr

2017-11-14 Thread Sricharan R
Export rproc_elf_get_boot_addr so that it can be
used by any remoteproc to get the bootaddr of the
elf type firmware images. This is used in the
subsequent patch by the q6v5 based remoteproc
while loading its elf based mdt type image.

Signed-off-by: Sricharan R 
---
 drivers/remoteproc/remoteproc_elf_loader.c | 2 +-
 drivers/remoteproc/remoteproc_internal.h   | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/remoteproc/remoteproc_elf_loader.c 
b/drivers/remoteproc/remoteproc_elf_loader.c
index c523983..f6d07d9 100644
--- a/drivers/remoteproc/remoteproc_elf_loader.c
+++ b/drivers/remoteproc/remoteproc_elf_loader.c
@@ -110,13 +110,13 @@
  * Note that the boot address is not a configurable property of all remote
  * processors. Some will always boot at a specific hard-coded address.
  */
-static
 u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
 {
struct elf32_hdr *ehdr  = (struct elf32_hdr *)fw->data;
 
return ehdr->e_entry;
 }
+EXPORT_SYMBOL(rproc_elf_get_boot_addr);
 
 /**
  * rproc_elf_load_segments() - load firmware segments to memory
diff --git a/drivers/remoteproc/remoteproc_internal.h 
b/drivers/remoteproc/remoteproc_internal.h
index c1077be..1bbbfea 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -124,4 +124,7 @@ struct resource_table *rproc_find_loaded_rsc_table(struct 
rproc *rproc,
 
 extern const struct rproc_fw_ops rproc_elf_fw_ops;
 
+/* from remoteproc_elf_loader.c */
+u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
+
 #endif /* REMOTEPROC_INTERNAL_H */
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH v5 6/6] remoteproc: qcom: Add q6v5-wcss rproc ops

2017-11-14 Thread Sricharan R
q6v5-wcss core's start function is mostly common
with the q6v5 of msm8996. So reuse that and add
the stop function.

Signed-off-by: Sricharan R 
---
 drivers/remoteproc/qcom_q6v5_pil.c | 212 +
 1 file changed, 212 insertions(+)

diff --git a/drivers/remoteproc/qcom_q6v5_pil.c 
b/drivers/remoteproc/qcom_q6v5_pil.c
index 3c401ff..1b560a6 100644
--- a/drivers/remoteproc/qcom_q6v5_pil.c
+++ b/drivers/remoteproc/qcom_q6v5_pil.c
@@ -104,6 +104,17 @@
 #define QDSP6SS_XO_CBCR0x0038
 #define QDSP6SS_ACC_OVERRIDE_VAL   0x20
 
+/* QDSP6v5-WCSS config/status registers */
+#define TCSR_GLOBAL_CFG0   0x0
+#define TCSR_GLOBAL_CFG1   0x4
+#define SSCAON_CONFIG  0x8
+#define SSCAON_STATUS  0xc
+#define QDSP6SS_BHS_STATUS 0x78
+#define QDSP6SS_RST_EVB0x10
+
+#define BHS_EN_REST_ACKBIT(0)
+#define SSCAON_ENABLE  BIT(13)
+
 struct reg_info {
struct regulator *reg;
int uV;
@@ -771,6 +782,61 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
return ret < 0 ? ret : 0;
 }
 
+static int q6v5_wcss_start(struct rproc *rproc)
+{
+   struct q6v5 *qproc = rproc->priv;
+   int ret = 0;
+
+   ret = q6v5_clk_enable(qproc->dev, qproc->active_clks,
+ qproc->active_clk_count);
+   if (ret) {
+   dev_err(qproc->dev, "failed to enable clocks\n");
+   return ret;
+   }
+
+   /* Release Q6 and WCSS reset */
+   ret = reset_control_deassert(qproc->wcss_reset);
+   if (ret)
+   dev_err(qproc->dev, "wcss_reset failed\n");
+
+   ret = reset_control_deassert(qproc->wcss_q6_reset);
+   if (ret)
+   dev_err(qproc->dev, "wcss_q6_reset failed\n");
+
+   /* Lithium configuration - clock gating and bus arbitration */
+   ret = regmap_update_bits(qproc->halt_map,
+qproc->halt_nc + TCSR_GLOBAL_CFG0,
+0x1F, 0x14);
+   if (ret)
+   return ret;
+
+   ret = regmap_update_bits(qproc->halt_map,
+qproc->halt_nc + TCSR_GLOBAL_CFG1,
+1, 0);
+   if (ret)
+   return ret;
+
+   /* Write bootaddr to EVB so that Q6WCSS will jump there after reset */
+   writel(rproc->bootaddr >> 4, qproc->reg_base + QDSP6SS_RST_EVB);
+
+   ret = q6v5_reset(qproc);
+   if (ret)
+   return ret;
+
+   q6v5_reset_rest(qproc);
+
+   ret = wait_for_completion_timeout(&qproc->start_done,
+ msecs_to_jiffies(5000));
+   if (ret == 0) {
+   dev_err(qproc->dev, "start timed out\n");
+   return -ETIMEDOUT;
+   }
+
+   qproc->running = true;
+
+   return 0;
+}
+
 static int q6v5_start(struct rproc *rproc)
 {
struct q6v5 *qproc = (struct q6v5 *)rproc->priv;
@@ -894,6 +960,146 @@ static int q6v5_start(struct rproc *rproc)
return ret;
 }
 
+static int q6v5_wcss_powerdown(struct q6v5 *qproc)
+{
+   unsigned int val = 0;
+   int ret;
+
+   /* 1 - Assert WCSS/Q6 HALTREQ */
+   q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem);
+
+   /* 2 - Enable WCSSAON_CONFIG */
+   val = readl(qproc->rmb_base + SSCAON_CONFIG);
+   val |= SSCAON_ENABLE;
+   writel(val, qproc->rmb_base + SSCAON_CONFIG);
+
+   /* 3 - Set SSCAON_CONFIG */
+   val |= BIT(15);
+   val &= ~BIT(16);
+   val &= ~BIT(17);
+   val &= ~BIT(18);
+   writel(val, qproc->rmb_base + SSCAON_CONFIG);
+
+   /* 4 - SSCAON_CONFIG 1 */
+   val |= BIT(1);
+   writel(val, qproc->rmb_base + SSCAON_CONFIG);
+
+   /* 5 - wait for SSCAON_STATUS */
+   ret = readl_poll_timeout(qproc->rmb_base + SSCAON_STATUS,
+val, (val & 0x) == 0x400, 1000,
+HALT_CHECK_MAX_LOOPS);
+   if (ret) {
+   dev_err(qproc->dev,
+   "can't get SSCAON_STATUS rc:%d)\n", ret);
+   }
+
+   /* 6 - De-assert WCSS_AON reset */
+   reset_control_assert(qproc->wcss_aon_reset);
+
+   /* 7 - Disable WCSSAON_CONFIG 13 */
+   val = readl(qproc->rmb_base + SSCAON_CONFIG);
+   val &= ~SSCAON_ENABLE;
+   writel(val, qproc->rmb_base + SSCAON_CONFIG);
+
+   /* 8 - De-assert WCSS/Q6 HALTREQ */
+   reset_control_assert(qproc->wcss_reset);
+
+   return ret;
+}
+
+static int q6v5_q6_powerdown(struct q6v5 *qproc)
+{
+   int i = 0, ret;
+   unsigned int val = 0;
+
+   /* 1 - Halt Q6 bus interface */
+   q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_q6);
+
+   /* 2 - Disable Q6 Core clock */
+ 

[PATCH v5 4/6] remoteproc: qcom: Split the head and tail of the q6v5-pil rproc start function

2017-11-14 Thread Sricharan R
Most of the q6v5-pil start function is same for the q6v5-wcss rproc
that will be added later. So split and move out the common pieces
so that the same code can be reused.

Signed-off-by: Sricharan R 
---
 drivers/remoteproc/qcom_q6v5_pil.c | 166 -
 1 file changed, 91 insertions(+), 75 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5_pil.c 
b/drivers/remoteproc/qcom_q6v5_pil.c
index 769c6af..75ff02d 100644
--- a/drivers/remoteproc/qcom_q6v5_pil.c
+++ b/drivers/remoteproc/qcom_q6v5_pil.c
@@ -405,75 +405,107 @@ static int q6v5_rmb_mba_wait(struct q6v5 *qproc, u32 
status, int ms)
return val;
 }
 
-static int q6v5proc_reset(struct q6v5 *qproc)
+static int q6v5_reset(struct q6v5 *qproc)
 {
-   u32 val;
-   int ret;
-   int i;
+   u32 ret;
+   int val, i;
 
+   /* Assert resets, stop core */
+   val = readl(qproc->reg_base + QDSP6SS_RESET_REG);
+   val |= Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE;
+   writel(val, qproc->reg_base + QDSP6SS_RESET_REG);
 
-   if (qproc->version == MSS_MSM8996) {
-   /* Override the ACC value if required */
-   writel(QDSP6SS_ACC_OVERRIDE_VAL,
-  qproc->reg_base + QDSP6SS_STRAP_ACC);
+   /* BHS require xo cbcr to be enabled */
+   val = readl(qproc->reg_base + QDSP6SS_XO_CBCR);
+   val |= 0x1;
+   writel(val, qproc->reg_base + QDSP6SS_XO_CBCR);
 
-   /* Assert resets, stop core */
-   val = readl(qproc->reg_base + QDSP6SS_RESET_REG);
-   val |= Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE;
-   writel(val, qproc->reg_base + QDSP6SS_RESET_REG);
+   /* Read CLKOFF bit to go low indicating CLK is enabled */
+   ret = readl_poll_timeout(qproc->reg_base + QDSP6SS_XO_CBCR,
+val, !(val & BIT(31)), 1,
+HALT_CHECK_MAX_LOOPS);
+   if (ret) {
+   dev_err(qproc->dev,
+   "xo cbcr enabling timed out (rc:%d)\n", ret);
+   return ret;
+   }
+   /* Enable power block headswitch and wait for it to stabilize */
+   val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);
+   val |= QDSP6v56_BHS_ON;
+   writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
+   val |= readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);
+   udelay(1);
 
-   /* BHS require xo cbcr to be enabled */
-   val = readl(qproc->reg_base + QDSP6SS_XO_CBCR);
-   val |= 0x1;
-   writel(val, qproc->reg_base + QDSP6SS_XO_CBCR);
+   /* Put LDO in bypass mode */
+   val |= QDSP6v56_LDO_BYP;
+   writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 
-   /* Read CLKOFF bit to go low indicating CLK is enabled */
-   ret = readl_poll_timeout(qproc->reg_base + QDSP6SS_XO_CBCR,
-val, !(val & BIT(31)), 1,
-HALT_CHECK_MAX_LOOPS);
-   if (ret) {
-   dev_err(qproc->dev,
-   "xo cbcr enabling timed out (rc:%d)\n", ret);
-   return ret;
-   }
-   /* Enable power block headswitch and wait for it to stabilize */
-   val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);
-   val |= QDSP6v56_BHS_ON;
-   writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
-   val |= readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);
+   /* Deassert QDSP6 compiler memory clamp */
+   val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);
+   val &= ~QDSP6v56_CLAMP_QMC_MEM;
+   writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
+
+   /* Deassert memory peripheral sleep and L2 memory standby */
+   val |= Q6SS_L2DATA_STBY_N | Q6SS_SLP_RET_N;
+   writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
+
+   /* Turn on L1, L2, ETB and JU memories 1 at a time */
+   val = readl(qproc->reg_base + QDSP6SS_MEM_PWR_CTL);
+   for (i = 19; i >= 0; i--) {
+   val |= BIT(i);
+   writel(val, qproc->reg_base + QDSP6SS_MEM_PWR_CTL);
+   /*
+* Read back value to ensure the write is done then
+* wait for 1us for both memory peripheral and data
+* array to turn on.
+*/
+   val |= readl(qproc->reg_base + QDSP6SS_MEM_PWR_CTL);
udelay(1);
+   }
+   /* Remove word line clamp */
+   val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);
+   val &= ~QDSP6v56_CLAMP_WL;
+   writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 
-   /* Put LDO in bypass mode */
-   val |= QDSP6v56_LDO_BYP;
-   writ

[PATCH v5 5/6] remoteproc: qcom: Add support for q6v5-wcss pil

2017-11-14 Thread Sricharan R
IPQ8074 has an integrated Hexagon dsp core q6v5 and a wireless lan
(Lithium) IP. An mdt type single image format is used for the
firmware. So the mdt_load function can be directly used to load
the firmware. Also add the relevant resets required for this core.

Acked-by: Rob Herring 
Signed-off-by: Sricharan R 
---
 .../devicetree/bindings/remoteproc/qcom,q6v5.txt   |  7 ++-
 drivers/remoteproc/Kconfig |  1 +
 drivers/remoteproc/qcom_q6v5_pil.c | 53 +-
 3 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt 
b/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt
index 00d3d58..d52d05e 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt
@@ -11,6 +11,7 @@ on the Qualcomm Hexagon core.
"qcom,msm8916-mss-pil",
"qcom,msm8974-mss-pil"
"qcom,msm8996-mss-pil"
+   "qcom,ipq8074-wcss-pil"
 
 - reg:
Usage: required
@@ -49,11 +50,15 @@ on the Qualcomm Hexagon core.
Usage: required
Value type: 
Definition: reference to the reset-controller for the modem sub-system
+   reference to the list of 3 reset-controllers for the
+   wcss sub-system
 
 - reset-names:
Usage: required
Value type: 
-   Definition: must be "mss_restart"
+   Definition: must be "mss_restart" for the modem sub-system
+   Definition: must be "wcss_aon_reset", "wcss_reset", "wcss_q6_reset"
+   for the wcss syb-system
 
 - cx-supply:
 - mss-supply:
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index bf04479..e7e9979 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -113,6 +113,7 @@ config QCOM_Q6V5_PIL
select MFD_SYSCON
select QCOM_RPROC_COMMON
select QCOM_SCM
+   select QCOM_MDT_LOADER
help
  Say y here to support the Qualcomm Peripherial Image Loader for the
  Hexagon V5 based remote processors.
diff --git a/drivers/remoteproc/qcom_q6v5_pil.c 
b/drivers/remoteproc/qcom_q6v5_pil.c
index 75ff02d..3c401ff 100644
--- a/drivers/remoteproc/qcom_q6v5_pil.c
+++ b/drivers/remoteproc/qcom_q6v5_pil.c
@@ -129,6 +129,9 @@ struct q6v5 {
u32 halt_nc;
 
struct reset_control *mss_restart;
+   struct reset_control *wcss_aon_reset;
+   struct reset_control *wcss_reset;
+   struct reset_control *wcss_q6_reset;
 
struct qcom_smem_state *state;
unsigned stop_bit;
@@ -181,6 +184,7 @@ enum {
MSS_MSM8916,
MSS_MSM8974,
MSS_MSM8996,
+   WCSS_IPQ8074,
 };
 
 static int q6v5_regulator_init(struct device *dev, struct reg_info *regs,
@@ -354,6 +358,21 @@ static int q6v5_load(struct rproc *rproc, const struct 
firmware *fw)
return 0;
 }
 
+static int q6v5_wcss_load(struct rproc *rproc, const struct firmware *fw)
+{
+   struct q6v5 *qproc = rproc->priv;
+
+   return qcom_mdt_load_no_init(qproc->dev, fw, rproc->firmware,
+0, qproc->mba_region, qproc->mba_phys,
+qproc->mba_size);
+}
+
+static const struct rproc_fw_ops q6v5_wcss_fw_ops = {
+   .find_rsc_table = q6v5_find_rsc_table,
+   .load = q6v5_wcss_load,
+   .get_boot_addr = rproc_elf_get_boot_addr,
+};
+
 static const struct rproc_fw_ops q6v5_fw_ops = {
.find_rsc_table = q6v5_find_rsc_table,
.load = q6v5_load,
@@ -1057,6 +1076,26 @@ static int q6v5_init_clocks(struct device *dev, struct 
clk **clks,
return i;
 }
 
+static int q6v5_wcss_init_reset(struct q6v5 *qproc)
+{
+   qproc->wcss_aon_reset = devm_reset_control_get(qproc->dev,
+  "wcss_aon_reset");
+   if (IS_ERR(qproc->wcss_aon_reset))
+   return PTR_ERR(qproc->wcss_aon_reset);
+
+   qproc->wcss_reset = devm_reset_control_get(qproc->dev,
+  "wcss_reset");
+   if (IS_ERR(qproc->wcss_reset))
+   return PTR_ERR(qproc->wcss_reset);
+
+   qproc->wcss_q6_reset = devm_reset_control_get(qproc->dev,
+ "wcss_q6_reset");
+   if (IS_ERR(qproc->wcss_q6_reset))
+   return PTR_ERR(qproc->wcss_q6_reset);
+
+   return 0;
+}
+
 static int q6v5_init_reset(struct q6v5 *qproc)
 {
qproc->mss_restart = devm_reset_control_get_exclusive(qproc->dev,
@@ -1116,6 +1155,9 @@ static int q6v5_alloc_memory_region(struct q6v5 *qproc)
return -EBUSY;
}
 
+   if (qproc->version 

[PATCH v5 3/6] remoteproc: qcom: Push reset ops, fw ops, rproc ops in to of_match data

2017-11-14 Thread Sricharan R
Instead of directly assigning reset, fw and rproc ops, put them
in to of_match data and get from that. Currently same ops
are used for all compatibles, but that will change when we add
q6v5-wcss support.

Signed-off-by: Sricharan R 
---
 drivers/remoteproc/qcom_q6v5_pil.c | 38 +-
 1 file changed, 25 insertions(+), 13 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5_pil.c 
b/drivers/remoteproc/qcom_q6v5_pil.c
index df8723d..769c6af 100644
--- a/drivers/remoteproc/qcom_q6v5_pil.c
+++ b/drivers/remoteproc/qcom_q6v5_pil.c
@@ -116,16 +116,6 @@ struct qcom_mss_reg_res {
int uA;
 };
 
-struct rproc_hexagon_res {
-   const char *hexagon_mba_image;
-   struct qcom_mss_reg_res *proxy_supply;
-   struct qcom_mss_reg_res *active_supply;
-   char **proxy_clk_names;
-   char **active_clk_names;
-   int version;
-   bool need_mem_protection;
-};
-
 struct q6v5 {
struct device *dev;
struct rproc *rproc;
@@ -174,6 +164,19 @@ struct q6v5 {
int version;
 };
 
+struct rproc_hexagon_res {
+   const char *hexagon_mba_image;
+   struct qcom_mss_reg_res *proxy_supply;
+   struct qcom_mss_reg_res *active_supply;
+   char **proxy_clk_names;
+   char **active_clk_names;
+   int version;
+   bool need_mem_protection;
+   int (*init_reset)(struct q6v5 *qproc);
+   const struct rproc_fw_ops *fw_ops;
+   const struct rproc_ops *ops;
+};
+
 enum {
MSS_MSM8916,
MSS_MSM8974,
@@ -1128,14 +1131,14 @@ static int q6v5_probe(struct platform_device *pdev)
if (!desc)
return -EINVAL;
 
-   rproc = rproc_alloc(&pdev->dev, pdev->name, &q6v5_ops,
+   rproc = rproc_alloc(&pdev->dev, pdev->name, desc->ops,
desc->hexagon_mba_image, sizeof(*qproc));
if (!rproc) {
dev_err(&pdev->dev, "failed to allocate rproc\n");
return -ENOMEM;
}
 
-   rproc->fw_ops = &q6v5_fw_ops;
+   rproc->fw_ops = desc->fw_ops;
 
qproc = (struct q6v5 *)rproc->priv;
qproc->dev = &pdev->dev;
@@ -1185,7 +1188,7 @@ static int q6v5_probe(struct platform_device *pdev)
}
qproc->active_reg_count = ret;
 
-   ret = q6v5_init_reset(qproc);
+   ret = desc->init_reset(qproc);
if (ret)
goto free_rproc;
 
@@ -1258,6 +1261,9 @@ static int q6v5_remove(struct platform_device *pdev)
},
.need_mem_protection = true,
.version = MSS_MSM8996,
+   .init_reset = q6v5_init_reset,
+   .fw_ops = &q6v5_fw_ops,
+   .ops = &q6v5_ops,
 };
 
 static const struct rproc_hexagon_res msm8916_mss = {
@@ -1289,6 +1295,9 @@ static int q6v5_remove(struct platform_device *pdev)
},
.need_mem_protection = false,
.version = MSS_MSM8916,
+   .init_reset = q6v5_init_reset,
+   .fw_ops = &q6v5_fw_ops,
+   .ops = &q6v5_ops,
 };
 
 static const struct rproc_hexagon_res msm8974_mss = {
@@ -1328,6 +1337,9 @@ static int q6v5_remove(struct platform_device *pdev)
},
.need_mem_protection = false,
.version = MSS_MSM8974,
+   .init_reset = q6v5_init_reset,
+   .fw_ops = &q6v5_fw_ops,
+   .ops = &q6v5_ops,
 };
 
 static const struct of_device_id q6v5_of_match[] = {
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



Re: [PATCH v5 5/6] remoteproc: qcom: Add support for q6v5-wcss pil

2017-11-14 Thread Sricharan R


On 11/14/2017 4:23 PM, Sricharan R wrote:
> IPQ8074 has an integrated Hexagon dsp core q6v5 and a wireless lan
> (Lithium) IP. An mdt type single image format is used for the
> firmware. So the mdt_load function can be directly used to load
> the firmware. Also add the relevant resets required for this core.
> 
> Acked-by: Rob Herring 

Infact should have said,
Acked-by: Rob Herring  (DT bindings)

Regards,
  Sricharan

> Signed-off-by: Sricharan R 
> ---
>  .../devicetree/bindings/remoteproc/qcom,q6v5.txt   |  7 ++-
>  drivers/remoteproc/Kconfig |  1 +
>  drivers/remoteproc/qcom_q6v5_pil.c | 53 
> +-
>  3 files changed, 59 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt 
> b/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt
> index 00d3d58..d52d05e 100644
> --- a/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt
> +++ b/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt
> @@ -11,6 +11,7 @@ on the Qualcomm Hexagon core.
>   "qcom,msm8916-mss-pil",
>   "qcom,msm8974-mss-pil"
>   "qcom,msm8996-mss-pil"
> + "qcom,ipq8074-wcss-pil"
>  
>  - reg:
>   Usage: required
> @@ -49,11 +50,15 @@ on the Qualcomm Hexagon core.
>   Usage: required
>   Value type: 
>   Definition: reference to the reset-controller for the modem sub-system
> + reference to the list of 3 reset-controllers for the
> + wcss sub-system
>  
>  - reset-names:
>   Usage: required
>   Value type: 
> - Definition: must be "mss_restart"
> + Definition: must be "mss_restart" for the modem sub-system
> + Definition: must be "wcss_aon_reset", "wcss_reset", "wcss_q6_reset"
> + for the wcss syb-system
>  
>  - cx-supply:
>  - mss-supply:
> diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
> index bf04479..e7e9979 100644
> --- a/drivers/remoteproc/Kconfig
> +++ b/drivers/remoteproc/Kconfig
> @@ -113,6 +113,7 @@ config QCOM_Q6V5_PIL
>   select MFD_SYSCON
>   select QCOM_RPROC_COMMON
>   select QCOM_SCM
> + select QCOM_MDT_LOADER
>   help
> Say y here to support the Qualcomm Peripherial Image Loader for the
> Hexagon V5 based remote processors.
> diff --git a/drivers/remoteproc/qcom_q6v5_pil.c 
> b/drivers/remoteproc/qcom_q6v5_pil.c
> index 75ff02d..3c401ff 100644
> --- a/drivers/remoteproc/qcom_q6v5_pil.c
> +++ b/drivers/remoteproc/qcom_q6v5_pil.c
> @@ -129,6 +129,9 @@ struct q6v5 {
>   u32 halt_nc;
>  
>   struct reset_control *mss_restart;
> + struct reset_control *wcss_aon_reset;
> + struct reset_control *wcss_reset;
> + struct reset_control *wcss_q6_reset;
>  
>   struct qcom_smem_state *state;
>   unsigned stop_bit;
> @@ -181,6 +184,7 @@ enum {
>   MSS_MSM8916,
>   MSS_MSM8974,
>   MSS_MSM8996,
> + WCSS_IPQ8074,
>  };
>  
>  static int q6v5_regulator_init(struct device *dev, struct reg_info *regs,
> @@ -354,6 +358,21 @@ static int q6v5_load(struct rproc *rproc, const struct 
> firmware *fw)
>   return 0;
>  }
>  
> +static int q6v5_wcss_load(struct rproc *rproc, const struct firmware *fw)
> +{
> + struct q6v5 *qproc = rproc->priv;
> +
> + return qcom_mdt_load_no_init(qproc->dev, fw, rproc->firmware,
> +  0, qproc->mba_region, qproc->mba_phys,
> +  qproc->mba_size);
> +}
> +
> +static const struct rproc_fw_ops q6v5_wcss_fw_ops = {
> + .find_rsc_table = q6v5_find_rsc_table,
> + .load = q6v5_wcss_load,
> + .get_boot_addr = rproc_elf_get_boot_addr,
> +};
> +
>  static const struct rproc_fw_ops q6v5_fw_ops = {
>   .find_rsc_table = q6v5_find_rsc_table,
>   .load = q6v5_load,
> @@ -1057,6 +1076,26 @@ static int q6v5_init_clocks(struct device *dev, struct 
> clk **clks,
>   return i;
>  }
>  
> +static int q6v5_wcss_init_reset(struct q6v5 *qproc)
> +{
> + qproc->wcss_aon_reset = devm_reset_control_get(qproc->dev,
> +"wcss_aon_reset");
> + if (IS_ERR(qproc->wcss_aon_reset))
> + return PTR_ERR(qproc->wcss_aon_reset);
> +
> + qproc->wcss_reset = devm_reset_control_get(qproc->dev,
> +"wcss_reset");
> + if (IS_ERR(qproc->wcss_reset))
> + r

Re: [PATCH v3 1/6] remoteproc: qcom: mdt_loader: Make the firmware authentication optional

2017-10-18 Thread Sricharan R
Hi Bjorn,

On 10/12/2017 11:56 PM, Bjorn Andersson wrote:
> On Wed 30 Aug 21:45 PDT 2017, Sricharan R wrote:
> 
>> qcom_mdt_load function loads the mdt type firmware and
>> initialises the secure memory as well. Make the initialisation only
>> when requested by the caller, so that the function can be used
>> by self-authenticating remoteproc as well.
>>
>> Signed-off-by: Sricharan R 
>> ---
>>  drivers/soc/qcom/mdt_loader.c   | 70 
>> +++--
>>  include/linux/soc/qcom/mdt_loader.h |  3 ++
>>  2 files changed, 62 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
>> index bd63df0..851f5d7 100644
>> --- a/drivers/soc/qcom/mdt_loader.c
>> +++ b/drivers/soc/qcom/mdt_loader.c
>> @@ -86,9 +86,9 @@ ssize_t qcom_mdt_get_size(const struct firmware *fw)
>>   *
>>   * Returns 0 on success, negative errno otherwise.
>>   */
> 
> This kerneldoc is now lacks @pas_init, but as it's just an internal
> function and you have kerneldoc on the public functions I suggest that
> you drop it.
> 

 Sure. Will change.

>> -int qcom_mdt_load(struct device *dev, const struct firmware *fw,
>> -  const char *firmware, int pas_id, void *mem_region,
>> -  phys_addr_t mem_phys, size_t mem_size)
>> +static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
>> +   const char *firmware, int pas_id, void *mem_region,
>> +   phys_addr_t mem_phys, size_t mem_size, bool pas_init)
> 
> With this you have my Acked-by.
> 

 Thanks.

Regards,
 Sricharan

-- 
"QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation

---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus



Re: [PATCH v7 4/4] remoteproc: qcom: Add support for mss remoteproc on msm8996

2017-10-18 Thread Sricharan R
Hi Bjorn,

On 10/17/2017 12:28 AM, Bjorn Andersson wrote:
> On Mon 16 Oct 06:19 PDT 2017, Dwivedi, Avaneesh Kumar (avani) wrote:
>> On 10/12/2017 11:50 PM, Bjorn Andersson wrote:
> [..]
>>> Please fix this and add my Acked-by
>> Sure will do, just want to ask, when i am sending updated patches, should i
>> sent all the 4 patches in series or should skip those which are acked by
>> you.
> 
> Please include all the patches in each submission (unless the maintainer
> tells you that he/she applied some of them already).
> 
> Make sure to add any "Acked-by", "Reviewed-by" and "Tested-by" on your
> patches, so that people know that they are already reviewed/tested.
> 
> 
> And finally, when resending patches, add a section between "---" and the
> diff-stat describing changes since the last version - that makes it
> easier to see what changed since last time and will help the reviewer
> look at the "new" things.

 So i was having the ipq8074 q6 remoteproc support based on this series last 
time.
 With the msm8996 now getting cleared, i will rebase my patches and repost.
 Otherwise, just hope that you were ok with the approach [1].

[1] https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1481961.html


Regards,
 Sricharan

-- 
"QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation

---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus



[PATCH 2/5] arm: dts: qcom: Add sdcc nodes for ipq8064

2018-08-03 Thread Sricharan R
The relevant data for sdcc.

Signed-off-by: Sricharan R 
---
 arch/arm/boot/dts/qcom-ipq8064.dtsi | 76 +
 1 file changed, 76 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-ipq8064.dtsi 
b/arch/arm/boot/dts/qcom-ipq8064.dtsi
index e02d588..e78618e 100644
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
@@ -555,5 +555,81 @@
status = "disabled";
perst-gpio = <&qcom_pinmux 63 GPIO_ACTIVE_LOW>;
};
+
+   vsdcc_fixed: vsdcc-regulator {
+   compatible = "regulator-fixed";
+   regulator-name = "SDCC Power";
+   regulator-min-microvolt = <330>;
+   regulator-max-microvolt = <330>;
+   regulator-always-on;
+   };
+
+   sdcc1bam:dma@12402000 {
+   compatible = "qcom,bam-v1.3.0";
+   reg = <0x12402000 0x8000>;
+   interrupts = ;
+   clocks = <&gcc SDC1_H_CLK>;
+   clock-names = "bam_clk";
+   #dma-cells = <1>;
+   qcom,ee = <0>;
+   };
+
+   sdcc3bam:dma@12182000 {
+   compatible = "qcom,bam-v1.3.0";
+   reg = <0x12182000 0x8000>;
+   interrupts = ;
+   clocks = <&gcc SDC3_H_CLK>;
+   clock-names = "bam_clk";
+   #dma-cells = <1>;
+   qcom,ee = <0>;
+   };
+
+   amba {
+   compatible = "simple-bus";
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   sdcc@1240 {
+   status  = "disabled";
+   compatible  = "arm,pl18x", "arm,primecell";
+   arm,primecell-periphid = <0x00051180>;
+   reg = <0x1240 0x2000>;
+   interrupts  = ;
+   interrupt-names = "cmd_irq";
+   clocks  = <&gcc SDC1_CLK>, <&gcc 
SDC1_H_CLK>;
+   clock-names = "mclk", "apb_pclk";
+   bus-width   = <8>;
+   max-frequency   = <9600>;
+   non-removable;
+   cap-sd-highspeed;
+   cap-mmc-highspeed;
+   mmc-ddr-1_8v;
+   vmmc-supply = <&vsdcc_fixed>;
+   dmas = <&sdcc1bam 2>, <&sdcc1bam 1>;
+   dma-names = "tx", "rx";
+   };
+
+   sdcc@1218 {
+   compatible  = "arm,pl18x", "arm,primecell";
+   arm,primecell-periphid = <0x00051180>;
+   status  = "disabled";
+   reg = <0x1218 0x2000>;
+   interrupts  = ;
+   interrupt-names = "cmd_irq";
+   clocks  = <&gcc SDC3_CLK>, <&gcc 
SDC3_H_CLK>;
+   clock-names = "mclk", "apb_pclk";
+   bus-width   = <8>;
+   cap-sd-highspeed;
+   cap-mmc-highspeed;
+   max-frequency   = <19200>;
+   #mmc-ddr-1_8v;
+   sd-uhs-sdr104;
+   sd-uhs-ddr50;
+   vqmmc-supply = <&vsdcc_fixed>;
+   dmas = <&sdcc3bam 2>, <&sdcc3bam 1>;
+   dma-names = "tx", "rx";
+   };
+   };
};
 };
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 1/5] arm: dts: qcom: Add pcie nodes for ipq8064

2018-08-03 Thread Sricharan R
Adding the pcie nodes and pins.

Signed-off-by: Sricharan R 
---
 arch/arm/boot/dts/qcom-ipq8064.dtsi | 182 
 1 file changed, 182 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-ipq8064.dtsi 
b/arch/arm/boot/dts/qcom-ipq8064.dtsi
index 70790ac..e02d588 100644
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
@@ -2,8 +2,11 @@
 /dts-v1/;
 
 #include "skeleton.dtsi"
+#include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 
@@ -114,6 +117,33 @@
interrupt-controller;
#interrupt-cells = <2>;
interrupts = ;
+
+   pcie0_pins: pcie0_pinmux {
+   mux {
+   pins = "gpio3";
+   function = "pcie1_rst";
+   drive-strength = <12>;
+   bias-disable;
+   };
+   };
+
+   pcie1_pins: pcie1_pinmux {
+   mux {
+   pins = "gpio48";
+   function = "pcie2_rst";
+   drive-strength = <12>;
+   bias-disable;
+   };
+   };
+
+   pcie2_pins: pcie2_pinmux {
+   mux {
+   pins = "gpio63";
+   function = "pcie3_rst";
+   drive-strength = <12>;
+   bias-disable;
+   };
+   };
};
 
intc: interrupt-controller@200 {
@@ -373,5 +403,157 @@
#reset-cells = <1>;
};
 
+   pcie0: pci@1b50 {
+   compatible = "qcom,pcie-ipq8064";
+   reg = <0x1b50 0x1000
+  0x1b502000 0x80
+  0x1b60 0x100
+  0x0ff0 0x10>;
+   reg-names = "dbi", "elbi", "parf", "config";
+   device_type = "pci";
+   linux,pci-domain = <0>;
+   bus-range = <0x00 0xff>;
+   num-lanes = <1>;
+   #address-cells = <3>;
+   #size-cells = <2>;
+
+   ranges = <0x8100 0 0x0fe0 0x0fe0 0 
0x0010   /* downstream I/O */
+ 0x8200 0 0x0800 0x0800 0 
0x07e0>; /* non-prefetchable memory */
+
+   interrupts = ;
+   interrupt-names = "msi";
+   #interrupt-cells = <1>;
+   interrupt-map-mask = <0 0 0 0x7>;
+   interrupt-map = <0 0 0 1 &intc 0 36 
IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+   <0 0 0 2 &intc 0 37 
IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+   <0 0 0 3 &intc 0 38 
IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+   <0 0 0 4 &intc 0 39 
IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+
+   clocks = <&gcc PCIE_A_CLK>,
+<&gcc PCIE_H_CLK>,
+<&gcc PCIE_PHY_CLK>,
+<&gcc PCIE_AUX_CLK>,
+<&gcc PCIE_ALT_REF_CLK>;
+   clock-names = "core", "iface", "phy", "aux", "ref";
+
+   assigned-clocks = <&gcc PCIE_ALT_REF_CLK>;
+   assigned-clock-rates = <1>;
+
+   resets = <&gcc PCIE_ACLK_RESET>,
+<&gcc PCIE_HCLK_RESET>,
+<&gcc PCIE_POR_RESET>,
+<&gcc PCIE_PCI_RESET>,
+<&gcc PCIE_PHY_RESET>,
+<&gcc PCIE_EXT_RESET>;
+   reset-names = "axi", "ahb", "por", "pci", "phy", "ext";
+
+   pinctrl-0 = <&pcie0_pins>;
+   pinctrl-names = "default";
+
+

[PATCH 5/5] arm: dts: qcom: Add led and gpio-button nodes to ipq8064 boards

2018-08-03 Thread Sricharan R
Add the dt nodes for enabling the leds and gpio-buttons.

Signed-off-by: Sricharan R 
---
 arch/arm/boot/dts/qcom-ipq8064-ap148.dts |  8 +
 arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi | 60 
 arch/arm/boot/dts/qcom-ipq8064.dtsi  | 19 ++
 3 files changed, 87 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts 
b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
index f45b05e..554c65e 100644
--- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
@@ -12,6 +12,14 @@
function = "gsbi4";
bias-disable;
};
+
+   buttons_pins: buttons_pins {
+   mux {
+   pins = "gpio54", "gpio65";
+   drive-strength = <2>;
+   bias-pull-up;
+   };
+   };
};
 
gsbi@1630 {
diff --git a/arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi 
b/arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi
index ee32f97..e239a04 100644
--- a/arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include "qcom-ipq8064.dtsi"
+#include 
 
 / {
model = "Qualcomm Technologies, Inc. IPQ8064-v1.0";
@@ -63,5 +64,64 @@
ports-implemented = <0x1>;
status = "ok";
};
+
+   gpio_keys {
+   compatible = "gpio-keys";
+   pinctrl-0 = <&buttons_pins>;
+   pinctrl-names = "default";
+
+   button@1 {
+   label = "reset";
+   linux,code = ;
+   gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>;
+   linux,input-type = <1>;
+   debounce-interval = <60>;
+   };
+   button@2 {
+   label = "wps";
+   linux,code = ;
+   gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>;
+   linux,input-type = <1>;
+   debounce-interval = <60>;
+   };
+   };
+
+   leds {
+   compatible = "gpio-leds";
+   pinctrl-0 = <&leds_pins>;
+   pinctrl-names = "default";
+
+   led@7 {
+   label = "led_usb1";
+   gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>;
+   linux,default-trigger = "usbdev";
+   default-state = "off";
+   };
+
+   led@8 {
+   label = "led_usb3";
+   gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>;
+   linux,default-trigger = "usbdev";
+   default-state = "off";
+   };
+
+   led@9 {
+   label = "status_led_fail";
+   gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>;
+   default-state = "off";
+   };
+
+   led@26 {
+   label = "sata_led";
+   gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>;
+   default-state = "off";
+   };
+
+   led@53 {
+   label = "status_led_pass";
+   gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>;
+   default-state = "off";
+   };
+   };
};
 };
diff --git a/arch/arm/boot/dts/qcom-ipq8064.dtsi 
b/arch/arm/boot/dts/qcom-ipq8064.dtsi
index 04cc822..f793cd1 100644
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
@@ -153,6 +153,25 @@
bias-none;
};
};
+
+   leds_pins: leds_pins {
+   mux {
+   pins = "gpio7", "gpio8", "gpio9",
+ 

[PATCH 0/5] arm: dts: qcom: Few updates for ipq8064

2018-08-03 Thread Sricharan R
Adding pcie,sdcc nodes and a new board file ipq8064-ap161

Sricharan R (5):
  arm: dts: qcom: Add pcie nodes for ipq8064
  arm: dts: qcom: Add sdcc nodes for ipq8064
  arm: dts: qcom: Move common nodes to ipq8064-v.1.0.dtsi
  arm: dts: qcom: Add ipq8064-ap161.dts
  arm: dts: qcom: Add led and gpio-button nodes to ipq8064 boards

 arch/arm/boot/dts/Makefile   |   1 +
 arch/arm/boot/dts/qcom-ipq8064-ap148.dts |  83 +
 arch/arm/boot/dts/qcom-ipq8064-ap161.dts |   7 +
 arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi | 125 ++
 arch/arm/boot/dts/qcom-ipq8064.dtsi  | 286 +++
 5 files changed, 426 insertions(+), 76 deletions(-)
 create mode 100644 arch/arm/boot/dts/qcom-ipq8064-ap161.dts

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 4/5] arm: dts: qcom: Add ipq8064-ap161.dts

2018-08-03 Thread Sricharan R
Add a new board dts for ipq8064-ap161.

Signed-off-by: Sricharan R 
---
 Documentation/devicetree/bindings/arm/qcom.txt | 2 ++
 arch/arm/boot/dts/Makefile | 1 +
 arch/arm/boot/dts/qcom-ipq8064-ap161.dts   | 7 +++
 3 files changed, 10 insertions(+)
 create mode 100644 arch/arm/boot/dts/qcom-ipq8064-ap161.dts

diff --git a/Documentation/devicetree/bindings/arm/qcom.txt 
b/Documentation/devicetree/bindings/arm/qcom.txt
index ee532e7..2325135 100644
--- a/Documentation/devicetree/bindings/arm/qcom.txt
+++ b/Documentation/devicetree/bindings/arm/qcom.txt
@@ -15,6 +15,7 @@ The 'SoC' and 'board' elements are required. All other 
elements are optional.
 
 The 'SoC' element must be one of the following strings:
 
+   ipq8064
apq8016
apq8074
apq8084
@@ -30,6 +31,7 @@ The 'SoC' element must be one of the following strings:
 
 The 'board' element must be one of the following strings:
 
+   ap
cdp
liquid
dragonboard
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 37a3de7..233661a 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -772,6 +772,7 @@ dtb-$(CONFIG_ARCH_QCOM) += \
qcom-ipq4019-ap.dk07.1-c1.dtb \
qcom-ipq4019-ap.dk07.1-c2.dtb \
qcom-ipq8064-ap148.dtb \
+   qcom-ipq8064-ap161.dtb \
qcom-msm8660-surf.dtb \
qcom-msm8960-cdp.dtb \
qcom-msm8974-fairphone-fp2.dtb \
diff --git a/arch/arm/boot/dts/qcom-ipq8064-ap161.dts 
b/arch/arm/boot/dts/qcom-ipq8064-ap161.dts
new file mode 100644
index 000..aab5174
--- /dev/null
+++ b/arch/arm/boot/dts/qcom-ipq8064-ap161.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "qcom-ipq8064-v1.0.dtsi"
+
+/ {
+   model = "Qualcomm Technologies, Inc. IPQ8064/AP-161";
+   compatible = "qcom,ipq8064-ap161";
+};
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 3/5] arm: dts: qcom: Move common nodes to ipq8064-v.1.0.dtsi

2018-08-03 Thread Sricharan R
The nodes in ipq8064-ap148.dts currently are common with
boards that we will add next. So move the common data to
ipq8064-v.1.0.dtsi.

Signed-off-by: Sricharan R 
---
 arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 83 ++--
 arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi | 65 +
 arch/arm/boot/dts/qcom-ipq8064.dtsi  |  9 
 3 files changed, 77 insertions(+), 80 deletions(-)

diff --git a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts 
b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
index bcf53e3..f45b05e 100644
--- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
@@ -2,26 +2,8 @@
 #include "qcom-ipq8064-v1.0.dtsi"
 
 / {
-   model = "Qualcomm IPQ8064/AP148";
-   compatible = "qcom,ipq8064-ap148", "qcom,ipq8064";
-
-   aliases {
-   serial0 = &gsbi4_serial;
-   };
-
-   chosen {
-   stdout-path = "serial0:115200n8";
-   };
-
-   reserved-memory {
-   #address-cells = <1>;
-   #size-cells = <1>;
-   ranges;
-   rsvd@4120 {
-   reg = <0x4120 0x30>;
-   no-map;
-   };
-   };
+   model = "Qualcomm Technologies, Inc. IPQ8064/AP-148";
+   compatible = "qcom,ipq8064-ap148";
 
soc {
pinmux@80 {
@@ -30,74 +12,15 @@
function = "gsbi4";
bias-disable;
};
-
-   spi_pins: spi_pins {
-   mux {
-   pins = "gpio18", "gpio19", "gpio21";
-   function = "gsbi5";
-   drive-strength = <10>;
-   bias-none;
-   };
-   };
};
 
gsbi@1630 {
-   qcom,mode = ;
-   status = "ok";
-   serial@1634 {
-   status = "ok";
-   };
-
-   i2c4: i2c@1638 {
+   i2c@1638 {
status = "ok";
-
clock-frequency = <20>;
-
pinctrl-0 = <&i2c4_pins>;
pinctrl-names = "default";
};
};
-
-   gsbi5: gsbi@1a20 {
-   qcom,mode = ;
-   status = "ok";
-
-   spi4: spi@1a28 {
-   status = "ok";
-   spi-max-frequency = <5000>;
-
-   pinctrl-0 = <&spi_pins>;
-   pinctrl-names = "default";
-
-   cs-gpios = <&qcom_pinmux 20 0>;
-
-   flash: m25p80@0 {
-   compatible = "s25fl256s1";
-   #address-cells = <1>;
-   #size-cells = <1>;
-   spi-max-frequency = <5000>;
-   reg = <0>;
-
-   partition@0 {
-   label = "rootfs";
-   reg = <0x0 0x100>;
-   };
-
-   partition@1 {
-   label = "scratch";
-   reg = <0x100 0x100>;
-   };
-   };
-   };
-   };
-
-   sata-phy@1b40 {
-   status = "ok";
-   };
-
-   sata@2900 {
-   ports-implemented = <0x1>;
-   status = "ok";
-   };
};
 };
diff --git a/arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi 
b/arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi
index e118119..ee32f97 100644
--- a/arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi
@@ -1,2 +1,67 @@
 // SPDX-License-Identifier: GPL-2.0
 #include "qcom-ipq8064.dtsi"
+
+/ {
+   model = "Qualcomm Technologies, Inc. IPQ8064-v1.0";
+
+   aliases {
+   serial0 = &gsbi4_serial;
+   };
+
+ 

Re: [PATCH 4/5] arm: dts: qcom: Add ipq8064-ap161.dts

2018-08-06 Thread Sricharan R
Hi Rob,

On 8/7/2018 2:05 AM, Rob Herring wrote:
> On Fri, Aug 3, 2018 at 8:10 AM Sricharan R  wrote:
>>
>> Add a new board dts for ipq8064-ap161.
>>
>> Signed-off-by: Sricharan R 
>> ---
>>  Documentation/devicetree/bindings/arm/qcom.txt | 2 ++
>>  arch/arm/boot/dts/Makefile | 1 +
>>  arch/arm/boot/dts/qcom-ipq8064-ap161.dts   | 7 +++
>>  3 files changed, 10 insertions(+)
>>  create mode 100644 arch/arm/boot/dts/qcom-ipq8064-ap161.dts
>>
>> diff --git a/Documentation/devicetree/bindings/arm/qcom.txt 
>> b/Documentation/devicetree/bindings/arm/qcom.txt
>> index ee532e7..2325135 100644
>> --- a/Documentation/devicetree/bindings/arm/qcom.txt
>> +++ b/Documentation/devicetree/bindings/arm/qcom.txt
>> @@ -15,6 +15,7 @@ The 'SoC' and 'board' elements are required. All other 
>> elements are optional.
>>
>>  The 'SoC' element must be one of the following strings:
>>
>> +   ipq8064
>> apq8016
>> apq8074
>> apq8084
>> @@ -30,6 +31,7 @@ The 'SoC' element must be one of the following strings:
>>
>>  The 'board' element must be one of the following strings:
>>
>> +   ap
>> cdp
>> liquid
>> dragonboard
>> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
>> index 37a3de7..233661a 100644
>> --- a/arch/arm/boot/dts/Makefile
>> +++ b/arch/arm/boot/dts/Makefile
>> @@ -772,6 +772,7 @@ dtb-$(CONFIG_ARCH_QCOM) += \
>> qcom-ipq4019-ap.dk07.1-c1.dtb \
>> qcom-ipq4019-ap.dk07.1-c2.dtb \
>> qcom-ipq8064-ap148.dtb \
>> +   qcom-ipq8064-ap161.dtb \
>> qcom-msm8660-surf.dtb \
>> qcom-msm8960-cdp.dtb \
>> qcom-msm8974-fairphone-fp2.dtb \
>> diff --git a/arch/arm/boot/dts/qcom-ipq8064-ap161.dts 
>> b/arch/arm/boot/dts/qcom-ipq8064-ap161.dts
>> new file mode 100644
>> index 000..aab5174
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/qcom-ipq8064-ap161.dts
>> @@ -0,0 +1,7 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +#include "qcom-ipq8064-v1.0.dtsi"
>> +
>> +/ {
>> +   model = "Qualcomm Technologies, Inc. IPQ8064/AP-161";
>> +   compatible = "qcom,ipq8064-ap161";
> 
> Doesn't match what you documented above. I'm guessing the ap148 board
> didn't either...

oops. yeah, ap148 id not having it. will add that and also correct this.
would call it as 'ap161' as the name for the board part.

Regards,
 Sricharan

-- 
"QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation


[PATCH V11 00/14] Krait clocks + Krait CPUfreq

2018-08-13 Thread Sricharan R
t of the PLL when changing its frequency.
This means we have to switch over to the secondary mux and use one of the
fixed sources. This is why we need something like the safe parent patch.

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-March/332607.html
[2] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-March/332615.html
[3] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-March/332608.html
[4] https://lwn.net/Articles/740994/ 
[5] https://lkml.org/lkml/2017/12/19/537


Sricharan R (3):
  clk: qcom: Add safe switch hook for krait mux clocks
  cpufreq: qcom: Re-organise kryo cpufreq to use it for other nvmem
based qcom socs
  cpufreq: qcom: Add support for krait based socs

Stephen Boyd (11):
  ARM: Add Krait L2 register accessor functions
  clk: qcom: Add support for High-Frequency PLLs (HFPLLs)
  clk: qcom: Add HFPLL driver
  dt-bindings: clock: Document qcom,hfpll
  clk: qcom: Add MSM8960/APQ8064's HFPLLs
  clk: qcom: Add IPQ806X's HFPLLs
  clk: qcom: Add support for Krait clocks
  clk: qcom: Add KPSS ACC/GCC driver
  dt-bindings: arm: Document qcom,kpss-gcc
  clk: qcom: Add Krait clock controller driver
  dt-bindings: clock: Document qcom,krait-cc

 .../devicetree/bindings/arm/msm/qcom,kpss-acc.txt  |  19 +
 .../devicetree/bindings/arm/msm/qcom,kpss-gcc.txt  |  44 +++
 .../devicetree/bindings/clock/qcom,hfpll.txt   |  60 
 .../devicetree/bindings/clock/qcom,krait-cc.txt|  34 ++
 .../{kryo-cpufreq.txt => qcom-nvmem-cpufreq.txt}   |   7 +-
 arch/arm/common/Kconfig|   3 +
 arch/arm/common/Makefile   |   1 +
 arch/arm/common/krait-l2-accessors.c   |  48 +++
 arch/arm/include/asm/krait-l2-accessors.h  |   9 +
 drivers/clk/qcom/Kconfig   |  28 ++
 drivers/clk/qcom/Makefile  |   5 +
 drivers/clk/qcom/clk-hfpll.c   | 244 +
 drivers/clk/qcom/clk-hfpll.h   |  44 +++
 drivers/clk/qcom/clk-krait.c   | 126 +++
 drivers/clk/qcom/clk-krait.h   |  40 +++
 drivers/clk/qcom/gcc-ipq806x.c |  82 +
 drivers/clk/qcom/gcc-msm8960.c | 172 +
 drivers/clk/qcom/hfpll.c   |  96 +
 drivers/clk/qcom/kpss-xcc.c|  87 +
 drivers/clk/qcom/krait-cc.c| 397 +
 drivers/cpufreq/Kconfig.arm|   6 +-
 drivers/cpufreq/Makefile   |   2 +-
 drivers/cpufreq/cpufreq-dt-platdev.c   |   5 +
 drivers/cpufreq/qcom-cpufreq-kryo.c| 232 
 drivers/cpufreq/qcom-cpufreq-nvmem.c   | 387 
 include/dt-bindings/clock/qcom,gcc-msm8960.h   |   2 +
 26 files changed, 1941 insertions(+), 239 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,hfpll.txt
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,krait-cc.txt
 rename Documentation/devicetree/bindings/opp/{kryo-cpufreq.txt => 
qcom-nvmem-cpufreq.txt} (98%)
 create mode 100644 arch/arm/common/krait-l2-accessors.c
 create mode 100644 arch/arm/include/asm/krait-l2-accessors.h
 create mode 100644 drivers/clk/qcom/clk-hfpll.c
 create mode 100644 drivers/clk/qcom/clk-hfpll.h
 create mode 100644 drivers/clk/qcom/clk-krait.c
 create mode 100644 drivers/clk/qcom/clk-krait.h
 create mode 100644 drivers/clk/qcom/hfpll.c
 create mode 100644 drivers/clk/qcom/kpss-xcc.c
 create mode 100644 drivers/clk/qcom/krait-cc.c
 delete mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c
 create mode 100644 drivers/cpufreq/qcom-cpufreq-nvmem.c

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 01/14] ARM: Add Krait L2 register accessor functions

2018-08-13 Thread Sricharan R
From: Stephen Boyd 

Krait CPUs have a handful of L2 cache controller registers that
live behind a cp15 based indirection register. First you program
the indirection register (l2cpselr) to point the L2 'window'
register (l2cpdr) at what you want to read/write.  Then you
read/write the 'window' register to do what you want. The
l2cpselr register is not banked per-cpu so we must lock around
accesses to it to prevent other CPUs from re-pointing l2cpdr
underneath us.

Cc: Mark Rutland 
Cc: Russell King 
Signed-off-by: Stephen Boyd 
---
 arch/arm/common/Kconfig   |  3 ++
 arch/arm/common/Makefile  |  1 +
 arch/arm/common/krait-l2-accessors.c  | 48 +++
 arch/arm/include/asm/krait-l2-accessors.h |  9 ++
 4 files changed, 61 insertions(+)
 create mode 100644 arch/arm/common/krait-l2-accessors.c
 create mode 100644 arch/arm/include/asm/krait-l2-accessors.h

diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index e5ad070..c8e1986 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -7,6 +7,9 @@ config DMABOUNCE
bool
select ZONE_DMA
 
+config KRAIT_L2_ACCESSORS
+   bool
+
 config SHARP_LOCOMO
bool
 
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 3157be4..219a260 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -7,6 +7,7 @@ obj-y   += firmware.o
 
 obj-$(CONFIG_SA)   += sa.o
 obj-$(CONFIG_DMABOUNCE)+= dmabounce.o
+obj-$(CONFIG_KRAIT_L2_ACCESSORS) += krait-l2-accessors.o
 obj-$(CONFIG_SHARP_LOCOMO) += locomo.o
 obj-$(CONFIG_SHARP_PARAM)  += sharpsl_param.o
 obj-$(CONFIG_SHARP_SCOOP)  += scoop.o
diff --git a/arch/arm/common/krait-l2-accessors.c 
b/arch/arm/common/krait-l2-accessors.c
new file mode 100644
index 000..9a97dda
--- /dev/null
+++ b/arch/arm/common/krait-l2-accessors.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+
+#include 
+#include 
+
+#include 
+#include 
+
+static DEFINE_RAW_SPINLOCK(krait_l2_lock);
+
+void krait_set_l2_indirect_reg(u32 addr, u32 val)
+{
+   unsigned long flags;
+
+   raw_spin_lock_irqsave(&krait_l2_lock, flags);
+   /*
+* Select the L2 window by poking l2cpselr, then write to the window
+* via l2cpdr.
+*/
+   asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
+   isb();
+   asm volatile ("mcr p15, 3, %0, c15, c0, 7 @ l2cpdr" : : "r" (val));
+   isb();
+
+   raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
+}
+EXPORT_SYMBOL(krait_set_l2_indirect_reg);
+
+u32 krait_get_l2_indirect_reg(u32 addr)
+{
+   u32 val;
+   unsigned long flags;
+
+   raw_spin_lock_irqsave(&krait_l2_lock, flags);
+   /*
+* Select the L2 window by poking l2cpselr, then read from the window
+* via l2cpdr.
+*/
+   asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
+   isb();
+   asm volatile ("mrc p15, 3, %0, c15, c0, 7 @ l2cpdr" : "=r" (val));
+
+   raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
+
+   return val;
+}
+EXPORT_SYMBOL(krait_get_l2_indirect_reg);
diff --git a/arch/arm/include/asm/krait-l2-accessors.h 
b/arch/arm/include/asm/krait-l2-accessors.h
new file mode 100644
index 000..a5f2cdd
--- /dev/null
+++ b/arch/arm/include/asm/krait-l2-accessors.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASMARM_KRAIT_L2_ACCESSORS_H
+#define __ASMARM_KRAIT_L2_ACCESSORS_H
+
+extern void krait_set_l2_indirect_reg(u32 addr, u32 val);
+extern u32 krait_get_l2_indirect_reg(u32 addr);
+
+#endif
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 02/14] clk: qcom: Add support for High-Frequency PLLs (HFPLLs)

2018-08-13 Thread Sricharan R
From: Stephen Boyd 

HFPLLs are the main frequency source for Krait CPU clocks. Add
support for changing the rate of these PLLs.

Signed-off-by: Stephen Boyd 
---
 drivers/clk/qcom/Makefile|   1 +
 drivers/clk/qcom/clk-hfpll.c | 244 +++
 drivers/clk/qcom/clk-hfpll.h |  44 
 3 files changed, 289 insertions(+)
 create mode 100644 drivers/clk/qcom/clk-hfpll.c
 create mode 100644 drivers/clk/qcom/clk-hfpll.h

diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 762c011..1331ed7 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -11,6 +11,7 @@ clk-qcom-y += clk-branch.o
 clk-qcom-y += clk-regmap-divider.o
 clk-qcom-y += clk-regmap-mux.o
 clk-qcom-y += clk-regmap-mux-div.o
+clk-qcom-y += clk-hfpll.o
 clk-qcom-y += reset.o
 clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o
 
diff --git a/drivers/clk/qcom/clk-hfpll.c b/drivers/clk/qcom/clk-hfpll.c
new file mode 100644
index 000..3c04805
--- /dev/null
+++ b/drivers/clk/qcom/clk-hfpll.c
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk-regmap.h"
+#include "clk-hfpll.h"
+
+#define PLL_OUTCTRLBIT(0)
+#define PLL_BYPASSNL   BIT(1)
+#define PLL_RESET_NBIT(2)
+
+/* Initialize a HFPLL at a given rate and enable it. */
+static void __clk_hfpll_init_once(struct clk_hw *hw)
+{
+   struct clk_hfpll *h = to_clk_hfpll(hw);
+   struct hfpll_data const *hd = h->d;
+   struct regmap *regmap = h->clkr.regmap;
+
+   if (likely(h->init_done))
+   return;
+
+   /* Configure PLL parameters for integer mode. */
+   if (hd->config_val)
+   regmap_write(regmap, hd->config_reg, hd->config_val);
+   regmap_write(regmap, hd->m_reg, 0);
+   regmap_write(regmap, hd->n_reg, 1);
+
+   if (hd->user_reg) {
+   u32 regval = hd->user_val;
+   unsigned long rate;
+
+   rate = clk_hw_get_rate(hw);
+
+   /* Pick the right VCO. */
+   if (hd->user_vco_mask && rate > hd->low_vco_max_rate)
+   regval |= hd->user_vco_mask;
+   regmap_write(regmap, hd->user_reg, regval);
+   }
+
+   if (hd->droop_reg)
+   regmap_write(regmap, hd->droop_reg, hd->droop_val);
+
+   h->init_done = true;
+}
+
+static void __clk_hfpll_enable(struct clk_hw *hw)
+{
+   struct clk_hfpll *h = to_clk_hfpll(hw);
+   struct hfpll_data const *hd = h->d;
+   struct regmap *regmap = h->clkr.regmap;
+   u32 val;
+
+   __clk_hfpll_init_once(hw);
+
+   /* Disable PLL bypass mode. */
+   regmap_update_bits(regmap, hd->mode_reg, PLL_BYPASSNL, PLL_BYPASSNL);
+
+   /*
+* H/W requires a 5us delay between disabling the bypass and
+* de-asserting the reset. Delay 10us just to be safe.
+*/
+   udelay(10);
+
+   /* De-assert active-low PLL reset. */
+   regmap_update_bits(regmap, hd->mode_reg, PLL_RESET_N, PLL_RESET_N);
+
+   /* Wait for PLL to lock. */
+   if (hd->status_reg) {
+   do {
+   regmap_read(regmap, hd->status_reg, &val);
+   } while (!(val & BIT(hd->lock_bit)));
+   } else {
+   udelay(60);
+   }
+
+   /* Enable PLL output. */
+   regmap_update_bits(regmap, hd->mode_reg, PLL_OUTCTRL, PLL_OUTCTRL);
+}
+
+/* Enable an already-configured HFPLL. */
+static int clk_hfpll_enable(struct clk_hw *hw)
+{
+   unsigned long flags;
+   struct clk_hfpll *h = to_clk_hfpll(hw);
+   struct hfpll_data const *hd = h->d;
+   struct regmap *regmap = h->clkr.regmap;
+   u32 mode;
+
+   spin_lock_irqsave(&h->lock, flags);
+   regmap_read(regmap, hd->mode_reg, &mode);
+   if (!(mode & (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL)))
+   __clk_hfpll_enable(hw);
+   spin_unlock_irqrestore(&h->lock, flags);
+
+   return 0;
+}
+
+static void __clk_hfpll_disable(struct clk_hfpll *h)
+{
+   struct hfpll_data const *hd = h->d;
+   struct regmap *regmap = h->clkr.regmap;
+
+   /*
+* Disable the PLL output, disable test mode, enable the bypass mode,
+* and assert the reset.
+*/
+   regmap_update_bits(regmap, hd->mode_reg,
+  PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL, 0);
+}
+
+static void clk_hfpll_disable(struct clk_hw *hw)
+{
+   struct clk_hfpll *h = to_clk_hfpll(hw);
+   unsigned long flags;
+
+   spin_lock_irqsave(&h->lock, flags);
+   __clk_hfpll_disable(h);
+   spin_unlock_irqrestore(&h->lock, flags);
+}
+
+static long clk_hfpll_round_rate(struct clk_hw *hw, unsigned long rate,
+unsigned long *parent_rate)
+{
+   struct clk_hfpll *h = to_clk_hfpll(hw);
+   struct hfpll_data const *hd = h->d;
+   unsigned long rrate;

[PATCH 03/14] clk: qcom: Add HFPLL driver

2018-08-13 Thread Sricharan R
From: Stephen Boyd 

On some devices (MSM8974 for example), the HFPLLs are
instantiated within the Krait processor subsystem as separate
register regions. Add a driver for these PLLs so that we can
provide HFPLL clocks for use by the system.

Cc: 
Signed-off-by: Stephen Boyd 
---
 drivers/clk/qcom/Kconfig  |  8 
 drivers/clk/qcom/Makefile |  1 +
 drivers/clk/qcom/hfpll.c  | 96 +++
 3 files changed, 105 insertions(+)
 create mode 100644 drivers/clk/qcom/hfpll.c

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 9c3480d..95f9980 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -253,3 +253,11 @@ config SPMI_PMIC_CLKDIV
  Technologies, Inc. SPMI PMIC. It configures the frequency of
  clkdiv outputs of the PMIC. These clocks are typically wired
  through alternate functions on GPIO pins.
+
+config QCOM_HFPLL
+   tristate "High-Frequency PLL (HFPLL) Clock Controller"
+   depends on COMMON_CLK_QCOM
+   help
+ Support for the high-frequency PLLs present on Qualcomm devices.
+ Say Y if you want to support CPU frequency scaling on devices
+ such as MSM8974, APQ8084, etc.
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 1331ed7..d486aa3 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -42,3 +42,4 @@ obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
 obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
 obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
 obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
+obj-$(CONFIG_QCOM_HFPLL) += hfpll.o
diff --git a/drivers/clk/qcom/hfpll.c b/drivers/clk/qcom/hfpll.c
new file mode 100644
index 000..a6de7101
--- /dev/null
+++ b/drivers/clk/qcom/hfpll.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk-regmap.h"
+#include "clk-hfpll.h"
+
+static const struct hfpll_data hdata = {
+   .mode_reg = 0x00,
+   .l_reg = 0x04,
+   .m_reg = 0x08,
+   .n_reg = 0x0c,
+   .user_reg = 0x10,
+   .config_reg = 0x14,
+   .config_val = 0x430405d,
+   .status_reg = 0x1c,
+   .lock_bit = 16,
+
+   .user_val = 0x8,
+   .user_vco_mask = 0x10,
+   .low_vco_max_rate = 124800,
+   .min_rate = 53760UL,
+   .max_rate = 29UL,
+};
+
+static const struct of_device_id qcom_hfpll_match_table[] = {
+   { .compatible = "qcom,hfpll" },
+   { }
+};
+MODULE_DEVICE_TABLE(of, qcom_hfpll_match_table);
+
+static const struct regmap_config hfpll_regmap_config = {
+   .reg_bits   = 32,
+   .reg_stride = 4,
+   .val_bits   = 32,
+   .max_register   = 0x30,
+   .fast_io= true,
+};
+
+static int qcom_hfpll_probe(struct platform_device *pdev)
+{
+   struct resource *res;
+   struct device *dev = &pdev->dev;
+   void __iomem *base;
+   struct regmap *regmap;
+   struct clk_hfpll *h;
+   struct clk_init_data init = {
+   .parent_names = (const char *[]){ "xo" },
+   .num_parents = 1,
+   .ops = &clk_ops_hfpll,
+   };
+
+   h = devm_kzalloc(dev, sizeof(*h), GFP_KERNEL);
+   if (!h)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   base = devm_ioremap_resource(dev, res);
+   if (IS_ERR(base))
+   return PTR_ERR(base);
+
+   regmap = devm_regmap_init_mmio(&pdev->dev, base, &hfpll_regmap_config);
+   if (IS_ERR(regmap))
+   return PTR_ERR(regmap);
+
+   if (of_property_read_string_index(dev->of_node, "clock-output-names",
+ 0, &init.name))
+   return -ENODEV;
+
+   h->d = &hdata;
+   h->clkr.hw.init = &init;
+   spin_lock_init(&h->lock);
+
+   return devm_clk_register_regmap(&pdev->dev, &h->clkr);
+}
+
+static struct platform_driver qcom_hfpll_driver = {
+   .probe  = qcom_hfpll_probe,
+   .driver = {
+   .name   = "qcom-hfpll",
+   .of_match_table = qcom_hfpll_match_table,
+   },
+};
+module_platform_driver(qcom_hfpll_driver);
+
+MODULE_DESCRIPTION("QCOM HFPLL Clock Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:qcom-hfpll");
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 09/14] dt-bindings: arm: Document qcom,kpss-gcc

2018-08-13 Thread Sricharan R
From: Stephen Boyd 

The ACC and GCC regions present in KPSSv1 contain registers to
control clocks and power to each Krait CPU and L2. Documenting
the bindings here.

Reviewed-by: Rob Herring 
Signed-off-by: Stephen Boyd 
---
 .../devicetree/bindings/arm/msm/qcom,kpss-acc.txt  | 19 ++
 .../devicetree/bindings/arm/msm/qcom,kpss-gcc.txt  | 44 ++
 2 files changed, 63 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt

diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt 
b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt
index 1333db9..7f69636 100644
--- a/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt
@@ -21,10 +21,29 @@ PROPERTIES
the register region. An optional second element specifies
the base address and size of the alias register region.
 
+- clocks:
+Usage: required
+Value type: 
+Definition: reference to the pll parents.
+
+- clock-names:
+Usage: required
+Value type: 
+Definition: must be "pll8_vote", "pxo".
+
+- clock-output-names:
+   Usage: optional
+   Value type: 
+   Definition: Name of the output clock. Typically acpuX_aux where X is a
+   CPU number starting at 0.
+
 Example:
 
clock-controller@2088000 {
compatible = "qcom,kpss-acc-v2";
reg = <0x02088000 0x1000>,
  <0x02008000 0x1000>;
+   clocks = <&gcc PLL8_VOTE>, <&gcc PXO_SRC>;
+   clock-names = "pll8_vote", "pxo";
+   clock-output-names = "acpu0_aux";
};
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt 
b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt
new file mode 100644
index 000..e628758
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt
@@ -0,0 +1,44 @@
+Krait Processor Sub-system (KPSS) Global Clock Controller (GCC)
+
+PROPERTIES
+
+- compatible:
+   Usage: required
+   Value type: 
+   Definition: should be one of the following. The generic compatible
+   "qcom,kpss-gcc" should also be included.
+   "qcom,kpss-gcc-ipq8064", "qcom,kpss-gcc"
+   "qcom,kpss-gcc-apq8064", "qcom,kpss-gcc"
+   "qcom,kpss-gcc-msm8974", "qcom,kpss-gcc"
+   "qcom,kpss-gcc-msm8960", "qcom,kpss-gcc"
+
+- reg:
+   Usage: required
+   Value type: 
+   Definition: base address and size of the register region
+
+- clocks:
+   Usage: required
+   Value type: 
+   Definition: reference to the pll parents.
+
+- clock-names:
+   Usage: required
+   Value type: 
+   Definition: must be "pll8_vote", "pxo".
+
+- clock-output-names:
+   Usage: required
+   Value type: 
+   Definition: Name of the output clock. Typically acpu_l2_aux indicating
+   an L2 cache auxiliary clock.
+
+Example:
+
+   l2cc: clock-controller@2011000 {
+   compatible = "qcom,kpss-gcc-ipq8064", "qcom,kpss-gcc";
+   reg = <0x2011000 0x1000>;
+   clocks = <&gcc PLL8_VOTE>, <&gcc PXO_SRC>;
+   clock-names = "pll8_vote", "pxo";
+   clock-output-names = "acpu_l2_aux";
+   };
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 05/14] clk: qcom: Add MSM8960/APQ8064's HFPLLs

2018-08-13 Thread Sricharan R
From: Stephen Boyd 

Describe the HFPLLs present on MSM8960 and APQ8064 devices.

Acked-by: Rob Herring  (bindings)
Signed-off-by: Stephen Boyd 
---
 drivers/clk/qcom/gcc-msm8960.c   | 172 +++
 include/dt-bindings/clock/qcom,gcc-msm8960.h |   2 +
 2 files changed, 174 insertions(+)

diff --git a/drivers/clk/qcom/gcc-msm8960.c b/drivers/clk/qcom/gcc-msm8960.c
index eb551c7..809f16a 100644
--- a/drivers/clk/qcom/gcc-msm8960.c
+++ b/drivers/clk/qcom/gcc-msm8960.c
@@ -30,6 +30,7 @@
 #include "clk-pll.h"
 #include "clk-rcg.h"
 #include "clk-branch.h"
+#include "clk-hfpll.h"
 #include "reset.h"
 
 static struct clk_pll pll3 = {
@@ -86,6 +87,164 @@
},
 };
 
+static struct hfpll_data hfpll0_data = {
+   .mode_reg = 0x3200,
+   .l_reg = 0x3208,
+   .m_reg = 0x320c,
+   .n_reg = 0x3210,
+   .config_reg = 0x3204,
+   .status_reg = 0x321c,
+   .config_val = 0x7845c665,
+   .droop_reg = 0x3214,
+   .droop_val = 0x0108c000,
+   .min_rate = 6UL,
+   .max_rate = 18UL,
+};
+
+static struct clk_hfpll hfpll0 = {
+   .d = &hfpll0_data,
+   .clkr.hw.init = &(struct clk_init_data){
+   .parent_names = (const char *[]){ "pxo" },
+   .num_parents = 1,
+   .name = "hfpll0",
+   .ops = &clk_ops_hfpll,
+   .flags = CLK_IGNORE_UNUSED,
+   },
+   .lock = __SPIN_LOCK_UNLOCKED(hfpll0.lock),
+};
+
+static struct hfpll_data hfpll1_8064_data = {
+   .mode_reg = 0x3240,
+   .l_reg = 0x3248,
+   .m_reg = 0x324c,
+   .n_reg = 0x3250,
+   .config_reg = 0x3244,
+   .status_reg = 0x325c,
+   .config_val = 0x7845c665,
+   .droop_reg = 0x3254,
+   .droop_val = 0x0108c000,
+   .min_rate = 6UL,
+   .max_rate = 18UL,
+};
+
+static struct hfpll_data hfpll1_data = {
+   .mode_reg = 0x3300,
+   .l_reg = 0x3308,
+   .m_reg = 0x330c,
+   .n_reg = 0x3310,
+   .config_reg = 0x3304,
+   .status_reg = 0x331c,
+   .config_val = 0x7845c665,
+   .droop_reg = 0x3314,
+   .droop_val = 0x0108c000,
+   .min_rate = 6UL,
+   .max_rate = 18UL,
+};
+
+static struct clk_hfpll hfpll1 = {
+   .d = &hfpll1_data,
+   .clkr.hw.init = &(struct clk_init_data){
+   .parent_names = (const char *[]){ "pxo" },
+   .num_parents = 1,
+   .name = "hfpll1",
+   .ops = &clk_ops_hfpll,
+   .flags = CLK_IGNORE_UNUSED,
+   },
+   .lock = __SPIN_LOCK_UNLOCKED(hfpll1.lock),
+};
+
+static struct hfpll_data hfpll2_data = {
+   .mode_reg = 0x3280,
+   .l_reg = 0x3288,
+   .m_reg = 0x328c,
+   .n_reg = 0x3290,
+   .config_reg = 0x3284,
+   .status_reg = 0x329c,
+   .config_val = 0x7845c665,
+   .droop_reg = 0x3294,
+   .droop_val = 0x0108c000,
+   .min_rate = 6UL,
+   .max_rate = 18UL,
+};
+
+static struct clk_hfpll hfpll2 = {
+   .d = &hfpll2_data,
+   .clkr.hw.init = &(struct clk_init_data){
+   .parent_names = (const char *[]){ "pxo" },
+   .num_parents = 1,
+   .name = "hfpll2",
+   .ops = &clk_ops_hfpll,
+   .flags = CLK_IGNORE_UNUSED,
+   },
+   .lock = __SPIN_LOCK_UNLOCKED(hfpll2.lock),
+};
+
+static struct hfpll_data hfpll3_data = {
+   .mode_reg = 0x32c0,
+   .l_reg = 0x32c8,
+   .m_reg = 0x32cc,
+   .n_reg = 0x32d0,
+   .config_reg = 0x32c4,
+   .status_reg = 0x32dc,
+   .config_val = 0x7845c665,
+   .droop_reg = 0x32d4,
+   .droop_val = 0x0108c000,
+   .min_rate = 6UL,
+   .max_rate = 18UL,
+};
+
+static struct clk_hfpll hfpll3 = {
+   .d = &hfpll3_data,
+   .clkr.hw.init = &(struct clk_init_data){
+   .parent_names = (const char *[]){ "pxo" },
+   .num_parents = 1,
+   .name = "hfpll3",
+   .ops = &clk_ops_hfpll,
+   .flags = CLK_IGNORE_UNUSED,
+   },
+   .lock = __SPIN_LOCK_UNLOCKED(hfpll3.lock),
+};
+
+static struct hfpll_data hfpll_l2_8064_data = {
+   .mode_reg = 0x3300,
+   .l_reg = 0x3308,
+   .m_reg = 0x330c,
+   .n_reg = 0x3310,
+   .config_reg = 0x3304,
+   .status_reg = 0x331c,
+   .config_val = 0x7845c665,
+   .droop_reg = 0x3314,
+   .droop_val = 0x0108c000,
+   .min_rate = 6UL,
+   .max_rate = 18UL,
+};
+
+static struct hfpll_data hfpll_l2_data = {
+   .mode_reg = 0x3400,
+   .l_reg = 0x3408,
+   .m_reg = 0x340c,
+   .n_reg = 0x3410,
+   .config_reg = 0x3404,
+   .status_reg = 0x341c,
+   .config_val = 0x7845c665,
+   .droop_reg = 0x3414,
+   .droop_val = 0x0108c000,
+   .min_rate = 6UL,
+   .max_rate = 18UL,
+};
+
+static struct clk_hfpll hfpll_l2 = {
+   .d = &hfpll_l2_data,
+   .clkr.hw.init = &(struct clk_

[PATCH 04/14] dt-bindings: clock: Document qcom,hfpll

2018-08-13 Thread Sricharan R
From: Stephen Boyd 

Adds bindings document for qcom,hfpll instantiated within
the Krait processor subsystem as separate register region.

Reviewed-by: Rob Herring 
Signed-off-by: Stephen Boyd 
---
 .../devicetree/bindings/clock/qcom,hfpll.txt   | 60 ++
 1 file changed, 60 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,hfpll.txt

diff --git a/Documentation/devicetree/bindings/clock/qcom,hfpll.txt 
b/Documentation/devicetree/bindings/clock/qcom,hfpll.txt
new file mode 100644
index 000..ec02a02
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,hfpll.txt
@@ -0,0 +1,60 @@
+High-Frequency PLL (HFPLL)
+
+PROPERTIES
+
+- compatible:
+   Usage: required
+   Value type: :
+   shall contain only one of the following. The generic
+   compatible "qcom,hfpll" should be also included.
+
+"qcom,hfpll-ipq8064", "qcom,hfpll"
+"qcom,hfpll-apq8064", "qcom,hfpll"
+"qcom,hfpll-msm8974", "qcom,hfpll"
+"qcom,hfpll-msm8960", "qcom,hfpll"
+
+- reg:
+   Usage: required
+   Value type: 
+   Definition: address and size of HPLL registers. An optional second
+   element specifies the address and size of the alias
+   register region.
+
+- clocks:
+   Usage: required
+   Value type: 
+   Definition: reference to the xo clock.
+
+- clock-names:
+   Usage: required
+   Value type: 
+   Definition: must be "xo".
+
+- clock-output-names:
+   Usage: required
+   Value type: 
+   Definition: Name of the PLL. Typically hfpllX where X is a CPU number
+   starting at 0. Otherwise hfpll_Y where Y is more specific
+   such as "l2".
+
+Example:
+
+1) An HFPLL for the L2 cache.
+
+   clock-controller@f9016000 {
+   compatible = "qcom,hfpll-ipq8064", "qcom,hfpll";
+   reg = <0xf9016000 0x30>;
+   clocks = <&xo_board>;
+   clock-names = "xo";
+   clock-output-names = "hfpll_l2";
+   };
+
+2) An HFPLL for CPU0. This HFPLL has the alias register region.
+
+   clock-controller@f908a000 {
+   compatible = "qcom,hfpll-ipq8064", "qcom,hfpll";
+   reg = <0xf908a000 0x30>, <0xf900a000 0x30>;
+   clocks = <&xo_board>;
+   clock-names = "xo";
+   clock-output-names = "hfpll0";
+   };
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 08/14] clk: qcom: Add KPSS ACC/GCC driver

2018-08-13 Thread Sricharan R
From: Stephen Boyd 

The ACC and GCC regions present in KPSSv1 contain registers to
control clocks and power to each Krait CPU and L2. For CPUfreq
purposes probe these devices and expose a mux clock that chooses
between PXO and PLL8.

Cc: 
Signed-off-by: Stephen Boyd 
---
 drivers/clk/qcom/Kconfig|  8 +
 drivers/clk/qcom/Makefile   |  1 +
 drivers/clk/qcom/kpss-xcc.c | 87 +
 3 files changed, 96 insertions(+)
 create mode 100644 drivers/clk/qcom/kpss-xcc.c

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 66894d2..b17f638 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -262,6 +262,14 @@ config QCOM_HFPLL
  Say Y if you want to support CPU frequency scaling on devices
  such as MSM8974, APQ8084, etc.
 
+config KPSS_XCC
+   tristate "KPSS Clock Controller"
+   depends on COMMON_CLK_QCOM
+   help
+ Support for the Krait ACC and GCC clock controllers. Say Y
+ if you want to support CPU frequency scaling on devices such
+ as MSM8960, APQ8064, etc.
+
 config KRAIT_CLOCKS
bool
select KRAIT_L2_ACCESSORS
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 82615ed..b9cf068 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -43,4 +43,5 @@ obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
 obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
 obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
 obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
+obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o
 obj-$(CONFIG_QCOM_HFPLL) += hfpll.o
diff --git a/drivers/clk/qcom/kpss-xcc.c b/drivers/clk/qcom/kpss-xcc.c
new file mode 100644
index 000..8590b5e
--- /dev/null
+++ b/drivers/clk/qcom/kpss-xcc.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static const char *aux_parents[] = {
+   "pll8_vote",
+   "pxo",
+};
+
+static unsigned int aux_parent_map[] = {
+   3,
+   0,
+};
+
+static const struct of_device_id kpss_xcc_match_table[] = {
+   { .compatible = "qcom,kpss-acc-v1", .data = (void *)1UL },
+   { .compatible = "qcom,kpss-gcc" },
+   {}
+};
+MODULE_DEVICE_TABLE(of, kpss_xcc_match_table);
+
+static int kpss_xcc_driver_probe(struct platform_device *pdev)
+{
+   const struct of_device_id *id;
+   struct clk *clk;
+   struct resource *res;
+   void __iomem *base;
+   const char *name;
+
+   id = of_match_device(kpss_xcc_match_table, &pdev->dev);
+   if (!id)
+   return -ENODEV;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   base = devm_ioremap_resource(&pdev->dev, res);
+   if (IS_ERR(base))
+   return PTR_ERR(base);
+
+   if (id->data) {
+   if (of_property_read_string_index(pdev->dev.of_node,
+ "clock-output-names",
+ 0, &name))
+   return -ENODEV;
+   base += 0x14;
+   } else {
+   name = "acpu_l2_aux";
+   base += 0x28;
+   }
+
+   clk = clk_register_mux_table(&pdev->dev, name, aux_parents,
+ARRAY_SIZE(aux_parents), 0, base, 0, 0x3,
+0, aux_parent_map, NULL);
+
+   platform_set_drvdata(pdev, clk);
+
+   return PTR_ERR_OR_ZERO(clk);
+}
+
+static int kpss_xcc_driver_remove(struct platform_device *pdev)
+{
+   clk_unregister_mux(platform_get_drvdata(pdev));
+   return 0;
+}
+
+static struct platform_driver kpss_xcc_driver = {
+   .probe = kpss_xcc_driver_probe,
+   .remove = kpss_xcc_driver_remove,
+   .driver = {
+   .name = "kpss-xcc",
+   .of_match_table = kpss_xcc_match_table,
+   },
+};
+module_platform_driver(kpss_xcc_driver);
+
+MODULE_DESCRIPTION("Krait Processor Sub System (KPSS) Clock Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:kpss-xcc");
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 07/14] clk: qcom: Add support for Krait clocks

2018-08-13 Thread Sricharan R
From: Stephen Boyd 

The Krait clocks are made up of a series of muxes and a divider
that choose between a fixed rate clock and dedicated HFPLLs for
each CPU. Instead of using mmio accesses to remux parents, the
Krait implementation exposes the remux control via cp15
registers. Support these clocks.

Signed-off-by: Stephen Boyd 
---
 drivers/clk/qcom/Kconfig |   4 ++
 drivers/clk/qcom/Makefile|   1 +
 drivers/clk/qcom/clk-krait.c | 124 +++
 drivers/clk/qcom/clk-krait.h |  37 +
 4 files changed, 166 insertions(+)
 create mode 100644 drivers/clk/qcom/clk-krait.c
 create mode 100644 drivers/clk/qcom/clk-krait.h

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 95f9980..66894d2 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -261,3 +261,7 @@ config QCOM_HFPLL
  Support for the high-frequency PLLs present on Qualcomm devices.
  Say Y if you want to support CPU frequency scaling on devices
  such as MSM8974, APQ8084, etc.
+
+config KRAIT_CLOCKS
+   bool
+   select KRAIT_L2_ACCESSORS
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index d486aa3..82615ed 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -11,6 +11,7 @@ clk-qcom-y += clk-branch.o
 clk-qcom-y += clk-regmap-divider.o
 clk-qcom-y += clk-regmap-mux.o
 clk-qcom-y += clk-regmap-mux-div.o
+clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-krait.o
 clk-qcom-y += clk-hfpll.o
 clk-qcom-y += reset.o
 clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o
diff --git a/drivers/clk/qcom/clk-krait.c b/drivers/clk/qcom/clk-krait.c
new file mode 100644
index 000..2e41767
--- /dev/null
+++ b/drivers/clk/qcom/clk-krait.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "clk-krait.h"
+
+/* Secondary and primary muxes share the same cp15 register */
+static DEFINE_SPINLOCK(krait_clock_reg_lock);
+
+#define LPL_SHIFT  8
+static void __krait_mux_set_sel(struct krait_mux_clk *mux, int sel)
+{
+   unsigned long flags;
+   u32 regval;
+
+   spin_lock_irqsave(&krait_clock_reg_lock, flags);
+   regval = krait_get_l2_indirect_reg(mux->offset);
+   regval &= ~(mux->mask << mux->shift);
+   regval |= (sel & mux->mask) << mux->shift;
+   if (mux->lpl) {
+   regval &= ~(mux->mask << (mux->shift + LPL_SHIFT));
+   regval |= (sel & mux->mask) << (mux->shift + LPL_SHIFT);
+   }
+   krait_set_l2_indirect_reg(mux->offset, regval);
+   spin_unlock_irqrestore(&krait_clock_reg_lock, flags);
+
+   /* Wait for switch to complete. */
+   mb();
+   udelay(1);
+}
+
+static int krait_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+   struct krait_mux_clk *mux = to_krait_mux_clk(hw);
+   u32 sel;
+
+   sel = clk_mux_reindex(index, mux->parent_map, 0);
+   mux->en_mask = sel;
+   /* Don't touch mux if CPU is off as it won't work */
+   if (__clk_is_enabled(hw->clk))
+   __krait_mux_set_sel(mux, sel);
+
+   return 0;
+}
+
+static u8 krait_mux_get_parent(struct clk_hw *hw)
+{
+   struct krait_mux_clk *mux = to_krait_mux_clk(hw);
+   u32 sel;
+
+   sel = krait_get_l2_indirect_reg(mux->offset);
+   sel >>= mux->shift;
+   sel &= mux->mask;
+   mux->en_mask = sel;
+
+   return clk_mux_get_parent(hw, sel, mux->parent_map, 0);
+}
+
+const struct clk_ops krait_mux_clk_ops = {
+   .set_parent = krait_mux_set_parent,
+   .get_parent = krait_mux_get_parent,
+   .determine_rate = __clk_mux_determine_rate_closest,
+};
+EXPORT_SYMBOL_GPL(krait_mux_clk_ops);
+
+/* The divider can divide by 2, 4, 6 and 8. But we only really need div-2. */
+static long krait_div2_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+   *parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), rate * 2);
+   return DIV_ROUND_UP(*parent_rate, 2);
+}
+
+static int krait_div2_set_rate(struct clk_hw *hw, unsigned long rate,
+  unsigned long parent_rate)
+{
+   struct krait_div2_clk *d = to_krait_div2_clk(hw);
+   unsigned long flags;
+   u32 val;
+   u32 mask = BIT(d->width) - 1;
+
+   if (d->lpl)
+   mask = mask << (d->shift + LPL_SHIFT) | mask << d->shift;
+
+   spin_lock_irqsave(&krait_clock_reg_lock, flags);
+   val = krait_get_l2_indirect_reg(d->offset);
+   val &= ~mask;
+   krait_set_l2_indirect_reg(d->offset, val);
+   spin_unlock_irqrestore(&krait_clock_reg_lock, flags);
+
+   return 0;
+}
+
+static unsigned long
+krait_div2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+   struct krait_div2_clk *d = to_krait_div2_clk(hw);
+   u32 mask = BIT(d->width) - 1;
+ 

[PATCH 06/14] clk: qcom: Add IPQ806X's HFPLLs

2018-08-13 Thread Sricharan R
From: Stephen Boyd 

Describe the HFPLLs present on IPQ806X devices.

Signed-off-by: Stephen Boyd 
---
 drivers/clk/qcom/gcc-ipq806x.c | 82 ++
 1 file changed, 82 insertions(+)

diff --git a/drivers/clk/qcom/gcc-ipq806x.c b/drivers/clk/qcom/gcc-ipq806x.c
index 28eb200..d571cf8 100644
--- a/drivers/clk/qcom/gcc-ipq806x.c
+++ b/drivers/clk/qcom/gcc-ipq806x.c
@@ -30,6 +30,7 @@
 #include "clk-pll.h"
 #include "clk-rcg.h"
 #include "clk-branch.h"
+#include "clk-hfpll.h"
 #include "reset.h"
 
 static struct clk_pll pll0 = {
@@ -113,6 +114,84 @@
},
 };
 
+static struct hfpll_data hfpll0_data = {
+   .mode_reg = 0x3200,
+   .l_reg = 0x3208,
+   .m_reg = 0x320c,
+   .n_reg = 0x3210,
+   .config_reg = 0x3204,
+   .status_reg = 0x321c,
+   .config_val = 0x7845c665,
+   .droop_reg = 0x3214,
+   .droop_val = 0x0108c000,
+   .min_rate = 6UL,
+   .max_rate = 18UL,
+};
+
+static struct clk_hfpll hfpll0 = {
+   .d = &hfpll0_data,
+   .clkr.hw.init = &(struct clk_init_data){
+   .parent_names = (const char *[]){ "pxo" },
+   .num_parents = 1,
+   .name = "hfpll0",
+   .ops = &clk_ops_hfpll,
+   .flags = CLK_IGNORE_UNUSED,
+   },
+   .lock = __SPIN_LOCK_UNLOCKED(hfpll0.lock),
+};
+
+static struct hfpll_data hfpll1_data = {
+   .mode_reg = 0x3240,
+   .l_reg = 0x3248,
+   .m_reg = 0x324c,
+   .n_reg = 0x3250,
+   .config_reg = 0x3244,
+   .status_reg = 0x325c,
+   .config_val = 0x7845c665,
+   .droop_reg = 0x3314,
+   .droop_val = 0x0108c000,
+   .min_rate = 6UL,
+   .max_rate = 18UL,
+};
+
+static struct clk_hfpll hfpll1 = {
+   .d = &hfpll1_data,
+   .clkr.hw.init = &(struct clk_init_data){
+   .parent_names = (const char *[]){ "pxo" },
+   .num_parents = 1,
+   .name = "hfpll1",
+   .ops = &clk_ops_hfpll,
+   .flags = CLK_IGNORE_UNUSED,
+   },
+   .lock = __SPIN_LOCK_UNLOCKED(hfpll1.lock),
+};
+
+static struct hfpll_data hfpll_l2_data = {
+   .mode_reg = 0x3300,
+   .l_reg = 0x3308,
+   .m_reg = 0x330c,
+   .n_reg = 0x3310,
+   .config_reg = 0x3304,
+   .status_reg = 0x331c,
+   .config_val = 0x7845c665,
+   .droop_reg = 0x3314,
+   .droop_val = 0x0108c000,
+   .min_rate = 6UL,
+   .max_rate = 18UL,
+};
+
+static struct clk_hfpll hfpll_l2 = {
+   .d = &hfpll_l2_data,
+   .clkr.hw.init = &(struct clk_init_data){
+   .parent_names = (const char *[]){ "pxo" },
+   .num_parents = 1,
+   .name = "hfpll_l2",
+   .ops = &clk_ops_hfpll,
+   .flags = CLK_IGNORE_UNUSED,
+   },
+   .lock = __SPIN_LOCK_UNLOCKED(hfpll_l2.lock),
+};
+
 static struct clk_pll pll14 = {
.l_reg = 0x31c4,
.m_reg = 0x31c8,
@@ -2800,6 +2879,9 @@ enum {
[UBI32_CORE2_CLK_SRC] = &ubi32_core2_src_clk.clkr,
[NSSTCM_CLK_SRC] = &nss_tcm_src.clkr,
[NSSTCM_CLK] = &nss_tcm_clk.clkr,
+   [PLL9] = &hfpll0.clkr,
+   [PLL10] = &hfpll1.clkr,
+   [PLL12] = &hfpll_l2.clkr,
 };
 
 static const struct qcom_reset_map gcc_ipq806x_resets[] = {
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 11/14] dt-bindings: clock: Document qcom,krait-cc

2018-08-13 Thread Sricharan R
From: Stephen Boyd 

The Krait clock controller controls the krait CPU and the L2 clocks
consisting a primary mux and secondary mux. Add document for that.

Reviewed-by: Rob Herring 
Signed-off-by: Stephen Boyd 
---
 .../devicetree/bindings/clock/qcom,krait-cc.txt| 34 ++
 1 file changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,krait-cc.txt

diff --git a/Documentation/devicetree/bindings/clock/qcom,krait-cc.txt 
b/Documentation/devicetree/bindings/clock/qcom,krait-cc.txt
new file mode 100644
index 000..030ba60
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,krait-cc.txt
@@ -0,0 +1,34 @@
+Krait Clock Controller
+
+PROPERTIES
+
+- compatible:
+   Usage: required
+   Value type: 
+   Definition: must be one of:
+   "qcom,krait-cc-v1"
+   "qcom,krait-cc-v2"
+
+- #clock-cells:
+   Usage: required
+   Value type: 
+   Definition: must be 1
+
+- clocks:
+   Usage: required
+   Value type: 
+   Definition: reference to the clock parents of hfpll, secondary muxes.
+
+- clock-names:
+   Usage: required
+   Value type: 
+   Definition: must be "hfpll0", "hfpll1", "acpu0_aux", "acpu1_aux", "qsb".
+
+Example:
+
+   kraitcc: clock-controller {
+   compatible = "qcom,krait-cc-v1";
+   clocks = <&hfpll0>, <&hfpll1>, <&acpu0_aux>, <&acpu1_aux>, 
;
+   clock-names = "hfpll0", "hfpll1", "acpu0_aux", "acpu1_aux", 
"qsb";
+   #clock-cells = <1>;
+   };
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH 10/14] clk: qcom: Add Krait clock controller driver

2018-08-13 Thread Sricharan R
From: Stephen Boyd 

The Krait CPU clocks are made up of a primary mux and secondary
mux for each CPU and the L2, controlled via cp15 accessors. For
Kraits within KPSSv1 each secondary mux accepts a different aux
source, but on KPSSv2 each secondary mux accepts the same aux
source.

Cc: 
Signed-off-by: Stephen Boyd 
---
 drivers/clk/qcom/Kconfig |   8 +
 drivers/clk/qcom/Makefile|   1 +
 drivers/clk/qcom/clk-krait.c |   4 +-
 drivers/clk/qcom/krait-cc.c  | 341 +++
 4 files changed, 352 insertions(+), 2 deletions(-)
 create mode 100644 drivers/clk/qcom/krait-cc.c

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index b17f638..4d0b88f 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -270,6 +270,14 @@ config KPSS_XCC
  if you want to support CPU frequency scaling on devices such
  as MSM8960, APQ8064, etc.
 
+config KRAITCC
+   tristate "Krait Clock Controller"
+   depends on COMMON_CLK_QCOM && ARM
+   select KRAIT_CLOCKS
+   help
+ Support for the Krait CPU clocks on Qualcomm devices.
+ Say Y if you want to support CPU frequency scaling.
+
 config KRAIT_CLOCKS
bool
select KRAIT_L2_ACCESSORS
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index b9cf068..dd30198 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -45,3 +45,4 @@ obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
 obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
 obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o
 obj-$(CONFIG_QCOM_HFPLL) += hfpll.o
+obj-$(CONFIG_KRAITCC) += krait-cc.o
diff --git a/drivers/clk/qcom/clk-krait.c b/drivers/clk/qcom/clk-krait.c
index 2e41767..7ede744 100644
--- a/drivers/clk/qcom/clk-krait.c
+++ b/drivers/clk/qcom/clk-krait.c
@@ -44,7 +44,7 @@ static int krait_mux_set_parent(struct clk_hw *hw, u8 index)
struct krait_mux_clk *mux = to_krait_mux_clk(hw);
u32 sel;
 
-   sel = clk_mux_reindex(index, mux->parent_map, 0);
+   sel = clk_mux_index_to_val(mux->parent_map, 0, index);
mux->en_mask = sel;
/* Don't touch mux if CPU is off as it won't work */
if (__clk_is_enabled(hw->clk))
@@ -63,7 +63,7 @@ static u8 krait_mux_get_parent(struct clk_hw *hw)
sel &= mux->mask;
mux->en_mask = sel;
 
-   return clk_mux_get_parent(hw, sel, mux->parent_map, 0);
+   return clk_mux_val_to_index(hw, mux->parent_map, 0, sel);
 }
 
 const struct clk_ops krait_mux_clk_ops = {
diff --git a/drivers/clk/qcom/krait-cc.c b/drivers/clk/qcom/krait-cc.c
new file mode 100644
index 000..7c9dfb0
--- /dev/null
+++ b/drivers/clk/qcom/krait-cc.c
@@ -0,0 +1,341 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk-krait.h"
+
+static unsigned int sec_mux_map[] = {
+   2,
+   0,
+};
+
+static unsigned int pri_mux_map[] = {
+   1,
+   2,
+   0,
+};
+
+static int
+krait_add_div(struct device *dev, int id, const char *s, unsigned int offset)
+{
+   struct krait_div2_clk *div;
+   struct clk_init_data init = {
+   .num_parents = 1,
+   .ops = &krait_div2_clk_ops,
+   .flags = CLK_SET_RATE_PARENT,
+   };
+   const char *p_names[1];
+   struct clk *clk;
+
+   div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
+   if (!div)
+   return -ENOMEM;
+
+   div->width = 2;
+   div->shift = 6;
+   div->lpl = id >= 0;
+   div->offset = offset;
+   div->hw.init = &init;
+
+   init.name = kasprintf(GFP_KERNEL, "hfpll%s_div", s);
+   if (!init.name)
+   return -ENOMEM;
+
+   init.parent_names = p_names;
+   p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s);
+   if (!p_names[0]) {
+   kfree(init.name);
+   return -ENOMEM;
+   }
+
+   clk = devm_clk_register(dev, &div->hw);
+   kfree(p_names[0]);
+   kfree(init.name);
+
+   return PTR_ERR_OR_ZERO(clk);
+}
+
+static int
+krait_add_sec_mux(struct device *dev, int id, const char *s,
+ unsigned int offset, bool unique_aux)
+{
+   struct krait_mux_clk *mux;
+   static const char *sec_mux_list[] = {
+   "acpu_aux",
+   "qsb",
+   };
+   struct clk_init_data init = {
+   .parent_names = sec_mux_list,
+   .num_parents = ARRAY_SIZE(sec_mux_list),
+   .ops = &krait_mux_clk_ops,
+   .flags = CLK_SET_RATE_PARENT,
+   };
+   struct clk *clk;
+
+   mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+   if (!mux)
+   return -ENOMEM;
+
+   mux->offset = offset;
+   mux->lpl = id >= 0;
+   mux->mask = 0x3;
+   mux->shift = 2;
+   mux->parent_map = sec_mux_map;
+  

[PATCH 12/14] clk: qcom: Add safe switch hook for krait mux clocks

2018-08-13 Thread Sricharan R
When the Hfplls are reprogrammed during the rate change,
the primary muxes which are sourced from the same hfpll
for higher frequencies, needs to be switched to the 'safe
secondary mux' as the parent for that small window. This
is done by registering a clk notifier for the muxes and
switching to the safe parent in the PRE_RATE_CHANGE notifier
and back to the original parent in the POST_RATE_CHANGE notifier.

Signed-off-by: Sricharan R 
---
 drivers/clk/qcom/clk-krait.c |  2 ++
 drivers/clk/qcom/clk-krait.h |  3 +++
 drivers/clk/qcom/krait-cc.c  | 56 
 3 files changed, 61 insertions(+)

diff --git a/drivers/clk/qcom/clk-krait.c b/drivers/clk/qcom/clk-krait.c
index 7ede744..59f1af4 100644
--- a/drivers/clk/qcom/clk-krait.c
+++ b/drivers/clk/qcom/clk-krait.c
@@ -50,6 +50,8 @@ static int krait_mux_set_parent(struct clk_hw *hw, u8 index)
if (__clk_is_enabled(hw->clk))
__krait_mux_set_sel(mux, sel);
 
+   mux->reparent = true;
+
return 0;
 }
 
diff --git a/drivers/clk/qcom/clk-krait.h b/drivers/clk/qcom/clk-krait.h
index 441ba1e..9120bd2 100644
--- a/drivers/clk/qcom/clk-krait.h
+++ b/drivers/clk/qcom/clk-krait.h
@@ -12,6 +12,9 @@ struct krait_mux_clk {
u32 shift;
u32 en_mask;
boollpl;
+   u8  safe_sel;
+   u8  old_index;
+   boolreparent;
 
struct clk_hw   hw;
struct notifier_block   clk_nb;
diff --git a/drivers/clk/qcom/krait-cc.c b/drivers/clk/qcom/krait-cc.c
index 7c9dfb0..4d4b657 100644
--- a/drivers/clk/qcom/krait-cc.c
+++ b/drivers/clk/qcom/krait-cc.c
@@ -26,6 +26,49 @@
0,
 };
 
+/*
+ * Notifier function for switching the muxes to safe parent
+ * while the hfpll is getting reprogrammed.
+ */
+static int krait_notifier_cb(struct notifier_block *nb,
+unsigned long event,
+void *data)
+{
+   int ret = 0;
+   struct krait_mux_clk *mux = container_of(nb, struct krait_mux_clk,
+clk_nb);
+   /* Switch to safe parent */
+   if (event == PRE_RATE_CHANGE) {
+   mux->old_index = krait_mux_clk_ops.get_parent(&mux->hw);
+   ret = krait_mux_clk_ops.set_parent(&mux->hw, mux->safe_sel);
+   mux->reparent = false;
+   /*
+* By the time POST_RATE_CHANGE notifier is called,
+* clk framework itself would have changed the parent for the new rate.
+* Only otherwise, put back to the old parent.
+*/
+   } else if (event == POST_RATE_CHANGE) {
+   if (!mux->reparent)
+   ret = krait_mux_clk_ops.set_parent(&mux->hw,
+  mux->old_index);
+   }
+
+   return notifier_from_errno(ret);
+}
+
+static int krait_notifier_register(struct device *dev, struct clk *clk,
+  struct krait_mux_clk *mux)
+{
+   int ret = 0;
+
+   mux->clk_nb.notifier_call = krait_notifier_cb;
+   ret = clk_notifier_register(clk, &mux->clk_nb);
+   if (ret)
+   dev_err(dev, "failed to register clock notifier: %d\n", ret);
+
+   return ret;
+}
+
 static int
 krait_add_div(struct device *dev, int id, const char *s, unsigned int offset)
 {
@@ -70,6 +113,7 @@
 krait_add_sec_mux(struct device *dev, int id, const char *s,
  unsigned int offset, bool unique_aux)
 {
+   int ret;
struct krait_mux_clk *mux;
static const char *sec_mux_list[] = {
"acpu_aux",
@@ -93,6 +137,7 @@
mux->shift = 2;
mux->parent_map = sec_mux_map;
mux->hw.init = &init;
+   mux->safe_sel = 0;
 
init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
if (!init.name)
@@ -108,6 +153,11 @@
 
clk = devm_clk_register(dev, &mux->hw);
 
+   ret = krait_notifier_register(dev, clk, mux);
+   if (ret)
+   goto unique_aux;
+
+unique_aux:
if (unique_aux)
kfree(sec_mux_list[0]);
 err_aux:
@@ -119,6 +169,7 @@
 krait_add_pri_mux(struct device *dev, int id, const char *s,
  unsigned int offset)
 {
+   int ret;
struct krait_mux_clk *mux;
const char *p_names[3];
struct clk_init_data init = {
@@ -139,6 +190,7 @@
mux->lpl = id >= 0;
mux->parent_map = pri_mux_map;
mux->hw.init = &init;
+   mux->safe_sel = 2;
 
init.name = kasprintf(GFP_KERNEL, "krait%s_pri_mux", s);
if (!init.name)
@@ -164,6 +216,10 @@
 
clk = devm_clk_register(dev, &mux->hw);
 
+   ret = krait_notifier_register(dev, clk, mux);
+   if (ret)
+   goto err_p3;
+err_p3:
kfree(p_names[2]);

[PATCH 14/14] cpufreq: qcom: Add support for krait based socs

2018-08-13 Thread Sricharan R
In Certain QCOM SoCs like ipq8064, apq8064, msm8960, msm8974
that has KRAIT processors the voltage/current value of each OPP
varies based on the silicon variant in use.

The required OPP related data is determined based on
the efuse value. This is similar to the existing code for
kryo cores. So adding support for krait cores here.

Signed-off-by: Sricharan R 
---
 .../devicetree/bindings/opp/qcom-nvmem-cpufreq.txt |   3 +-
 drivers/cpufreq/Kconfig.arm|   2 +-
 drivers/cpufreq/cpufreq-dt-platdev.c   |   5 +
 drivers/cpufreq/qcom-cpufreq-nvmem.c   | 151 +++--
 4 files changed, 149 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt 
b/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt
index 6dcdfcd..7bc0f1a 100644
--- a/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt
+++ b/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt
@@ -19,7 +19,8 @@ In 'cpus' nodes:
 
 In 'operating-points-v2' table:
 - compatible: Should be
-   - 'operating-points-v2-qcom-cpu' for apq8096 and msm8996.
+   - 'operating-points-v2-qcom-cpu' for apq8096, msm8996, msm8974,
+apq8064, msm8960 and ipq8074.
 - nvmem-cells: A phandle pointing to a nvmem-cells node representing the
efuse registers that has information about the
speedbin that is used to select the right frequency/voltage
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 13fbd97..497ae89 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -126,7 +126,7 @@ config ARM_OMAP2PLUS_CPUFREQ
 
 config ARM_QCOM_CPUFREQ_NVMEM
tristate "Qualcomm nvmem based CPUFreq"
-   depends on ARM64
+   depends on ARCH_QCOM
depends on QCOM_QFPROM
depends on QCOM_SMEM
select PM_OPP
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c 
b/drivers/cpufreq/cpufreq-dt-platdev.c
index fe14c57..917cdc2 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -128,6 +128,11 @@
{ .compatible = "ti,am43", },
{ .compatible = "ti,dra7", },
 
+   { .compatible = "qcom,ipq8064", },
+   { .compatible = "qcom,apq8064", },
+   { .compatible = "qcom,msm8974", },
+   { .compatible = "qcom,msm8960", },
+
{ }
 };
 
diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c 
b/drivers/cpufreq/qcom-cpufreq-nvmem.c
index 0ad8e5b..5f2add0 100644
--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
@@ -45,6 +45,82 @@ enum _msm8996_version {
 
 static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev;
 
+static void __init get_krait_bin_format_a(int *speed, int *pvs, int *pvs_ver,
+ struct nvmem_cell *pvs_nvmem, u8 *buf)
+{
+   u32 pte_efuse;
+
+   pte_efuse = *((u32 *)buf);
+
+   *speed = pte_efuse & 0xf;
+   if (*speed == 0xf)
+   *speed = (pte_efuse >> 4) & 0xf;
+
+   if (*speed == 0xf) {
+   *speed = 0;
+   pr_warn("Speed bin: Defaulting to %d\n", *speed);
+   } else {
+   pr_info("Speed bin: %d\n", *speed);
+   }
+
+   *pvs = (pte_efuse >> 10) & 0x7;
+   if (*pvs == 0x7)
+   *pvs = (pte_efuse >> 13) & 0x7;
+
+   if (*pvs == 0x7) {
+   *pvs = 0;
+   pr_warn("PVS bin: Defaulting to %d\n", *pvs);
+   } else {
+   pr_info("PVS bin: %d\n", *pvs);
+   }
+
+   kfree(buf);
+}
+
+static void __init get_krait_bin_format_b(int *speed, int *pvs, int *pvs_ver,
+ struct nvmem_cell *pvs_nvmem, u8 *buf)
+{
+   u32 pte_efuse, redundant_sel;
+
+   pte_efuse = *((u32 *)buf);
+   redundant_sel = (pte_efuse >> 24) & 0x7;
+   *speed = pte_efuse & 0x7;
+
+   /* 4 bits of PVS are in efuse register bits 31, 8-6. */
+   *pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7);
+   *pvs_ver = (pte_efuse >> 4) & 0x3;
+
+   switch (redundant_sel) {
+   case 1:
+   *speed = (pte_efuse >> 27) & 0xf;
+   break;
+   case 2:
+   *pvs = (pte_efuse >> 27) & 0xf;
+   break;
+   }
+
+   /* Check SPEED_BIN_BLOW_STATUS */
+   if (pte_efuse & BIT(3)) {
+   pr_info("Speed bin: %d\n", *speed);
+   } else {
+   pr_warn("Speed bin not set. Defaulting to 0!\n");
+   *speed = 0;
+   }
+
+   /* Check PVS_BLOW_STATUS */
+   pte_efuse = *(((u32 *)buf) + 4);
+   pte_efuse &= BIT(21);
+

[PATCH 13/14] cpufreq: qcom: Re-organise kryo cpufreq to use it for other nvmem based qcom socs

2018-08-13 Thread Sricharan R
The kryo cpufreq driver reads the nvmem cell and uses that data to
populate the opps. There are other qcom cpufreq socs like krait which
does similar thing. Except for the interpretation of the read data,
rest of the driver is same for both the cases. So pull the common things
out for reuse.

Signed-off-by: Sricharan R 
---
 .../{kryo-cpufreq.txt => qcom-nvmem-cpufreq.txt}   |   6 +-
 drivers/cpufreq/Kconfig.arm|   4 +-
 drivers/cpufreq/Makefile   |   2 +-
 .../{qcom-cpufreq-kryo.c => qcom-cpufreq-nvmem.c}  | 124 -
 4 files changed, 80 insertions(+), 56 deletions(-)
 rename Documentation/devicetree/bindings/opp/{kryo-cpufreq.txt => 
qcom-nvmem-cpufreq.txt} (99%)
 rename drivers/cpufreq/{qcom-cpufreq-kryo.c => qcom-cpufreq-nvmem.c} (65%)

diff --git a/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt 
b/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt
similarity index 99%
rename from Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
rename to Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt
index c2127b9..6dcdfcd 100644
--- a/Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
+++ b/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt
@@ -19,7 +19,7 @@ In 'cpus' nodes:
 
 In 'operating-points-v2' table:
 - compatible: Should be
-   - 'operating-points-v2-kryo-cpu' for apq8096 and msm8996.
+   - 'operating-points-v2-qcom-cpu' for apq8096 and msm8996.
 - nvmem-cells: A phandle pointing to a nvmem-cells node representing the
efuse registers that has information about the
speedbin that is used to select the right frequency/voltage
@@ -127,7 +127,7 @@ Example 1:
};
 
cluster0_opp: opp_table0 {
-   compatible = "operating-points-v2-kryo-cpu";
+   compatible = "operating-points-v2-qcom-cpu";
nvmem-cells = <&speedbin_efuse>;
opp-shared;
 
@@ -338,7 +338,7 @@ Example 1:
};
 
cluster1_opp: opp_table1 {
-   compatible = "operating-points-v2-kryo-cpu";
+   compatible = "operating-points-v2-qcom-cpu";
nvmem-cells = <&speedbin_efuse>;
opp-shared;
 
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 52f5f1a..13fbd97 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -124,8 +124,8 @@ config ARM_OMAP2PLUS_CPUFREQ
depends on ARCH_OMAP2PLUS
default ARCH_OMAP2PLUS
 
-config ARM_QCOM_CPUFREQ_KRYO
-   tristate "Qualcomm Kryo based CPUFreq"
+config ARM_QCOM_CPUFREQ_NVMEM
+   tristate "Qualcomm nvmem based CPUFreq"
depends on ARM64
depends on QCOM_QFPROM
depends on QCOM_SMEM
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index fb4a2ec..551 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -65,7 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7)   += mvebu-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)+= omap-cpufreq.o
 obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)   += pxa2xx-cpufreq.o
 obj-$(CONFIG_PXA3xx)   += pxa3xx-cpufreq.o
-obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO)+= qcom-cpufreq-kryo.o
+obj-$(CONFIG_ARM_QCOM_CPUFREQ_NVMEM)   += qcom-cpufreq-nvmem.o
 obj-$(CONFIG_ARM_S3C2410_CPUFREQ)  += s3c2410-cpufreq.o
 obj-$(CONFIG_ARM_S3C2412_CPUFREQ)  += s3c2412-cpufreq.o
 obj-$(CONFIG_ARM_S3C2416_CPUFREQ)  += s3c2416-cpufreq.o
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c 
b/drivers/cpufreq/qcom-cpufreq-nvmem.c
similarity index 65%
rename from drivers/cpufreq/qcom-cpufreq-kryo.c
rename to drivers/cpufreq/qcom-cpufreq-nvmem.c
index efc9a7a..0ad8e5b 100644
--- a/drivers/cpufreq/qcom-cpufreq-kryo.c
+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
@@ -9,7 +9,7 @@
  * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
  * defines the voltage and frequency value based on the msm-id in SMEM
  * and speedbin blown in the efuse combination.
- * The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC
+ * The qcom-cpufreq driver reads the msm-id and efuse value from the SoC
  * to provide the OPP framework with required information.
  * This is used to determine the voltage and frequency value for each OPP of
  * operating-points-v2 table when it is parsed by the OPP framework.
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -42,9 +43,9 @@ enum _msm8996_version {
NUM_OF_MSM8996_VERSIONS,
 };
 
-struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev;
+static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev;
 
-static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
+static enum _msm8996_version __init qcom_cpufreq_get_msm_id(void)
 {

[PATCH v12 03/14] clk: qcom: Add HFPLL driver

2018-08-14 Thread Sricharan R
From: Stephen Boyd 

On some devices (MSM8974 for example), the HFPLLs are
instantiated within the Krait processor subsystem as separate
register regions. Add a driver for these PLLs so that we can
provide HFPLL clocks for use by the system.

Cc: 
Signed-off-by: Stephen Boyd 
Signed-off-by: Sricharan R 
---
 drivers/clk/qcom/Kconfig  |  8 
 drivers/clk/qcom/Makefile |  1 +
 drivers/clk/qcom/hfpll.c  | 96 +++
 3 files changed, 105 insertions(+)
 create mode 100644 drivers/clk/qcom/hfpll.c

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 0647686..21aec10 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -272,3 +272,11 @@ config SPMI_PMIC_CLKDIV
  Technologies, Inc. SPMI PMIC. It configures the frequency of
  clkdiv outputs of the PMIC. These clocks are typically wired
  through alternate functions on GPIO pins.
+
+config QCOM_HFPLL
+   tristate "High-Frequency PLL (HFPLL) Clock Controller"
+   depends on COMMON_CLK_QCOM
+   help
+ Support for the high-frequency PLLs present on Qualcomm devices.
+ Say Y if you want to support CPU frequency scaling on devices
+ such as MSM8974, APQ8084, etc.
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 7818e6c..f82eeac 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -44,3 +44,4 @@ obj-$(CONFIG_SDM_DISPCC_845) += dispcc-sdm845.o
 obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
 obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
 obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
+obj-$(CONFIG_QCOM_HFPLL) += hfpll.o
diff --git a/drivers/clk/qcom/hfpll.c b/drivers/clk/qcom/hfpll.c
new file mode 100644
index 000..a6de7101
--- /dev/null
+++ b/drivers/clk/qcom/hfpll.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk-regmap.h"
+#include "clk-hfpll.h"
+
+static const struct hfpll_data hdata = {
+   .mode_reg = 0x00,
+   .l_reg = 0x04,
+   .m_reg = 0x08,
+   .n_reg = 0x0c,
+   .user_reg = 0x10,
+   .config_reg = 0x14,
+   .config_val = 0x430405d,
+   .status_reg = 0x1c,
+   .lock_bit = 16,
+
+   .user_val = 0x8,
+   .user_vco_mask = 0x10,
+   .low_vco_max_rate = 124800,
+   .min_rate = 53760UL,
+   .max_rate = 29UL,
+};
+
+static const struct of_device_id qcom_hfpll_match_table[] = {
+   { .compatible = "qcom,hfpll" },
+   { }
+};
+MODULE_DEVICE_TABLE(of, qcom_hfpll_match_table);
+
+static const struct regmap_config hfpll_regmap_config = {
+   .reg_bits   = 32,
+   .reg_stride = 4,
+   .val_bits   = 32,
+   .max_register   = 0x30,
+   .fast_io= true,
+};
+
+static int qcom_hfpll_probe(struct platform_device *pdev)
+{
+   struct resource *res;
+   struct device *dev = &pdev->dev;
+   void __iomem *base;
+   struct regmap *regmap;
+   struct clk_hfpll *h;
+   struct clk_init_data init = {
+   .parent_names = (const char *[]){ "xo" },
+   .num_parents = 1,
+   .ops = &clk_ops_hfpll,
+   };
+
+   h = devm_kzalloc(dev, sizeof(*h), GFP_KERNEL);
+   if (!h)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   base = devm_ioremap_resource(dev, res);
+   if (IS_ERR(base))
+   return PTR_ERR(base);
+
+   regmap = devm_regmap_init_mmio(&pdev->dev, base, &hfpll_regmap_config);
+   if (IS_ERR(regmap))
+   return PTR_ERR(regmap);
+
+   if (of_property_read_string_index(dev->of_node, "clock-output-names",
+ 0, &init.name))
+   return -ENODEV;
+
+   h->d = &hdata;
+   h->clkr.hw.init = &init;
+   spin_lock_init(&h->lock);
+
+   return devm_clk_register_regmap(&pdev->dev, &h->clkr);
+}
+
+static struct platform_driver qcom_hfpll_driver = {
+   .probe  = qcom_hfpll_probe,
+   .driver = {
+   .name   = "qcom-hfpll",
+   .of_match_table = qcom_hfpll_match_table,
+   },
+};
+module_platform_driver(qcom_hfpll_driver);
+
+MODULE_DESCRIPTION("QCOM HFPLL Clock Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:qcom-hfpll");
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



[PATCH v12 02/14] clk: qcom: Add support for High-Frequency PLLs (HFPLLs)

2018-08-14 Thread Sricharan R
From: Stephen Boyd 

HFPLLs are the main frequency source for Krait CPU clocks. Add
support for changing the rate of these PLLs.

Signed-off-by: Stephen Boyd 
Signed-off-by: Sricharan R 
---
 drivers/clk/qcom/Makefile|   1 +
 drivers/clk/qcom/clk-hfpll.c | 244 +++
 drivers/clk/qcom/clk-hfpll.h |  44 
 3 files changed, 289 insertions(+)
 create mode 100644 drivers/clk/qcom/clk-hfpll.c
 create mode 100644 drivers/clk/qcom/clk-hfpll.h

diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 21a4503..7818e6c 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -11,6 +11,7 @@ clk-qcom-y += clk-branch.o
 clk-qcom-y += clk-regmap-divider.o
 clk-qcom-y += clk-regmap-mux.o
 clk-qcom-y += clk-regmap-mux-div.o
+clk-qcom-y += clk-hfpll.o
 clk-qcom-y += reset.o
 clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o
 
diff --git a/drivers/clk/qcom/clk-hfpll.c b/drivers/clk/qcom/clk-hfpll.c
new file mode 100644
index 000..3c04805
--- /dev/null
+++ b/drivers/clk/qcom/clk-hfpll.c
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk-regmap.h"
+#include "clk-hfpll.h"
+
+#define PLL_OUTCTRLBIT(0)
+#define PLL_BYPASSNL   BIT(1)
+#define PLL_RESET_NBIT(2)
+
+/* Initialize a HFPLL at a given rate and enable it. */
+static void __clk_hfpll_init_once(struct clk_hw *hw)
+{
+   struct clk_hfpll *h = to_clk_hfpll(hw);
+   struct hfpll_data const *hd = h->d;
+   struct regmap *regmap = h->clkr.regmap;
+
+   if (likely(h->init_done))
+   return;
+
+   /* Configure PLL parameters for integer mode. */
+   if (hd->config_val)
+   regmap_write(regmap, hd->config_reg, hd->config_val);
+   regmap_write(regmap, hd->m_reg, 0);
+   regmap_write(regmap, hd->n_reg, 1);
+
+   if (hd->user_reg) {
+   u32 regval = hd->user_val;
+   unsigned long rate;
+
+   rate = clk_hw_get_rate(hw);
+
+   /* Pick the right VCO. */
+   if (hd->user_vco_mask && rate > hd->low_vco_max_rate)
+   regval |= hd->user_vco_mask;
+   regmap_write(regmap, hd->user_reg, regval);
+   }
+
+   if (hd->droop_reg)
+   regmap_write(regmap, hd->droop_reg, hd->droop_val);
+
+   h->init_done = true;
+}
+
+static void __clk_hfpll_enable(struct clk_hw *hw)
+{
+   struct clk_hfpll *h = to_clk_hfpll(hw);
+   struct hfpll_data const *hd = h->d;
+   struct regmap *regmap = h->clkr.regmap;
+   u32 val;
+
+   __clk_hfpll_init_once(hw);
+
+   /* Disable PLL bypass mode. */
+   regmap_update_bits(regmap, hd->mode_reg, PLL_BYPASSNL, PLL_BYPASSNL);
+
+   /*
+* H/W requires a 5us delay between disabling the bypass and
+* de-asserting the reset. Delay 10us just to be safe.
+*/
+   udelay(10);
+
+   /* De-assert active-low PLL reset. */
+   regmap_update_bits(regmap, hd->mode_reg, PLL_RESET_N, PLL_RESET_N);
+
+   /* Wait for PLL to lock. */
+   if (hd->status_reg) {
+   do {
+   regmap_read(regmap, hd->status_reg, &val);
+   } while (!(val & BIT(hd->lock_bit)));
+   } else {
+   udelay(60);
+   }
+
+   /* Enable PLL output. */
+   regmap_update_bits(regmap, hd->mode_reg, PLL_OUTCTRL, PLL_OUTCTRL);
+}
+
+/* Enable an already-configured HFPLL. */
+static int clk_hfpll_enable(struct clk_hw *hw)
+{
+   unsigned long flags;
+   struct clk_hfpll *h = to_clk_hfpll(hw);
+   struct hfpll_data const *hd = h->d;
+   struct regmap *regmap = h->clkr.regmap;
+   u32 mode;
+
+   spin_lock_irqsave(&h->lock, flags);
+   regmap_read(regmap, hd->mode_reg, &mode);
+   if (!(mode & (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL)))
+   __clk_hfpll_enable(hw);
+   spin_unlock_irqrestore(&h->lock, flags);
+
+   return 0;
+}
+
+static void __clk_hfpll_disable(struct clk_hfpll *h)
+{
+   struct hfpll_data const *hd = h->d;
+   struct regmap *regmap = h->clkr.regmap;
+
+   /*
+* Disable the PLL output, disable test mode, enable the bypass mode,
+* and assert the reset.
+*/
+   regmap_update_bits(regmap, hd->mode_reg,
+  PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL, 0);
+}
+
+static void clk_hfpll_disable(struct clk_hw *hw)
+{
+   struct clk_hfpll *h = to_clk_hfpll(hw);
+   unsigned long flags;
+
+   spin_lock_irqsave(&h->lock, flags);
+   __clk_hfpll_disable(h);
+   spin_unlock_irqrestore(&h->lock, flags);
+}
+
+static long clk_hfpll_round_rate(struct clk_hw *hw, uns

[PATCH V12 00/14] Krait clocks + Krait CPUfreq

2018-08-14 Thread Sricharan R
cy.

When switching rates we can't leave the CPU clocked by the HFPLL because
we need to turn off the output of the PLL when changing its frequency.
This means we have to switch over to the secondary mux and use one of the
fixed sources. This is why we need something like the safe parent patch.

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-March/332607.html
[2] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-March/332615.html
[3] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-March/332608.html
[4] https://lwn.net/Articles/740994/ 
[5] https://lkml.org/lkml/2017/12/19/537


Sricharan R (3):
  clk: qcom: Add safe switch hook for krait mux clocks
  cpufreq: qcom: Re-organise kryo cpufreq to use it for other nvmem
based qcom socs
  cpufreq: qcom: Add support for krait based socs

Stephen Boyd (11):
  ARM: Add Krait L2 register accessor functions
  clk: qcom: Add support for High-Frequency PLLs (HFPLLs)
  clk: qcom: Add HFPLL driver
  dt-bindings: clock: Document qcom,hfpll
  clk: qcom: Add MSM8960/APQ8064's HFPLLs
  clk: qcom: Add IPQ806X's HFPLLs
  clk: qcom: Add support for Krait clocks
  clk: qcom: Add KPSS ACC/GCC driver
  dt-bindings: arm: Document qcom,kpss-gcc
  clk: qcom: Add Krait clock controller driver
  dt-bindings: clock: Document qcom,krait-cc

 .../devicetree/bindings/arm/msm/qcom,kpss-acc.txt  |  19 +
 .../devicetree/bindings/arm/msm/qcom,kpss-gcc.txt  |  44 +++
 .../devicetree/bindings/clock/qcom,hfpll.txt   |  60 
 .../devicetree/bindings/clock/qcom,krait-cc.txt|  34 ++
 .../{kryo-cpufreq.txt => qcom-nvmem-cpufreq.txt}   |   7 +-
 arch/arm/common/Kconfig|   3 +
 arch/arm/common/Makefile   |   1 +
 arch/arm/common/krait-l2-accessors.c   |  48 +++
 arch/arm/include/asm/krait-l2-accessors.h  |   9 +
 drivers/clk/qcom/Kconfig   |  28 ++
 drivers/clk/qcom/Makefile  |   5 +
 drivers/clk/qcom/clk-hfpll.c   | 244 +
 drivers/clk/qcom/clk-hfpll.h   |  44 +++
 drivers/clk/qcom/clk-krait.c   | 126 +++
 drivers/clk/qcom/clk-krait.h   |  40 +++
 drivers/clk/qcom/gcc-ipq806x.c |  82 +
 drivers/clk/qcom/gcc-msm8960.c | 172 +
 drivers/clk/qcom/hfpll.c   |  96 +
 drivers/clk/qcom/kpss-xcc.c|  87 +
 drivers/clk/qcom/krait-cc.c| 397 +
 drivers/cpufreq/Kconfig.arm|   6 +-
 drivers/cpufreq/Makefile   |   2 +-
 drivers/cpufreq/cpufreq-dt-platdev.c   |   5 +
 drivers/cpufreq/qcom-cpufreq-kryo.c| 232 
 drivers/cpufreq/qcom-cpufreq-nvmem.c   | 387 
 include/dt-bindings/clock/qcom,gcc-msm8960.h   |   2 +
 26 files changed, 1941 insertions(+), 239 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,hfpll.txt
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,krait-cc.txt
 rename Documentation/devicetree/bindings/opp/{kryo-cpufreq.txt => 
qcom-nvmem-cpufreq.txt} (98%)
 create mode 100644 arch/arm/common/krait-l2-accessors.c
 create mode 100644 arch/arm/include/asm/krait-l2-accessors.h
 create mode 100644 drivers/clk/qcom/clk-hfpll.c
 create mode 100644 drivers/clk/qcom/clk-hfpll.h
 create mode 100644 drivers/clk/qcom/clk-krait.c
 create mode 100644 drivers/clk/qcom/clk-krait.h
 create mode 100644 drivers/clk/qcom/hfpll.c
 create mode 100644 drivers/clk/qcom/kpss-xcc.c
 create mode 100644 drivers/clk/qcom/krait-cc.c
 delete mode 100644 drivers/cpufreq/qcom-cpufreq-kryo.c
 create mode 100644 drivers/cpufreq/qcom-cpufreq-nvmem.c

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation



  1   2   3   4   5   6   7   8   9   >