Devicetree
 help / color / mirror / Atom feed
* Re: Extending OPP bindings
From: Nishanth Menon @ 2014-01-31  0:43 UTC (permalink / raw)
  To: Sudeep Holla, devicetree@vger.kernel.org
  Cc: linux-arm-kernel@lists.infradead.org, linux-pm@vger.kernel.org,
	Lorenzo Pieralisi, Mark Rutland, Charles Garcia-Tobin,
	Rob Herring, grant.likely@linaro.org, Morten Rasmussen, Shawn Guo,
	mturquette@linaro.org, Mark Brown, Eduardo Valentin,
	Sudeep KarkadaNagesha
In-Reply-To: <52EA570A.8040501@arm.com>

Hi Sudeep,

On 01/30/2014 07:43 AM, Sudeep Holla wrote:

> 
> I am looking into a couple shortcomings in the current OPP bindings and
> how to address them. Feel free to add to the list if you think of any more
> issues that needs to be addressed or if and how any problem mentioned below
> can be handled with the existing bindings.
> 
> 1. indexing: currently there are no indices in the operating-points.
indexing is based on frequency which is why the accessors use
frequency to pull out the OPP data.

indexing is a horrible idea - on platforms where OPP may be disabled
or enabled for various reasons(see arch/arm/mach-imx/mach-imx6q.c,
arch/arm/mach-omap2/board-omap3beagle.c etc) - the indexing you see in
dts is just a myth that may not exist once the nodes are loaded and
operated upon depending on SoC variations (example efuse describing
which OPPs can be used and which not).

That said, the original OPP[1][2] series discussion started by trying
to kill indexing precisely for the same reason.. once you have it - it
becomes just crazy to deal with.

> 	It's assumed that the list is either in ascending or descending
> 	order of frequency but not explicit in the binding document.
> 	There are arch/arm/boot/dts/* files with opps in both styles.
it should not matter -> opp library should do an insertion sort and
organize it in ascending order once all the data is inserted. (line
449ish in opp.c)

if you see issues with the insertion sort not functioning, it is a bug
and should be easy to track down and fix.

> 	Few other bindings like thermal defines bindings like
> 	cooling-{min,max}-state assuming some order which is broken IMO.
Now that you bring it up, I missed it :(.. yeah, I might have
preferred it to be min frequency and max_frequency - I agree it is
probably broken. I'd let Eduardo comment more about it.

> 
> 	One such use-case that came up recently[0] is the c-state latencies
> 	which could be different for each OPP. It would be good if the
> 	latencies are specified with the indices to OPP table to avoid
> 	inconsistency between the bindings.

You can define C states based on frequencies as well - which really
makes sense - since that sounds really like our constraint (say
valid-at-frequency "xyz"

> 
> 	It's mainly to avoid issues due to inconsistency and duplication
> 	on data(frequency) in multiple bindings requiring it.
> 
> 	Once we have indices to each on the OPP entries, then other binding
> 	using it can refer to OPP with phandle and OPP index/specifier pairs
> 	very similar to clock provider and consumer.

Having used indexing in OMAP platforms, indexing is a problem waiting
to happen unfortunately :(

> 
> 2. sharing opps: I have tried to address this issue previously[1] but unable
> 	to conclude yet on this.

yes - more details in [3] - which is a more interesting discussion
there - lets revive it in that context.

It is a valid concern and IMHO a great idea - yeah we already have a
thread started.

> 
> 3. latencies(*): currently the latency that the CPU/memory access is unavailable
> 	during an OPP transition is generic i.e. same from any OPP to any
> 	other OPP. Does it make sense to have this per-OPP entry ?

Why modify OPP when you are describing something else? you are
describing "latency at a frequency" - just because an OPP definition
as it stands right now is {frequency, voltage} tuple, makes it a very
attractive target to keep extending it -> believe me, we have done
that in the past ->arch/arm/mach-omap2/opp4xxx_data.c efuse register
describing AVS per frequency is tempting..

why not have memory-latency-per-opp = <frequency latency>?

that allows OPP definitions to change in the future, but the
definition remain constant.

That said -> consider the following usecase: AM335x, OMAP3,4... (i
will use omap4 as an example)
MPU@300MHz and bus (on which LPDDR2 memory is) at 100MHz
AND
MPU@300MHz and bus (on which LPDDR2 memory is) at 200MHz

are both valid with different memory access latencies. tying it down
to OPP for MPU is just plain wrong - as it ignores other factors.

> 
> 4. power(*): A measure of maximum power dissipation in an OPP state.
> 	This might be useful measure for power aware scheduling ?
Umm.. this is a hard nut to crack -> I had considered that previously
as well -> In reality the leakage characteristics of the SoC
distribution varies dramatically depending on which end of the
distribution you look for a specific process node. in my company, we
typically use cold, hot,nominal devices, this is some form or other
(example - Samsung calls it "SoC's ASV group" [4]) - and every SoC
company comes up with some strategy or other to control it optimally
-> TI uses ABB[5], AVS[6] - etc... - not an unique problem -> so what
will "power" mean? we cannot create dts per SoC part.

> 
> (*) these are already part of P-state in ACPI(refer struct acpi_processor_px
> in include/acpi/processor.h)

Hmm.. what do we do with legacy processors that dont support ACPI or
what ever our latest ARM term is for the equivalent?

> 
> Apart from these I have seen on-going discussion for Samsung Exynos CPUFreq[2]
> which might have some feedback for OPP bindings.
> 
> It would be good to consolidate the shortcomings found so far, that could
> help in extending the current OPP bindings.

I hope this discussion helps. open to more views as well.

> [0] http://www.spinics.net/lists/arm-kernel/msg301971.html
> [1] http://www.spinics.net/lists/cpufreq/msg07911.html
> [2] http://www.spinics.net/lists/cpufreq/msg09169.html

[1] http://marc.info/?t=125546601600001&r=1&w=2
[2] http://marc.info/?l=linux-omap&m=125474840119392&w=2
[3] http://marc.info/?t=138063448000008&r=1&w=2
[4] http://marc.info/?l=linux-pm&m=138451581304412&w=2
[5]
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/regulator/ti-abb-regulator.c
[6]
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/power/avs/smartreflex.c
-- 
Regards,
Nishanth Menon

^ permalink raw reply

* Re: [PATCH v2 08/11] of: Increase MAX_PHANDLE_ARGS
From: Will Deacon @ 2014-01-31  0:18 UTC (permalink / raw)
  To: Suravee Suthikulanit
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org,
	Rob Herring, Rob Herring, Andreas Herrmann,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
In-Reply-To: <52EAD7EF.3040305-5C7GfCeVMHo@public.gmane.org>

On Thu, Jan 30, 2014 at 10:53:35PM +0000, Suravee Suthikulanit wrote:
> On 1/29/2014 12:03 PM, Will Deacon wrote:
> > Interesting... how does that work for PCI? Do you force all devices behind a
> > given RC into the same address space?
> >
> 
> For PCI devices, we are using the bus, device, and function id to make 
> up the 15-bit SID for devices behind a particular PCI root complex.

Very good!

> I also notice that we are currently not supporting the streamID mask in 
> the SMR.  Is this something planed for the future?

Andreas and I are curently working on this -- that's what I was referring to
above. Any feedback from you would be welcomed.

Will

^ permalink raw reply

* Re: [PATCH v2 3/5] spi: sunxi: Add Allwinner A31 SPI controller driver
From: Kevin Hilman @ 2014-01-30 23:52 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Mark Brown, Mike Turquette, Emilio Lopez,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
	linux-spi-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, LKML,
	kevin.z.m.zh-Re5JQEeQqe8AvxtiuMwx3w,
	sunny-0TFLnhJekD6UEPyfVivIlAC/G2K4zDHf,
	shuge-0TFLnhJekD6UEPyfVivIlAC/G2K4zDHf,
	zhuzhenhua-0TFLnhJekD6UEPyfVivIlAC/G2K4zDHf
In-Reply-To: <20140129133227.GQ3867@lukather>

On Wed, Jan 29, 2014 at 5:32 AM, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> On Wed, Jan 29, 2014 at 12:25:20PM +0000, Mark Brown wrote:
>> On Wed, Jan 29, 2014 at 12:10:48PM +0100, Maxime Ripard wrote:
>>
>> > +config SPI_SUN6I
>> > +   tristate "Allwinner A31 SPI controller"
>> > +   depends on ARCH_SUNXI || COMPILE_TEST
>> > +   select PM_RUNTIME
>> > +   help
>> > +     This enables using the SPI controller on the Allwinner A31 SoCs.
>> > +
>>
>> A select of PM_RUNTIME is both surprising and odd - why is that there?
>> The usual idiom is that the device starts out powered up (flagged using
>> pm_runtime_set_active()) and then runtime PM then suspends it when it's
>> compiled in.  That way if for some reason people want to avoid runtime
>> PM they can still use the device.
>
> Since pm_runtime_set_active and all the pm_runtime* callbacks in
> general are defined to pretty much empty functions, how the
> suspend/resume callbacks are called then? Obviously, we need them to
> be run, hence why I added the select here, but now I'm seeing a
> construct like what's following acceptable then?

Even with your 'select', The runtime PM callbacks will never be called
in the current driver.  pm_runtime_enable() doesn't do any runtime PM
transitions.  It just allows transitions to happen when they're
triggered by _get()/_put()/etc.

> pm_runtime_enable(&pdev->dev);
> if (!pm_runtime_enabled(&pdev->dev))
>    sun6i_spi_runtime_resume(&pdev->dev);

Similarily here, it's not the pm_runtime_enable that will fail when
runtime PM is disabled (or not built-in), it's a pm_runtime_get_sync()
that will fail.

What you want is something like this in ->probe()

   sun6i_spi_runtime_resume();
   /* now, device is always activated whether or not runtime PM is enabled */
   pm_runtime_enable();
   pm_runtime_set_active();  /* tells runtime PM core device is
already active */
   pm_runtime_get_sync();

This 'get' will increase the usecount, but not actually call the
callbacks because we told the RPM core that the device was already
activated with _set_active().

And then, in ->remove(), you'll want

   pm_runtime_put();
   pm_runtime_disable();

And if runtime PM is not enabled in the kernel, then the device will
be left on (which is kinda what you want if you didn't build runtime
PM into the kernel.)

Kevin
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH] of: fix PCI bus match for PCIe slots
From: Kleber Sacilotto de Souza @ 2014-01-30 23:29 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Benjamin Herrenschmidt, Brian King, Grant Likely, Rob Herring,
	Kleber Sacilotto de Souza

On IBM pseries systems the device_type device-tree property of a PCIe
bridge contains the string "pciex". The of_bus_pci_match() function was
looking only for "pci" on this property, so in such cases the bus
matching code was falling back to the default bus, causing problems on
functions that should be using "assigned-addresses" for region address
translation. This patch fixes the problem by also looking for "pciex" on
the PCI bus match function.

Signed-off-by: Kleber Sacilotto de Souza <klebers-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
---
 drivers/of/address.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index d3dd41c..0da2c0f 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -102,8 +102,8 @@ static int of_bus_pci_match(struct device_node *np)
 	 * "vci" is for the /chaos bridge on 1st-gen PCI powermacs
 	 * "ht" is hypertransport
 	 */
