*
* These headers and macros are used to define OMAP on-chip module
* data and their integration with other OMAP modules and Linux.
- *
- * References:
- * - OMAP2420 Multimedia Processor Silicon Revision 2.1.1, 2.2 (SWPU064)
- * - OMAP2430 Multimedia Device POP Silicon Revision 2.1 (SWPU090)
- * - OMAP34xx Multimedia Device Silicon Revision 3.1 (SWPU108)
- * - OMAP4430 Multimedia Device Silicon Revision 1.0 (SWPU140)
- * - Open Core Protocol Specification 2.2
+ * Copious documentation and references can also be found in the
+ * omap_hwmod code, in arch/arm/mach-omap2/omap_hwmod.c (as of this
+ * writing).
*
* To do:
* - add interconnect error log structures
* - add pinmuxing
* - init_conn_id_bit (CONNID_BIT_VECTOR)
* - implement default hwmod SMS/SDRC flags?
+ * - remove unused fields
*
*/
#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/ioport.h>
+#include <linux/mutex.h>
#include <plat/cpu.h>
struct omap_device;
/**
* struct omap_hwmod_dma_info - DMA channels used by the hwmod
* @name: name of the DMA channel (module local name)
- * @dma_ch: DMA channel ID
+ * @dma_req: DMA request ID
*
* @name should be something short, e.g., "tx" or "rx". It is for use
* by platform_get_resource_byname(). It is defined locally to the
*/
struct omap_hwmod_dma_info {
const char *name;
- u16 dma_ch;
+ u16 dma_req;
+};
+
+/**
+ * struct omap_hwmod_rst_info - IPs reset lines use by hwmod
+ * @name: name of the reset line (module local name)
+ * @rst_shift: Offset of the reset bit
+ *
+ * @name should be something short, e.g., "cpu0" or "rst". It is defined
+ * locally to the hwmod.
+ */
+struct omap_hwmod_rst_info {
+ const char *name;
+ u8 rst_shift;
};
/**
#define SYSC_HAS_CLOCKACTIVITY (1 << 4)
#define SYSC_HAS_SIDLEMODE (1 << 5)
#define SYSC_HAS_MIDLEMODE (1 << 6)
-#define SYSS_MISSING (1 << 7)
+#define SYSS_HAS_RESET_STATUS (1 << 7)
#define SYSC_NO_CACHE (1 << 8) /* XXX SW flag, belongs elsewhere */
+#define SYSC_HAS_RESET_STATUS (1 << 9)
/* omap_hwmod_sysconfig.clockact flags */
#define CLOCKACT_TEST_BOTH 0x0
/**
* struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
* @clkctrl_reg: PRCM address of the clock control register
+ * @rstctrl_reg: adress of the XXX_RSTCTRL register located in the PRM
* @submodule_wkdep_bit: bit shift of the WKDEP range
*/
struct omap_hwmod_omap4_prcm {
void __iomem *clkctrl_reg;
+ void __iomem *rstctrl_reg;
u8 submodule_wkdep_bit;
};
* HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup
* HWMOD_NO_IDLEST : this module does not have idle status - this is the case
* only for few initiator modules on OMAP2 & 3.
+ * HWMOD_CONTROL_OPT_CLKS_IN_RESET: Enable all optional clocks during reset.
+ * This is needed for devices like DSS that require optional clocks enabled
+ * in order to complete the reset. Optional clocks will be disabled
+ * again after the reset.
*/
#define HWMOD_SWSUP_SIDLE (1 << 0)
#define HWMOD_SWSUP_MSTANDBY (1 << 1)
#define HWMOD_NO_OCP_AUTOIDLE (1 << 4)
#define HWMOD_SET_DEFAULT_CLOCKACT (1 << 5)
#define HWMOD_NO_IDLEST (1 << 6)
+#define HWMOD_CONTROL_OPT_CLKS_IN_RESET (1 << 7)
/*
* omap_hwmod._int_flags definitions
* @class: struct omap_hwmod_class * to the class of this hwmod
* @od: struct omap_device currently associated with this hwmod (internal use)
* @mpu_irqs: ptr to an array of MPU IRQs (see also mpu_irqs_cnt)
- * @sdma_chs: ptr to an array of SDMA channel IDs (see also sdma_chs_cnt)
+ * @sdma_reqs: ptr to an array of System DMA request IDs (see sdma_reqs_cnt)
* @prcm: PRCM data pertaining to this hwmod
* @main_clk: main clock: OMAP clock name
* @_clk: pointer to the main struct clk (filled in at runtime)
* @msuspendmux_reg_id: CONTROL_MSUSPENDMUX register ID (1-6)
* @msuspendmux_shift: CONTROL_MSUSPENDMUX register bit shift
* @mpu_irqs_cnt: number of @mpu_irqs
- * @sdma_chs_cnt: number of @sdma_chs
+ * @sdma_reqs_cnt: number of @sdma_reqs
* @opt_clks_cnt: number of @opt_clks
* @master_cnt: number of @master entries
* @slaves_cnt: number of @slave entries
* @_state: internal-use hwmod state
* @flags: hwmod flags (documented below)
* @omap_chip: OMAP chips this hwmod is present on
+ * @_mutex: mutex serializing operations on this hwmod
* @node: list node for hwmod list (internal use)
*
* @main_clk refers to this module's "main clock," which for our
struct omap_hwmod_class *class;
struct omap_device *od;
struct omap_hwmod_irq_info *mpu_irqs;
- struct omap_hwmod_dma_info *sdma_chs;
+ struct omap_hwmod_dma_info *sdma_reqs;
+ struct omap_hwmod_rst_info *rst_lines;
union {
struct omap_hwmod_omap2_prcm omap2;
struct omap_hwmod_omap4_prcm omap4;
void *dev_attr;
u32 _sysc_cache;
void __iomem *_mpu_rt_va;
+ struct mutex _mutex;
struct list_head node;
u16 flags;
u8 _mpu_port_index;
u8 msuspendmux_shift;
u8 response_lat;
u8 mpu_irqs_cnt;
- u8 sdma_chs_cnt;
+ u8 sdma_reqs_cnt;
+ u8 rst_lines_cnt;
u8 opt_clks_cnt;
u8 masters_cnt;
u8 slaves_cnt;
int _omap_hwmod_idle(struct omap_hwmod *oh);
int omap_hwmod_shutdown(struct omap_hwmod *oh);
+int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name);
+int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name);
+int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name);
+
int omap_hwmod_enable_clocks(struct omap_hwmod *oh);
int omap_hwmod_disable_clocks(struct omap_hwmod *oh);
extern int omap2420_hwmod_init(void);
extern int omap2430_hwmod_init(void);
extern int omap3xxx_hwmod_init(void);
+ extern int omap44xx_hwmod_init(void);
#endif
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/io.h>
+#include <linux/clk.h>
#include <plat/omap_device.h>
#include <plat/omap_hwmod.h>
#define USE_WAKEUP_LAT 0
#define IGNORE_WAKEUP_LAT 1
- /*
- * OMAP_DEVICE_MAGIC: used to determine whether a struct omap_device
- * obtained via container_of() is in fact a struct omap_device
- */
- #define OMAP_DEVICE_MAGIC 0xf00dcafe
-
/* Private functions */
/**
return container_of(pdev, struct omap_device, pdev);
}
+/**
+ * _add_optional_clock_alias - Add clock alias for hwmod optional clocks
+ * @od: struct omap_device *od
+ *
+ * For every optional clock present per hwmod per omap_device, this function
+ * adds an entry in the clocks list of the form <dev-id=dev_name, con-id=role>
+ * if an entry is already present in it with the form <dev-id=NULL, con-id=role>
+ *
+ * The function is called from inside omap_device_build_ss(), after
+ * omap_device_register.
+ *
+ * This allows drivers to get a pointer to its optional clocks based on its role
+ * by calling clk_get(<dev*>, <role>).
+ *
+ * No return value.
+ */
+static void _add_optional_clock_alias(struct omap_device *od,
+ struct omap_hwmod *oh)
+{
+ int i;
+
+ for (i = 0; i < oh->opt_clks_cnt; i++) {
+ struct omap_hwmod_opt_clk *oc;
+ int r;
+
+ oc = &oh->opt_clks[i];
+
+ if (!oc->_clk)
+ continue;
+
+ r = clk_add_alias(oc->role, dev_name(&od->pdev.dev),
+ (char *)oc->clk, &od->pdev.dev);
+ if (r)
+ pr_err("omap_device: %s: clk_add_alias for %s failed\n",
+ dev_name(&od->pdev.dev), oc->role);
+ }
+}
+
/* Public functions for use by core code */
od->pm_lats = pm_lats;
od->pm_lats_cnt = pm_lats_cnt;
- od->magic = OMAP_DEVICE_MAGIC;
-
if (is_early_device)
ret = omap_early_device_register(od);
else
ret = omap_device_register(od);
- for (i = 0; i < oh_cnt; i++)
+ for (i = 0; i < oh_cnt; i++) {
hwmods[i]->od = od;
+ _add_optional_clock_alias(od, hwmods[i]);
+ }
if (ret)
goto odbs_exit4;
{
pr_debug("omap_device: %s: registering\n", od->pdev.name);
+ od->pdev.dev.parent = &omap_device_parent;
return platform_device_register(&od->pdev);
}
return ret;
}
- /**
- * omap_device_is_valid - Check if pointer is a valid omap_device
- * @od: struct omap_device *
- *
- * Return whether struct omap_device pointer @od points to a valid
- * omap_device.
- */
- bool omap_device_is_valid(struct omap_device *od)
- {
- return (od && od->magic == OMAP_DEVICE_MAGIC);
- }
-
/**
* omap_device_get_pwrdm - return the powerdomain * associated with @od
* @od: struct omap_device *
/* XXX pass along return value here? */
return 0;
}
+
+ struct device omap_device_parent = {
+ .init_name = "omap",
+ .parent = &platform_bus,
+ };
+
+ static int __init omap_device_init(void)
+ {
+ return device_register(&omap_device_parent);
+ }
+ core_initcall(omap_device_init);