-	return !strcmp(np->type, "pci") || !strcmp(np->type, "vci") ||
-		!strcmp(np->type, "ht");
+	return !strcmp(np->type, "pci") || !strcmp(np->type, "pciex") ||
+		!strcmp(np->type, "vci") || !strcmp(np->type, "ht");
 }
 
 static void of_bus_pci_count_cells(struct device_node *np,
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [PATCH v3 0/2] Qualcomm Universal Peripheral (QUP) I2C controller
From: Bjorn Andersson @ 2014-01-30 23:27 UTC (permalink / raw)
  To: Ivan T. Ivanov
  Cc: Mark Rutland, linux-doc@vger.kernel.org,
	linux-i2c@vger.kernel.org, Matt Porter, Wolfram Sang,
	Bjorn Andersson, Grant Likely, James Ralston,
	devicetree@vger.kernel.org, Pawel Moll, Ian Campbell,
	linux-arm-msm, Rob Herring, Jean Delvare, Andy Shevchenko,
	linux-arm-kernel@lists.infradead.org, Bill Brown,
	Greg Kroah-Hartman, linux-kernel@vger.kernel.org
In-Reply-To: <1391095811.3275.17.camel@iivanov-dev>

On Thu, Jan 30, 2014 at 7:30 AM, Ivan T. Ivanov <iivanov@mm-sol.com> wrote:
>
> Hi Bjorn,
>
> On Wed, 2014-01-29 at 08:32 -0800, Bjorn Andersson wrote:
>> On Wed, Jan 29, 2014 at 12:14 AM, Ivan T. Ivanov <iivanov@mm-sol.com> wrote:
>> >
>> > Hi Bjorn,
>> >
>> > On Fri, 2014-01-17 at 15:03 -0800, Bjorn Andersson wrote:
>> >> Continuing on Ivans i2c-qup series.
>> >>
>> >
>> > Do you plan to send v4 of this driver? I would like to address
>> > the remaining errors and suggestions and send a new version.
>> >
>> Hi Ivan,
>>
>> Yes I'm planning to send out a new revision of the patch set.
>>
>> I've incorporated fixes from the review comments here and my colleague
>> concluded through some testing that block read did not work, so we've
>> fixed that as well.
>
> Busted. I have not test it.

No worries, I'm glad you did the major cleanup from codeaurora!

>
>>
>> What have been holding me from submitting a new patchset is the 3
>> functions that does polling of state and status updates;
>> * qup_i2c_poll_state() reads the state register up to 1000 times,
>> hoping we reach the expected state, will delay 100uS and then continue
>> with 1000 more retries.
>>   According to the data sheet a state transition is supposed to take
>> up to 2 bus cycles. Only time I can see that this would take longer
>> time are all error states, but the data sheet is not very clear
>> regarding this.
>>
>> * qup_i2c_wait_idle() reads the status register up to 1000 times,
>> hoping the fifo gets drained and the bus go idle, if that fails it
>> sleeps for the time we expect it to take to drain a full fifo and then
>> loops another 1000 times. This waits for the fifo to have drained and
>> the bus to go idle. On a read we get to this state if we issue the
>> write and then hit the error state, so we would reset the entire
>> block. On write we will only wait for the buffer not to be full before
>> returning.
>>
>> * qup_i2c_wait_clock_ready() waits up to 300 bus-clocks for the i2c
>> bus to go idle or forced low, I don't know why it retries 300 times.
>> This is called at the end of a write, possibly to wait for the fifo to
>> drain.
>>
>>
>> All three loops are in line with how it's been in codeaurora since the
>> beginning of time, but I at least need to figure out some good names
>> for those "magic numbers".
>
>
> Sure. I have keep them this way, just because I don't have information
> for internal trickery of the block.

I'll continue to talk to the Qualcomm guys to see if we can figure out
anything regarding the expected timings of those operations and I'll
send out a new version when we have something saner.

Regards,
Bjorn

^ permalink raw reply

* Re: [PATCH v2] DT: net: document Ethernet bindings in one place
From: Sergei Shtylyov @ 2014-01-30 22:56 UTC (permalink / raw)
  To: Rob Herring
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree@vger.kernel.org, Rob Landley,
	linux-doc@vger.kernel.org, Max Filippov
In-Reply-To: <CAL_JsqLJrS2w0idwpi0Ar4RyuZ050sb0eYVyzM1HE4df4FxdZQ@mail.gmail.com>

Hello.

On 01/29/2014 07:16 PM, Rob Herring wrote:

>>>> This patch is an attempt to gather the Ethernet related bindings in one
>>>> file,
>>>> like it's done in the MMC and some other subsystems. It should save some
>>>> of
>>>> the trouble of documenting several properties over and over in each
>>>> binding
>>>> document, instead only making reference to the main file.

> [snip]

>>>>    - compatible: should be "allwinner,sun4i-emac".
>>>>    - reg: address and length of the register set for the device.
>>>>    - interrupts: interrupt for the device
>>>> -- phy: A phandle to a phy node defining the PHY address (as the reg
>>>> -  property, a single integer).
>>>> +- phy: see ethernet.txt file in the same directory.
>>>>    - clocks: A phandle to the reference clock for this device
>>>>
>>>>    Optional properties:
>>>> -- (local-)mac-address: mac address to be used by this driver
>>>> +- [local-]mac-address: see ethernet.txt file in the same directory

>>> Sorry, but I meant you should just have a single statement like:

>>> This binding uses standard ethernet properties defined in ethernet.txt.

>>     This way it won't be clear which of the properties are used and which are
>> not, no?

> You're right. For the phy properties we need to specify which ones are
> used. This could be done only for bindings using the not recommended
> properties.

> For optional properties like local-mac-address, I don't think these
> need to be listed. They can be used for all devices and whether or not
> a given Linux driver supports using the property is not really the
> concern of the binding documentation. An exception could be a device
> that requires a optional property (i.e. a NIC with no eeprom to store
> a MAC address).

    So, to avoid any ambiguities, will this fragment be OK with you:

Index: net-next/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt
===================================================================
--- net-next.orig/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt
+++ net-next/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt
@@ -4,13 +4,9 @@ Required properties:
  - compatible: should be "allwinner,sun4i-emac".
  - reg: address and length of the register set for the device.
  - interrupts: interrupt for the device
-- phy: A phandle to a phy node defining the PHY address (as the reg
-  property, a single integer).
+- phy: see ethernet.txt file in the same directory.
  - clocks: A phandle to the reference clock for this device

-Optional properties:
-- (local-)mac-address: mac address to be used by this driver
-
  Example:

  emac: ethernet@01c0b000 {

    Or do I still need to insert "this binding uses standard Ethernet 
properties defined in ethernet.txt in the same directory" somewhere?

> Rob

WBR, Sergei


^ permalink raw reply

* Re: [PATCH v2 08/11] of: Increase MAX_PHANDLE_ARGS
From: Suravee Suthikulanit @ 2014-01-30 22:53 UTC (permalink / raw)
  To: Will Deacon
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org,
	Rob Herring, Rob Herring, Andreas Herrmann,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
In-Reply-To: <20140129180350.GS26622-MRww78TxoiP5vMa5CHWGZ34zcgK1vI+I0E9HWUfgJXw@public.gmane.org>

On 1/29/2014 12:03 PM, Will Deacon wrote:
> On Wed, Jan 29, 2014 at 05:57:16PM +0000, Suravee Suthikulanit wrote:
>> On 1/29/2014 11:29 AM, Will Deacon wrote:
>>> On Wed, Jan 29, 2014 at 05:26:35PM +0000, Suravee Suthikulanit wrote:
>>>> On 1/29/2014 11:16 AM, Andreas Herrmann wrote:
>>>>> On Wed, Jan 29, 2014 at 11:59:12AM -0500, Suravee Suthikulanit wrote:
>>>>>> Actually, we are using 32 on the AMD system. So, do you think we can set
>>>>>> this to 32 instead?
>>>>>
>>>>> I think that's ok.
>>>>>
>>>>> But are we really talking about number of SMRs or number of StreamIDs
>>>>> per master device here? Ie. are you just having 32 SMRs for an SMMU on
>>>>> your AMD system or do you have master devices which have 32 StreamIDs?
>>>>>
>>>>> If it's just number of SMRs we don't need to modify this macro.
>>>>>
>>>>
>>>> I am referring to the case where each mmu-master can have upto 32 streamID.
>>>
>>> Crikey, how many SMRs do you have? Andreas and I have been struggling to
>>> write a decent allocator for those, so if you have any algorithms that don't
>>> require a quantum computer, we'd love to hear from you :)!
>>>
>>> Will
>>>
>>
>> Are you talking about the __arm_smmu_alloc_bitmap()?
>>
>> Currently, we have configured the each SMMU to have 32 SMRs and using
>> 15-bit streamID. However, we mostly have upto 32 streamID for each
>> master, and most of the SMMU only have one master.  So it looks like the
>> current logic should be ok.
>
> Interesting... how does that work for PCI? Do you force all devices behind a
> given RC into the same address space?
>
> Will
>

For PCI devices, we are using the bus, device, and function id to make 
up the 15-bit SID for devices behind a particular PCI root complex.

I also notice that we are currently not supporting the streamID mask in 
the SMR.  Is this something planed for the future?

Suravee

^ permalink raw reply

* Re: [PATCH v5 00/20] Armada 370/XP watchdog support
From: Ezequiel Garcia @ 2014-01-30 22:37 UTC (permalink / raw)
  To: Sebastian Hesselbarth
  Cc: Jason Cooper, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA, Andrew Lunn,
	Gregory Clement, Lior Amsalem, Tawfik Bayouk, Wim Van Sebroeck,
	Arnd Bergmann, Daniel Lezcano, Guenter Roeck
In-Reply-To: <52EACB92.2080700-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

On Thu, Jan 30, 2014 at 11:00:50PM +0100, Sebastian Hesselbarth wrote:
> On 01/30/2014 10:50 PM, Ezequiel Garcia wrote:
> > On Thu, Jan 30, 2014 at 03:53:15PM -0500, Jason Cooper wrote:
> >> Ezequiel,
> >>
> >> On Wed, Jan 29, 2014 at 03:19:50PM -0300, Ezequiel Garcia wrote:
> >>> On Mon, Jan 27, 2014 at 12:27:00PM -0300, Ezequiel Garcia wrote:
> >>>> A new round, mostly fixing some minor nitpicks.
> >>>>
> >>>
> >>> If anyone wants to give this a test, here's a public branch:
> >>>
> >>> https://github.com/MISL-EBU-System-SW/mainline-public/tree/wdt_for_v3.14_v5
> >>
> >> I just took a quick glance at this (commit oneliners/tags) and there
> >> doesn't appear to be any dependence on Sebastian's series.  Did I miss
> >> something?
> >>
> >
> > True, I've completely missed that. I pushed the branch in a rush!
> >
> > Let me prepare a v6, fixing the remaining issue pointed out by Russell,
> > and push again (together with Sebastian's irqchip fixes).
> 
> Umm, no. Just directly name irqchip-orion fixes. Jason will send a PR
> for irqchip-fixes _with-in_ v3.14 while watchdog will go into v3.15.
> 

That sounds good.

> Or are there any plans to get watchdog in *now*?
> 

Not on my side, I'm aiming at v3.15.

> In any way, do not include my patches into your set.
> 

Hm, maybe I've misexpressed myself. I wasn't intending to include
the patches on a submission, but just in a branch on the github repo.
-- 
Ezequiel García, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v5 00/20] Armada 370/XP watchdog support
From: Jason Cooper @ 2014-01-30 22:16 UTC (permalink / raw)
  To: Sebastian Hesselbarth
  Cc: Ezequiel Garcia,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA, Andrew Lunn,
	Gregory Clement, Lior Amsalem, Tawfik Bayouk, Wim Van Sebroeck,
	Arnd Bergmann, Daniel Lezcano, Guenter Roeck
In-Reply-To: <52EACB92.2080700-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

On Thu, Jan 30, 2014 at 11:00:50PM +0100, Sebastian Hesselbarth wrote:
> On 01/30/2014 10:50 PM, Ezequiel Garcia wrote:
> >On Thu, Jan 30, 2014 at 03:53:15PM -0500, Jason Cooper wrote:
> >>Ezequiel,
> >>
> >>On Wed, Jan 29, 2014 at 03:19:50PM -0300, Ezequiel Garcia wrote:
> >>>On Mon, Jan 27, 2014 at 12:27:00PM -0300, Ezequiel Garcia wrote:
> >>>>A new round, mostly fixing some minor nitpicks.
> >>>>
> >>>
> >>>If anyone wants to give this a test, here's a public branch:
> >>>
> >>>https://github.com/MISL-EBU-System-SW/mainline-public/tree/wdt_for_v3.14_v5
> >>
> >>I just took a quick glance at this (commit oneliners/tags) and there
> >>doesn't appear to be any dependence on Sebastian's series.  Did I miss
> >>something?
> >>
> >
> >True, I've completely missed that. I pushed the branch in a rush!
> >
> >Let me prepare a v6, fixing the remaining issue pointed out by Russell,
> >and push again (together with Sebastian's irqchip fixes).
> 
> Umm, no. Just directly name irqchip-orion fixes. Jason will send a PR
> for irqchip-fixes _with-in_ v3.14 while watchdog will go into v3.15.

Yes, but I'd like to do a topic branch for that irqchip PR.  That way,
we don't have to wait for them to land in an -rc.  We can push the
watchdog changes when they are ready, and they can be based on v3.14-rc1
with irqchip/orion-fixes (or whatever) pulled in.

> In any way, do not include my patches into your set.

Agreed.  I wasn't really keen on including the MMIO patch in the series
since it was already in rmk's patch tracker.  Listing the deps in the
coverletter is enough.

> Jason: Ezequiel's watchdog patches install an irq handler that will
> panic(TM) on a watchdog irq. irqchip-orion does not properly clear
> stale bridge irqs which could signal a watchdog irq left by bootloader
> (or watchdog triggering between bootloader and driver probe).

Ok.  I'll look things over and get some branches setup this weekend.

thx,

Jason.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v9] gpio: add a driver for Synopsys DesignWare APB GPIO
From: delicious quinoa @ 2014-01-30 22:05 UTC (permalink / raw)
  To: Steffen Trumtrar
  Cc: Linus Walleij, linux-kernel, linux-gpio@vger.kernel.org,
	linux-doc@vger.kernel.org, Jamie Iles, devicetree@vger.kernel.org,
	Grant Likely, Sebastian Hesselbarth, Heiko Stuebner, Alan Tull,
	Dinh Nguyen, Yves Vandervennet
In-Reply-To: <20140130213232.GC26861@pengutronix.de>

On Thu, Jan 30, 2014 at 3:32 PM, Steffen Trumtrar
<s.trumtrar@pengutronix.de> wrote:
> On Thu, Jan 30, 2014 at 03:15:11PM -0600, delicious quinoa wrote:
>> On Thu, Jan 30, 2014 at 2:50 PM, Steffen Trumtrar
>> <s.trumtrar@pengutronix.de> wrote:
>> > Hi!
>> >
>> > On Thu, Jan 30, 2014 at 01:40:04PM -0600, delicious quinoa wrote:
>> >> On Thu, Dec 12, 2013 at 3:08 AM, Steffen Trumtrar
>> >> <s.trumtrar@pengutronix.de> wrote:
>> >>
>> >> > Second: The interrupt is registered as "GIC 37", which is a real interrupt on
>> >> > the Socfpga. I would expect it to be marked as "GPIO 2xx" (or something in that
>> >> > range). The interrupt from the gpiochip itself isn't registered at all ?!
>> >>
>> >> Hi Stephen,
>> >>
>> >> Did you export the gpio lines and set the edge in sysfs?  Because the
>> >> interrupts aren't allocated otherwise.
>> >>
>> >> For instance:
>> >>
>> >> root@socfpga_cyclone5:~# echo 195 > /sys/class/gpio/export
>> >> root@socfpga_cyclone5:~# echo rising > /sys/class/gpio/gpio195/edge
>> >>
>> >> Now I can see a pretty nicely named interrupt in /proc/interrupts:
>> >>
>> >> 256:          0          0  gpio-dwapb  24  gpiolib
>> >>
>> >
>> > I didn't try that and I think this behaviour is pretty uncommon.
>> > This should be fixed in the driver. I never wrote a gpiochip-driver,
>> > so I don't know what is missing, but maybe just some functioncall ?!
>> > All other drivers I came across have that entry from probing without
>> > any fiddling.
>>
>> Hi Steffen,
>>
>> Do you mean 'all other gpio drivers' or 'all other non-gpio drivers'?
>
> I meant gpio drivers (at least the ones I have used).
>
>>
>> This is the behavior that is implemented in the community gpio
>> framework drivers/gpio/gpiolib.c, not anything special implemented in
>> this dw gpio driver.
>>
>> It's documented in Documentation/gpio/sysfs.txt and
>> Documentation/ABI/testing/sysfs-gpio.
>>
>> You get userspace control of a gpio by 'export'ing it in sysfs.  And
>> then by default, the interrupt edge is set to 'none' (no irq) until
>> you set the edge in sysfs.
>>
>
> Hm, okay...for GPIOs I'm with you. But when I specify a gpio as
> interrupt for a device, I have to first export it manually before I can
> use the device? Sounds weird.
>
> Steffen

Seems normal usage both in userspace and in kernel drivers that need a gpio.

Looking at other kernel drivers that use a gpio, I can see examples
that do gpio_request() to get the gpio that they care about.  Then
gpio_to_irq() and request_irq().  If you grep for 'gpio_to_irq' then
look to see how they got the gpio, you'll see it pretty quickly.

Alan

^ permalink raw reply

* Re: [PATCH v5 00/20] Armada 370/XP watchdog support
From: Sebastian Hesselbarth @ 2014-01-30 22:00 UTC (permalink / raw)
  To: Ezequiel Garcia, Jason Cooper
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA, Andrew Lunn,
	Gregory Clement, Lior Amsalem, Tawfik Bayouk, Wim Van Sebroeck,
	Arnd Bergmann, Daniel Lezcano, Guenter Roeck
In-Reply-To: <20140130215056.GA1063@localhost>

On 01/30/2014 10:50 PM, Ezequiel Garcia wrote:
> On Thu, Jan 30, 2014 at 03:53:15PM -0500, Jason Cooper wrote:
>> Ezequiel,
>>
>> On Wed, Jan 29, 2014 at 03:19:50PM -0300, Ezequiel Garcia wrote:
>>> On Mon, Jan 27, 2014 at 12:27:00PM -0300, Ezequiel Garcia wrote:
>>>> A new round, mostly fixing some minor nitpicks.
>>>>
>>>
>>> If anyone wants to give this a test, here's a public branch:
>>>
>>> https://github.com/MISL-EBU-System-SW/mainline-public/tree/wdt_for_v3.14_v5
>>
>> I just took a quick glance at this (commit oneliners/tags) and there
>> doesn't appear to be any dependence on Sebastian's series.  Did I miss
>> something?
>>
>
> True, I've completely missed that. I pushed the branch in a rush!
>
> Let me prepare a v6, fixing the remaining issue pointed out by Russell,
> and push again (together with Sebastian's irqchip fixes).

Umm, no. Just directly name irqchip-orion fixes. Jason will send a PR
for irqchip-fixes _with-in_ v3.14 while watchdog will go into v3.15.

Or are there any plans to get watchdog in *now*?

In any way, do not include my patches into your set.

Jason: Ezequiel's watchdog patches install an irq handler that will
panic(TM) on a watchdog irq. irqchip-orion does not properly clear
stale bridge irqs which could signal a watchdog irq left by bootloader
(or watchdog triggering between bootloader and driver probe).

Sebastian
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v5 00/20] Armada 370/XP watchdog support
From: Ezequiel Garcia @ 2014-01-30 21:50 UTC (permalink / raw)
  To: Jason Cooper
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA, Andrew Lunn,
	Sebastian Hesselbarth, Gregory Clement, Lior Amsalem,
	Tawfik Bayouk, Wim Van Sebroeck, Arnd Bergmann, Daniel Lezcano,
	Guenter Roeck
In-Reply-To: <20140130205315.GD29184-u4khhh1J0LxI1Ri9qeTfzeTW4wlIGRCZ@public.gmane.org>

On Thu, Jan 30, 2014 at 03:53:15PM -0500, Jason Cooper wrote:
> Ezequiel,
> 
> On Wed, Jan 29, 2014 at 03:19:50PM -0300, Ezequiel Garcia wrote:
> > On Mon, Jan 27, 2014 at 12:27:00PM -0300, Ezequiel Garcia wrote:
> > > A new round, mostly fixing some minor nitpicks.
> > > 
> > 
> > If anyone wants to give this a test, here's a public branch:
> > 
> > https://github.com/MISL-EBU-System-SW/mainline-public/tree/wdt_for_v3.14_v5
> 
> I just took a quick glance at this (commit oneliners/tags) and there
> doesn't appear to be any dependence on Sebastian's series.  Did I miss
> something?
> 

True, I've completely missed that. I pushed the branch in a rush!

Let me prepare a v6, fixing the remaining issue pointed out by Russell,
and push again (together with Sebastian's irqchip fixes).

> Also, the MMIO patch hit mainline last night.
> 

Yup, I saw it. Thanks for the notice!
-- 
Ezequiel García, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 0/3] RFC/RFT: Powering on MMC Wifi/BT modules in MMC core
From: Russell King - ARM Linux @ 2014-01-30 21:49 UTC (permalink / raw)
  To: Olof Johansson, Chris Ball
  Cc: linux-mmc, devicetree, linux-arm-kernel, robh+dt, mark.rutland,
	pawel.moll, ijc+devicetree, galak
In-Reply-To: <1390190215-22700-1-git-send-email-olof@lixom.net>

On Sun, Jan 19, 2014 at 07:56:52PM -0800, Olof Johansson wrote:
> This is a small series enhancing the MMC core code to power on modules
> before the host in cases where needed, and the corresponding DT bindings
> changes.
> 
> I've got some other issues to debug on the Chromebook, i.e. the interface
> doens't actually work. So far it seems unrelated to this patch set so
> it's worth posting this and get things going since others need the same
> functionality (i.e Cubox-i).
> 
> As mentioned in the patch in the series, I haven't implemented power-down
> yet, I wanted to make sure that the power-on side will be adequate for
> those who are looking to use it right away.
> 
> Comments/test reports/etc welcome.

So, I thought I'd give this a go on the Cubox-i4, and... it doesn't work
there.  It's not your patches, it's down to sdhci-esdhc-imx.c not using
mmc_of_parse() at all, so those new properties have no way to be used
there.

It doesn't look like it could in its current form use mmc_of_parse(),
as the imx code manually parses some of the generic properties to hand
them into the sdhci layer.  This looks icky, and it looks like something
that should be fixed - why should drivers be parsing the core attributes
themselves?

-- 
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".

^ permalink raw reply

* Re: [PATCH v9] gpio: add a driver for Synopsys DesignWare APB GPIO
From: Steffen Trumtrar @ 2014-01-30 21:32 UTC (permalink / raw)
  To: delicious quinoa
  Cc: Linus Walleij, linux-kernel, linux-gpio@vger.kernel.org,
	linux-doc@vger.kernel.org, Jamie Iles, devicetree@vger.kernel.org,
	Grant Likely, Sebastian Hesselbarth, Heiko Stuebner, Alan Tull,
	Dinh Nguyen, Yves Vandervennet
In-Reply-To: <CANk1AXS9fbNafLxiUz8OoPVUtwPDhHhYx7+MGi_JyDdG6J9F-Q@mail.gmail.com>

On Thu, Jan 30, 2014 at 03:15:11PM -0600, delicious quinoa wrote:
> On Thu, Jan 30, 2014 at 2:50 PM, Steffen Trumtrar
> <s.trumtrar@pengutronix.de> wrote:
> > Hi!
> >
> > On Thu, Jan 30, 2014 at 01:40:04PM -0600, delicious quinoa wrote:
> >> On Thu, Dec 12, 2013 at 3:08 AM, Steffen Trumtrar
> >> <s.trumtrar@pengutronix.de> wrote:
> >>
> >> > Second: The interrupt is registered as "GIC 37", which is a real interrupt on
> >> > the Socfpga. I would expect it to be marked as "GPIO 2xx" (or something in that
> >> > range). The interrupt from the gpiochip itself isn't registered at all ?!
> >>
> >> Hi Stephen,
> >>
> >> Did you export the gpio lines and set the edge in sysfs?  Because the
> >> interrupts aren't allocated otherwise.
> >>
> >> For instance:
> >>
> >> root@socfpga_cyclone5:~# echo 195 > /sys/class/gpio/export
> >> root@socfpga_cyclone5:~# echo rising > /sys/class/gpio/gpio195/edge
> >>
> >> Now I can see a pretty nicely named interrupt in /proc/interrupts:
> >>
> >> 256:          0          0  gpio-dwapb  24  gpiolib
> >>
> >
> > I didn't try that and I think this behaviour is pretty uncommon.
> > This should be fixed in the driver. I never wrote a gpiochip-driver,
> > so I don't know what is missing, but maybe just some functioncall ?!
> > All other drivers I came across have that entry from probing without
> > any fiddling.
> 
> Hi Steffen,
> 
> Do you mean 'all other gpio drivers' or 'all other non-gpio drivers'?

I meant gpio drivers (at least the ones I have used).

> 
> This is the behavior that is implemented in the community gpio
> framework drivers/gpio/gpiolib.c, not anything special implemented in
> this dw gpio driver.
> 
> It's documented in Documentation/gpio/sysfs.txt and
> Documentation/ABI/testing/sysfs-gpio.
> 
> You get userspace control of a gpio by 'export'ing it in sysfs.  And
> then by default, the interrupt edge is set to 'none' (no irq) until
> you set the edge in sysfs.
> 

Hm, okay...for GPIOs I'm with you. But when I specify a gpio as
interrupt for a device, I have to first export it manually before I can
use the device? Sounds weird.

Steffen

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply

* Re: recommended action for bootloaders regarding modifying device-tree nodes
From: Jason Gunthorpe @ 2014-01-30 21:15 UTC (permalink / raw)
  To: Jason Cooper
  Cc: Tim Harvey, Grant Likely,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	u-boot-0aAXYlwwYIKGBzrmiIFOJg
In-Reply-To: <20140130204558.GC29184-u4khhh1J0LxI1Ri9qeTfzeTW4wlIGRCZ@public.gmane.org>

On Thu, Jan 30, 2014 at 03:45:58PM -0500, Jason Cooper wrote:

> This is more of a process question:  Is there any information captured
> in your EEPROM that can't be represented in the dtb?  iow, at the point
> when you write the EEPROM, why not write the dtb to it as configured?

I can share what we do here.. In our systems the serial EEPROM is only
256 bytes, so storing things in DT format would be challenging.

What we do is have a master DTB that has the union of all our
configurations. The boot process has a very simple bit of code that
runs down the DTB in binary format and replaces entire
OF_DT_BEGIN_NODE->OF_DT_END_NODE regions with OF_DT_NOP.

The NOP approach is very simple, no other changes (eg offset
recalculation) needs to be done to the DT, so we can do this process
with a very small code footprint and without libfdt.

Choosing which sections to drop is done with some combination of
hardwired code and searching for specific property patterns. There are
also a few places where placeholder sections are directly fixed up, eg
a mac address is written into a placeholder of 0s, etc.

So an example might be

   optional_peripheral@10000 {
      orc,board-style = <1>;
      [..]
   }

Eg The board-style number comes from the EEPROM and if board-style !=
1 then the entire stanza is replaced with NOP.

Jason
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v9] gpio: add a driver for Synopsys DesignWare APB GPIO
From: delicious quinoa @ 2014-01-30 21:15 UTC (permalink / raw)
  To: Steffen Trumtrar
  Cc: Linus Walleij, linux-kernel, linux-gpio@vger.kernel.org,
	linux-doc@vger.kernel.org, Jamie Iles, devicetree@vger.kernel.org,
	Grant Likely, Rob Herring, Sebastian Hesselbarth, Heiko Stuebner,
	Alan Tull, Dinh Nguyen, Yves Vandervennet
In-Reply-To: <20140130205000.GB26861@pengutronix.de>

On Thu, Jan 30, 2014 at 2:50 PM, Steffen Trumtrar
<s.trumtrar@pengutronix.de> wrote:
> Hi!
>
> On Thu, Jan 30, 2014 at 01:40:04PM -0600, delicious quinoa wrote:
>> On Thu, Dec 12, 2013 at 3:08 AM, Steffen Trumtrar
>> <s.trumtrar@pengutronix.de> wrote:
>>
>> > Second: The interrupt is registered as "GIC 37", which is a real interrupt on
>> > the Socfpga. I would expect it to be marked as "GPIO 2xx" (or something in that
>> > range). The interrupt from the gpiochip itself isn't registered at all ?!
>>
>> Hi Stephen,
>>
>> Did you export the gpio lines and set the edge in sysfs?  Because the
>> interrupts aren't allocated otherwise.
>>
>> For instance:
>>
>> root@socfpga_cyclone5:~# echo 195 > /sys/class/gpio/export
>> root@socfpga_cyclone5:~# echo rising > /sys/class/gpio/gpio195/edge
>>
>> Now I can see a pretty nicely named interrupt in /proc/interrupts:
>>
>> 256:          0          0  gpio-dwapb  24  gpiolib
>>
>
> I didn't try that and I think this behaviour is pretty uncommon.
> This should be fixed in the driver. I never wrote a gpiochip-driver,
> so I don't know what is missing, but maybe just some functioncall ?!
> All other drivers I came across have that entry from probing without
> any fiddling.

Hi Steffen,

Do you mean 'all other gpio drivers' or 'all other non-gpio drivers'?

This is the behavior that is implemented in the community gpio
framework drivers/gpio/gpiolib.c, not anything special implemented in
this dw gpio driver.

It's documented in Documentation/gpio/sysfs.txt and
Documentation/ABI/testing/sysfs-gpio.

You get userspace control of a gpio by 'export'ing it in sysfs.  And
then by default, the interrupt edge is set to 'none' (no irq) until
you set the edge in sysfs.

Alan

>
> Thanks,
> Steffen
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply

* Re: [PATCH v5 00/20] Armada 370/XP watchdog support
From: Jason Cooper @ 2014-01-30 20:53 UTC (permalink / raw)
  To: Ezequiel Garcia
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA, Andrew Lunn,
	Sebastian Hesselbarth, Gregory Clement, Lior Amsalem,
	Tawfik Bayouk, Wim Van Sebroeck, Arnd Bergmann, Daniel Lezcano,
	Guenter Roeck
In-Reply-To: <20140129181949.GB27143@localhost>

Ezequiel,

On Wed, Jan 29, 2014 at 03:19:50PM -0300, Ezequiel Garcia wrote:
> On Mon, Jan 27, 2014 at 12:27:00PM -0300, Ezequiel Garcia wrote:
> > A new round, mostly fixing some minor nitpicks.
> > 
> 
> If anyone wants to give this a test, here's a public branch:
> 
> https://github.com/MISL-EBU-System-SW/mainline-public/tree/wdt_for_v3.14_v5

I just took a quick glance at this (commit oneliners/tags) and there
doesn't appear to be any dependence on Sebastian's series.  Did I miss
something?

Also, the MMIO patch hit mainline last night.

thx,

Jason.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v9] gpio: add a driver for Synopsys DesignWare APB GPIO
From: Steffen Trumtrar @ 2014-01-30 20:50 UTC (permalink / raw)
  To: delicious quinoa
  Cc: Linus Walleij, linux-kernel, linux-gpio@vger.kernel.org,
	linux-doc@vger.kernel.org, Jamie Iles, devicetree@vger.kernel.org,
	Grant Likely, Rob Herring, Sebastian Hesselbarth, Heiko Stuebner,
	Alan Tull, Dinh Nguyen, Yves Vandervennet
In-Reply-To: <CANk1AXRxTGRMJMvXe4jgG2GfuELsDTNJnRLXK-MGe3gGxinmLA@mail.gmail.com>

Hi!

On Thu, Jan 30, 2014 at 01:40:04PM -0600, delicious quinoa wrote:
> On Thu, Dec 12, 2013 at 3:08 AM, Steffen Trumtrar
> <s.trumtrar@pengutronix.de> wrote:
> 
> > Second: The interrupt is registered as "GIC 37", which is a real interrupt on
> > the Socfpga. I would expect it to be marked as "GPIO 2xx" (or something in that
> > range). The interrupt from the gpiochip itself isn't registered at all ?!
> 
> Hi Stephen,
> 
> Did you export the gpio lines and set the edge in sysfs?  Because the
> interrupts aren't allocated otherwise.
> 
> For instance:
> 
> root@socfpga_cyclone5:~# echo 195 > /sys/class/gpio/export
> root@socfpga_cyclone5:~# echo rising > /sys/class/gpio/gpio195/edge
> 
> Now I can see a pretty nicely named interrupt in /proc/interrupts:
> 
> 256:          0          0  gpio-dwapb  24  gpiolib
> 

I didn't try that and I think this behaviour is pretty uncommon.
This should be fixed in the driver. I never wrote a gpiochip-driver,
so I don't know what is missing, but maybe just some functioncall ?!
All other drivers I came across have that entry from probing without
any fiddling.

Thanks,
Steffen

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply

* Re: recommended action for bootloaders regarding modifying device-tree nodes
From: Jason Cooper @ 2014-01-30 20:45 UTC (permalink / raw)
  To: Tim Harvey
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	Grant Likely
In-Reply-To: <CAJ+vNU366GiY4k_rnh1Jf0kra+PU99w4tDdM2sNioUAJCiZqOA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

Hi Tim,

On Thu, Jan 30, 2014 at 01:11:18AM -0800, Tim Harvey wrote:
> My approach has been to define a per-baseboard device-tree in Linux
> for a 'fully loaded' board, then remove nodes which the EEPROM claims
> are not present in the bootloader before it passes the DTB to the
> kernel.  I do this by defining aliases in the device-tree for the
> peripherals that are 'optional' so that the bootloader itself does not
> need to know the details about how the device is connected.

This is more of a process question:  Is there any information captured
in your EEPROM that can't be represented in the dtb?  iow, at the point
when you write the EEPROM, why not write the dtb to it as configured?

You could have pre-configured dtsi fragments for each config option, and
then dynamically create the board dts from the order.

I only ask because it would solve the problem below.  However, there's a
lot more to changing a manufacturing process than meets the eye. :)

> Is it more appropriate for the bootloader to 'remove' nodes for
> devices that are not physically present or should I be setting their
> status property to 'disabled' instead?  I'm not clear if either option
> really has any pros or cons.

That depends on how you have it structured.  Is it a valid dtb?
Meaning, do you have four nodes all at the same register address?
Perhaps you could provide an example dts?

thx,

Jason.

> Tim Harvey - Principal Software Engineer
> Gateworks Corporation

btw - one of my first embedded projects was on one of your boards. An
ixp425 with 4 mini-pci slots.

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2 00/21] pinctrl: mvebu: restructure and remove hardcoded addresses from Dove pinctrl
From: Andrew Lunn @ 2014-01-30 20:25 UTC (permalink / raw)
  To: Sebastian Hesselbarth
  Cc: Thomas Petazzoni, Andrew Lunn, Russell King, Jason Cooper,
	devicetree, Linus Walleij, linux-doc, linux-kernel,
	Gregory Clement, linux-arm-kernel
In-Reply-To: <52EA9EFA.1030609@gmail.com>

On Thu, Jan 30, 2014 at 07:50:34PM +0100, Sebastian Hesselbarth wrote:
> On 01/30/2014 07:29 PM, Andrew Lunn wrote:
> >On Tue, Jan 28, 2014 at 01:39:12AM +0100, Sebastian Hesselbarth wrote:
> >>This patch set is one required step for Dove to hop into mach-mvebu.
> >>Until now, pinctrl-dove was hardcoding some registers that do not
> >>directly belong to MPP core registers. This is not compatible with
> >>what we want for mach-mvebu.
> >
> >I think there might be something wrong here....
> 
> There _is_ something wrong. I'll have a look at it. For the record,
> what SoC are you testing with? From the base address, I guess it is
> Kirkwood?

Yes, Kirkwood. Sorry for not saying.

     Andrew

^ permalink raw reply

* Re: [PATCH v10 0/4] ata: Add APM X-Gene SoC SATA host controller support
From: Loc Ho @ 2014-01-30 19:56 UTC (permalink / raw)
  To: Olof Johansson, Tejun Heo, Arnd Bergmann
  Cc: Linux SCSI List, linux-ide@vger.kernel.org,
	devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	David Milburn, Jon Masters, patches@apm.com, Tuan Phan,
	Suman Tripathi

Hi Tejun,

As it had being awhile, any issue with this version of the SATA
drivers before I post the follow on errata patches?

-Loc

On Thu, Jan 16, 2014 at 8:11 AM, Loc Ho <lho@apm.com> wrote:
> This patch adds support for the APM X-Gene SoC SATA host controller. In
> order for the host controller to work, the corresponding PHY driver
> musts also be available.
>
> v10:
>  * Update binding documentation
>
> v9:
>  * Remove ACPI/EFI include files
>  * Remove the IO flush support, interrupt routine, and DTS resources
>  * Remove function xgene_rd, xgene_wr, and xgene_wr_flush
>  * Remove PMP support (function xgene_ahci_qc_issue, xgene_ahci_qc_prep,
>    xgene_ahci_qc_fill_rtf, xgene_ahci_softreset, and xgene_ahci_do_softreset)
>  * Rename function xgene_ahci_enable_phy to xgene_ahci_force_phy_rdy
>  * Clean up hardreset functions
>  * Require v7 of the PHY driver
>
> v8:
>  * Remove _ADDR from defines
>  * Remove define MSTAWAUX_COHERENT_BYPASS_SET and
>    STARAUX_COHERENT_BYPASS_SET and use direct coding
>  * Remove the un-necessary check for DTS boot with built in ACPI table
>  * Switch to use dma_set_mask_and_coherent for setting DMA mask
>  * Remove ACPI table matching code
>  * Update clock-names for sata01clk, sata23clk, and sata45clk
>
> v7:
>  * Update the clock code by toggle the clock
>  * Update the DTS clock mask values due to the clock spilt between host and
>    v5 of the PHY drivers
>
> v6:
>  * Update binding documentation
>  * Change select PHY_XGENE_SATA to PHY_XGENE
>  * Add ULL to constants
>  * Change indentation and comments
>  * Clean up the probe functions a bit more
>  * Remove xgene_ahci_remove function
>  * Add the flush register to DTS
>  * Remove the interrupt-parent from DTS
>
> v5:
>  * Sync up to v3 of the PHY driver
>  * Remove MSLIM wrapper functions
>  * Change the memory shutdown loop to use usleep_range
>  * Use devm_ioremap_resource instead devm_ioremap
>  * Remove suspend/resume functions as not needed
>
> v4:
>  * Remove the ID property in DT
>  * Remove the temporary PHY direct function call and use PHY function
>  * Change printk to pr_debug
>  * Move the IOB flush addresses into the DT
>  * Remove the parameters retrieval function as no longer needed
>  * Remove the header file as no longer needed
>  * Require v2 patch of the SATA PHY driver. Require slightly modification
>    in the Kconfig as it is moved to folder driver/phy and use Kconfig
>    PHY_XGENE_SATA instead SATA_XGENE_PHY.
>
> v3:
>  * Move out the SATA PHY to another driver
>  * Remove the clock-cells entry from DTS
>  * Remove debug wrapper
>  * Remove delay functions wrapper
>  * Clean up resource and IRQ query
>  * Remove query clock name
>  * Switch to use dma_set_mask/dma_coherent_mask
>  * Remove un-necessary devm_kfree
>  * Update GPL license header to v2
>  * Spilt up function xgene_ahci_hardreset
>  * Spilt up function xgene_ahci_probe
>  * Remove all reference of CONFIG_ARCH_MSLIM
>  * Clean up chip revision code
>
> v2:
>  * Clean up file sata_xgene.c with Lindent and etc
>  * Clean up file sata_xgene_serdes.c with Lindent and etc
>  * Add description to each patch
>
> v1:
>  * inital version
>
> Signed-off-by: Loc Ho <lho@apm.com>
> Signed-off-by: Tuan Phan <tphan@apm.com>
> Signed-off-by: Suman Tripathi <stripathi@apm.com>
> ---
> Loc Ho (4):
>   ata: Export required functions by APM X-Gene SATA driver
>   Documentation: Add documentation for APM X-Gene SoC SATA host
>     controller DTS binding
>   ata: Add APM X-Gene SoC SATA host controller driver
>   arm64: Add APM X-Gene SoC SATA host controller DTS entries
>
>  .../devicetree/bindings/ata/apm-xgene.txt          |   70 +++
>  arch/arm64/boot/dts/apm-storm.dtsi                 |   75 +++
>  drivers/ata/Kconfig                                |    8 +
>  drivers/ata/Makefile                               |    1 +
>  drivers/ata/ahci.h                                 |    9 +
>  drivers/ata/libahci.c                              |   16 +-
>  drivers/ata/sata_xgene.c                           |  630 ++++++++++++++++++++
>  7 files changed, 803 insertions(+), 6 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/ata/apm-xgene.txt
>  create mode 100644 drivers/ata/sata_xgene.c
>

^ permalink raw reply

* Re: [PATCH v9] gpio: add a driver for Synopsys DesignWare APB GPIO
From: delicious quinoa @ 2014-01-30 19:40 UTC (permalink / raw)
  To: Steffen Trumtrar
  Cc: Linus Walleij, linux-kernel, linux-gpio@vger.kernel.org,
	linux-doc@vger.kernel.org, Jamie Iles, devicetree@vger.kernel.org,
	Grant Likely, Rob Herring, Sebastian Hesselbarth, Heiko Stuebner,
	Alan Tull, Dinh Nguyen, Yves Vandervennet
In-Reply-To: <20131212090838.GD25478@pengutronix.de>

On Thu, Dec 12, 2013 at 3:08 AM, Steffen Trumtrar
<s.trumtrar@pengutronix.de> wrote:

> Second: The interrupt is registered as "GIC 37", which is a real interrupt on
> the Socfpga. I would expect it to be marked as "GPIO 2xx" (or something in that
> range). The interrupt from the gpiochip itself isn't registered at all ?!

Hi Stephen,

Did you export the gpio lines and set the edge in sysfs?  Because the
interrupts aren't allocated otherwise.

For instance:

root@socfpga_cyclone5:~# echo 195 > /sys/class/gpio/export
root@socfpga_cyclone5:~# echo rising > /sys/class/gpio/gpio195/edge

Now I can see a pretty nicely named interrupt in /proc/interrupts:

256:          0          0  gpio-dwapb  24  gpiolib

Alan Tull
Altera Corp

^ permalink raw reply

* Re: [PATCH v2 00/21] pinctrl: mvebu: restructure and remove hardcoded addresses from Dove pinctrl
From: Sebastian Hesselbarth @ 2014-01-30 18:50 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Jason Cooper, Gregory Clement, Thomas Petazzoni, Russell King,
	Linus Walleij, devicetree, linux-doc, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20140130182925.GM10864@lunn.ch>

On 01/30/2014 07:29 PM, Andrew Lunn wrote:
> On Tue, Jan 28, 2014 at 01:39:12AM +0100, Sebastian Hesselbarth wrote:
>> This patch set is one required step for Dove to hop into mach-mvebu.
>> Until now, pinctrl-dove was hardcoding some registers that do not
>> directly belong to MPP core registers. This is not compatible with
>> what we want for mach-mvebu.
>
> I think there might be something wrong here....

There _is_ something wrong. I'll have a look at it. For the record,
what SoC are you testing with? From the base address, I guess it is
Kirkwood?

Sebastian

> /debug/pinctrl/f1010000.pinctrl/pinconf-groups used to contain:
>
> Pin config settings per pin group
> Format: group (name): configs
> 0 (mpp0):current: spi(cs), available = [ gpio(io) nand(io2) ]
> 1 (mpp1):current: spi(mosi), available = [ gpo(o) nand(io3) ]
> 2 (mpp2):current: spi(sck), available = [ gpo(o) nand(io4) ]
> 3 (mpp3):current: spi(miso), available = [ gpo(o) nand(io5) ]
> 4 (mpp4):current: sata1(act), available = [ gpio(io) nand(io6) uart0(rxd) lcd(hsync) ]
> 5 (mpp5):current: sata0(act), available = [ gpo(o) nand(io7) uart0(txd) lcd(vsync) ]
> 6 (mpp6):current: sysrst(out), available = [ spi(mosi) ]
> ...
>
> It now has:
>
> Pin config settings per pin group
> Format: group (name): configs
> 0 (mpp0):current: gpio(io), available = [ nand(io2) spi(cs) ]
> 1 (mpp1):current: gpo(o), available = [ nand(io3) spi(mosi) ]
> 2 (mpp2):current: gpo(o), available = [ nand(io4) spi(sck) ]
> 3 (mpp3):current: gpo(o), available = [ nand(io5) spi(miso) ]
> 4 (mpp4):current: gpio(io), available = [ nand(io6) uart0(rxd) sata1(act) lcd(hsync) ]
> 5 (mpp5):current: gpo(o), available = [ nand(io7) uart0(txd) sata0(act) lcd(vsync) ]
> 6 (mpp6):current: UNKNOWN, available = [ sysrst(out) spi(mosi) ]
>
> The device i'm testing on does use spi and sata, so i would say the
> old contents was correct and the new is wrong.



^ permalink raw reply

* [PATCH v8 3/3] mmc: sdhci-msm: Add platform_execute_tunning implementation
From: Georgi Djakov @ 2014-01-30 18:45 UTC (permalink / raw)
  To: linux-mmc, cjb, devicetree, grant.likely, rob.herring, pawel.moll,
	mark.rutland, swarren, ijc+devicetree, galak, rob, linux-doc,
	linux-kernel
  Cc: linux-arm-msm, Georgi Djakov
In-Reply-To: <1391107507-17321-1-git-send-email-gdjakov@mm-sol.com>

This patch adds implementation for platform specific tuning in order to support
HS200 bus speed mode on Qualcomm SDHCI controller.

Signed-off-by: Georgi Djakov <gdjakov@mm-sol.com>
---
 drivers/mmc/host/sdhci-msm.c |  417 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 412 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 900e813..5ae099f 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -19,6 +19,8 @@
 #include <linux/of_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/delay.h>
+#include <linux/mmc/mmc.h>
+#include <linux/slab.h>
 
 #include "sdhci-pltfm.h"
 
@@ -44,7 +46,40 @@
 #define CORE_PWRCTL_IO_FAIL	BIT(3)
 
 #define INT_MASK		0xf
+#define MAX_PHASES		16
+
+#define CORE_DLL_LOCK		BIT(7)
+#define CORE_DLL_EN		BIT(16)
+#define CORE_CDR_EN		BIT(17)
+#define CORE_CK_OUT_EN		BIT(18)
+#define CORE_CDR_EXT_EN		BIT(19)
+#define CORE_DLL_PDN		BIT(29)
+#define CORE_DLL_RST		BIT(30)
+#define CORE_DLL_CONFIG		0x100
+#define CORE_DLL_TEST_CTL	0x104
+#define CORE_DLL_STATUS		0x108
+
+#define CORE_VENDOR_SPEC	0x10c
+#define CORE_CLK_PWRSAVE	BIT(1)
+#define CORE_IO_PAD_PWR_SWITCH	BIT(16)
+
+static const u32 tuning_block_64[] = {
+	0x00ff0fff, 0xccc3ccff, 0xffcc3cc3, 0xeffefffe,
+	0xddffdfff, 0xfbfffbff, 0xff7fffbf, 0xefbdf777,
+	0xf0fff0ff, 0x3cccfc0f, 0xcfcc33cc, 0xeeffefff,
+	0xfdfffdff, 0xffbfffdf, 0xfff7ffbb, 0xde7b7ff7
+};
 
+static const u32 tuning_block_128[] = {
+	0xff00ffff, 0x0000ffff, 0xccccffff, 0xcccc33cc,
+	0xcc3333cc, 0xffffcccc, 0xffffeeff, 0xffeeeeff,
+	0xffddffff, 0xddddffff, 0xbbffffff, 0xbbffffff,
+	0xffffffbb, 0xffffff77, 0x77ff7777, 0xffeeddbb,
+	0x00ffffff, 0x00ffffff, 0xccffff00, 0xcc33cccc,
+	0x3333cccc, 0xffcccccc, 0xffeeffff, 0xeeeeffff,
+	0xddffffff, 0xddffffff, 0xffffffdd, 0xffffffbb,
+	0xffffbbbb, 0xffff77ff, 0xff7777ff, 0xeeddbb77
+};
 
 /* This structure keeps information per regulator */
 struct sdhci_msm_reg_data {
@@ -75,17 +110,389 @@ struct sdhci_msm_host {
 };
 
 /* MSM platform specific tuning */
-int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
+static inline int msm_dll_poll_ck_out_en(struct sdhci_host *host, u8 poll)
+{
+	u32 wait_cnt = 50;
+	u8 ck_out_en = 0;
+	struct mmc_host *mmc = host->mmc;
+
+	/* poll for CK_OUT_EN bit.  max. poll time = 50us */
+	ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
+			CORE_CK_OUT_EN);
+
+	while (ck_out_en != poll) {
+		if (--wait_cnt == 0) {
+			dev_err(mmc_dev(mmc), "%s: CK_OUT_EN bit is not %d\n",
+			       mmc_hostname(mmc), poll);
+			return -ETIMEDOUT;
+		}
+		udelay(1);
+
+		ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
+				CORE_CK_OUT_EN);
+	}
+
+	return 0;
+}
+
+static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase)
+{
+	int rc = 0;
+	u8 grey_coded_phase_table[] = {
+		0x0, 0x1, 0x3, 0x2, 0x6, 0x7, 0x5, 0x4,
+		0xc, 0xd, 0xf, 0xe, 0xa, 0xb, 0x9, 0x8
+	};
+	unsigned long flags;
+	u32 config;
+	struct mmc_host *mmc = host->mmc;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+	config &= ~(CORE_CDR_EN | CORE_CK_OUT_EN);
+	config |= (CORE_CDR_EXT_EN | CORE_DLL_EN);
+	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+	/* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '0' */
+	rc = msm_dll_poll_ck_out_en(host, 0);
+	if (rc)
+		goto err_out;
+
+	/*
+	 * Write the selected DLL clock output phase (0 ... 15)
+	 * to CDR_SELEXT bit field of DLL_CONFIG register.
+	 */
+	writel_relaxed(((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
+			 & ~(0xF << 20))
+			| (grey_coded_phase_table[phase] << 20)),
+		       host->ioaddr + CORE_DLL_CONFIG);
+
+	/* Set CK_OUT_EN bit of DLL_CONFIG register to 1. */
+	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
+			| CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
+
+	/* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '1' */
+	rc = msm_dll_poll_ck_out_en(host, 1);
+	if (rc)
+		goto err_out;
+
+	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+	config |= CORE_CDR_EN;
+	config &= ~CORE_CDR_EXT_EN;
+	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+	goto out;
+
+err_out:
+	dev_err(mmc_dev(mmc), "%s: Failed to set DLL phase: %d\n",
+	       mmc_hostname(mmc), phase);
+out:
+	spin_unlock_irqrestore(&host->lock, flags);
+	return rc;
+}
+
+/*
+ * Find out the greatest range of consecuitive selected
+ * DLL clock output phases that can be used as sampling
+ * setting for SD3.0 UHS-I card read operation (in SDR104
+ * timing mode) or for eMMC4.5 card read operation (in HS200
+ * timing mode).
+ * Select the 3/4 of the range and configure the DLL with the
+ * selected DLL clock output phase.
+ */
+
+static int msm_find_most_appropriate_phase(struct sdhci_host *host,
+					   u8 *phase_table, u8 total_phases)
+{
+	int ret;
+	u8 ranges[MAX_PHASES][MAX_PHASES] = { {0}, {0} };
+	u8 phases_per_row[MAX_PHASES] = { 0 };
+	int row_index = 0, col_index = 0, selected_row_index = 0, curr_max = 0;
+	int i, cnt, phase_0_raw_index = 0, phase_15_raw_index = 0;
+	bool phase_0_found = false, phase_15_found = false;
+	struct mmc_host *mmc = host->mmc;
+
+	if (!total_phases || (total_phases > MAX_PHASES)) {
+		dev_err(mmc_dev(mmc), "%s: invalid argument: total_phases=%d\n",
+		       mmc_hostname(mmc), total_phases);
+		return -EINVAL;
+	}
+
+	for (cnt = 0; cnt < total_phases; cnt++) {
+		ranges[row_index][col_index] = phase_table[cnt];
+		phases_per_row[row_index] += 1;
+		col_index++;
+
+		if ((cnt + 1) == total_phases) {
+			continue;
+		/* check if next phase in phase_table is consecutive or not */
+		} else if ((phase_table[cnt] + 1) != phase_table[cnt + 1]) {
+			row_index++;
+			col_index = 0;
+		}
+	}
+
+	if (row_index >= MAX_PHASES)
+		return -EINVAL;
+
+	/* Check if phase-0 is present in first valid window? */
+	if (!ranges[0][0]) {
+		phase_0_found = true;
+		phase_0_raw_index = 0;
+		/* Check if cycle exist between 2 valid windows */
+		for (cnt = 1; cnt <= row_index; cnt++) {
+			if (phases_per_row[cnt]) {
+				for (i = 0; i < phases_per_row[cnt]; i++) {
+					if (ranges[cnt][i] == 15) {
+						phase_15_found = true;
+						phase_15_raw_index = cnt;
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	/* If 2 valid windows form cycle then merge them as single window */
+	if (phase_0_found && phase_15_found) {
+		/* number of phases in raw where phase 0 is present */
+		u8 phases_0 = phases_per_row[phase_0_raw_index];
+		/* number of phases in raw where phase 15 is present */
+		u8 phases_15 = phases_per_row[phase_15_raw_index];
+
+		if (phases_0 + phases_15 >= MAX_PHASES)
+			/*
+			 * If there are more than 1 phase windows then total
+			 * number of phases in both the windows should not be
+			 * more than or equal to MAX_PHASES.
+			 */
+			return -EINVAL;
+
+		/* Merge 2 cyclic windows */
+		i = phases_15;
+		for (cnt = 0; cnt < phases_0; cnt++) {
+			ranges[phase_15_raw_index][i] =
+			    ranges[phase_0_raw_index][cnt];
+			if (++i >= MAX_PHASES)
+				break;
+		}
+
+		phases_per_row[phase_0_raw_index] = 0;
+		phases_per_row[phase_15_raw_index] = phases_15 + phases_0;
+	}
+
+	for (cnt = 0; cnt <= row_index; cnt++) {
+		if (phases_per_row[cnt] > curr_max) {
+			curr_max = phases_per_row[cnt];
+			selected_row_index = cnt;
+		}
+	}
+
+	i = ((curr_max * 3) / 4);
+	if (i)
+		i--;
+
+	ret = (int)ranges[selected_row_index][i];
+
+	if (ret >= MAX_PHASES) {
+		ret = -EINVAL;
+		dev_err(mmc_dev(mmc), "%s: invalid phase selected=%d\n",
+		       mmc_hostname(mmc), ret);
+	}
+
+	return ret;
+}
+
+static inline void msm_cm_dll_set_freq(struct sdhci_host *host)
+{
+	u32 mclk_freq = 0;
+
+	/* Program the MCLK value to MCLK_FREQ bit field */
+	if (host->clock <= 112000000)
+		mclk_freq = 0;
+	else if (host->clock <= 125000000)
+		mclk_freq = 1;
+	else if (host->clock <= 137000000)
+		mclk_freq = 2;
+	else if (host->clock <= 150000000)
+		mclk_freq = 3;
+	else if (host->clock <= 162000000)
+		mclk_freq = 4;
+	else if (host->clock <= 175000000)
+		mclk_freq = 5;
+	else if (host->clock <= 187000000)
+		mclk_freq = 6;
+	else if (host->clock <= 200000000)
+		mclk_freq = 7;
+
+	writel_relaxed(((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
+			 & ~(7 << 24)) | (mclk_freq << 24)),
+		       host->ioaddr + CORE_DLL_CONFIG);
+}
+
+/* Initialize the DLL (Programmable Delay Line ) */
+static int msm_init_cm_dll(struct sdhci_host *host)
 {
+	struct mmc_host *mmc = host->mmc;
+	int wait_cnt = 50;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
 	/*
-	 * Tuning is required for SDR104, HS200 and HS400 cards and if the clock
-	 * frequency greater than 100MHz in those modes. The standard tuning
-	 * procedure should not be executed, but a custom implementation will be
-	 * added here instead.
+	 * Make sure that clock is always enabled when DLL
+	 * tuning is in progress. Keeping PWRSAVE ON may
+	 * turn off the clock.
 	 */
+	writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
+			& ~CORE_CLK_PWRSAVE), host->ioaddr + CORE_VENDOR_SPEC);
+
+	/* Write 1 to DLL_RST bit of DLL_CONFIG register */
+	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
+			| CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG);
+
+	/* Write 1 to DLL_PDN bit of DLL_CONFIG register */
+	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
+			| CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG);
+	msm_cm_dll_set_freq(host);
+
+	/* Write 0 to DLL_RST bit of DLL_CONFIG register */
+	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
+			& ~CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG);
+
+	/* Write 0 to DLL_PDN bit of DLL_CONFIG register */
+	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
+			& ~CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG);
+
+	/* Set DLL_EN bit to 1. */
+	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
+			| CORE_DLL_EN), host->ioaddr + CORE_DLL_CONFIG);
+
+	/* Set CK_OUT_EN bit to 1. */
+	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
+			| CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
+
+	/* Wait until DLL_LOCK bit of DLL_STATUS register becomes '1' */
+	while (!(readl_relaxed(host->ioaddr + CORE_DLL_STATUS) &
+		 CORE_DLL_LOCK)) {
+		/* max. wait for 50us sec for LOCK bit to be set */
+		if (--wait_cnt == 0) {
+			dev_err(mmc_dev(mmc), "%s: DLL failed to LOCK\n",
+			       mmc_hostname(mmc));
+			spin_unlock_irqrestore(&host->lock, flags);
+			return -ETIMEDOUT;
+		}
+		/* wait for 1us before polling again */
+		udelay(1);
+	}
+
+	spin_unlock_irqrestore(&host->lock, flags);
 	return 0;
 }
 
+int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
+{
+	int tuning_seq_cnt = 3;
+	u8 phase, *data_buf, tuned_phases[16], tuned_phase_cnt = 0;
+	const u32 *tuning_block_pattern = tuning_block_64;
+	int size = sizeof(tuning_block_64);	/* Pattern size in bytes */
+	int rc;
+	struct mmc_host *mmc = host->mmc;
+	struct mmc_ios ios = host->mmc->ios;
+
+	/*
+	 * Tuning is required for SDR104, HS200 and HS400 cards and
+	 * if clock frequency is greater than 100MHz in these modes.
+	 */
+	if (host->clock <= 100 * 1000 * 1000 ||
+	    !((ios.timing == MMC_TIMING_MMC_HS200) ||
+	      (ios.timing == MMC_TIMING_UHS_SDR104)))
+		return 0;
+
+	if ((opcode == MMC_SEND_TUNING_BLOCK_HS200) &&
+	    (mmc->ios.bus_width == MMC_BUS_WIDTH_8)) {
+		tuning_block_pattern = tuning_block_128;
+		size = sizeof(tuning_block_128);
+	}
+
+	data_buf = kmalloc(size, GFP_KERNEL);
+	if (!data_buf)
+		return -ENOMEM;
+
+retry:
+	/* first of all reset the tuning block */
+	rc = msm_init_cm_dll(host);
+	if (rc)
+		goto out;
+
+	phase = 0;
+	do {
+		struct mmc_command cmd = { 0 };
+		struct mmc_data data = { 0 };
+		struct mmc_request mrq = {
+			.cmd = &cmd,
+			.data = &data
+		};
+		struct scatterlist sg;
+
+		/* set the phase in delay line hw block */
+		rc = msm_config_cm_dll_phase(host, phase);
+		if (rc)
+			goto out;
+
+		cmd.opcode = opcode;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+		data.blksz = size;
+		data.blocks = 1;
+		data.flags = MMC_DATA_READ;
+		data.timeout_ns = 1000 * 1000 * 1000;	/* 1 sec */
+
+		data.sg = &sg;
+		data.sg_len = 1;
+		sg_init_one(&sg, data_buf, sizeof(data_buf));
+		memset(data_buf, 0, sizeof(data_buf));
+		mmc_wait_for_req(mmc, &mrq);
+
+		if (!cmd.error && !data.error &&
+		    !memcmp(data_buf, tuning_block_pattern, sizeof(data_buf))) {
+			/* tuning is successful at this tuning point */
+			tuned_phases[tuned_phase_cnt++] = phase;
+			dev_dbg(mmc_dev(mmc), "%s: found good phase = %d\n",
+				 mmc_hostname(mmc), phase);
+		}
+	} while (++phase < 16);
+
+	if (tuned_phase_cnt) {
+		rc = msm_find_most_appropriate_phase(host, tuned_phases,
+						     tuned_phase_cnt);
+		if (rc < 0)
+			goto out;
+		else
+			phase = (u8) rc;
+
+		/*
+		 * Finally set the selected phase in delay
+		 * line hw block.
+		 */
+		rc = msm_config_cm_dll_phase(host, phase);
+		if (rc)
+			goto out;
+		dev_dbg(mmc_dev(mmc), "%s: setting the tuning phase to %d\n",
+			 mmc_hostname(mmc), phase);
+	} else {
+		if (--tuning_seq_cnt)
+			goto retry;
+		/* tuning failed */
+		dev_dbg(mmc_dev(mmc), "%s: no tuning point found\n",
+		       mmc_hostname(mmc));
+		rc = -EIO;
+	}
+
+out:
+	kfree(data_buf);
+	return rc;
+}
+
 #define MAX_PROP_SIZE 32
 static int sdhci_msm_dt_parse_vreg_info(struct device *dev,
 			struct sdhci_msm_reg_data *vreg, const char *vreg_name)
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v8 2/3] mmc: sdhci-msm: Initial support for Qualcomm chipsets
From: Georgi Djakov @ 2014-01-30 18:45 UTC (permalink / raw)
  To: linux-mmc, cjb, devicetree, grant.likely, rob.herring, pawel.moll,
	mark.rutland, swarren, ijc+devicetree, galak, rob, linux-doc,
	linux-kernel
  Cc: linux-arm-msm, Georgi Djakov
In-Reply-To: <1391107507-17321-1-git-send-email-gdjakov@mm-sol.com>

This platform driver adds the initial support of Secure
Digital Host Controller Interface compliant controller
found in Qualcomm chipsets.

Signed-off-by: Georgi Djakov <gdjakov@mm-sol.com>
---
 drivers/mmc/host/Kconfig     |   13 ++
 drivers/mmc/host/Makefile    |    1 +
 drivers/mmc/host/sdhci-msm.c |  531 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 545 insertions(+)
 create mode 100644 drivers/mmc/host/sdhci-msm.c

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 1384f67..c32d092 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -334,6 +334,19 @@ config MMC_ATMELMCI
 
 	  If unsure, say N.
 
+config MMC_SDHCI_MSM
+	tristate "Qualcomm SDHCI Controller Support"
+	depends on ARCH_MSM
+	depends on MMC_SDHCI_PLTFM
+	help
+	  This selects the Secure Digital Host Controller Interface (SDHCI)
+	  support present in MSM SOCs from Qualcomm. The controller
+	  supports SD/MMC/SDIO devices.
+
+	  If you have a controller with this interface, say Y or M here.
+
+	  If unsure, say N.
+
 config MMC_MSM
 	tristate "Qualcomm SDCC Controller Support"
 	depends on MMC && (ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50)
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 3483b6b..bbc8445 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -64,6 +64,7 @@ obj-$(CONFIG_MMC_SDHCI_OF_ESDHC)	+= sdhci-of-esdhc.o
 obj-$(CONFIG_MMC_SDHCI_OF_HLWD)		+= sdhci-of-hlwd.o
 obj-$(CONFIG_MMC_SDHCI_BCM_KONA)	+= sdhci-bcm-kona.o
 obj-$(CONFIG_MMC_SDHCI_BCM2835)		+= sdhci-bcm2835.o
+obj-$(CONFIG_MMC_SDHCI_MSM)		+= sdhci-msm.o
 
 ifeq ($(CONFIG_CB710_DEBUG),y)
 	CFLAGS-cb710-mmc	+= -DDEBUG
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
new file mode 100644
index 0000000..900e813
--- /dev/null
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -0,0 +1,531 @@
+/*
+ * drivers/mmc/host/sdhci-msm.c - Qualcomm MSM SDHCI Platform
+ * driver source file
+ *
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ *
+ * 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 <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/delay.h>
+
+#include "sdhci-pltfm.h"
+
+#define CORE_HC_MODE		0x78
+#define HC_MODE_EN		0x1
+
+#define CORE_POWER		0x0
+#define CORE_SW_RST		BIT(7)
+
+#define CORE_PWRCTL_STATUS	0xdc
+#define CORE_PWRCTL_MASK	0xe0
+#define CORE_PWRCTL_CLEAR	0xe4
+#define CORE_PWRCTL_CTL		0xe8
+
+#define CORE_PWRCTL_BUS_OFF	BIT(0)
+#define CORE_PWRCTL_BUS_ON	BIT(1)
+#define CORE_PWRCTL_IO_LOW	BIT(2)
+#define CORE_PWRCTL_IO_HIGH	BIT(3)
+
+#define CORE_PWRCTL_BUS_SUCCESS	BIT(0)
+#define CORE_PWRCTL_BUS_FAIL	BIT(1)
+#define CORE_PWRCTL_IO_SUCCESS	BIT(2)
+#define CORE_PWRCTL_IO_FAIL	BIT(3)
+
+#define INT_MASK		0xf
+
+
+/* This structure keeps information per regulator */
+struct sdhci_msm_reg_data {
+	struct regulator *reg;
+	const char *name;
+	/* Voltage level values */
+	u32 low_vol_level;
+	u32 high_vol_level;
+};
+
+struct sdhci_msm_pltfm_data {
+	u32 caps;				/* Supported UHS-I Modes */
+	u32 caps2;				/* More capabilities */
+	struct sdhci_msm_reg_data vdd;		/* VDD/VCC regulator info */
+	struct sdhci_msm_reg_data vdd_io;	/* VDD IO regulator info */
+};
+
+struct sdhci_msm_host {
+	struct platform_device *pdev;
+	void __iomem *core_mem;	/* MSM SDCC mapped address */
+	int pwr_irq;		/* power irq */
+	struct clk *clk;	/* main SD/MMC bus clock */
+	struct clk *pclk;	/* SDHC peripheral bus clock */
+	struct clk *bus_clk;	/* SDHC bus voter clock */
+	struct sdhci_msm_pltfm_data pdata;
+	struct mmc_host *mmc;
+	struct sdhci_pltfm_data sdhci_msm_pdata;
+};
+
+/* MSM platform specific tuning */
+int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
+{
+	/*
+	 * Tuning is required for SDR104, HS200 and HS400 cards and if the clock
+	 * frequency greater than 100MHz in those modes. The standard tuning
+	 * procedure should not be executed, but a custom implementation will be
+	 * added here instead.
+	 */
+	return 0;
+}
+
+#define MAX_PROP_SIZE 32
+static int sdhci_msm_dt_parse_vreg_info(struct device *dev,
+			struct sdhci_msm_reg_data *vreg, const char *vreg_name)
+{
+	char prop_name[MAX_PROP_SIZE];
+	struct device_node *np = dev->of_node;
+
+	vreg->name = vreg_name;
+
+	snprintf(prop_name, MAX_PROP_SIZE, "qcom,%s-voltage-min", vreg_name);
+	of_property_read_u32(np, prop_name, &vreg->low_vol_level);
+	snprintf(prop_name, MAX_PROP_SIZE, "qcom,%s-voltage-max", vreg_name);
+	of_property_read_u32(np, prop_name, &vreg->high_vol_level);
+
+	/* sanity check */
+	if (vreg->low_vol_level > vreg->high_vol_level) {
+		dev_err(dev, "%s invalid constraints specified\n", vreg->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* Parse devicetree data */
+static int sdhci_msm_populate_pdata(struct device *dev,
+				    struct sdhci_msm_pltfm_data *pdata)
+{
+	if (sdhci_msm_dt_parse_vreg_info(dev, &pdata->vdd, "vdd")) {
+		dev_err(dev, "failed parsing vdd data\n");
+		return -EINVAL;
+	}
+
+	if (sdhci_msm_dt_parse_vreg_info(dev, &pdata->vdd_io, "vdd-io")) {
+		dev_err(dev, "failed parsing vdd-io data\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int sdhci_msm_vreg_enable(struct device *dev,
+				 struct sdhci_msm_reg_data *vreg)
+{
+	int ret = 0;
+
+	if (!regulator_is_enabled(vreg->reg)) {
+		/* Set voltage level */
+		ret = regulator_set_voltage(vreg->reg, vreg->high_vol_level,
+					    vreg->high_vol_level);
+		if (ret)
+			return ret;
+	}
+
+	ret = regulator_enable(vreg->reg);
+	if (ret) {
+		dev_err(dev, "regulator_enable(%s) fail (%d)\n",
+			vreg->name, ret);
+	}
+
+	return ret;
+}
+
+static int sdhci_msm_vreg_disable(struct device *dev,
+				  struct sdhci_msm_reg_data *vreg)
+{
+	int ret = 0;
+
+	if (!regulator_is_enabled(vreg->reg))
+		return ret;
+
+	/* Set min. voltage to 0 */
+	ret = regulator_set_voltage(vreg->reg, 0, vreg->high_vol_level);
+	if (ret)
+		return ret;
+
+	ret = regulator_disable(vreg->reg);
+	if (ret) {
+		dev_err(dev, "regulator_disable(%s) fail (%d)\n",
+			vreg->name, ret);
+	}
+
+	return ret;
+}
+
+static int sdhci_msm_setup_vreg(struct sdhci_msm_host *msm_host, bool enable)
+{
+	int ret, i;
+	struct sdhci_msm_reg_data *vreg_table[2];
+
+	vreg_table[0] = &msm_host->pdata.vdd;
+	vreg_table[1] = &msm_host->pdata.vdd_io;
+
+	for (i = 0; i < ARRAY_SIZE(vreg_table); i++) {
+		if (enable)
+			ret = sdhci_msm_vreg_enable(&msm_host->pdev->dev,
+						    vreg_table[i]);
+		else
+			ret = sdhci_msm_vreg_disable(&msm_host->pdev->dev,
+						     vreg_table[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/* This init function should be called only once for each SDHC slot */
+static int sdhci_msm_vreg_init(struct device *dev,
+			       struct sdhci_msm_pltfm_data *pdata)
+{
+	struct sdhci_msm_reg_data *vdd_reg = &pdata->vdd;
+	struct sdhci_msm_reg_data *vdd_io_reg = &pdata->vdd_io;
+
+	vdd_reg->reg = devm_regulator_get(dev, vdd_reg->name);
+	if (IS_ERR(vdd_reg->reg))
+		return PTR_ERR(vdd_reg->reg);
+
+	vdd_io_reg->reg = devm_regulator_get(dev, vdd_io_reg->name);
+	if (IS_ERR(vdd_io_reg->reg))
+		return PTR_ERR(vdd_io_reg->reg);
+
+	return 0;
+}
+
+static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
+{
+	struct sdhci_host *host = (struct sdhci_host *)data;
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+	u8 irq_status;
+	u8 irq_ack = 0;
+	int ret = 0;
+
+	irq_status = readb_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
+	dev_dbg(mmc_dev(msm_host->mmc), "%s: Received IRQ(%d), status=0x%x\n",
+		mmc_hostname(msm_host->mmc), irq, irq_status);
+
+	/* Clear the interrupt */
+	writeb_relaxed(irq_status, (msm_host->core_mem + CORE_PWRCTL_CLEAR));
+	/*
+	 * SDHC has core_mem and hc_mem device memory and these memory
+	 * addresses do not fall within 1KB region. Hence, any update to
+	 * core_mem address space would require an mb() to ensure this gets
+	 * completed before its next update to registers within hc_mem.
+	 */
+	mb();
+
+	/* Handle BUS ON/OFF */
+	if (irq_status & CORE_PWRCTL_BUS_ON) {
+		ret = sdhci_msm_setup_vreg(msm_host, true);
+		if (!ret)
+			ret = regulator_set_voltage(msm_host->pdata.vdd_io.reg,
+						    msm_host->pdata.
+						    vdd_io.high_vol_level,
+						    msm_host->pdata.
+						    vdd_io.high_vol_level);
+		if (ret)
+			irq_ack |= CORE_PWRCTL_BUS_FAIL;
+		else
+			irq_ack |= CORE_PWRCTL_BUS_SUCCESS;
+	}
+
+	if (irq_status & CORE_PWRCTL_BUS_OFF) {
+		ret = sdhci_msm_setup_vreg(msm_host, false);
+		if (!ret)
+			ret = regulator_set_voltage(msm_host->pdata.vdd_io.reg,
+						    msm_host->pdata.
+						    vdd_io.low_vol_level,
+						    msm_host->pdata.
+						    vdd_io.low_vol_level);
+		if (ret)
+			irq_ack |= CORE_PWRCTL_BUS_FAIL;
+		else
+			irq_ack |= CORE_PWRCTL_BUS_SUCCESS;
+	}
+
+	/* Handle IO LOW/HIGH */
+	if (irq_status & CORE_PWRCTL_IO_LOW) {
+		ret = regulator_set_voltage(msm_host->pdata.vdd_io.reg,
+					    msm_host->pdata.
+					    vdd_io.low_vol_level,
+					    msm_host->pdata.
+					    vdd_io.low_vol_level);
+		if (ret)
+			irq_ack |= CORE_PWRCTL_IO_FAIL;
+		else
+			irq_ack |= CORE_PWRCTL_IO_SUCCESS;
+	}
+
+	if (irq_status & CORE_PWRCTL_IO_HIGH) {
+		ret = regulator_set_voltage(msm_host->pdata.vdd_io.reg,
+					    msm_host->pdata.
+					    vdd_io.high_vol_level,
+					    msm_host->pdata.
+					    vdd_io.high_vol_level);
+		if (ret)
+			irq_ack |= CORE_PWRCTL_IO_FAIL;
+		else
+			irq_ack |= CORE_PWRCTL_IO_SUCCESS;
+	}
+
+	/* ACK status to the core */
+	writeb_relaxed(irq_ack, (msm_host->core_mem + CORE_PWRCTL_CTL));
+	/*
+	 * SDHC has core_mem and hc_mem device memory and these memory
+	 * addresses do not fall within 1KB region. Hence, any update to
+	 * core_mem address space would require an mb() to ensure this gets
+	 * completed before its next update to registers within hc_mem.
+	 */
+	mb();
+
+	dev_dbg(mmc_dev(msm_host->mmc), "%s: Handled IRQ(%d), ret=%d, ack=0x%x\n",
+		 mmc_hostname(msm_host->mmc), irq, ret, irq_ack);
+	return IRQ_HANDLED;
+}
+
+static const struct of_device_id sdhci_msm_dt_match[] = {
+	{ .compatible = "qcom,sdhci-msm" },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, sdhci_msm_dt_match);
+
+static struct sdhci_ops sdhci_msm_ops = {
+	.platform_execute_tuning = sdhci_msm_execute_tuning,
+};
+
+static int sdhci_msm_probe(struct platform_device *pdev)
+{
+	struct sdhci_host *host;
+	struct sdhci_pltfm_host *pltfm_host;
+	struct sdhci_msm_host *msm_host;
+	struct resource *core_memres = NULL;
+	int ret, dead;
+	u16 host_version;
+
+	if (!pdev->dev.of_node) {
+		dev_err(&pdev->dev, "No device tree data\n");
+		return -ENOENT;
+	}
+
+	msm_host = devm_kzalloc(&pdev->dev, sizeof(*msm_host), GFP_KERNEL);
+	if (!msm_host)
+		return -ENOMEM;
+
+	msm_host->sdhci_msm_pdata.ops = &sdhci_msm_ops;
+	host = sdhci_pltfm_init(pdev, &msm_host->sdhci_msm_pdata, 0);
+	if (IS_ERR(host)) {
+		dev_err(&pdev->dev, "sdhci_pltfm_init error\n");
+		return PTR_ERR(host);
+	}
+
+	pltfm_host = sdhci_priv(host);
+	pltfm_host->priv = msm_host;
+	msm_host->mmc = host->mmc;
+	msm_host->pdev = pdev;
+
+	ret = mmc_of_parse(host->mmc);
+	if (ret) {
+		dev_err(&pdev->dev, "failed parsing mmc device tree\n");
+		goto pltfm_free;
+	}
+
+	sdhci_get_of_property(pdev);
+
+	ret = sdhci_msm_populate_pdata(&pdev->dev, &msm_host->pdata);
+	if (ret) {
+		dev_err(&pdev->dev, "DT parsing error\n");
+		goto pltfm_free;
+	}
+
+	/* Setup SDCC bus voter clock. */
+	msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus");
+	if (!IS_ERR(msm_host->bus_clk)) {
+		/* Vote for max. clk rate for max. performance */
+		ret = clk_set_rate(msm_host->bus_clk, INT_MAX);
+		if (ret)
+			goto pltfm_free;
+		ret = clk_prepare_enable(msm_host->bus_clk);
+		if (ret)
+			goto pltfm_free;
+	}
+
+	/* Setup main peripheral bus clock */
+	msm_host->pclk = devm_clk_get(&pdev->dev, "iface");
+	if (!IS_ERR(msm_host->pclk)) {
+		ret = clk_prepare_enable(msm_host->pclk);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Main peripheral clock setup fail (%d)\n", ret);
+			goto bus_clk_disable;
+		}
+	}
+
+	/* Setup SDC MMC clock */
+	msm_host->clk = devm_clk_get(&pdev->dev, "core");
+	if (IS_ERR(msm_host->clk)) {
+		ret = PTR_ERR(msm_host->clk);
+		dev_err(&pdev->dev, "SDC MMC clock setup fail (%d)\n", ret);
+		goto pclk_disable;
+	}
+
+	ret = clk_prepare_enable(msm_host->clk);
+	if (ret)
+		goto pclk_disable;
+
+	/* Setup regulators */
+	ret = sdhci_msm_vreg_init(&pdev->dev, &msm_host->pdata);
+	if (ret) {
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Regulator setup fail (%d)\n", ret);
+		goto clk_disable;
+	}
+
+	core_memres = platform_get_resource_byname(pdev,
+						   IORESOURCE_MEM, "core_mem");
+	msm_host->core_mem = devm_ioremap_resource(&pdev->dev, core_memres);
+
+	if (IS_ERR(msm_host->core_mem)) {
+		dev_err(&pdev->dev, "Failed to remap registers\n");
+		ret = PTR_ERR(msm_host->core_mem);
+		goto vreg_disable;
+	}
+
+	/* Reset the core and Enable SDHC mode */
+	writel_relaxed(readl_relaxed(msm_host->core_mem + CORE_POWER) |
+		       CORE_SW_RST, msm_host->core_mem + CORE_POWER);
+
+	/* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
+	usleep_range(1000, 5000);
+	if (readl(msm_host->core_mem + CORE_POWER) & CORE_SW_RST) {
+		dev_err(&pdev->dev, "Stuck in reset\n");
+		ret = -ETIMEDOUT;
+		goto vreg_disable;
+	}
+
+	/* Set HC_MODE_EN bit in HC_MODE register */
+	writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE));
+
+	/*
+	 * Following are the deviations from SDHC spec v3.0 -
+	 * 1. Card detection is handled using separate GPIO.
+	 * 2. Bus power control is handled by interacting with PMIC.
+	 */
+	host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+	host->quirks |= SDHCI_QUIRK_SINGLE_POWER_WRITE;
+
+	host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
+	dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n",
+		host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >>
+			       SDHCI_VENDOR_VER_SHIFT));
+
+	/* Setup PWRCTL irq */
+	msm_host->pwr_irq = platform_get_irq_byname(pdev, "pwr_irq");
+	if (msm_host->pwr_irq < 0) {
+		dev_err(&pdev->dev, "Failed to get pwr_irq by name (%d)\n",
+			msm_host->pwr_irq);
+		goto vreg_disable;
+	}
+	ret = devm_request_threaded_irq(&pdev->dev, msm_host->pwr_irq, NULL,
+					sdhci_msm_pwr_irq, IRQF_ONESHOT,
+					dev_name(&pdev->dev), host);
+	if (ret) {
+		dev_err(&pdev->dev, "Request threaded irq(%d) fail (%d)\n",
+			msm_host->pwr_irq, ret);
+		goto vreg_disable;
+	}
+
+	/* Enable pwr irq interrupts */
+	writel_relaxed(INT_MASK, (msm_host->core_mem + CORE_PWRCTL_MASK));
+
+	msm_host->mmc->caps |= msm_host->pdata.caps;
+	msm_host->mmc->caps2 |= msm_host->pdata.caps2;
+
+	ret = sdhci_add_host(host);
+	if (ret) {
+		dev_err(&pdev->dev, "Add host fail (%d)\n", ret);
+		goto vreg_disable;
+	}
+
+	ret = clk_set_rate(msm_host->clk, host->max_clk);
+	if (ret) {
+		dev_err(&pdev->dev, "MClk rate set fail (%d)\n", ret);
+		goto remove_host;
+	}
+
+	return 0;
+
+remove_host:
+	dead = (readl_relaxed(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
+	sdhci_remove_host(host, dead);
+vreg_disable:
+	if (!IS_ERR(msm_host->pdata.vdd.reg))
+		sdhci_msm_vreg_disable(&pdev->dev, &msm_host->pdata.vdd);
+	if (!IS_ERR(msm_host->pdata.vdd_io.reg))
+		sdhci_msm_vreg_disable(&pdev->dev, &msm_host->pdata.vdd_io);
+clk_disable:
+	if (!IS_ERR(msm_host->clk))
+		clk_disable_unprepare(msm_host->clk);
+pclk_disable:
+	if (!IS_ERR(msm_host->pclk))
+		clk_disable_unprepare(msm_host->pclk);
+bus_clk_disable:
+	if (!IS_ERR(msm_host->bus_clk))
+		clk_disable_unprepare(msm_host->bus_clk);
+pltfm_free:
+	sdhci_pltfm_free(pdev);
+	return ret;
+}
+
+static int sdhci_msm_remove(struct platform_device *pdev)
+{
+	struct sdhci_host *host = platform_get_drvdata(pdev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+	int dead = (readl_relaxed(host->ioaddr + SDHCI_INT_STATUS) ==
+		    0xffffffff);
+
+	sdhci_remove_host(host, dead);
+	sdhci_pltfm_free(pdev);
+	sdhci_msm_vreg_disable(&pdev->dev, &msm_host->pdata.vdd);
+	sdhci_msm_vreg_disable(&pdev->dev, &msm_host->pdata.vdd_io);
+	clk_disable_unprepare(msm_host->clk);
+	clk_disable_unprepare(msm_host->pclk);
+	if (!IS_ERR(msm_host->bus_clk))
+		clk_disable_unprepare(msm_host->bus_clk);
+	return 0;
+}
+
+static struct platform_driver sdhci_msm_driver = {
+	.probe = sdhci_msm_probe,
+	.remove = sdhci_msm_remove,
+	.driver = {
+		   .name = "sdhci_msm",
+		   .owner = THIS_MODULE,
+		   .of_match_table = sdhci_msm_dt_match,
+	},
+};
+
+module_platform_driver(sdhci_msm_driver);
+
+MODULE_DESCRIPTION("Qualcomm Secure Digital Host Controller Interface driver");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox